Skip to content

Commit 5079f51

Browse files
committed
rustc: Associate type descriptors with allocas as metadata
1 parent 4b22243 commit 5079f51

File tree

4 files changed

+88
-12
lines changed

4 files changed

+88
-12
lines changed

src/comp/middle/gc.rs

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Routines useful for garbage collection.
2+
3+
import lib::llvm::llvm::ValueRef;
4+
import middle::trans::get_tydesc;
5+
import middle::trans_common::*;
6+
import middle::ty;
7+
import std::option::none;
8+
import std::ptr;
9+
import std::str;
10+
import std::unsafe;
11+
12+
import lll = lib::llvm::llvm;
13+
14+
fn add_gc_root(cx: &@block_ctxt, llval: ValueRef, ty: ty::t) -> @block_ctxt {
15+
let bcx = cx;
16+
if !type_is_gc_relevant(bcx_tcx(cx), ty) { ret bcx; }
17+
18+
let md_kind_name = "rusttydesc";
19+
let md_kind = lll::LLVMGetMDKindID(str::buf(md_kind_name),
20+
str::byte_len(md_kind_name));
21+
22+
let ti = none;
23+
let r = get_tydesc(bcx, ty, false, ti);
24+
bcx = r.bcx;
25+
let lltydesc = r.val;
26+
27+
let llmdnode =
28+
lll::LLVMMDNode(unsafe::reinterpret_cast(ptr::addr_of(lltydesc)), 1u);
29+
lll::LLVMSetMetadata(llval, md_kind, llmdnode);
30+
ret bcx;
31+
}
32+
33+
fn type_is_gc_relevant(cx: &ty::ctxt, ty: &ty::t) -> bool {
34+
alt ty::struct(cx, ty) {
35+
ty::ty_nil. | ty::ty_bot. | ty::ty_bool. | ty::ty_int. |
36+
ty::ty_float. | ty::ty_uint. | ty::ty_machine(_) | ty::ty_char. |
37+
ty::ty_istr. | ty::ty_type. | ty::ty_native(_) | ty::ty_ptr(_) |
38+
ty::ty_port(_) | ty::ty_chan(_) | ty::ty_task. | ty::ty_type. |
39+
ty::ty_native(_) {
40+
ret false;
41+
}
42+
43+
ty::ty_rec(fields) {
44+
for f in fields {
45+
if type_is_gc_relevant(cx, f.mt.ty) { ret true; }
46+
}
47+
ret false;
48+
}
49+
50+
ty::ty_tag(did, tps) {
51+
let variants = ty::tag_variants(cx, did);
52+
for variant in variants {
53+
for aty in variant.args {
54+
let arg_ty = ty::substitute_type_params(cx, tps, aty);
55+
if type_is_gc_relevant(cx, arg_ty) {
56+
ret true;
57+
}
58+
}
59+
}
60+
ret false;
61+
}
62+
63+
ty::ty_ivec(tm) { ret type_is_gc_relevant(cx, tm.ty); }
64+
ty::ty_constr(sub, _) { ret type_is_gc_relevant(cx, sub); }
65+
66+
ty::ty_str. | ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_vec(_) |
67+
ty::ty_fn(_,_,_,_,_) | ty::ty_native_fn(_,_,_) | ty::ty_obj(_) |
68+
ty::ty_param(_,_) | ty::ty_res(_,_,_) { ret true; }
69+
70+
ty::ty_var(_) { fail "ty_var in type_is_gc_relevant"; }
71+
}
72+
}
73+

src/comp/middle/shape.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -281,12 +281,10 @@ fn shape_of(ccx : &@crate_ctxt, t : ty::t) -> [u8] {
281281
let s = ~[];
282282

283283
alt ty::struct(ccx.tcx, t) {
284-
ty::ty_nil. | ty::ty_bool. | ty::ty_machine(ast::ty_u8.) {
284+
ty::ty_nil. | ty::ty_bool. | ty::ty_machine(ast::ty_u8.) | ty::ty_bot. {
285285
s += ~[shape_u8];
286286
}
287287

288-
ty::ty_bot. { fail "bot ty in shape_of"; }
289-
290288
ty::ty_int. { s += ~[s_int(ccx.tcx)]; }
291289
ty::ty_float. { s += ~[s_float(ccx.tcx)]; }
292290

@@ -299,6 +297,8 @@ fn shape_of(ccx : &@crate_ctxt, t : ty::t) -> [u8] {
299297
ty::ty_machine(ast::ty_i16.) { s += ~[shape_i16]; }
300298
ty::ty_machine(ast::ty_u32.) | ty::ty_char. { s += ~[shape_u32]; }
301299
ty::ty_machine(ast::ty_i32.) { s += ~[shape_i32]; }
300+
ty::ty_machine(ast::ty_u64.) { s += ~[shape_u64]; }
301+
ty::ty_machine(ast::ty_i64.) { s += ~[shape_i64]; }
302302

303303
ty::ty_str. { s += ~[shape_evec, 1u8, 1u8, 0u8, shape_u8]; }
304304
ty::ty_istr. { s += ~[shape_ivec, 1u8, 1u8, 0u8, shape_u8]; }

src/comp/middle/trans.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import syntax::ast;
2727
import driver::session;
2828
import middle::ty;
2929
import middle::freevars::*;
30+
import middle::gc;
3031
import back::link;
3132
import back::x86;
3233
import back::abi;
@@ -5634,24 +5635,29 @@ fn lldynamicallocas_block_ctxt(fcx: &@fn_ctxt) -> @block_ctxt {
56345635

56355636

56365637
fn alloc_ty(cx: &@block_ctxt, t: &ty::t) -> result {
5638+
let bcx = cx;
56375639
let val = C_int(0);
5638-
if ty::type_has_dynamic_size(bcx_tcx(cx), t) {
5640+
if ty::type_has_dynamic_size(bcx_tcx(bcx), t) {
56395641
// NB: we have to run this particular 'size_of' in a
56405642
// block_ctxt built on the llderivedtydescs block for the fn,
56415643
// so that the size dominates the array_alloca that
56425644
// comes next.
56435645

5644-
let n = size_of(llderivedtydescs_block_ctxt(cx.fcx), t);
5645-
cx.fcx.llderivedtydescs = n.bcx.llbb;
5646-
val = array_alloca(cx, T_i8(), n.val);
5647-
} else { val = alloca(cx, type_of(bcx_ccx(cx), cx.sp, t)); }
5646+
let n = size_of(llderivedtydescs_block_ctxt(bcx.fcx), t);
5647+
bcx.fcx.llderivedtydescs = n.bcx.llbb;
5648+
val = array_alloca(bcx, T_i8(), n.val);
5649+
} else {
5650+
val = alloca(bcx, type_of(bcx_ccx(cx), cx.sp, t));
5651+
}
56485652
// NB: since we've pushed all size calculations in this
56495653
// function up to the alloca block, we actually return the
56505654
// block passed into us unmodified; it doesn't really
56515655
// have to be passed-and-returned here, but it fits
56525656
// past caller conventions and may well make sense again,
56535657
// so we leave it as-is.
56545658

5659+
bcx = gc::add_gc_root(bcx, val, t);
5660+
56555661
ret rslt(cx, val);
56565662
}
56575663

@@ -6756,9 +6762,6 @@ fn declare_intrinsics(llmod: ModuleRef) -> hashmap[str, ValueRef] {
67566762
let T_memset64_args: [TypeRef] =
67576763
~[T_ptr(T_i8()), T_i8(), T_i64(), T_i32(), T_i1()];
67586764
let T_trap_args: [TypeRef] = ~[];
6759-
let gcroot =
6760-
decl_cdecl_fn(llmod, "llvm.gcroot",
6761-
T_fn(~[T_ptr(T_ptr(T_i8())), T_ptr(T_i8())], T_void()));
67626765
let gcread =
67636766
decl_cdecl_fn(llmod, "llvm.gcread",
67646767
T_fn(~[T_ptr(T_i8()), T_ptr(T_ptr(T_i8()))], T_void()));
@@ -6776,7 +6779,6 @@ fn declare_intrinsics(llmod: ModuleRef) -> hashmap[str, ValueRef] {
67766779
T_fn(T_memset64_args, T_void()));
67776780
let trap = decl_cdecl_fn(llmod, "llvm.trap", T_fn(T_trap_args, T_void()));
67786781
let intrinsics = new_str_hash[ValueRef]();
6779-
intrinsics.insert("llvm.gcroot", gcroot);
67806782
intrinsics.insert("llvm.gcread", gcread);
67816783
intrinsics.insert("llvm.memmove.p0i8.p0i8.i32", memmove32);
67826784
intrinsics.insert("llvm.memmove.p0i8.p0i8.i64", memmove64);

src/comp/rustc.rc

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ mod middle {
3131
mod kind;
3232
mod freevars;
3333
mod shape;
34+
mod gc;
3435

3536
mod tstate {
3637
mod ck;

0 commit comments

Comments
 (0)