about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorTim Chevalier <chevalier@alum.wellesley.edu>2012-06-28 10:49:51 -0700
committerTim Chevalier <chevalier@alum.wellesley.edu>2012-06-30 00:34:03 -0700
commitf64c23fdfd2a6c22d809d573f3db91ec2677952e (patch)
tree2974e907321841ff892665cb392d12bdefad0ee1 /src
parent328fd30cf4c0f34ad6ea97d8a1468935d0a60101 (diff)
downloadrust-f64c23fdfd2a6c22d809d573f3db91ec2677952e.tar.gz
rust-f64c23fdfd2a6c22d809d573f3db91ec2677952e.zip
Descend into ty_boxes in type_use
type_use was failing to look into ty_boxes, which caused monomorphize
to coalesce instances that shouldn't have been coalesced (because they
should actually use different type glue)

Closes #2734
Diffstat (limited to 'src')
-rw-r--r--src/rustc/middle/trans/base.rs48
-rw-r--r--src/rustc/middle/trans/type_use.rs23
2 files changed, 46 insertions, 25 deletions
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 0b81392659b..2978cd04b96 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -242,7 +242,7 @@ fn trans_free(cx: block, v: ValueRef) -> block {
 }
 
 fn trans_unique_free(cx: block, v: ValueRef) -> block {
-    let _icx = cx.insn_ctxt("trans_shared_free");
+    let _icx = cx.insn_ctxt("trans_unique_free");
     Call(cx, cx.ccx().upcalls.exchange_free,
          ~[PointerCast(cx, v, T_ptr(T_i8()))]);
     ret cx;
@@ -422,12 +422,12 @@ fn get_tydesc(ccx: @crate_ctxt, t: ty::t,
 
 fn get_static_tydesc(ccx: @crate_ctxt, t: ty::t) -> @tydesc_info {
     alt ccx.tydescs.find(t) {
-      some(inf) { ret inf; }
-      none {
+      some(inf) { inf }
+      _ {
         ccx.stats.n_static_tydescs += 1u;
         let inf = declare_tydesc(ccx, t);
         ccx.tydescs.insert(t, inf);
-        ret inf;
+        inf
       }
     }
 }
@@ -490,16 +490,15 @@ fn note_unique_llvm_symbol(ccx: @crate_ctxt, sym: str) {
 // Generates the declaration for (but doesn't emit) a type descriptor.
 fn declare_tydesc(ccx: @crate_ctxt, t: ty::t) -> @tydesc_info {
     let _icx = ccx.insn_ctxt("declare_tydesc");
-    log(debug, "+++ declare_tydesc " + ty_to_str(ccx.tcx, t));
     let llty = type_of(ccx, t);
     let llsize = llsize_of(ccx, llty);
     let llalign = llalign_of(ccx, llty);
-    let mut name;
     //XXX this triggers duplicate LLVM symbols
-    if false /*ccx.sess.opts.debuginfo*/ {
-        name = mangle_internal_name_by_type_only(ccx, t, @"tydesc");
-    } else { name = mangle_internal_name_by_seq(ccx, @"tydesc"); }
+    let name = if false /*ccx.sess.opts.debuginfo*/ {
+        mangle_internal_name_by_type_only(ccx, t, @"tydesc")
+    } else { mangle_internal_name_by_seq(ccx, @"tydesc") };
     note_unique_llvm_symbol(ccx, name);
+    log(debug, #fmt("+++ declare_tydesc %s %s", ty_to_str(ccx.tcx, t), name));
     let gvar = str::as_c_str(name, {|buf|
         llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type, buf)
     });
@@ -613,14 +612,14 @@ fn emit_tydescs(ccx: @crate_ctxt) {
                             drop_glue, // drop_glue
                             free_glue, // free_glue
                             visit_glue, // visit_glue
-                            C_int(ccx, 0), // ununsed
-                            C_int(ccx, 0), // ununsed
-                            C_int(ccx, 0), // ununsed
-                            C_int(ccx, 0), // ununsed
+                            C_int(ccx, 0), // unused
+                            C_int(ccx, 0), // unused
+                            C_int(ccx, 0), // unused
+                            C_int(ccx, 0), // unused
                             C_shape(ccx, shape), // shape
                             shape_tables, // shape_tables
-                            C_int(ccx, 0), // ununsed
-                            C_int(ccx, 0)]); // unused
+                            C_int(ccx, 0), // unused
+                            C_int(ccx, 0)]/~); // unused
 
         let gvar = ti.tydesc;
         llvm::LLVMSetInitializer(gvar, tydesc);
@@ -704,8 +703,10 @@ fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
       }
       ty::ty_opaque_box {
         let v = PointerCast(bcx, v, type_of(ccx, t));
-        let td = Load(bcx, GEPi(bcx, v, ~[0u, abi::box_field_tydesc]));
-        let valptr = GEPi(bcx, v, ~[0u, abi::box_field_body]);
+        let td = Load(bcx, GEPi(bcx, v, [0u, abi::box_field_tydesc]/~));
+        let valptr = GEPi(bcx, v, [0u, abi::box_field_body]/~);
+        // Generate code that, dynamically, indexes into the
+        // tydesc and calls the drop glue that got set dynamically
         call_tydesc_glue_full(bcx, valptr, td, abi::tydesc_field_drop_glue,
                               none);
         trans_free(bcx, v)
@@ -1194,6 +1195,7 @@ fn call_tydesc_glue_full(++cx: block, v: ValueRef, tydesc: ValueRef,
     let llfn = {
         alt static_glue_fn {
           none {
+            // Select out the glue function to call from the tydesc
             let llfnptr = GEPi(cx, tydesc, ~[0u, field]);
             Load(cx, llfnptr)
           }
@@ -2136,11 +2138,6 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id,
         }
     });
 
-    #debug["monomorphic_fn(fn_id=%? (%s), real_substs=%?, substs=%?",
-           fn_id, ty::item_path_str(ccx.tcx, fn_id),
-           real_substs.map({|s| ty_to_str(ccx.tcx, s)}),
-           substs.map({|s| ty_to_str(ccx.tcx, s)})];
-
     for real_substs.each() {|s| assert !ty::type_has_params(s); };
     for substs.each() {|s| assert !ty::type_has_params(s); };
 
@@ -2150,6 +2147,13 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id,
                 {|p| alt p { mono_precise(_, _) { false } _ { true } } }) {
         must_cast = true;
     }
+
+    #debug["monomorphic_fn(fn_id=%? (%s), real_substs=%?, substs=%?, \
+           hash_id = %?",
+           fn_id, ty::item_path_str(ccx.tcx, fn_id),
+           real_substs.map({|s| ty_to_str(ccx.tcx, s)}),
+           substs.map({|s| ty_to_str(ccx.tcx, s)}), hash_id];
+
     alt ccx.monomorphized.find(hash_id) {
       some(val) {
         ret {val: val, must_cast: must_cast};
diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs
index 722746217e6..20747a91f14 100644
--- a/src/rustc/middle/trans/type_use.rs
+++ b/src/rustc/middle/trans/type_use.rs
@@ -117,8 +117,14 @@ fn type_needs_inner(cx: ctx, use: uint, ty: ty::t,
     ty::maybe_walk_ty(ty) {|ty|
         if ty::type_has_params(ty) {
             alt ty::get(ty).struct {
-              ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _) |
-              ty::ty_box(_) | ty::ty_iface(_, _) { false }
+                /*
+                  This previously included ty_box -- that was wrong
+                  because if we cast an @T to an iface (for example) and return
+                  it, we depend on the drop glue for T (we have to write the
+                  right tydesc into the result)
+                 */
+              ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _)
+               | ty::ty_iface(_, _) { false }
               ty::ty_enum(did, substs) {
                 if option::is_none(list::find(enums_seen, {|id| id == did})) {
                     let seen = @cons(did, enums_seen);
@@ -151,10 +157,21 @@ fn mark_for_expr(cx: ctx, e: @expr) {
       expr_vec(_, _) |
       expr_rec(_, _) | expr_tup(_) |
       expr_unary(box(_), _) | expr_unary(uniq(_), _) |
-      expr_cast(_, _) | expr_binary(add, _, _) |
+      expr_binary(add, _, _) |
       expr_copy(_) | expr_move(_, _) {
         node_type_needs(cx, use_repr, e.id);
       }
+      expr_cast(base, _) {
+        let result_t = ty::node_id_to_type(cx.ccx.tcx, e.id);
+        alt ty::get(result_t).struct {
+            ty::ty_iface(*) {
+              // When we're casting to an iface, we need the
+              // tydesc for the expr that's being cast.
+              node_type_needs(cx, use_tydesc, base.id);
+            }
+            _ {}
+        }
+      }
       expr_binary(op, lhs, _) {
         alt op {
           eq | lt | le | ne | ge | gt {