about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorTim Chevalier <chevalier@alum.wellesley.edu>2012-06-19 14:44:38 -0700
committerTim Chevalier <chevalier@alum.wellesley.edu>2012-06-20 20:12:14 -0700
commitb02172971fa658f2e6d3cdb3cbf3bf663801d656 (patch)
tree00fac80cda795ef11ffb6af11e11cd80ed1c3cd9 /src/rustc
parent00171165205a1d5222563d0e2bdf7f970758b388 (diff)
downloadrust-b02172971fa658f2e6d3cdb3cbf3bf663801d656.tar.gz
rust-b02172971fa658f2e6d3cdb3cbf3bf663801d656.zip
Make trans give correct types to monomorphic dtors
Irritatingly, class dtors have a different type from resource
dtors (because class dtors have a self argument), and the monomorphic
case wasn't reflecting that. Fixed.
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/middle/trans/base.rs32
-rw-r--r--src/rustc/middle/trans/shape.rs15
-rw-r--r--src/rustc/middle/trans/type_of.rs7
3 files changed, 41 insertions, 13 deletions
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 8eab69b1133..47baa8aebca 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -754,7 +754,8 @@ fn trans_class_drop(bcx: block, v0: ValueRef, dtor_did: ast::def_id,
       // We have to cast v0
      let classptr = GEPi(bcx, v0, [0u, 1u]);
      // Find and call the actual destructor
-     let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did, substs.tps);
+     let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did, some(class_did),
+                                  substs.tps);
      // The second argument is the "self" argument for drop
      let params = lib::llvm::fn_ty_param_tys
          (llvm::LLVMGetElementType
@@ -829,7 +830,11 @@ 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])
+fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id,
+                // Parent ID is an option because resources don't
+                // have one. We can make this a def_id when
+                // resources get removed.
+                opt_id: option<ast::def_id>, substs: [ty::t])
    -> ValueRef {
     let _icx = ccx.insn_ctxt("trans_res_dtor");
     if (substs.len() > 0u) {
@@ -841,14 +846,27 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, substs: [ty::t])
     } else if did.crate == ast::local_crate {
         get_item_val(ccx, did.node)
     } else {
-        let fty = ty::mk_fn(ccx.tcx, {purity: ast::impure_fn,
-                                      proto: ast::proto_bare,
-                                      inputs: [{mode: ast::expl(ast::by_ref),
+        alt opt_id {
+           some(parent_id) {
+             let tcx = ccx.tcx;
+             let name = csearch::get_symbol(ccx.sess.cstore, did);
+             let class_ty = ty::subst_tps(tcx, substs,
+                              ty::lookup_item_type(tcx, parent_id).ty);
+             let llty = type_of_dtor(ccx, class_ty);
+             get_extern_fn(ccx.externs, ccx.llmod, name, lib::llvm::CCallConv,
+                           llty)
+           }
+           none {
+             let fty = ty::mk_fn(ccx.tcx, {purity: ast::impure_fn,
+                                       proto: ast::proto_bare,
+                                     inputs: [{mode: ast::expl(ast::by_ref),
                                                 ty: ty::mk_nil_ptr(ccx.tcx)}],
                                       output: ty::mk_nil(ccx.tcx),
                                       ret_style: ast::return_val,
                                       constraints: []});
-        trans_external_path(ccx, did, fty)
+             trans_external_path(ccx, did, fty)
+           }
+      }
     }
 }
 
@@ -862,7 +880,7 @@ fn trans_res_drop(bcx: block, rs: ValueRef, did: ast::def_id,
     with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag))) {|bcx|
         let valptr = GEPi(bcx, rs, [0u, 1u]);
         // Find and call the actual destructor.
-        let dtor_addr = get_res_dtor(ccx, did, tps);
+        let dtor_addr = get_res_dtor(ccx, did, none, tps);
         let args = [bcx.fcx.llretptr, null_env_ptr(bcx)];
         // Kludge to work around the fact that we know the precise type of the
         // value here, but the dtor expects a type that might have opaque
diff --git a/src/rustc/middle/trans/shape.rs b/src/rustc/middle/trans/shape.rs
index 61f82997e93..f0d98da5adb 100644
--- a/src/rustc/middle/trans/shape.rs
+++ b/src/rustc/middle/trans/shape.rs
@@ -21,12 +21,14 @@ import std::map::hashmap;
 
 import ty_ctxt = middle::ty::ctxt;
 
-type nominal_id = @{did: ast::def_id, tps: [ty::t]};
+type nominal_id = @{did: ast::def_id, parent_id: option<ast::def_id>,
+                    tps: [ty::t]};
 
 fn mk_nominal_id(tcx: ty::ctxt, did: ast::def_id,
+                 parent_id: option<ast::def_id>,
                  tps: [ty::t]) -> nominal_id {
     let tps_norm = tps.map { |t| ty::normalize_ty(tcx, t) };
-    @{did: did, tps: tps_norm}
+    @{did: did, parent_id: parent_id, tps: tps_norm}
 }
 
 fn hash_nominal_id(&&ri: nominal_id) -> uint {
@@ -233,7 +235,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t) -> [u8] {
           tk_enum { [s_variant_enum_t(ccx.tcx)] }
           tk_newtype | tk_complex {
             let mut s = [shape_enum], id;
-            let nom_id = mk_nominal_id(ccx.tcx, did, substs.tps);
+            let nom_id = mk_nominal_id(ccx.tcx, did, none, substs.tps);
             alt ccx.shape_cx.tag_id_to_index.find(nom_id) {
               none {
                 id = ccx.shape_cx.next_tag_id;
@@ -335,7 +337,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t) -> [u8] {
           else { [shape_struct] };
         let mut sub = [];
         option::iter(m_dtor_did) {|dtor_did|
-          let ri = @{did: dtor_did, tps: tps};
+          let ri = @{did: dtor_did, parent_id: some(did), tps: tps};
           let id = interner::intern(ccx.shape_cx.resources, ri);
           add_u16(s, id as u16);
 
@@ -362,7 +364,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t) -> [u8] {
         for substs.tps.each() {|t| assert !ty::type_has_params(t); }
         let subt = ty::subst(ccx.tcx, substs, raw_subt);
         let tps = substs.tps;
-        let ri = @{did: did, tps: tps};
+        let ri = @{did: did, parent_id: none, tps: tps};
         let id = interner::intern(ccx.shape_cx.resources, ri);
 
         let mut s = [shape_res];
@@ -597,7 +599,8 @@ fn gen_resource_shapes(ccx: @crate_ctxt) -> ValueRef {
     for uint::range(0u, len) {|i|
         let ri = interner::get(ccx.shape_cx.resources, i);
         for ri.tps.each() {|s| assert !ty::type_has_params(s); }
-        dtors += [trans::base::get_res_dtor(ccx, ri.did, ri.tps)];
+        dtors += [trans::base::get_res_dtor(ccx, ri.did, ri.parent_id,
+                                            ri.tps)];
     }
     ret mk_global(ccx, "resource_shapes", C_struct(dtors), true);
 }
diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs
index c0f3014cf96..dc8dc1b92cf 100644
--- a/src/rustc/middle/trans/type_of.rs
+++ b/src/rustc/middle/trans/type_of.rs
@@ -8,6 +8,7 @@ import std::map::hashmap;
 import ty::*;
 
 export type_of;
+export type_of_dtor;
 export type_of_explicit_args;
 export type_of_fn_from_ty;
 export type_of_fn;
@@ -251,3 +252,9 @@ fn llvm_type_name(cx: @crate_ctxt, t: ty::t) -> str {
     );
 }
 
+fn type_of_dtor(ccx: @crate_ctxt, self_ty: ty::t) -> TypeRef {
+    T_fn([T_ptr(type_of(ccx, ty::mk_nil(ccx.tcx))),
+          T_ptr(type_of(ccx, self_ty))],
+         llvm::LLVMVoidType())
+}
+