79 lines
2.4 KiB
Rust
Raw Normal View History

// 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_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_tup(elts) {
for elt in elts {
2011-08-15 12:08:05 +02:00
if type_is_gc_relevant(cx, elt) { 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"; }
}
}