@@ -64,68 +64,65 @@ fn mk_const(&@crate_ctxt ccx, &str name, bool exported, ValueRef llval)
64
64
65
65
// Destination utilities
66
66
67
- tag dest_slot {
68
- dst_nil;
69
- dst_imm ( @mutable option[ ValueRef ] ) ;
70
- dst_ptr ( ValueRef ) ;
67
+ tag dest {
68
+ dst_nil; // Unit destination; ignore.
69
+ dst_imm ( @mutable option[ ValueRef ] ) ; // Fill with an immediate value.
70
+ dst_alias ( @mutable option[ ValueRef ] ) ; // Fill with an alias pointer.
71
+ dst_copy ( ValueRef ) ; // Copy to the given address.
72
+ dst_move ( ValueRef ) ; // Move to the given address.
71
73
}
72
74
73
- tag dest_mode { dm_copy ; dm_move ; dm_alias ; }
74
-
75
- type dest = rec ( dest_slot slot , dest_mode mode ) ;
75
+ fn dest_imm ( & ty :: ctxt tcx , ty :: t t ) -> dest {
76
+ if ty :: type_is_nil ( tcx , t ) { dst_nil } else { dst_imm ( @mutable none ) }
77
+ }
76
78
77
- fn dest_slot_for_ptr ( & ty:: ctxt tcx, ValueRef llptr , ty:: t t) -> dest_slot {
78
- if ty:: type_is_nil ( tcx, t) { dst_nil } else { dst_ptr ( llptr ) }
79
+ fn dest_alias ( & ty:: ctxt tcx, ty:: t t) -> dest {
80
+ if ty:: type_is_nil ( tcx, t) { dst_nil } else { dst_alias ( @mutable none ) }
79
81
}
80
82
81
83
fn dest_copy ( & ty:: ctxt tcx, ValueRef llptr, ty:: t t) -> dest {
82
- ret rec ( slot= dest_slot_for_ptr ( tcx, llptr , t ) , mode=dm_copy ) ;
84
+ if ty :: type_is_nil ( tcx, t ) { dst_nil } else { dst_copy ( llptr ) }
83
85
}
84
86
85
87
fn dest_move ( & ty:: ctxt tcx, ValueRef llptr, ty:: t t) -> dest {
86
- ret rec ( slot=dest_slot_for_ptr ( tcx, llptr, t) , mode=dm_move) ;
87
- }
88
-
89
- fn dest_alias ( & ty:: ctxt tcx, ValueRef llptr, ty:: t t) -> dest {
90
- ret rec ( slot=dest_slot_for_ptr ( tcx, llptr, t) , mode=dm_alias) ;
91
- }
92
-
93
- fn dest_tmp ( & @block_ctxt bcx , ty:: t t, bool alias ) -> tup ( @block_ctxt , dest ) {
94
- auto mode = if alias { dm_alias } else { dm_move } ;
95
- if ty:: type_is_nil ( bcx_tcx ( bcx) , t) {
96
- ret tup ( bcx, rec ( slot=dst_nil, mode=mode) ) ;
97
- }
98
- if trans:: type_is_immediate ( bcx_ccx ( bcx) , t) {
99
- ret tup ( bcx, rec ( slot=dst_imm ( @mutable none) , mode=mode) ) ;
100
- }
101
- auto r = trans:: alloc_ty ( bcx, t) ;
102
- trans:: add_clean ( bcx, r. val , t) ;
103
- ret tup( r. bcx , rec ( slot=dest_slot_for_ptr ( bcx_tcx ( bcx) , r. val , t) ,
104
- mode=mode) ) ;
88
+ if ty:: type_is_nil ( tcx, t) { dst_nil } else { dst_move ( llptr) }
105
89
}
106
90
107
91
// Invariant: the type of the destination must be structural (non-immediate).
108
92
fn dest_ptr ( & dest dest) -> ValueRef {
109
- alt ( dest. slot ) {
93
+ alt ( dest) {
110
94
dst_nil { fail "nil dest in dest_ptr" }
111
95
dst_imm ( _) { fail "immediate dest in dest_ptr" }
112
- dst_ptr ( ?llptr) { llptr }
96
+ dst_alias ( _) { fail "alias dest in dest_ptr" }
97
+ dst_copy ( ?llptr) { llptr }
98
+ dst_move ( ?llptr) { llptr }
113
99
}
114
100
}
115
101
116
102
fn dest_llval ( & dest dest) -> ValueRef {
117
- alt ( dest. slot ) {
103
+ alt ( dest) {
118
104
dst_nil { ret tc:: C_nil ( ) ; }
119
105
dst_imm ( ?box) {
120
106
alt ( * box) {
121
107
none { fail "immediate wasn't filled in prior to dest_llval" ; }
122
108
some ( ?llval) { ret llval; }
123
109
}
124
110
}
125
- dst_ptr ( ?llval) { ret llval; }
111
+ dst_alias ( ?box) {
112
+ alt ( * box) {
113
+ none { fail "alias wasn't filled in prior to dest_llval" ; }
114
+ some ( ?llval) { ret llval; }
115
+ }
116
+ }
117
+ dst_copy ( ?llptr) { ret llptr; }
118
+ dst_move ( ?llptr) { ret llptr; }
126
119
}
127
120
}
128
121
122
+ fn dest_is_alias ( & dest dest) -> bool {
123
+ alt ( dest) { dst_alias ( _) { true } _ { false } }
124
+ }
125
+
129
126
130
127
// Accessors
131
128
// TODO: When we have overloading, simplify these names!
@@ -135,42 +132,44 @@ fn bcx_ccx(&@block_ctxt bcx) -> @crate_ctxt { ret bcx.fcx.lcx.ccx; }
135
132
fn bcx_lcx ( & @block_ctxt bcx ) -> @local_ctxt { ret bcx. fcx . lcx ; }
136
133
fn bcx_fcx ( & @block_ctxt bcx ) -> @fn_ctxt { ret bcx. fcx ; }
137
134
fn lcx_ccx ( & @local_ctxt lcx ) -> @crate_ctxt { ret lcx. ccx ; }
135
+ fn ccx_tcx ( & @crate_ctxt ccx ) -> ty:: ctxt { ret ccx. tcx ; }
138
136
139
137
140
138
// Common operations
141
139
142
140
// If "cast" is true, casts dest appropriately before the store.
143
- fn store ( & @block_ctxt bcx , & dest dest, ValueRef llsrc, bool cast)
141
+ fn store_imm ( & @block_ctxt bcx , & dest dest, ValueRef llsrc, bool cast)
144
142
-> @block_ctxt {
145
- alt ( dest. slot ) {
143
+ alt ( dest) {
146
144
dst_nil { /* no-op */ }
147
145
dst_imm( ?box) {
148
- if !std:: option:: is_none ( * box) {
149
- fail "attempt to store an immediate twice" ;
150
- } ;
146
+ assert ( std:: option:: is_none ( * box) ) ;
151
147
* box = some ( llsrc) ;
152
148
}
153
- dst_ptr ( ?lldestptr_orig) {
149
+ dst_alias ( ?box) {
150
+ bcx_ccx ( bcx) . sess . unimpl ( "dst_alias spill in store_imm" ) ;
151
+ }
152
+ dst_copy ( ?lldestptr_orig) | dst_move ( ?lldestptr_orig) {
154
153
auto lldestptr = lldestptr_orig;
155
154
if cast {
156
155
lldestptr = bcx. build . PointerCast ( lldestptr,
157
156
tc:: T_ptr ( lltype_of ( llsrc) ) ) ;
158
157
}
159
-
160
158
bcx. build . Store ( llsrc, lldestptr) ;
161
159
}
162
160
}
163
161
ret bcx;
164
162
}
165
163
166
- fn memmove ( & @block_ctxt bcx , & dest dest, ValueRef llsrcptr) -> @block_ctxt {
167
- alt ( dest. slot ) {
168
- // TODO: We might want to support these; I can't think of any case in
169
- // which we would want them off the top of my head, but feel free to add
170
- // them if they aid orthogonality.
171
- dst_nil { fail "dst_nil in memmove" ; }
172
- dst_imm ( _) { fail "dst_imm in memmove" ; }
173
- dst_ptr ( ?lldestptr) {
164
+ fn store_ptr ( & @block_ctxt bcx , & dest dest, ValueRef llsrcptr) -> @block_ctxt {
165
+ alt ( dest) {
166
+ dst_nil { /* no-op */ }
167
+ dst_imm( ?box) { fail "dst_imm in store_ptr" ; }
168
+ dst_alias ( ?box) {
169
+ assert ( std:: option:: is_none ( * box) ) ;
170
+ * box = some ( llsrcptr) ;
171
+ }
172
+ dst_copy ( ?lldestptr) | dst_move ( ?lldestptr) {
174
173
auto lldestty = llelement_type ( trans:: val_ty ( llsrcptr) ) ;
175
174
auto llsrcty = llelement_type ( trans:: val_ty ( llsrcptr) ) ;
176
175
auto dest_align = llalign_of ( bcx_ccx ( bcx) , lldestty) ;
@@ -190,6 +189,7 @@ fn memmove(&@block_ctxt bcx, &dest dest, ValueRef llsrcptr) -> @block_ctxt {
190
189
ret bcx;
191
190
}
192
191
}
192
+ ret bcx;
193
193
}
194
194
195
195
// Allocates a value of the given LLVM size on either the task heap or the
@@ -228,9 +228,9 @@ fn trans_lit(&@block_ctxt cx, &dest dest, &ast::lit lit) -> @block_ctxt {
228
228
auto bcx = cx;
229
229
alt ( lit. node ) {
230
230
ast:: lit_str ( ?s, ast:: sk_unique) {
231
- auto r = trans_lit_str_common ( bcx_ccx ( bcx) , s) ;
231
+ auto r = trans_lit_str_common ( bcx_ccx ( bcx) , s, dest_is_alias ( dest ) ) ;
232
232
auto llstackpart = r. _0 ; auto llheappartopt = r. _1 ;
233
- bcx = memmove ( bcx, dest, llstackpart) ;
233
+ bcx = store_ptr ( bcx, dest, llstackpart) ;
234
234
alt ( llheappartopt) {
235
235
none { /* no-op */ }
236
236
some( ?llheappart) {
@@ -244,13 +244,13 @@ fn trans_lit(&@block_ctxt cx, &dest dest, &ast::lit lit) -> @block_ctxt {
244
244
tc:: T_ptr ( tc:: T_ptr ( llheappartty) ) ) ;
245
245
malloc ( bcx, lldestptrptr, hp_shared, none) ;
246
246
auto lldestptr = bcx. build . Load ( lldestptrptr) ;
247
- memmove ( bcx, rec ( slot=dst_ptr ( lldestptr) , mode=dm_copy) ,
248
- llheappart) ;
247
+ store_ptr ( bcx, dst_copy ( lldestptr) , llheappart) ;
249
248
}
250
249
}
251
250
}
252
251
_ {
253
- bcx = store ( bcx, dest, trans_lit_common ( bcx_ccx ( bcx) , lit) , false ) ;
252
+ bcx = store_imm ( bcx, dest, trans_lit_common ( bcx_ccx ( bcx) , lit) ,
253
+ false ) ;
254
254
}
255
255
}
256
256
@@ -280,47 +280,35 @@ fn trans_log(&@block_ctxt cx, &span sp, int level, &@ast::expr expr)
280
280
ret lllevelptr;
281
281
}
282
282
283
- fn trans_log_upcall ( & @block_ctxt cx , & span sp, ValueRef in_llval,
284
- int level , ty:: t t) -> @block_ctxt {
285
- auto bcx = cx;
286
- auto llval = in_llval;
287
- auto llupcall;
288
- alt ( ty:: struct ( bcx_tcx ( bcx) , t) ) {
283
+ tag upcall_style { us_imm; us_imm_i32_zext; us_alias; us_alias_istr; }
284
+ fn get_upcall ( & @crate_ctxt ccx , & span sp, ty:: t t)
285
+ -> tup ( ValueRef , upcall_style ) {
286
+ alt ( ty:: struct ( ccx_tcx ( ccx) , t) ) {
289
287
ty:: ty_machine ( ast:: ty_f32) {
290
- llupcall = bcx_ccx ( bcx ) . upcalls . log_float ;
288
+ ret tup ( ccx . upcalls . log_float , us_imm ) ;
291
289
}
292
290
ty:: ty_machine ( ast:: ty_f64) | ty:: ty_float {
293
- llupcall = bcx_ccx ( bcx) . upcalls . log_double ;
294
-
295
- // TODO: Here we have to spill due to legacy calling conventions.
296
- // This is no longer necessary.
297
- auto r = trans:: alloc_ty ( bcx, t) ;
298
- bcx = r. bcx ; auto llptr = r. val ;
299
- bcx. build . Store ( llval, llptr) ;
300
- llval = llptr;
291
+ // TODO: We have to spill due to legacy calling conventions that
292
+ // should probably be modernized.
293
+ ret tup( ccx. upcalls . log_double , us_alias) ;
301
294
}
302
295
ty:: ty_bool | ty:: ty_machine ( ast:: ty_i8) |
303
296
ty:: ty_machine ( ast:: ty_i16) | ty:: ty_machine ( ast:: ty_u8) |
304
297
ty:: ty_machine ( ast:: ty_u16) {
305
- llupcall = bcx_ccx ( bcx) . upcalls . log_int ;
306
- llval = bcx. build . ZExt ( llval, tc:: T_i32 ( ) ) ;
298
+ ret tup ( ccx. upcalls . log_int , us_imm_i32_zext) ;
307
299
}
308
300
ty:: ty_int | ty:: ty_machine ( ast:: ty_i32) |
309
301
ty:: ty_machine ( ast:: ty_u32) {
310
- llupcall = bcx_ccx ( bcx ) . upcalls . log_int ;
302
+ ret tup ( ccx . upcalls . log_int , us_imm ) ;
311
303
}
312
304
ty:: ty_istr {
313
- llupcall = bcx_ccx ( bcx ) . upcalls . log_istr ;
305
+ ret tup ( ccx . upcalls . log_istr , us_alias_istr ) ;
314
306
}
315
307
_ {
316
- bcx_ccx ( bcx ) . sess . span_unimpl ( sp, "logging for values of type " +
317
- ppaux:: ty_to_str ( bcx_tcx ( bcx ) , t) ) ;
308
+ ccx . sess . span_unimpl ( sp, "logging for values of type " +
309
+ ppaux:: ty_to_str ( ccx_tcx ( ccx ) , t) ) ;
318
310
}
319
311
}
320
-
321
- bcx. build . Call ( llupcall,
322
- ~[ bcx_fcx ( bcx) . lltaskptr , tc:: C_int ( level) , llval] ) ;
323
- ret bcx;
324
312
}
325
313
326
314
auto bcx = cx;
@@ -336,11 +324,32 @@ fn trans_log(&@block_ctxt cx, &span sp, int level, &@ast::expr expr)
336
324
bcx. build . CondBr ( should_log, log_bcx. llbb , next_bcx. llbb ) ;
337
325
338
326
auto expr_t = ty:: expr_ty ( bcx_tcx ( log_bcx) , expr) ;
339
- auto r = dest_tmp ( log_bcx, expr_t, true ) ;
340
- log_bcx = r. _0 ; auto tmp = r. _1 ;
341
- log_bcx = trans_expr ( log_bcx, tmp, expr) ;
327
+ auto r = get_upcall ( bcx_ccx ( bcx) , sp, expr_t) ;
328
+ auto llupcall = r. _0 ; auto style = r. _1 ;
342
329
343
- log_bcx = trans_log_upcall ( log_bcx, sp, dest_llval ( tmp) , level, expr_t) ;
330
+ auto arg_dest;
331
+ alt ( style) {
332
+ us_imm | us_imm_i32_zext {
333
+ arg_dest = dest_imm ( bcx_tcx ( log_bcx) , expr_t) ;
334
+ }
335
+ us_alias | us_alias_istr {
336
+ arg_dest = dest_alias ( bcx_tcx ( log_bcx) , expr_t) ;
337
+ }
338
+ }
339
+ log_bcx = trans_expr ( log_bcx, arg_dest, expr) ;
340
+
341
+ auto llarg = dest_llval ( arg_dest) ;
342
+ alt ( style) {
343
+ us_imm | us_alias { /* no-op */ }
344
+ us_imm_i32_zext { llarg = log_bcx. build . ZExt ( llarg, tc:: T_i32 ( ) ) ; }
345
+ us_alias_istr {
346
+ llarg = log_bcx. build . PointerCast ( llarg,
347
+ tc:: T_ptr ( tc:: T_ivec ( tc:: T_i8 ( ) ) ) ) ;
348
+ }
349
+ }
350
+
351
+ log_bcx. build . Call ( llupcall,
352
+ ~[ bcx_fcx ( bcx) . lltaskptr , tc:: C_int ( level) , llarg] ) ;
344
353
345
354
log_bcx = trans:: trans_block_cleanups ( log_bcx,
346
355
trans:: find_scope_cx ( log_bcx) ) ;
@@ -393,7 +402,10 @@ fn trans_block(&@block_ctxt cx, &dest dest, &ast::block block)
393
402
// Common setup code shared between the crate-constant literal string case and
394
403
// the block-local literal string case. We don't use destination-passing style
395
404
// since that doesn't work for crate constants.
396
- fn trans_lit_str_common ( & @crate_ctxt ccx , & str s)
405
+ //
406
+ // If |expand| is true, we never spill to the heap. This should be used
407
+ // whenever the destination size isn't fixed.
408
+ fn trans_lit_str_common ( & @crate_ctxt ccx , & str s, bool expand )
397
409
-> tup ( ValueRef , option[ ValueRef ] ) {
398
410
auto llstackpart; auto llheappartopt;
399
411
@@ -403,7 +415,12 @@ fn trans_lit_str_common(&@crate_ctxt ccx, &str s)
403
415
for ( u8 ch in s) { array += ~[ tc:: C_u8 ( ch as uint ) ] ; }
404
416
array += ~[ tc:: C_u8 ( 0 u) ] ;
405
417
406
- if len < abi:: ivec_default_length - 1 u { // minus 1 because of the \0
418
+ if expand {
419
+ llstackpart = tc:: C_struct ( ~[ tc:: C_uint ( len + 1 u) ,
420
+ tc:: C_uint ( len + 1 u) ,
421
+ tc:: C_array ( tc:: T_i8 ( ) , array) ] ) ;
422
+ llheappartopt = none;
423
+ } else if len < abi:: ivec_default_length - 1 u { // minus one for the null
407
424
while ( ivec:: len ( array) < abi:: ivec_default_length) {
408
425
array += ~[ tc:: C_u8 ( 0 u) ] ;
409
426
}
@@ -492,19 +509,15 @@ fn trans_init_local(&@block_ctxt bcx, &@ast::local local) -> @block_ctxt {
492
509
}
493
510
}
494
511
}
495
- none {
496
- ret store( bcx, dest_copy ( bcx_tcx ( bcx) , llptr, t) ,
497
- tc:: C_null ( llelement_type ( trans:: val_ty ( llptr) ) ) , false ) ;
498
- }
512
+ none { ret bcx; }
499
513
}
500
514
}
501
515
502
516
fn trans_stmt ( & @block_ctxt cx , & @ast:: stmt stmt) -> @block_ctxt {
503
517
auto bcx = cx;
504
518
alt ( stmt. node ) {
505
519
ast:: stmt_expr ( ?e, _) {
506
- auto tmp_r = dest_tmp ( bcx, ty:: expr_ty ( bcx_tcx ( bcx) , e) , true ) ;
507
- bcx = tmp_r. _0 ; auto tmp = tmp_r. _1 ;
520
+ auto tmp = dest_alias ( bcx_tcx ( bcx) , ty:: expr_ty ( bcx_tcx ( bcx) , e) ) ;
508
521
ret trans_expr( bcx, tmp, e) ;
509
522
}
510
523
ast:: stmt_decl ( ?d, _) {
0 commit comments