about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2010-12-10 15:02:23 -0800
committerPatrick Walton <pcwalton@mimiga.net>2010-12-10 15:37:17 -0800
commit270b93bd710b9901f7bd831e193d3fcbebcb048c (patch)
treeb2f7dc9e4041ead0f8e27239bcfe9ba5684f0f2c /src/comp
parent10d5d32537c6c0a7c5ca67c6a29b998985c822d3 (diff)
downloadrust-270b93bd710b9901f7bd831e193d3fcbebcb048c.tar.gz
rust-270b93bd710b9901f7bd831e193d3fcbebcb048c.zip
rustc: Move refcount decrement-and-free (drop) logic out-of-line
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/middle/trans.rs179
1 files changed, 124 insertions, 55 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index f92d87fc454..2dce726adf9 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -3,6 +3,7 @@ import std._uint;
 import std._vec;
 import std._str.rustrt.sbuf;
 import std._vec.rustrt.vbuf;
+import std.map;
 import std.map.hashmap;
 import std.option;
 import std.option.some;
@@ -53,6 +54,8 @@ type tag_info = rec(type_handle th,
                     mutable vec[tup(ast.def_id,arity)] variants,
                     mutable uint size);
 
+type ty_info = rec(ValueRef drop_glue);
+
 state type crate_ctxt = rec(session.session sess,
                             ModuleRef llmod,
                             target_data td,
@@ -62,6 +65,7 @@ state type crate_ctxt = rec(session.session sess,
                             hashmap[ast.def_id, ValueRef] item_ids,
                             hashmap[ast.def_id, @ast.item] items,
                             hashmap[ast.def_id, @tag_info] tags,
+                            hashmap[@typeck.ty, @ty_info] types,
                             @glue_fns glues,
                             namegen names,
                             str path);
@@ -336,6 +340,22 @@ fn type_of_arg(@crate_ctxt cx, &typeck.arg arg) -> TypeRef {
     ret ty;
 }
 
+// Name sanitation. LLVM will happily accept identifiers with weird names, but
+// gas doesn't!
+
+fn sanitize(str s) -> str {
+    auto result = "";
+    for (u8 c in s) {
+        if (c == ('@' as u8)) {
+            result += "boxed_";
+        } else {
+            auto v = vec(c);
+            result += _str.from_bytes(v);
+        }
+    }
+    ret result;
+}
+
 // LLVM constant constructors.
 
 fn C_null(TypeRef t) -> ValueRef {
@@ -519,6 +539,102 @@ fn incr_refcnt(@block_ctxt cx, ValueRef box_ptr) -> result {
     ret res(next_cx, C_nil());
 }
 
+// Glue and referent count twiddling
+
+fn get_ty_info(@crate_ctxt cx, @typeck.ty ty) -> @ty_info {
+    if (!cx.types.contains_key(ty)) {
+        make_ty_info(cx, ty);
+    }
+    ret cx.types.get(ty);
+}
+
+fn make_ty_info(@crate_ctxt cx, @typeck.ty ty) {
+    cx.types.insert(ty, @rec(drop_glue=make_drop_glue(cx, ty)));
+}
+
+fn make_drop_glue(@crate_ctxt cx, @typeck.ty t) -> ValueRef {
+    auto arg_t;
+    if (typeck.type_is_structural(t)) {
+        arg_t = T_ptr(type_of(cx, t));
+    } else {
+        arg_t = type_of(cx, t);
+    }
+    auto llfnty = T_fn(vec(T_taskptr(), arg_t), T_void());
+
+    auto fn_name = cx.names.next("_rust_drop") + "." + typeck.ty_to_str(t);
+    fn_name = sanitize(fn_name);
+    auto llfn = decl_fastcall_fn(cx.llmod, fn_name, llfnty);
+
+    auto fcx = new_fn_ctxt(cx, fn_name, llfn);
+    auto bcx = new_top_block_ctxt(fcx);
+
+    auto llval = llvm.LLVMGetParam(llfn, 1u);
+    auto res = make_drop_glue_inner(bcx, llval, t);
+
+    res.bcx.build.RetVoid();
+
+    ret llfn;
+}
+
+fn make_drop_glue_inner(@block_ctxt cx, ValueRef v, @typeck.ty t) -> result {
+    alt (t.struct) {
+        case (typeck.ty_str) {
+            ret decr_refcnt_and_if_zero(cx, v,
+                                        bind trans_non_gc_free(_, v),
+                                        "free string",
+                                        T_int(), C_int(0));
+        }
+
+        case (typeck.ty_vec(_)) {
+            fn hit_zero(@block_ctxt cx, ValueRef v,
+                        @typeck.ty t) -> result {
+                auto res = iter_sequence(cx, v, t, bind drop_ty(_,_,_));
+                // FIXME: switch gc/non-gc on layer of the type.
+                ret trans_non_gc_free(res.bcx, v);
+            }
+            ret decr_refcnt_and_if_zero(cx, v,
+                                        bind hit_zero(_, v, t),
+                                        "free vector",
+                                        T_int(), C_int(0));
+        }
+
+        case (typeck.ty_box(?body_ty)) {
+            fn hit_zero(@block_ctxt cx, ValueRef v,
+                        @typeck.ty body_ty) -> result {
+                auto body = cx.build.GEP(v,
+                                         vec(C_int(0),
+                                             C_int(abi.box_rc_field_body)));
+
+                auto body_val = load_non_structural(cx, body, body_ty);
+                auto res = drop_ty(cx, body_val, body_ty);
+                // FIXME: switch gc/non-gc on layer of the type.
+                ret trans_non_gc_free(res.bcx, v);
+            }
+            ret decr_refcnt_and_if_zero(cx, v,
+                                        bind hit_zero(_, v, body_ty),
+                                        "free box",
+                                        T_int(), C_int(0));
+        }
+
+        case (_) {
+            if (typeck.type_is_structural(t)) {
+                ret iter_structural_ty(cx, v, t,
+                                       bind drop_ty(_, _, _));
+
+            } else if (typeck.type_is_binding(t)) {
+                cx.fcx.ccx.sess.unimpl("binding type in " +
+                                       "trans.make_drop_glue_inner");
+
+            } else if (typeck.type_is_scalar(t) ||
+                       typeck.type_is_nil(t)) {
+                ret res(cx, C_nil());
+            }
+        }
+    }
+    cx.fcx.ccx.sess.bug("bad type in trans.make_drop_glue_inner");
+    fail;
+}
+
 fn decr_refcnt_and_if_zero(@block_ctxt cx,
                            ValueRef box_ptr,
                            fn(@block_ctxt cx) -> result inner,
@@ -777,61 +893,9 @@ fn drop_slot(@block_ctxt cx,
 fn drop_ty(@block_ctxt cx,
            ValueRef v,
            @typeck.ty t) -> result {
-
-    alt (t.struct) {
-        case (typeck.ty_str) {
-            ret decr_refcnt_and_if_zero(cx, v,
-                                        bind trans_non_gc_free(_, v),
-                                        "free string",
-                                        T_int(), C_int(0));
-        }
-
-        case (typeck.ty_vec(_)) {
-            fn hit_zero(@block_ctxt cx, ValueRef v,
-                        @typeck.ty t) -> result {
-                auto res = iter_sequence(cx, v, t, bind drop_ty(_,_,_));
-                // FIXME: switch gc/non-gc on layer of the type.
-                ret trans_non_gc_free(res.bcx, v);
-            }
-            ret decr_refcnt_and_if_zero(cx, v,
-                                        bind hit_zero(_, v, t),
-                                        "free vector",
-                                        T_int(), C_int(0));
-        }
-
-        case (typeck.ty_box(?body_ty)) {
-            fn hit_zero(@block_ctxt cx, ValueRef v,
-                        @typeck.ty body_ty) -> result {
-                auto body = cx.build.GEP(v,
-                                         vec(C_int(0),
-                                             C_int(abi.box_rc_field_body)));
-
-                auto res = drop_ty(cx, body, body_ty);
-                // FIXME: switch gc/non-gc on layer of the type.
-                ret trans_non_gc_free(res.bcx, v);
-            }
-            ret decr_refcnt_and_if_zero(cx, v,
-                                        bind hit_zero(_, v, body_ty),
-                                        "free box",
-                                        T_int(), C_int(0));
-        }
-
-        case (_) {
-            if (typeck.type_is_structural(t)) {
-                ret iter_structural_ty(cx, v, t,
-                                       bind drop_ty(_, _, _));
-
-            } else if (typeck.type_is_binding(t)) {
-                cx.fcx.ccx.sess.unimpl("binding type in trans.drop_ty");
-
-            } else if (typeck.type_is_scalar(t) ||
-                       typeck.type_is_nil(t)) {
-                ret res(cx, C_nil());
-            }
-        }
-    }
-    cx.fcx.ccx.sess.bug("bad type in trans.drop_ty");
-    fail;
+    cx.build.FastCall(get_ty_info(cx.fcx.ccx, t).drop_glue,
+                      vec(cx.fcx.lltaskptr, v));
+    ret res(cx, C_nil());
 }
 
 fn build_memcpy(@block_ctxt cx,
@@ -2329,6 +2393,10 @@ fn trans_crate(session.session sess, @ast.crate crate, str output) {
                       _vec.init_fn[ValueRef](bind decl_upcall(llmod, _),
                                              abi.n_upcall_glues as uint));
 
+    auto hasher = typeck.hash_ty;
+    auto eqer = typeck.eq_ty;
+    auto types = map.mk_hashmap[@typeck.ty,@ty_info](hasher, eqer);
+
     auto cx = @rec(sess = sess,
                    llmod = llmod,
                    td = td,
@@ -2338,6 +2406,7 @@ fn trans_crate(session.session sess, @ast.crate crate, str output) {
                    item_ids = new_def_hash[ValueRef](),
                    items = new_def_hash[@ast.item](),
                    tags = new_def_hash[@tag_info](),
+                   types = types,
                    glues = glues,
                    names = namegen(0),
                    path = "_rust");