diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 8eab69b1133dcbeab5cac09c9ed452c7967e71e9..47baa8aebca52546cea0f52c7a781b0941ca9807 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, 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 61f82997e93672fb1548ad35aabb28b93380593b..f0d98da5adb9c91f801c93155fb45444339b7ea8 100644 --- a/src/rustc/middle/trans/shape.rs +++ b/src/rustc/middle/trans/shape.rs @@ -21,12 +21,14 @@ 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, + tps: [ty::t]}; fn mk_nominal_id(tcx: ty::ctxt, did: ast::def_id, + parent_id: option, 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 c0f3014cf961ee75fe28535a30128f4a36622344..dc8dc1b92cf362b939a1ceab64bb4f350c55d46c 100644 --- a/src/rustc/middle/trans/type_of.rs +++ b/src/rustc/middle/trans/type_of.rs @@ -8,6 +8,7 @@ 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()) +} +