@@ -5,7 +5,7 @@ import back::abi;
5
5
import base :: { call_memmove,
6
6
INIT , copy_val, load_if_immediate, get_tydesc,
7
7
sub_block, do_spill_noroot,
8
- dest, bcx_icx, non_gc_box_cast} ;
8
+ dest, bcx_icx, non_gc_box_cast, move_val , lval_owned } ;
9
9
import syntax:: codemap:: span;
10
10
import shape:: llsize_of;
11
11
import build:: * ;
@@ -118,18 +118,39 @@ fn make_drop_glue_unboxed(bcx: block, vptr: ValueRef, vec_ty: ty::t) ->
118
118
} else { bcx }
119
119
}
120
120
121
- fn trans_evec( bcx : block , args : ~[ @ast:: expr ] ,
121
+ enum evec_elements {
122
+ individual_evec( ~[ @ast:: expr ] ) ,
123
+ repeating_evec( @ast:: expr , uint )
124
+ }
125
+
126
+ fn trans_evec( bcx : block , elements : evec_elements ,
122
127
vst : ast:: vstore , id : ast:: node_id , dest : dest ) -> block {
123
128
let _icx = bcx. insn_ctxt ( ~"tvec:: trans_evec") ;
124
129
let ccx = bcx. ccx ( ) ;
125
130
let mut bcx = bcx;
131
+
132
+ // Handle the ignored case.
126
133
if dest == base:: ignore {
127
- for vec:: each( args) |arg| {
128
- bcx = base:: trans_expr ( bcx, arg, base:: ignore) ;
134
+ match elements {
135
+ individual_evec( args) => {
136
+ for vec:: each( args) |arg| {
137
+ bcx = base:: trans_expr ( bcx, arg, base:: ignore) ;
138
+ }
139
+ }
140
+ repeating_evec( element, _) => {
141
+ bcx = base:: trans_expr ( bcx, element, base:: ignore) ;
142
+ }
129
143
}
130
144
return bcx;
131
145
}
132
146
147
+ // Figure out the number of elements we need.
148
+ let count;
149
+ match elements {
150
+ individual_evec( args) => count = args. len ( ) ,
151
+ repeating_evec( _, len) => count = len
152
+ }
153
+
133
154
let vec_ty = node_id_type ( bcx, id) ;
134
155
let unit_ty = ty:: sequence_element_type ( bcx. tcx ( ) , vec_ty) ;
135
156
let llunitty = type_of:: type_of ( ccx, unit_ty) ;
@@ -151,13 +172,12 @@ fn trans_evec(bcx: block, args: ~[@ast::expr],
151
172
{ bcx: bcx, val: v, dataptr: v}
152
173
}
153
174
ast:: vstore_slice ( _) {
154
- let n = vec:: len ( args) ;
155
175
// Make a fake type to use for the cleanup
156
176
let ty = ty:: mk_evec ( bcx. tcx ( ) ,
157
177
{ ty: unit_ty, mutbl: ast:: m_mutbl} ,
158
- ty:: vstore_fixed ( n ) ) ;
178
+ ty:: vstore_fixed ( count ) ) ;
159
179
160
- let n = C_uint ( ccx, n ) ;
180
+ let n = C_uint ( ccx, count ) ;
161
181
let vp = base:: arrayalloca ( bcx, llunitty, n) ;
162
182
add_clean ( bcx, vp, ty) ;
163
183
@@ -171,15 +191,13 @@ fn trans_evec(bcx: block, args: ~[@ast::expr],
171
191
{ bcx: bcx, val: p, dataptr: vp}
172
192
}
173
193
ast:: vstore_uniq {
174
- let { bcx, val} = alloc_vec ( bcx, unit_ty, args. len ( ) ,
175
- heap_exchange) ;
194
+ let { bcx, val} = alloc_vec ( bcx, unit_ty, count, heap_exchange) ;
176
195
add_clean_free ( bcx, val, heap_exchange) ;
177
196
let dataptr = get_dataptr ( bcx, get_bodyptr ( bcx, val) ) ;
178
197
{ bcx: bcx, val: val, dataptr: dataptr}
179
198
}
180
199
ast:: vstore_box {
181
- let { bcx, val} = alloc_vec ( bcx, unit_ty, args. len ( ) ,
182
- heap_shared) ;
200
+ let { bcx, val} = alloc_vec ( bcx, unit_ty, count, heap_shared) ;
183
201
add_clean_free ( bcx, val, heap_shared) ;
184
202
let dataptr = get_dataptr ( bcx, get_bodyptr ( bcx, val) ) ;
185
203
{ bcx: bcx, val: val, dataptr: dataptr}
@@ -192,12 +210,38 @@ fn trans_evec(bcx: block, args: ~[@ast::expr],
192
210
debug ! { "trans_evec: v: %s, dataptr: %s" ,
193
211
val_str( ccx. tn, val) ,
194
212
val_str( ccx. tn, dataptr) } ;
195
- for vec:: each( args) |e| {
196
- let lleltptr = InBoundsGEP ( bcx, dataptr, ~[ C_uint ( ccx, i) ] ) ;
197
- bcx = base:: trans_expr_save_in ( bcx, e, lleltptr) ;
198
- add_clean_temp_mem ( bcx, lleltptr, unit_ty) ;
199
- vec:: push ( temp_cleanups, lleltptr) ;
200
- i += 1 u;
213
+ match elements {
214
+ individual_evec( args) => {
215
+ for vec:: each( args) |e| {
216
+ let lleltptr = InBoundsGEP ( bcx, dataptr, ~[ C_uint ( ccx, i) ] ) ;
217
+ bcx = base:: trans_expr_save_in ( bcx, e, lleltptr) ;
218
+ add_clean_temp_mem ( bcx, lleltptr, unit_ty) ;
219
+ vec:: push ( temp_cleanups, lleltptr) ;
220
+ i += 1 u;
221
+ }
222
+ }
223
+ repeating_evec( e, len) => {
224
+ // We make temporary space in the hope that this will be
225
+ // friendlier to LLVM alias analysis.
226
+ let lltmpspace = base:: alloca ( bcx, llunitty) ;
227
+ bcx = base:: trans_expr_save_in ( bcx, e, lltmpspace) ;
228
+ add_clean_temp_mem ( bcx, lltmpspace, unit_ty) ;
229
+ vec:: push ( temp_cleanups, lltmpspace) ;
230
+ for len. timesi |i| {
231
+ let lleltptr = InBoundsGEP ( bcx, dataptr, ~[ C_uint ( ccx, i) ] ) ;
232
+ if i == len - 1 {
233
+ // Move the last one in.
234
+ bcx = move_val ( bcx, INIT , lleltptr,
235
+ lval_owned ( bcx, lltmpspace) , unit_ty) ;
236
+ } else {
237
+ // Copy all but the last one in.
238
+ let llval = load_if_immediate ( bcx, lltmpspace, unit_ty) ;
239
+ bcx = copy_val ( bcx, INIT , lleltptr, llval, unit_ty) ;
240
+ }
241
+ add_clean_temp_mem ( bcx, lleltptr, unit_ty) ;
242
+ vec:: push ( temp_cleanups, lleltptr) ;
243
+ }
244
+ }
201
245
}
202
246
203
247
for vec:: each( temp_cleanups) |cln| { revoke_clean( bcx, cln) ; }
@@ -219,13 +263,17 @@ fn trans_evec(bcx: block, args: ~[@ast::expr],
219
263
fn trans_vstore( bcx: block, e: @ast:: expr,
220
264
v: ast:: vstore, dest: dest) -> block {
221
265
alt e. node {
222
- ast : : expr_lit ( @{ node : ast:: lit_str( s) , span : _} ) {
266
+ ast : : expr_lit ( @{ node : ast:: lit_str( s) , span : _} ) => {
223
267
return trans_estr( bcx, s, some( v) , dest) ;
224
268
}
225
- ast:: expr_vec( es, mutbl) {
226
- return trans_evec( bcx, es , v, e. id, dest) ;
269
+ ast:: expr_vec( es, mutbl) => {
270
+ return trans_evec( bcx, individual_evec ( es ) , v, e. id, dest) ;
227
271
}
228
- _ {
272
+ ast:: expr_repeat( element, count_expr, mutbl) => {
273
+ let count = ty:: eval_repeat_count( bcx. tcx( ) , count_expr, e. span) ;
274
+ return trans_evec( bcx, repeating_evec( element, count) , v, e. id, dest) ;
275
+ }
276
+ _ => {
229
277
bcx. sess( ) . span_bug( e. span, ~"vstore on non-sequence type") ;
230
278
}
231
279
}
0 commit comments