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
This commit is contained in:
Tim Chevalier 2012-06-28 10:49:51 -07:00
parent 328fd30cf4
commit f64c23fdfd
2 changed files with 46 additions and 25 deletions

View File

@ -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};

View File

@ -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 {