@@ -20,6 +20,7 @@ import std::ivec;
20
20
import std:: option:: none;
21
21
import std:: option:: some;
22
22
import std:: str;
23
+ import std:: uint;
23
24
24
25
import LLFalse = lib:: llvm:: False ;
25
26
import LLTrue = lib:: llvm:: True ;
@@ -36,6 +37,30 @@ fn llelement_type(TypeRef llty) -> TypeRef {
36
37
lib:: llvm:: llvm:: LLVMGetElementType ( llty)
37
38
}
38
39
40
+ fn llalign_of ( & @crate_ctxt ccx , TypeRef llty) -> uint {
41
+ ret llvm:: LLVMPreferredAlignmentOfType ( ccx. td . lltd , llty) ;
42
+ }
43
+
44
+ fn llsize_of ( & @crate_ctxt ccx , TypeRef llty) -> uint {
45
+ ret llvm:: LLVMStoreSizeOfType ( ccx. td . lltd , llty) ;
46
+ }
47
+
48
+ fn mk_const ( & @crate_ctxt ccx , & str name , bool exported , ValueRef llval)
49
+ -> ValueRef {
50
+ auto llglobal = llvm:: LLVMAddGlobal ( ccx. llmod , trans:: val_ty ( llval) ,
51
+ str:: buf ( name) ) ;
52
+
53
+ llvm:: LLVMSetInitializer ( llglobal, llval) ;
54
+ llvm:: LLVMSetGlobalConstant ( llglobal, LLTrue ) ;
55
+
56
+ if !exported {
57
+ llvm:: LLVMSetLinkage ( llglobal,
58
+ lib:: llvm:: LLVMInternalLinkage as llvm:: Linkage ) ;
59
+ }
60
+
61
+ ret llglobal;
62
+ }
63
+
39
64
40
65
// Destination utilities
41
66
@@ -138,10 +163,38 @@ fn store(&@block_ctxt bcx, &dest dest, ValueRef llsrc, bool cast)
138
163
ret bcx;
139
164
}
140
165
141
- tag heap { hp_task; hp_shared; }
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) {
174
+ auto lldestty = llelement_type ( trans:: val_ty ( llsrcptr) ) ;
175
+ auto llsrcty = llelement_type ( trans:: val_ty ( llsrcptr) ) ;
176
+ auto dest_align = llalign_of ( bcx_ccx ( bcx) , lldestty) ;
177
+ auto src_align = llalign_of ( bcx_ccx ( bcx) , llsrcty) ;
178
+ auto align = uint:: min ( dest_align, src_align) ;
179
+ auto llfn = bcx_ccx ( bcx) . intrinsics . get ( "llvm.memmove.p0i8.p0i8.i32" ) ;
180
+ auto lldestptr_i8 = bcx. build . PointerCast ( lldestptr,
181
+ tc:: T_ptr ( tc:: T_i8 ( ) ) ) ;
182
+ auto llsrcptr_i8 = bcx. build . PointerCast ( llsrcptr,
183
+ tc:: T_ptr ( tc:: T_i8 ( ) ) ) ;
184
+ bcx. build . Call ( llfn,
185
+ ~[ lldestptr_i8,
186
+ llsrcptr_i8,
187
+ tc:: C_uint ( llsize_of ( bcx_ccx ( bcx) , llsrcty) ) ,
188
+ tc:: C_uint ( align) ,
189
+ tc:: C_bool ( false ) ] ) ;
190
+ ret bcx;
191
+ }
192
+ }
193
+ }
142
194
143
195
// Allocates a value of the given LLVM size on either the task heap or the
144
196
// shared heap.
197
+ tag heap { hp_task; hp_shared; }
145
198
fn malloc ( & @block_ctxt bcx , ValueRef lldest, heap heap,
146
199
option[ ValueRef ] llcustom_size_opt ) -> @block_ctxt {
147
200
auto llptrty = llelement_type ( lltype_of ( lldest) ) ;
@@ -177,7 +230,7 @@ fn trans_lit(&@block_ctxt cx, &dest dest, &ast::lit lit) -> @block_ctxt {
177
230
ast:: lit_str ( ?s, ast:: sk_unique) {
178
231
auto r = trans_lit_str_common ( bcx_ccx ( bcx) , s) ;
179
232
auto llstackpart = r. _0 ; auto llheappartopt = r. _1 ;
180
- bcx = store ( bcx, dest, llstackpart, true ) ;
233
+ bcx = memmove ( bcx, dest, llstackpart) ;
181
234
alt ( llheappartopt) {
182
235
none { /* no-op */ }
183
236
some( ?llheappart) {
@@ -191,7 +244,8 @@ fn trans_lit(&@block_ctxt cx, &dest dest, &ast::lit lit) -> @block_ctxt {
191
244
tc:: T_ptr ( tc:: T_ptr ( llheappartty) ) ) ;
192
245
malloc ( bcx, lldestptrptr, hp_shared, none) ;
193
246
auto lldestptr = bcx. build . Load ( lldestptrptr) ;
194
- bcx. build . Store ( llheappart, lldestptr) ;
247
+ memmove ( bcx, rec ( slot=dst_ptr ( lldestptr) , mode=dm_copy) ,
248
+ llheappart) ;
195
249
}
196
250
}
197
251
}
@@ -341,6 +395,8 @@ fn trans_block(&@block_ctxt cx, &dest dest, &ast::block block)
341
395
// since that doesn't work for crate constants.
342
396
fn trans_lit_str_common ( & @crate_ctxt ccx , & str s)
343
397
-> tup ( ValueRef , option[ ValueRef ] ) {
398
+ auto llstackpart; auto llheappartopt;
399
+
344
400
auto len = str:: byte_len ( s) ;
345
401
346
402
auto array = ~[ ] ;
@@ -352,18 +408,23 @@ fn trans_lit_str_common(&@crate_ctxt ccx, &str s)
352
408
array += ~[ tc:: C_u8 ( 0 u) ] ;
353
409
}
354
410
355
- ret tup( tc:: C_struct ( ~[ tc:: C_uint ( len + 1 u) ,
356
- tc:: C_uint ( abi:: ivec_default_length) ,
357
- tc:: C_array ( tc:: T_i8 ( ) , array) ] ) ,
358
- none) ;
359
- }
360
-
361
- auto llheappart = tc:: C_struct ( ~[ tc:: C_uint ( len) ,
411
+ llstackpart = tc:: C_struct ( ~[ tc:: C_uint ( len + 1 u) ,
412
+ tc:: C_uint ( abi:: ivec_default_length) ,
362
413
tc:: C_array ( tc:: T_i8 ( ) , array) ] ) ;
363
- ret tup( tc:: C_struct ( ~[ tc:: C_uint ( 0 u) ,
414
+ llheappartopt = none;
415
+ } else {
416
+ auto llheappart = tc:: C_struct ( ~[ tc:: C_uint ( len) ,
417
+ tc:: C_array ( tc:: T_i8 ( ) , array) ] ) ;
418
+ llstackpart =
419
+ tc:: C_struct ( ~[ tc:: C_uint ( 0 u) ,
364
420
tc:: C_uint ( abi:: ivec_default_length) ,
365
- tc:: C_null ( tc:: T_ptr ( lltype_of ( llheappart) ) ) ] ) ,
366
- some ( llheappart) ) ;
421
+ tc:: C_null ( tc:: T_ptr ( lltype_of ( llheappart) ) ) ] ) ;
422
+ llheappartopt = some ( mk_const ( ccx, "const_istr_heap" , false ,
423
+ llheappart) ) ;
424
+ }
425
+
426
+ ret tup( mk_const ( ccx, "const_istr_stack" , false , llstackpart) ,
427
+ llheappartopt) ;
367
428
}
368
429
369
430
// As above, we don't use destination-passing style here.
0 commit comments