Make sure resource destructors are properly monomorphized
This commit is contained in:
parent
8f84d4c8b6
commit
4650e8bcf4
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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()
|
||||
}));
|
||||
}
|
||||
|
@ -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|
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user