Skip to content

Commit c2e99ba

Browse files
author
Elliott Slaughter
committed
rustc: Root resources with addrspaces.
1 parent c8daf2a commit c2e99ba

File tree

4 files changed

+108
-36
lines changed

4 files changed

+108
-36
lines changed

src/rustc/middle/trans/alt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ fn trans_opt(bcx: block, o: opt) -> opt_result {
5454
let cell = empty_dest_cell();
5555
bcx = tvec::trans_estr(bcx, s, some(ast::vstore_uniq),
5656
by_val(cell));
57-
add_clean_temp(bcx, *cell, strty);
57+
add_clean_temp_immediate(bcx, *cell, strty);
5858
return single_result(rslt(bcx, *cell));
5959
}
6060
_ => {

src/rustc/middle/trans/base.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,20 @@ fn note_unique_llvm_symbol(ccx: @crate_ctxt, sym: ~str) {
486486
ccx.all_llvm_symbols.insert(sym, ());
487487
}
488488
489+
// Chooses the addrspace for newly declared types.
490+
fn declare_tydesc_addrspace(ccx: @crate_ctxt, t: ty::t) -> addrspace {
491+
if !ty::type_needs_drop(ccx.tcx, t) {
492+
return default_addrspace;
493+
} else if ty::type_is_immediate(t) {
494+
// For immediate types, we don't actually need an addrspace, because
495+
// e.g. boxed types include pointers to their contents which are
496+
// already correctly tagged with addrspaces.
497+
return default_addrspace;
498+
} else {
499+
return ccx.next_addrspace();
500+
}
501+
}
502+
489503
// Generates the declaration for (but doesn't emit) a type descriptor.
490504
fn declare_tydesc(ccx: @crate_ctxt, t: ty::t) -> @tydesc_info {
491505
let _icx = ccx.insn_ctxt("declare_tydesc");
@@ -499,6 +513,7 @@ fn declare_tydesc(ccx: @crate_ctxt, t: ty::t) -> @tydesc_info {
499513

500514
let llsize = llsize_of(ccx, llty);
501515
let llalign = llalign_of(ccx, llty);
516+
let addrspace = declare_tydesc_addrspace(ccx, t);
502517
//XXX this triggers duplicate LLVM symbols
503518
let name = if false /*ccx.sess.opts.debuginfo*/ {
504519
mangle_internal_name_by_type_only(ccx, t, ~"tydesc")
@@ -513,6 +528,7 @@ fn declare_tydesc(ccx: @crate_ctxt, t: ty::t) -> @tydesc_info {
513528
tydesc: gvar,
514529
size: llsize,
515530
align: llalign,
531+
addrspace: addrspace,
516532
mut take_glue: none,
517533
mut drop_glue: none,
518534
mut free_glue: none,
@@ -1275,6 +1291,16 @@ fn drop_ty(cx: block, v: ValueRef, t: ty::t) -> block {
12751291
return cx;
12761292
}
12771293

1294+
fn drop_ty_root(bcx: block, v: ValueRef, rooted: bool, t: ty::t) -> block {
1295+
if rooted {
1296+
// NB: v is a raw ptr to an addrspace'd ptr to the value.
1297+
let v = PointerCast(bcx, Load(bcx, v), T_ptr(type_of(bcx.ccx(), t)));
1298+
drop_ty(bcx, v, t)
1299+
} else {
1300+
drop_ty(bcx, v, t)
1301+
}
1302+
}
1303+
12781304
fn drop_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block {
12791305
let _icx = bcx.insn_ctxt("drop_ty_immediate");
12801306
match ty::get(t).struct {
@@ -2751,7 +2777,7 @@ fn trans_lval(cx: block, e: @ast::expr) -> lval_result {
27512777
fn non_gc_box_cast(cx: block, val: ValueRef) -> ValueRef {
27522778
debug!("non_gc_box_cast");
27532779
add_comment(cx, ~"non_gc_box_cast");
2754-
assert(llvm::LLVMGetPointerAddressSpace(val_ty(val)) as uint == 1u);
2780+
assert(llvm::LLVMGetPointerAddressSpace(val_ty(val)) == gc_box_addrspace);
27552781
let non_gc_t = T_ptr(llvm::LLVMGetElementType(val_ty(val)));
27562782
PointerCast(cx, val, non_gc_t)
27572783
}
@@ -3639,12 +3665,12 @@ fn trans_temp_lval(bcx: block, e: @ast::expr) -> lval_result {
36393665
} else if ty::type_is_immediate(ty) {
36403666
let cell = empty_dest_cell();
36413667
bcx = trans_expr(bcx, e, by_val(cell));
3642-
add_clean_temp(bcx, *cell, ty);
3668+
add_clean_temp_immediate(bcx, *cell, ty);
36433669
return {bcx: bcx, val: *cell, kind: lv_temporary};
36443670
} else {
36453671
let scratch = alloc_ty(bcx, ty);
36463672
let bcx = trans_expr_save_in(bcx, e, scratch);
3647-
add_clean_temp(bcx, scratch, ty);
3673+
add_clean_temp_mem(bcx, scratch, ty);
36483674
return {bcx: bcx, val: scratch, kind: lv_temporary};
36493675
}
36503676
}
@@ -5815,6 +5841,7 @@ fn trans_crate(sess: session::session,
58155841
module_data: str_hash::<ValueRef>(),
58165842
lltypes: ty::new_ty_hash(),
58175843
names: new_namegen(sess.parse_sess.interner),
5844+
next_addrspace: new_addrspace_gen(),
58185845
symbol_hasher: symbol_hasher,
58195846
type_hashcodes: ty::new_ty_hash(),
58205847
type_short_names: ty::new_ty_hash(),

src/rustc/middle/trans/common.rs

Lines changed: 69 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,28 @@ fn new_namegen(intr: ident_interner) -> namegen {
3030
};
3131
}
3232

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+
3349
type tydesc_info =
3450
{ty: ty::t,
3551
tydesc: ValueRef,
3652
size: ValueRef,
3753
align: ValueRef,
54+
addrspace: addrspace,
3855
mut take_glue: option<ValueRef>,
3956
mut drop_glue: option<ValueRef>,
4057
mut free_glue: option<ValueRef>,
@@ -118,6 +135,7 @@ type crate_ctxt = {
118135
module_data: hashmap<~str, ValueRef>,
119136
lltypes: hashmap<ty::t, TypeRef>,
120137
names: namegen,
138+
next_addrspace: addrspace_gen,
121139
symbol_hasher: @hash::State,
122140
type_hashcodes: hashmap<ty::t, ~str>,
123141
type_short_names: hashmap<ty::t, ~str>,
@@ -254,47 +272,64 @@ fn cleanup_type(cx: ty::ctxt, ty: ty::t) -> cleantype {
254272
}
255273
}
256274
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; }
259298
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));
266307
scope_clean_changed(info);
267308
}
268309
}
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) {
270311
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)",
272313
cx.to_str(), val_str(cx.ccx().tn, val),
273314
ty_to_str(cx.ccx().tcx, ty));
274315
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-
}
283316
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));
286320
scope_clean_changed(info);
287321
}
288322
}
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; }
291325
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| {
296331
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),
298333
cleanup_type));
299334
scope_clean_changed(info);
300335
}
@@ -607,7 +642,11 @@ fn T_fn_pair(cx: @crate_ctxt, tfn: TypeRef) -> TypeRef {
607642
}
608643

609644
fn T_ptr(t: TypeRef) -> TypeRef {
610-
return llvm::LLVMPointerType(t, 0u 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);
611650
}
612651

613652
fn T_struct(elts: ~[TypeRef]) -> TypeRef unsafe {
@@ -738,8 +777,7 @@ fn T_box(cx: @crate_ctxt, t: TypeRef) -> TypeRef {
738777
}
739778

740779
fn T_box_ptr(t: TypeRef) -> TypeRef {
741-
const box_addrspace: uint = 1u;
742-
return llvm::LLVMPointerType(t, box_addrspace as c_uint);
780+
return llvm::LLVMPointerType(t, gc_box_addrspace);
743781
}
744782

745783
fn T_opaque_box(cx: @crate_ctxt) -> TypeRef {
@@ -755,8 +793,7 @@ fn T_unique(cx: @crate_ctxt, t: TypeRef) -> TypeRef {
755793
}
756794

757795
fn T_unique_ptr(t: TypeRef) -> TypeRef {
758-
const unique_addrspace: uint = 1u;
759-
return llvm::LLVMPointerType(t, unique_addrspace as c_uint);
796+
return llvm::LLVMPointerType(t, gc_box_addrspace);
760797
}
761798

762799
fn T_port(cx: @crate_ctxt, _t: TypeRef) -> TypeRef {

src/rustc/middle/trans/type_of.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export type_of_fn_from_ty;
1212
export type_of_fn;
1313
export type_of_glue_fn;
1414
export type_of_non_gc_box;
15+
export type_of_rooted;
1516

1617
fn type_of_explicit_args(cx: @crate_ctxt,
1718
inputs: ~[ty::arg]) -> ~[TypeRef] {
@@ -245,6 +246,13 @@ fn type_of_dtor(ccx: @crate_ctxt, self_ty: ty::t) -> TypeRef {
245246
llvm::LLVMVoidType())
246247
}
247248

249+
fn type_of_rooted(ccx: @crate_ctxt, t: ty::t) -> TypeRef {
250+
let addrspace = base::get_tydesc(ccx, t).addrspace;
251+
debug!{"type_of_rooted %s in addrspace %u",
252+
ty_to_str(ccx.tcx, t), addrspace as uint};
253+
return T_root(type_of(ccx, t), addrspace);
254+
}
255+
248256
fn type_of_glue_fn(ccx: @crate_ctxt, t: ty::t) -> TypeRef {
249257
let tydescpp = T_ptr(T_ptr(ccx.tydesc_type));
250258
let llty = T_ptr(type_of(ccx, t));

0 commit comments

Comments
 (0)