summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-03-08 21:16:04 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-03-15 09:32:53 +0100
commit4650e8bcf404d4c27dbbd5446a56fb066ada30f9 (patch)
tree7039da7407e5c71f1c0f3f2f0da0f2a98bb4d032 /src
parent8f84d4c8b6305c960cf51c35a5ea38697d7fa530 (diff)
downloadrust-4650e8bcf404d4c27dbbd5446a56fb066ada30f9.tar.gz
rust-4650e8bcf404d4c27dbbd5446a56fb066ada30f9.zip
Make sure resource destructors are properly monomorphized
Diffstat (limited to 'src')
-rw-r--r--src/rustc/metadata/astencode.rs4
-rw-r--r--src/rustc/metadata/encoder.rs9
-rw-r--r--src/rustc/metadata/reachable.rs20
-rw-r--r--src/rustc/middle/trans/base.rs48
-rw-r--r--src/rustc/middle/trans/common.rs16
-rw-r--r--src/rustc/middle/trans/shape.rs18
-rw-r--r--src/rustc/syntax/fold.rs4
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))
           }
         };
 }