From f64c23fdfd2a6c22d809d573f3db91ec2677952e Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 28 Jun 2012 10:49:51 -0700 Subject: [PATCH] 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 --- src/rustc/middle/trans/base.rs | 48 ++++++++++++++++-------------- src/rustc/middle/trans/type_use.rs | 23 ++++++++++++-- 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 {