Monomorphize dtors correctly

The same dtor was getting re-used for different instances, which
didn't always work right. Fixed.
This commit is contained in:
Tim Chevalier 2012-06-18 13:34:50 -07:00
parent 1b4dcbecac
commit 6db7843f46
1 changed files with 41 additions and 21 deletions

View File

@ -4930,15 +4930,15 @@ fn trans_class_ctor(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
}
fn trans_class_dtor(ccx: @crate_ctxt, path: path,
body: ast::blk,
dtor_id: ast::node_id, substs: option<param_substs>,
body: ast::blk, dtor_id: ast::node_id,
psubsts: option<param_substs>,
hash_id: option<mono_id>, parent_id: ast::def_id)
-> ValueRef {
let tcx = ccx.tcx;
/* Look up the parent class's def_id */
let mut class_ty = ty::lookup_item_type(tcx, parent_id).ty;
/* Substitute in the class type if necessary */
option::iter(substs) {|ss|
option::iter(psubsts) {|ss|
class_ty = ty::subst_tps(tcx, ss.tys, class_ty);
}
@ -4947,7 +4947,9 @@ fn trans_class_dtor(ccx: @crate_ctxt, path: path,
let lldty = T_fn([T_ptr(type_of(ccx, ty::mk_nil(tcx))),
T_ptr(type_of(ccx, class_ty))],
llvm::LLVMVoidType());
let s = get_dtor_symbol(ccx, path, dtor_id);
let s = get_dtor_symbol(ccx, path, dtor_id, psubsts);
/* Register the dtor as a function. It has external linkage */
let lldecl = decl_internal_cdecl_fn(ccx.llmod, s, lldty);
lib::llvm::SetLinkage(lldecl, lib::llvm::ExternalLinkage);
@ -4959,7 +4961,7 @@ fn trans_class_dtor(ccx: @crate_ctxt, path: path,
}
/* Translate the dtor body */
trans_fn(ccx, path, ast_util::dtor_dec(),
body, lldecl, impl_self(class_ty), substs, dtor_id);
body, lldecl, impl_self(class_ty), psubsts, dtor_id);
lldecl
}
@ -5196,17 +5198,35 @@ fn item_path(ccx: @crate_ctxt, i: @ast::item) -> path {
} + [path_name(i.ident)]
}
/* If there's already a symbol for the dtor with <id>, return it;
otherwise, create one and register it, returning it as well */
fn get_dtor_symbol(ccx: @crate_ctxt, path: path, id: ast::node_id) -> str {
/* If there's already a symbol for the dtor with <id> and substs <substs>,
return it; otherwise, create one and register it, returning it as well */
fn get_dtor_symbol(ccx: @crate_ctxt, path: path, id: ast::node_id,
substs: option<param_substs>) -> str {
let t = ty::node_id_to_type(ccx.tcx, id);
alt ccx.item_symbols.find(id) {
some(s) { s }
none {
let s = mangle_exported_name(ccx, path +
[path_name(@ccx.names("dtor"))], ty::node_id_to_type(ccx.tcx, id));
none if is_none(substs) {
let s = mangle_exported_name(ccx,
path + [path_name(@ccx.names("dtor"))],
t);
ccx.item_symbols.insert(id, s);
s
}
none {
// Monomorphizing, so just make a symbol, don't add
// this to item_symbols
alt substs {
some(ss) {
let mono_ty = ty::subst_tps(ccx.tcx, ss.tys, t);
mangle_exported_name(ccx, path +
[path_name(@ccx.names("dtor"))], mono_ty)
}
none {
ccx.sess.bug(#fmt("get_dtor_symbol: not monomorphizing and \
couldn't find a symbol for dtor %?", path));
}
}
}
}
}
@ -5289,7 +5309,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
let lldty = T_fn([T_ptr(type_of(ccx, ty::mk_nil(tcx))),
T_ptr(type_of(ccx, class_ty))],
llvm::LLVMVoidType());
let s = get_dtor_symbol(ccx, *pt, dt.node.id);
let s = get_dtor_symbol(ccx, *pt, dt.node.id, none);
/* Make the declaration for the dtor */
let llfn = decl_internal_cdecl_fn(ccx.llmod, s, lldty);