From 4650e8bcf404d4c27dbbd5446a56fb066ada30f9 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Thu, 8 Mar 2012 21:16:04 +0100 Subject: [PATCH] Make sure resource destructors are properly monomorphized --- src/rustc/metadata/astencode.rs | 4 +++ src/rustc/metadata/encoder.rs | 9 +++--- src/rustc/metadata/reachable.rs | 20 +++++++++++-- src/rustc/middle/trans/base.rs | 48 ++++++++++++++++++++++++-------- src/rustc/middle/trans/common.rs | 16 ----------- src/rustc/middle/trans/shape.rs | 18 ++++++------ src/rustc/syntax/fold.rs | 4 +-- 7 files changed, 73 insertions(+), 46 deletions(-) diff --git a/src/rustc/metadata/astencode.rs b/src/rustc/metadata/astencode.rs index 007b2ea2e0c..3d54ffe3944 100644 --- a/src/rustc/metadata/astencode.rs +++ b/src/rustc/metadata/astencode.rs @@ -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) { diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 5c6eb30bbeb..6a8a77b1191 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -339,10 +339,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item, } 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 encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item, 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) { diff --git a/src/rustc/metadata/reachable.rs b/src/rustc/metadata/reachable.rs index 9c911807122..1ee2d8eab95 100644 --- a/src/rustc/metadata/reachable.rs +++ b/src/rustc/metadata/reachable.rs @@ -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 @@ type ctx = {ccx: @middle::trans::common::crate_ctxt, 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_inline_body(cx: ctx, body: blk) { 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() + })); +} diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 2babf26b3b7..0dde3983dbd 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -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| diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 6c7b1aa916f..f8932a02250 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -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 diff --git a/src/rustc/middle/trans/shape.rs b/src/rustc/middle/trans/shape.rs index cf774e19acf..b5351321b96 100644 --- a/src/rustc/middle/trans/shape.rs +++ b/src/rustc/middle/trans/shape.rs @@ -21,7 +21,7 @@ import std::map::hashmap; 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; } diff --git a/src/rustc/syntax/fold.rs b/src/rustc/syntax/fold.rs index 9e6ee76db9b..62de1f881ef 100644 --- a/src/rustc/syntax/fold.rs +++ b/src/rustc/syntax/fold.rs @@ -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)) } }; }