Make sure resource destructors are properly monomorphized
This commit is contained in:
@@ -135,6 +135,10 @@ fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) {
|
|||||||
|
|
||||||
visit_item: fn@(i: @ast::item) {
|
visit_item: fn@(i: @ast::item) {
|
||||||
vfn(i.id);
|
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) {
|
visit_local: fn@(l: @ast::local) {
|
||||||
|
|||||||
@@ -339,10 +339,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
|||||||
}
|
}
|
||||||
|
|
||||||
let tcx = ecx.ccx.tcx;
|
let tcx = ecx.ccx.tcx;
|
||||||
let must_write = alt item.node {
|
let must_write = alt item.node { item_enum(_, _) { true } _ { false } };
|
||||||
item_enum(_, _) | item_res(_, _, _, _, _) { true }
|
|
||||||
_ { false }
|
|
||||||
};
|
|
||||||
if !must_write && !ecx.reachable.contains_key(item.id) { ret false; }
|
if !must_write && !ecx.reachable.contains_key(item.id) { ret false; }
|
||||||
|
|
||||||
alt item.node {
|
alt item.node {
|
||||||
@@ -419,6 +416,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
|||||||
encode_name(ebml_w, item.ident);
|
encode_name(ebml_w, item.ident);
|
||||||
if tps.len() == 0u {
|
if tps.len() == 0u {
|
||||||
encode_symbol(ecx, ebml_w, item.id);
|
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));
|
encode_path(ebml_w, path, ast_map::path_name(item.ident));
|
||||||
ebml_w.end_tag();
|
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|
|
ecx.ccx.tcx.items.items {|key, val|
|
||||||
let where = ebml_w.writer.tell();
|
let where = ebml_w.writer.tell();
|
||||||
let written = alt val {
|
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)
|
encode_info_for_item(ecx, ebml_w, i, index, *path)
|
||||||
}
|
}
|
||||||
middle::ast_map::node_native_item(i, _, path) {
|
middle::ast_map::node_native_item(i, _, path) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import middle::{resolve, ast_map, typeck};
|
import middle::{resolve, ast_map, typeck};
|
||||||
import syntax::ast::*;
|
import syntax::ast::*;
|
||||||
import syntax::visit;
|
import syntax::{visit, ast_util};
|
||||||
import syntax::ast_util::def_id_of_def;
|
import syntax::ast_util::def_id_of_def;
|
||||||
import front::attr;
|
import front::attr;
|
||||||
import std::map::hashmap;
|
import std::map::hashmap;
|
||||||
@@ -22,7 +22,9 @@ type ctx = {ccx: @middle::trans::common::crate_ctxt,
|
|||||||
fn find_reachable(ccx: @middle::trans::common::crate_ctxt, crate_mod: _mod)
|
fn find_reachable(ccx: @middle::trans::common::crate_ctxt, crate_mod: _mod)
|
||||||
-> map {
|
-> map {
|
||||||
let rmap = std::map::int_hash();
|
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
|
rmap
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,3 +126,17 @@ fn traverse_inline_body(cx: ctx, body: blk) {
|
|||||||
with *visit::default_visitor()
|
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);
|
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,
|
fn trans_res_drop(bcx: block, rs: ValueRef, did: ast::def_id,
|
||||||
inner_t: ty::t, tps: [ty::t]) -> block {
|
inner_t: ty::t, tps: [ty::t]) -> block {
|
||||||
let ccx = bcx.ccx();
|
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|
|
with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag))) {|bcx|
|
||||||
let {bcx, val: valptr} = GEP_tup_like(bcx, tup_ty, rs, [0, 1]);
|
let {bcx, val: valptr} = GEP_tup_like(bcx, tup_ty, rs, [0, 1]);
|
||||||
// Find and call the actual destructor.
|
// 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)];
|
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
|
// 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
|
// value here, but the dtor expects a type that might have opaque
|
||||||
// pointers for type variables.
|
// boxes and such.
|
||||||
let val_llty = lib::llvm::fn_ty_param_tys
|
let val_llty = lib::llvm::fn_ty_param_tys
|
||||||
(llvm::LLVMGetElementType
|
(llvm::LLVMGetElementType
|
||||||
(llvm::LLVMTypeOf(dtor_addr)))[args.len()];
|
(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 tpt = ty::lookup_item_type(ccx.tcx, fn_id);
|
||||||
let mono_ty = ty::substitute_type_params(ccx.tcx, substs, tpt.ty);
|
let item_ty = tpt.ty;
|
||||||
let llfty = type_of_fn_from_ty(ccx, mono_ty, 0u);
|
|
||||||
|
|
||||||
let map_node = ccx.tcx.items.get(fn_id.node);
|
let map_node = ccx.tcx.items.get(fn_id.node);
|
||||||
// Get the path so that we can create a symbol
|
// Get the path so that we can create a symbol
|
||||||
let (pt, name) = alt map_node {
|
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_variant(v, _, pt) { (pt, v.node.name) }
|
||||||
ast_map::node_method(m, _, pt) { (pt, m.ident) }
|
ast_map::node_method(m, _, pt) { (pt, m.ident) }
|
||||||
// We can't monomorphize native functions
|
// 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"; }
|
_ { 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 pt = *pt + [path_name(ccx.names(name))];
|
||||||
let s = mangle_exported_name(ccx, pt, mono_ty);
|
let s = mangle_exported_name(ccx, pt, mono_ty);
|
||||||
let lldecl = decl_cdecl_fn(ccx.llmod, s, llfty);
|
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,
|
trans_fn(ccx, pt, decl, body, lldecl, no_self, psubsts, fn_id.node,
|
||||||
none);
|
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, _) {
|
ast_map::node_variant(v, enum_item, _) {
|
||||||
let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.id));
|
let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.id));
|
||||||
let this_tv = option::get(vec::find(*tvs, {|tv|
|
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 {
|
enum block_kind {
|
||||||
// A scope at the end of which temporary values created inside of it are
|
// 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
|
// cleaned up. May correspond to an actual block in the language, but also
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import std::map::hashmap;
|
|||||||
|
|
||||||
import ty_ctxt = middle::ty::ctxt;
|
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 =
|
type ctxt =
|
||||||
{mutable next_tag_id: u16,
|
{mutable next_tag_id: u16,
|
||||||
@@ -67,13 +67,11 @@ fn hash_res_info(ri: res_info) -> uint {
|
|||||||
h += ri.did.crate as uint;
|
h += ri.did.crate as uint;
|
||||||
h *= 33u;
|
h *= 33u;
|
||||||
h += ri.did.node as uint;
|
h += ri.did.node as uint;
|
||||||
|
for t in ri.tps {
|
||||||
h *= 33u;
|
h *= 33u;
|
||||||
h += ty::type_id(ri.t);
|
h += ty::type_id(t);
|
||||||
ret h;
|
|
||||||
}
|
}
|
||||||
|
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) ->
|
fn mk_global(ccx: @crate_ctxt, name: str, llval: ValueRef, internal: bool) ->
|
||||||
@@ -278,7 +276,7 @@ fn mk_ctxt(llmod: ModuleRef) -> ctxt {
|
|||||||
pad: 0u16,
|
pad: 0u16,
|
||||||
tag_id_to_index: common::new_def_hash(),
|
tag_id_to_index: common::new_def_hash(),
|
||||||
mutable tag_order: [],
|
mutable tag_order: [],
|
||||||
resources: interner::mk(hash_res_info, eq_res_info),
|
resources: interner::mk(hash_res_info, {|a, b| a == b}),
|
||||||
llshapetablesty: llshapetablesty,
|
llshapetablesty: llshapetablesty,
|
||||||
llshapetables: llshapetables};
|
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) {
|
ty::ty_res(did, raw_subt, tps) {
|
||||||
let subt = ty::substitute_type_params(ccx.tcx, tps, raw_subt);
|
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);
|
let id = interner::intern(ccx.shape_cx.resources, ri);
|
||||||
|
|
||||||
s += [shape_res];
|
s += [shape_res];
|
||||||
@@ -553,7 +551,7 @@ fn gen_resource_shapes(ccx: @crate_ctxt) -> ValueRef {
|
|||||||
let len = interner::len(ccx.shape_cx.resources);
|
let len = interner::len(ccx.shape_cx.resources);
|
||||||
while i < len {
|
while i < len {
|
||||||
let ri = interner::get(ccx.shape_cx.resources, i);
|
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;
|
i += 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -289,8 +289,8 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
|
|||||||
item_res(fold_fn_decl(decl, fld),
|
item_res(fold_fn_decl(decl, fld),
|
||||||
fold_ty_params(typms, fld),
|
fold_ty_params(typms, fld),
|
||||||
fld.fold_block(body),
|
fld.fold_block(body),
|
||||||
did,
|
fld.new_id(did),
|
||||||
cid)
|
fld.new_id(cid))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user