Make sure resource destructors are properly monomorphized

This commit is contained in:
Marijn Haverbeke 2012-03-08 21:16:04 +01:00
parent 8f84d4c8b6
commit 4650e8bcf4
7 changed files with 73 additions and 46 deletions

View File

@ -135,6 +135,10 @@ fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) {
visit_item: fn@(i: @ast::item) {
vfn(i.id);
alt i.node {
ast::item_res(_, _, _, d_id, c_id) { vfn(d_id); vfn(c_id); }
_ {}
}
},
visit_local: fn@(l: @ast::local) {

View File

@ -339,10 +339,7 @@ fn should_inline(attrs: [attribute]) -> bool {
}
let tcx = ecx.ccx.tcx;
let must_write = alt item.node {
item_enum(_, _) | item_res(_, _, _, _, _) { true }
_ { false }
};
let must_write = alt item.node { item_enum(_, _) { true } _ { false } };
if !must_write && !ecx.reachable.contains_key(item.id) { ret false; }
alt item.node {
@ -419,6 +416,8 @@ fn should_inline(attrs: [attribute]) -> bool {
encode_name(ebml_w, item.ident);
if tps.len() == 0u {
encode_symbol(ecx, ebml_w, item.id);
} else {
astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(item));
}
encode_path(ebml_w, path, ast_map::path_name(item.ident));
ebml_w.end_tag();
@ -533,7 +532,7 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
ecx.ccx.tcx.items.items {|key, val|
let where = ebml_w.writer.tell();
let written = alt val {
middle::ast_map::node_item(i, path) {
middle::ast_map::node_item(i, path) if i.id == key {
encode_info_for_item(ecx, ebml_w, i, index, *path)
}
middle::ast_map::node_native_item(i, _, path) {

View File

@ -7,7 +7,7 @@
import middle::{resolve, ast_map, typeck};
import syntax::ast::*;
import syntax::visit;
import syntax::{visit, ast_util};
import syntax::ast_util::def_id_of_def;
import front::attr;
import std::map::hashmap;
@ -22,7 +22,9 @@
fn find_reachable(ccx: @middle::trans::common::crate_ctxt, crate_mod: _mod)
-> map {
let rmap = std::map::int_hash();
traverse_public_mod({ccx: ccx, rmap: rmap}, crate_mod);
let cx = {ccx: ccx, rmap: rmap};
traverse_public_mod(cx, crate_mod);
traverse_all_resources(cx, crate_mod);
rmap
}
@ -124,3 +126,17 @@ fn traverse_item(_i: @item, _cx: ctx, _v: visit::vt<ctx>) {}
with *visit::default_visitor()
}));
}
fn traverse_all_resources(cx: ctx, crate_mod: _mod) {
visit::visit_mod(crate_mod, ast_util::dummy_sp(), 0, cx, visit::mk_vt(@{
visit_expr: {|_e, _cx, _v|},
visit_item: {|i, cx, v|
visit::visit_item(i, cx, v);
alt i.node {
item_res(_, _, _, _, _) { traverse_public_item(cx, i); }
_ {}
}
}
with *visit::default_visitor()
}));
}

View File

@ -859,6 +859,24 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
build_return(bcx);
}
fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, substs: [ty::t])
-> ValueRef {
let did = if did.crate != ast::local_crate && substs.len() > 0u {
maybe_instantiate_inline(ccx, did)
} else { did };
if did.crate == ast::local_crate {
option::get(monomorphic_fn(ccx, did, substs, none))
} else {
assert substs.len() == 0u;
let nil = ty::mk_nil(ccx.tcx);
let arg = {mode: ast::expl(ast::by_ref),
ty: ty::mk_mut_ptr(ccx.tcx, nil)};
let f_t = type_of::type_of_fn(ccx, [arg], nil, 0u);
get_extern_const(ccx.externs, ccx.llmod,
csearch::get_symbol(ccx.sess.cstore, did), f_t)
}
}
fn trans_res_drop(bcx: block, rs: ValueRef, did: ast::def_id,
inner_t: ty::t, tps: [ty::t]) -> block {
let ccx = bcx.ccx();
@ -869,16 +887,11 @@ fn trans_res_drop(bcx: block, rs: ValueRef, did: ast::def_id,
with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag))) {|bcx|
let {bcx, val: valptr} = GEP_tup_like(bcx, tup_ty, rs, [0, 1]);
// Find and call the actual destructor.
let dtor_addr = common::get_res_dtor(ccx, did, inner_t);
let dtor_addr = get_res_dtor(ccx, did, tps);
let args = [bcx.fcx.llretptr, null_env_ptr(bcx)];
for tp in tps {
let td = get_tydesc_simple(bcx, tp);
args += [td.val];
bcx = td.bcx;
}
// Kludge to work around the fact that we know the precise type of the
// value here, but the dtor expects a type that still has opaque
// pointers for type variables.
// value here, but the dtor expects a type that might have opaque
// boxes and such.
let val_llty = lib::llvm::fn_ty_param_tys
(llvm::LLVMGetElementType
(llvm::LLVMTypeOf(dtor_addr)))[args.len()];
@ -1997,13 +2010,20 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
}
let tpt = ty::lookup_item_type(ccx.tcx, fn_id);
let mono_ty = ty::substitute_type_params(ccx.tcx, substs, tpt.ty);
let llfty = type_of_fn_from_ty(ccx, mono_ty, 0u);
let item_ty = tpt.ty;
let map_node = ccx.tcx.items.get(fn_id.node);
// Get the path so that we can create a symbol
let (pt, name) = alt map_node {
ast_map::node_item(i, pt) { (pt, i.ident) }
ast_map::node_item(i, pt) {
alt i.node {
ast::item_res(_, _, _, dtor_id, _) {
item_ty = ty::node_id_to_type(ccx.tcx, dtor_id);
}
_ {}
}
(pt, i.ident)
}
ast_map::node_variant(v, _, pt) { (pt, v.node.name) }
ast_map::node_method(m, _, pt) { (pt, m.ident) }
// We can't monomorphize native functions
@ -2015,6 +2035,9 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
}
_ { fail "unexpected node type"; }
};
let mono_ty = ty::substitute_type_params(ccx.tcx, substs, item_ty);
let llfty = type_of_fn_from_ty(ccx, mono_ty, 0u);
let pt = *pt + [path_name(ccx.names(name))];
let s = mangle_exported_name(ccx, pt, mono_ty);
let lldecl = decl_cdecl_fn(ccx.llmod, s, llfty);
@ -2027,6 +2050,9 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
trans_fn(ccx, pt, decl, body, lldecl, no_self, psubsts, fn_id.node,
none);
}
ast_map::node_item(@{node: ast::item_res(d, _, body, d_id, _), _}, _) {
trans_fn(ccx, pt, d, body, lldecl, no_self, psubsts, d_id, none);
}
ast_map::node_variant(v, enum_item, _) {
let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.id));
let this_tv = option::get(vec::find(*tvs, {|tv|

View File

@ -298,22 +298,6 @@ fn revoke_clean(cx: block, val: ValueRef) {
}
}
fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, inner_t: ty::t)
-> ValueRef {
if did.crate == ast::local_crate {
ret base::get_item_val(ccx, did.node);
}
let param_bounds = ty::lookup_item_type(ccx.tcx, did).bounds;
let nil_res = ty::mk_nil(ccx.tcx);
let fn_mode = ast::expl(ast::by_ref);
let f_t = type_of::type_of_fn(ccx, [{mode: fn_mode, ty: inner_t}],
nil_res, (*param_bounds).len());
ret base::get_extern_const(ccx.externs, ccx.llmod,
csearch::get_symbol(ccx.sess.cstore,
did), f_t);
}
enum block_kind {
// A scope at the end of which temporary values created inside of it are
// cleaned up. May correspond to an actual block in the language, but also

View File

@ -21,7 +21,7 @@
import ty_ctxt = middle::ty::ctxt;
type res_info = {did: ast::def_id, t: ty::t};
type res_info = {did: ast::def_id, tps: [ty::t]};
type ctxt =
{mutable next_tag_id: u16,
@ -67,15 +67,13 @@ fn hash_res_info(ri: res_info) -> uint {
h += ri.did.crate as uint;
h *= 33u;
h += ri.did.node as uint;
h *= 33u;
h += ty::type_id(ri.t);
for t in ri.tps {
h *= 33u;
h += ty::type_id(t);
}
ret h;
}
fn eq_res_info(a: res_info, b: res_info) -> bool {
ret a.did.crate == b.did.crate && a.did.node == b.did.node && a.t == b.t;
}
fn mk_global(ccx: @crate_ctxt, name: str, llval: ValueRef, internal: bool) ->
ValueRef {
let llglobal =
@ -278,7 +276,7 @@ fn mk_ctxt(llmod: ModuleRef) -> ctxt {
pad: 0u16,
tag_id_to_index: common::new_def_hash(),
mutable tag_order: [],
resources: interner::mk(hash_res_info, eq_res_info),
resources: interner::mk(hash_res_info, {|a, b| a == b}),
llshapetablesty: llshapetablesty,
llshapetables: llshapetables};
}
@ -391,7 +389,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] {
}
ty::ty_res(did, raw_subt, tps) {
let subt = ty::substitute_type_params(ccx.tcx, tps, raw_subt);
let ri = {did: did, t: subt};
let ri = {did: did, tps: tps};
let id = interner::intern(ccx.shape_cx.resources, ri);
s += [shape_res];
@ -553,7 +551,7 @@ fn gen_resource_shapes(ccx: @crate_ctxt) -> ValueRef {
let len = interner::len(ccx.shape_cx.resources);
while i < len {
let ri = interner::get(ccx.shape_cx.resources, i);
dtors += [trans::common::get_res_dtor(ccx, ri.did, ri.t)];
dtors += [trans::base::get_res_dtor(ccx, ri.did, ri.tps)];
i += 1u;
}

View File

@ -289,8 +289,8 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
item_res(fold_fn_decl(decl, fld),
fold_ty_params(typms, fld),
fld.fold_block(body),
did,
cid)
fld.new_id(did),
fld.new_id(cid))
}
};
}