rustc: Associate type descriptors with allocas as metadata

This commit is contained in:
Patrick Walton 2011-08-11 14:33:40 -07:00
parent 4b22243416
commit 5079f51386
4 changed files with 88 additions and 12 deletions

73
src/comp/middle/gc.rs Normal file
View file

@ -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"; }
}
}

View file

@ -281,12 +281,10 @@ fn shape_of(ccx : &@crate_ctxt, t : ty::t) -> [u8] {
let s = ~[]; let s = ~[];
alt ty::struct(ccx.tcx, t) { 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]; s += ~[shape_u8];
} }
ty::ty_bot. { fail "bot ty in shape_of"; }
ty::ty_int. { s += ~[s_int(ccx.tcx)]; } ty::ty_int. { s += ~[s_int(ccx.tcx)]; }
ty::ty_float. { s += ~[s_float(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_i16.) { s += ~[shape_i16]; }
ty::ty_machine(ast::ty_u32.) | ty::ty_char. { s += ~[shape_u32]; } 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_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_str. { s += ~[shape_evec, 1u8, 1u8, 0u8, shape_u8]; }
ty::ty_istr. { s += ~[shape_ivec, 1u8, 1u8, 0u8, shape_u8]; } ty::ty_istr. { s += ~[shape_ivec, 1u8, 1u8, 0u8, shape_u8]; }

View file

@ -27,6 +27,7 @@ import syntax::ast;
import driver::session; import driver::session;
import middle::ty; import middle::ty;
import middle::freevars::*; import middle::freevars::*;
import middle::gc;
import back::link; import back::link;
import back::x86; import back::x86;
import back::abi; 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 { fn alloc_ty(cx: &@block_ctxt, t: &ty::t) -> result {
let bcx = cx;
let val = C_int(0); 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 // NB: we have to run this particular 'size_of' in a
// block_ctxt built on the llderivedtydescs block for the fn, // block_ctxt built on the llderivedtydescs block for the fn,
// so that the size dominates the array_alloca that // so that the size dominates the array_alloca that
// comes next. // comes next.
let n = size_of(llderivedtydescs_block_ctxt(cx.fcx), t); let n = size_of(llderivedtydescs_block_ctxt(bcx.fcx), t);
cx.fcx.llderivedtydescs = n.bcx.llbb; bcx.fcx.llderivedtydescs = n.bcx.llbb;
val = array_alloca(cx, T_i8(), n.val); val = array_alloca(bcx, T_i8(), n.val);
} else { val = alloca(cx, type_of(bcx_ccx(cx), cx.sp, t)); } } else {
val = alloca(bcx, type_of(bcx_ccx(cx), cx.sp, t));
}
// NB: since we've pushed all size calculations in this // NB: since we've pushed all size calculations in this
// function up to the alloca block, we actually return the // function up to the alloca block, we actually return the
// block passed into us unmodified; it doesn't really // 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, // past caller conventions and may well make sense again,
// so we leave it as-is. // so we leave it as-is.
bcx = gc::add_gc_root(bcx, val, t);
ret rslt(cx, val); ret rslt(cx, val);
} }
@ -6756,9 +6762,6 @@ fn declare_intrinsics(llmod: ModuleRef) -> hashmap[str, ValueRef] {
let T_memset64_args: [TypeRef] = let T_memset64_args: [TypeRef] =
~[T_ptr(T_i8()), T_i8(), T_i64(), T_i32(), T_i1()]; ~[T_ptr(T_i8()), T_i8(), T_i64(), T_i32(), T_i1()];
let T_trap_args: [TypeRef] = ~[]; 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 = let gcread =
decl_cdecl_fn(llmod, "llvm.gcread", decl_cdecl_fn(llmod, "llvm.gcread",
T_fn(~[T_ptr(T_i8()), T_ptr(T_ptr(T_i8()))], T_void())); 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())); T_fn(T_memset64_args, T_void()));
let trap = decl_cdecl_fn(llmod, "llvm.trap", T_fn(T_trap_args, T_void())); let trap = decl_cdecl_fn(llmod, "llvm.trap", T_fn(T_trap_args, T_void()));
let intrinsics = new_str_hash[ValueRef](); let intrinsics = new_str_hash[ValueRef]();
intrinsics.insert("llvm.gcroot", gcroot);
intrinsics.insert("llvm.gcread", gcread); intrinsics.insert("llvm.gcread", gcread);
intrinsics.insert("llvm.memmove.p0i8.p0i8.i32", memmove32); intrinsics.insert("llvm.memmove.p0i8.p0i8.i32", memmove32);
intrinsics.insert("llvm.memmove.p0i8.p0i8.i64", memmove64); intrinsics.insert("llvm.memmove.p0i8.p0i8.i64", memmove64);

View file

@ -31,6 +31,7 @@ mod middle {
mod kind; mod kind;
mod freevars; mod freevars;
mod shape; mod shape;
mod gc;
mod tstate { mod tstate {
mod ck; mod ck;