@@ -30,11 +30,28 @@ fn new_namegen(intr: ident_interner) -> namegen {
30
30
} ;
31
31
}
32
32
33
+ type addrspace = c_uint ;
34
+
35
+ // Address spaces communicate to LLVM which destructors need to run for
36
+ // specifc types.
37
+ // 0 is ignored by the GC, and is used for all non-GC'd pointers.
38
+ // 1 is for opaque GC'd boxes.
39
+ // >= 2 are for specific types (e.g. resources).
40
+ const default_addrspace: addrspace = 0 ;
41
+ const gc_box_addrspace: addrspace = 1 ;
42
+
43
+ type addrspace_gen = fn @( ) -> addrspace ;
44
+ fn new_addrspace_gen ( ) -> addrspace_gen {
45
+ let i = @mut 1 ;
46
+ return fn @( ) -> addrspace { * i += 1 ; * i } ;
47
+ }
48
+
33
49
type tydesc_info =
34
50
{ ty: ty:: t,
35
51
tydesc: ValueRef ,
36
52
size: ValueRef ,
37
53
align: ValueRef ,
54
+ addrspace: addrspace,
38
55
mut take_glue: option<ValueRef >,
39
56
mut drop_glue: option<ValueRef >,
40
57
mut free_glue: option<ValueRef >,
@@ -118,6 +135,7 @@ type crate_ctxt = {
118
135
module_data : hashmap < ~str , ValueRef > ,
119
136
lltypes : hashmap < ty:: t , TypeRef > ,
120
137
names : namegen ,
138
+ next_addrspace : addrspace_gen ,
121
139
symbol_hasher : @hash:: State ,
122
140
type_hashcodes : hashmap < ty:: t , ~str > ,
123
141
type_short_names : hashmap < ty:: t , ~str > ,
@@ -254,47 +272,64 @@ fn cleanup_type(cx: ty::ctxt, ty: ty::t) -> cleantype {
254
272
}
255
273
}
256
274
257
- fn add_clean(cx: block, val: ValueRef, ty: ty::t) {
258
- if !ty::type_needs_drop(cx.tcx(), ty) { return; }
275
+ // This is not the same as base::root_value, which appears to be the vestigial
276
+ // remains of the previous GC regime. In the new GC, we can identify
277
+ // immediates on the stack without difficulty, but have trouble knowing where
278
+ // non-immediates are on the stack. For non-immediates, we must add an
279
+ // additional level of indirection, which allows us to alloca a pointer with
280
+ // the right addrspace.
281
+ fn root_for_cleanup(bcx: block, v: ValueRef, t: ty::t)
282
+ -> {root: ValueRef, rooted: bool} {
283
+ let ccx = bcx.ccx();
284
+
285
+ let addrspace = base::get_tydesc(ccx, t).addrspace;
286
+ if addrspace > gc_box_addrspace {
287
+ let llty = type_of::type_of_rooted(ccx, t);
288
+ let root = base::alloca(bcx, llty);
289
+ build::Store(bcx, build::PointerCast(bcx, v, llty), root);
290
+ {root: root, rooted: true}
291
+ } else {
292
+ {root: v, rooted: false}
293
+ }
294
+ }
295
+
296
+ fn add_clean(bcx: block, val: ValueRef, t: ty::t) {
297
+ if !ty::type_needs_drop(bcx.tcx(), t) { return; }
259
298
debug!(" add_clean( %s, %s, %s) ",
260
- cx. to_str ( ) , val_str( cx. ccx ( ) . tn , val) ,
261
- ty_to_str( cx. ccx ( ) . tcx , ty) ) ;
262
- let cleanup_type = cleanup_type ( cx. tcx ( ) , ty) ;
263
- do in_scope_cx ( cx) |info| {
264
- vec:: push ( info. cleanups , clean ( |a| base:: drop_ty ( a, val, ty) ,
265
- cleanup_type) ) ;
299
+ bcx. to_str ( ) , val_str( bcx. ccx ( ) . tn , val) ,
300
+ ty_to_str( bcx. ccx ( ) . tcx , t) ) ;
301
+ let { root, rooted} = root_for_cleanup ( bcx, val, t) ;
302
+ let cleanup_type = cleanup_type ( bcx. tcx ( ) , t) ;
303
+ do in_scope_cx ( bcx) |info| {
304
+ vec:: push ( info. cleanups ,
305
+ clean ( |a| base:: drop_ty_root ( a, root, rooted, t) ,
306
+ cleanup_type) ) ;
266
307
scope_clean_changed ( info) ;
267
308
}
268
309
}
269
- fn add_clean_temp ( cx : block , val : ValueRef , ty : ty:: t ) {
310
+ fn add_clean_temp_immediate ( cx : block , val : ValueRef , ty : ty:: t ) {
270
311
if !ty:: type_needs_drop ( cx. tcx ( ) , ty) { return ; }
271
- debug ! ( "add_clean_temp (%s, %s, %s)" ,
312
+ debug ! ( "add_clean_temp_immediate (%s, %s, %s)" ,
272
313
cx. to_str( ) , val_str( cx. ccx( ) . tn, val) ,
273
314
ty_to_str( cx. ccx( ) . tcx, ty) ) ;
274
315
let cleanup_type = cleanup_type ( cx. tcx ( ) , ty) ;
275
- fn do_drop ( bcx : block , val : ValueRef , ty : ty:: t ) ->
276
- block {
277
- if ty:: type_is_immediate ( ty) {
278
- return base:: drop_ty_immediate ( bcx, val, ty) ;
279
- } else {
280
- return base:: drop_ty ( bcx, val, ty) ;
281
- }
282
- }
283
316
do in_scope_cx ( cx) |info| {
284
- vec:: push ( info. cleanups , clean_temp ( val, |a| do_drop ( a, val, ty) ,
285
- cleanup_type) ) ;
317
+ vec:: push ( info. cleanups ,
318
+ clean_temp ( val, |a| base:: drop_ty_immediate ( a, val, ty) ,
319
+ cleanup_type) ) ;
286
320
scope_clean_changed ( info) ;
287
321
}
288
322
}
289
- fn add_clean_temp_mem ( cx : block , val : ValueRef , ty : ty:: t ) {
290
- if !ty:: type_needs_drop ( cx . tcx ( ) , ty ) { return ; }
323
+ fn add_clean_temp_mem ( bcx : block , val : ValueRef , t : ty:: t ) {
324
+ if !ty:: type_needs_drop ( bcx . tcx ( ) , t ) { return ; }
291
325
debug ! ( "add_clean_temp_mem(%s, %s, %s)" ,
292
- cx. to_str( ) , val_str( cx. ccx( ) . tn, val) ,
293
- ty_to_str( cx. ccx( ) . tcx, ty) ) ;
294
- let cleanup_type = cleanup_type ( cx. tcx ( ) , ty) ;
295
- do in_scope_cx ( cx) |info| {
326
+ bcx. to_str( ) , val_str( bcx. ccx( ) . tn, val) ,
327
+ ty_to_str( bcx. ccx( ) . tcx, t) ) ;
328
+ let { root, rooted} = root_for_cleanup ( bcx, val, t) ;
329
+ let cleanup_type = cleanup_type ( bcx. tcx ( ) , t) ;
330
+ do in_scope_cx ( bcx) |info| {
296
331
vec:: push ( info. cleanups ,
297
- clean_temp ( val, |a| base:: drop_ty ( a, val , ty ) ,
332
+ clean_temp ( val, |a| base:: drop_ty_root ( a, root , rooted , t ) ,
298
333
cleanup_type) ) ;
299
334
scope_clean_changed ( info) ;
300
335
}
@@ -607,7 +642,11 @@ fn T_fn_pair(cx: @crate_ctxt, tfn: TypeRef) -> TypeRef {
607
642
}
608
643
609
644
fn T_ptr ( t : TypeRef ) -> TypeRef {
610
- return llvm:: LLVMPointerType ( t, 0 u as c_uint ) ;
645
+ return llvm:: LLVMPointerType ( t, default_addrspace) ;
646
+ }
647
+
648
+ fn T_root ( t : TypeRef , addrspace : addrspace ) -> TypeRef {
649
+ return llvm:: LLVMPointerType ( t, addrspace) ;
611
650
}
612
651
613
652
fn T_struct ( elts : ~[ TypeRef ] ) -> TypeRef unsafe {
@@ -738,8 +777,7 @@ fn T_box(cx: @crate_ctxt, t: TypeRef) -> TypeRef {
738
777
}
739
778
740
779
fn T_box_ptr ( t : TypeRef ) -> TypeRef {
741
- const box_addrspace: uint = 1 u;
742
- return llvm:: LLVMPointerType ( t, box_addrspace as c_uint ) ;
780
+ return llvm:: LLVMPointerType ( t, gc_box_addrspace) ;
743
781
}
744
782
745
783
fn T_opaque_box ( cx : @crate_ctxt ) -> TypeRef {
@@ -755,8 +793,7 @@ fn T_unique(cx: @crate_ctxt, t: TypeRef) -> TypeRef {
755
793
}
756
794
757
795
fn T_unique_ptr ( t : TypeRef ) -> TypeRef {
758
- const unique_addrspace: uint = 1 u;
759
- return llvm:: LLVMPointerType ( t, unique_addrspace as c_uint ) ;
796
+ return llvm:: LLVMPointerType ( t, gc_box_addrspace) ;
760
797
}
761
798
762
799
fn T_port ( cx : @crate_ctxt , _t : TypeRef ) -> TypeRef {
0 commit comments