diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2011-08-11 14:33:40 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2011-08-11 14:35:33 -0700 |
| commit | 5079f5138649cb8bf52bbde6e2623fdb7d5c45f3 (patch) | |
| tree | 5c1911fe7f9701aecd42f3e24d7fdc0e7aac697b | |
| parent | 4b22243416f3f3ce66c7b8fb8d1709dd840656b7 (diff) | |
| download | rust-5079f5138649cb8bf52bbde6e2623fdb7d5c45f3.tar.gz rust-5079f5138649cb8bf52bbde6e2623fdb7d5c45f3.zip | |
rustc: Associate type descriptors with allocas as metadata
| -rw-r--r-- | src/comp/middle/gc.rs | 73 | ||||
| -rw-r--r-- | src/comp/middle/shape.rs | 6 | ||||
| -rw-r--r-- | src/comp/middle/trans.rs | 20 | ||||
| -rw-r--r-- | src/comp/rustc.rc | 1 |
4 files changed, 88 insertions, 12 deletions
diff --git a/src/comp/middle/gc.rs b/src/comp/middle/gc.rs new file mode 100644 index 00000000000..056adf94cc5 --- /dev/null +++ b/src/comp/middle/gc.rs @@ -0,0 +1,73 @@ +// Routines useful for garbage collection. + +import lib::llvm::llvm::ValueRef; +import middle::trans::get_tydesc; +import middle::trans_common::*; +import middle::ty; +import std::option::none; +import std::ptr; +import std::str; +import std::unsafe; + +import lll = lib::llvm::llvm; + +fn add_gc_root(cx: &@block_ctxt, llval: ValueRef, ty: ty::t) -> @block_ctxt { + let bcx = cx; + if !type_is_gc_relevant(bcx_tcx(cx), ty) { ret bcx; } + + let md_kind_name = "rusttydesc"; + let md_kind = lll::LLVMGetMDKindID(str::buf(md_kind_name), + str::byte_len(md_kind_name)); + + let ti = none; + let r = get_tydesc(bcx, ty, false, ti); + bcx = r.bcx; + let lltydesc = r.val; + + let llmdnode = + lll::LLVMMDNode(unsafe::reinterpret_cast(ptr::addr_of(lltydesc)), 1u); + lll::LLVMSetMetadata(llval, md_kind, llmdnode); + ret bcx; +} + +fn type_is_gc_relevant(cx: &ty::ctxt, ty: &ty::t) -> bool { + alt ty::struct(cx, ty) { + ty::ty_nil. | ty::ty_bot. | ty::ty_bool. | ty::ty_int. | + ty::ty_float. | ty::ty_uint. | ty::ty_machine(_) | ty::ty_char. | + ty::ty_istr. | ty::ty_type. | ty::ty_native(_) | ty::ty_ptr(_) | + ty::ty_port(_) | ty::ty_chan(_) | ty::ty_task. | ty::ty_type. | + ty::ty_native(_) { + ret false; + } + + ty::ty_rec(fields) { + for f in fields { + if type_is_gc_relevant(cx, f.mt.ty) { ret true; } + } + ret false; + } + + ty::ty_tag(did, tps) { + let variants = ty::tag_variants(cx, did); + for variant in variants { + for aty in variant.args { + let arg_ty = ty::substitute_type_params(cx, tps, aty); + if type_is_gc_relevant(cx, arg_ty) { + ret true; + } + } + } + ret false; + } + + ty::ty_ivec(tm) { ret type_is_gc_relevant(cx, tm.ty); } + ty::ty_constr(sub, _) { ret type_is_gc_relevant(cx, sub); } + + ty::ty_str. | ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_vec(_) | + ty::ty_fn(_,_,_,_,_) | ty::ty_native_fn(_,_,_) | ty::ty_obj(_) | + ty::ty_param(_,_) | ty::ty_res(_,_,_) { ret true; } + + ty::ty_var(_) { fail "ty_var in type_is_gc_relevant"; } + } +} + diff --git a/src/comp/middle/shape.rs b/src/comp/middle/shape.rs index 02b0253cf3f..9cbb546535b 100644 --- a/src/comp/middle/shape.rs +++ b/src/comp/middle/shape.rs @@ -281,12 +281,10 @@ fn shape_of(ccx : &@crate_ctxt, t : ty::t) -> [u8] { let s = ~[]; alt ty::struct(ccx.tcx, t) { - ty::ty_nil. | ty::ty_bool. | ty::ty_machine(ast::ty_u8.) { + ty::ty_nil. | ty::ty_bool. | ty::ty_machine(ast::ty_u8.) | ty::ty_bot. { s += ~[shape_u8]; } - ty::ty_bot. { fail "bot ty in shape_of"; } - ty::ty_int. { s += ~[s_int(ccx.tcx)]; } ty::ty_float. { s += ~[s_float(ccx.tcx)]; } @@ -299,6 +297,8 @@ fn shape_of(ccx : &@crate_ctxt, t : ty::t) -> [u8] { ty::ty_machine(ast::ty_i16.) { s += ~[shape_i16]; } ty::ty_machine(ast::ty_u32.) | ty::ty_char. { s += ~[shape_u32]; } ty::ty_machine(ast::ty_i32.) { s += ~[shape_i32]; } + ty::ty_machine(ast::ty_u64.) { s += ~[shape_u64]; } + ty::ty_machine(ast::ty_i64.) { s += ~[shape_i64]; } ty::ty_str. { s += ~[shape_evec, 1u8, 1u8, 0u8, shape_u8]; } ty::ty_istr. { s += ~[shape_ivec, 1u8, 1u8, 0u8, shape_u8]; } diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 165ad276188..659b99209ee 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -27,6 +27,7 @@ import syntax::ast; import driver::session; import middle::ty; import middle::freevars::*; +import middle::gc; import back::link; import back::x86; import back::abi; @@ -5634,17 +5635,20 @@ fn lldynamicallocas_block_ctxt(fcx: &@fn_ctxt) -> @block_ctxt { fn alloc_ty(cx: &@block_ctxt, t: &ty::t) -> result { + let bcx = cx; let val = C_int(0); - if ty::type_has_dynamic_size(bcx_tcx(cx), t) { + if ty::type_has_dynamic_size(bcx_tcx(bcx), t) { // NB: we have to run this particular 'size_of' in a // block_ctxt built on the llderivedtydescs block for the fn, // so that the size dominates the array_alloca that // comes next. - let n = size_of(llderivedtydescs_block_ctxt(cx.fcx), t); - cx.fcx.llderivedtydescs = n.bcx.llbb; - val = array_alloca(cx, T_i8(), n.val); - } else { val = alloca(cx, type_of(bcx_ccx(cx), cx.sp, t)); } + let n = size_of(llderivedtydescs_block_ctxt(bcx.fcx), t); + bcx.fcx.llderivedtydescs = n.bcx.llbb; + val = array_alloca(bcx, T_i8(), n.val); + } else { + val = alloca(bcx, type_of(bcx_ccx(cx), cx.sp, t)); + } // NB: since we've pushed all size calculations in this // function up to the alloca block, we actually return the // block passed into us unmodified; it doesn't really @@ -5652,6 +5656,8 @@ fn alloc_ty(cx: &@block_ctxt, t: &ty::t) -> result { // past caller conventions and may well make sense again, // so we leave it as-is. + bcx = gc::add_gc_root(bcx, val, t); + ret rslt(cx, val); } @@ -6756,9 +6762,6 @@ fn declare_intrinsics(llmod: ModuleRef) -> hashmap[str, ValueRef] { let T_memset64_args: [TypeRef] = ~[T_ptr(T_i8()), T_i8(), T_i64(), T_i32(), T_i1()]; let T_trap_args: [TypeRef] = ~[]; - let gcroot = - decl_cdecl_fn(llmod, "llvm.gcroot", - T_fn(~[T_ptr(T_ptr(T_i8())), T_ptr(T_i8())], T_void())); let gcread = decl_cdecl_fn(llmod, "llvm.gcread", 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] { T_fn(T_memset64_args, T_void())); let trap = decl_cdecl_fn(llmod, "llvm.trap", T_fn(T_trap_args, T_void())); let intrinsics = new_str_hash[ValueRef](); - intrinsics.insert("llvm.gcroot", gcroot); intrinsics.insert("llvm.gcread", gcread); intrinsics.insert("llvm.memmove.p0i8.p0i8.i32", memmove32); intrinsics.insert("llvm.memmove.p0i8.p0i8.i64", memmove64); diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc index 8e174f3f736..e47c6337e32 100644 --- a/src/comp/rustc.rc +++ b/src/comp/rustc.rc @@ -31,6 +31,7 @@ mod middle { mod kind; mod freevars; mod shape; + mod gc; mod tstate { mod ck; |
