about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-08-11 14:33:40 -0700
committerPatrick Walton <pcwalton@mimiga.net>2011-08-11 14:35:33 -0700
commit5079f5138649cb8bf52bbde6e2623fdb7d5c45f3 (patch)
tree5c1911fe7f9701aecd42f3e24d7fdc0e7aac697b
parent4b22243416f3f3ce66c7b8fb8d1709dd840656b7 (diff)
downloadrust-5079f5138649cb8bf52bbde6e2623fdb7d5c45f3.tar.gz
rust-5079f5138649cb8bf52bbde6e2623fdb7d5c45f3.zip
rustc: Associate type descriptors with allocas as metadata
-rw-r--r--src/comp/middle/gc.rs73
-rw-r--r--src/comp/middle/shape.rs6
-rw-r--r--src/comp/middle/trans.rs20
-rw-r--r--src/comp/rustc.rc1
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;