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, fn trans_class_dtor(ccx: @crate_ctxt, path: path,
body: ast::blk, body: ast::blk, dtor_id: ast::node_id,
dtor_id: ast::node_id, substs: option<param_substs>, psubsts: option<param_substs>,
hash_id: option<mono_id>, parent_id: ast::def_id) hash_id: option<mono_id>, parent_id: ast::def_id)
-> ValueRef { -> ValueRef {
let tcx = ccx.tcx; let tcx = ccx.tcx;
/* Look up the parent class's def_id */ /* Look up the parent class's def_id */
let mut class_ty = ty::lookup_item_type(tcx, parent_id).ty; let mut class_ty = ty::lookup_item_type(tcx, parent_id).ty;
/* Substitute in the class type if necessary */ /* 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); 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))), let lldty = T_fn([T_ptr(type_of(ccx, ty::mk_nil(tcx))),
T_ptr(type_of(ccx, class_ty))], T_ptr(type_of(ccx, class_ty))],
llvm::LLVMVoidType()); 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 */ /* Register the dtor as a function. It has external linkage */
let lldecl = decl_internal_cdecl_fn(ccx.llmod, s, lldty); let lldecl = decl_internal_cdecl_fn(ccx.llmod, s, lldty);
lib::llvm::SetLinkage(lldecl, lib::llvm::ExternalLinkage); lib::llvm::SetLinkage(lldecl, lib::llvm::ExternalLinkage);
@ -4959,7 +4961,7 @@ fn trans_class_dtor(ccx: @crate_ctxt, path: path,
} }
/* Translate the dtor body */ /* Translate the dtor body */
trans_fn(ccx, path, ast_util::dtor_dec(), 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 lldecl
} }
@ -5196,17 +5198,35 @@ fn item_path(ccx: @crate_ctxt, i: @ast::item) -> path {
} + [path_name(i.ident)] } + [path_name(i.ident)]
} }
/* If there's already a symbol for the dtor with <id>, return it; /* If there's already a symbol for the dtor with <id> and substs <substs>,
otherwise, create one and register it, returning it as well */ 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 { 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) { alt ccx.item_symbols.find(id) {
some(s) { s } some(s) { s }
none { none if is_none(substs) {
let s = mangle_exported_name(ccx, path + let s = mangle_exported_name(ccx,
[path_name(@ccx.names("dtor"))], ty::node_id_to_type(ccx.tcx, id)); path + [path_name(@ccx.names("dtor"))],
t);
ccx.item_symbols.insert(id, s); ccx.item_symbols.insert(id, s);
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))), let lldty = T_fn([T_ptr(type_of(ccx, ty::mk_nil(tcx))),
T_ptr(type_of(ccx, class_ty))], T_ptr(type_of(ccx, class_ty))],
llvm::LLVMVoidType()); 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 */ /* Make the declaration for the dtor */
let llfn = decl_internal_cdecl_fn(ccx.llmod, s, lldty); let llfn = decl_internal_cdecl_fn(ccx.llmod, s, lldty);