2011-08-11 14:33:40 -07:00
|
|
|
// 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(_) |
|
2011-08-16 10:57:44 -07:00
|
|
|
ty::ty_type. | ty::ty_native(_) {
|
2011-08-11 14:33:40 -07:00
|
|
|
ret false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ty::ty_rec(fields) {
|
|
|
|
for f in fields {
|
|
|
|
if type_is_gc_relevant(cx, f.mt.ty) { ret true; }
|
|
|
|
}
|
|
|
|
ret false;
|
|
|
|
}
|
2011-08-15 11:40:26 +02:00
|
|
|
ty::ty_tup(elts) {
|
|
|
|
for elt in elts {
|
2011-08-15 12:08:05 +02:00
|
|
|
if type_is_gc_relevant(cx, elt) { ret true; }
|
2011-08-15 11:40:26 +02:00
|
|
|
}
|
|
|
|
ret false;
|
|
|
|
}
|
2011-08-11 14:33:40 -07:00
|
|
|
|
|
|
|
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"; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|