use rustc::hir::map as hir_map;
use rustc::hir::def_id::DefId;
-use rustc::middle::lang_items::{ExchangeFreeFnLangItem, ExchangeMallocFnLangItem};
+use rustc::middle::lang_items::{BoxFreeFnLangItem, ExchangeMallocFnLangItem};
use rustc::traits;
-use rustc::ty::subst::{Substs, Subst};
+use rustc::ty::subst::{Kind, Substs, Subst};
use rustc::ty::{self, TypeFoldable, TyCtxt};
use rustc::ty::adjustment::CustomCoerceUnsized;
use rustc::mir::{self, Location};
use trans_item::{TransItem, DefPathBasedNames};
+use std::iter;
+
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
pub enum TransItemCollectionMode {
Eager,
debug!("find_drop_glue_neighbors: {}", type_to_string(scx.tcx(), ty));
- // Make sure the exchange_free_fn() lang-item gets translated if
- // there is a boxed value.
- if let ty::TyBox(_) = ty.sty {
- let exchange_free_fn_def_id = scx.tcx()
- .lang_items
- .require(ExchangeFreeFnLangItem)
- .unwrap_or_else(|e| scx.sess().fatal(&e));
-
- assert!(can_have_local_instance(scx.tcx(), exchange_free_fn_def_id));
- let fn_substs = scx.empty_substs_for_def_id(exchange_free_fn_def_id);
- let exchange_free_fn_trans_item =
+ // Make sure the BoxFreeFn lang-item gets translated if there is a boxed value.
+ if let ty::TyBox(content_type) = ty.sty {
+ let def_id = scx.tcx().require_lang_item(BoxFreeFnLangItem);
+ assert!(can_have_local_instance(scx.tcx(), def_id));
+ let box_free_fn_trans_item =
create_fn_trans_item(scx,
- exchange_free_fn_def_id,
- fn_substs,
+ def_id,
+ scx.tcx().mk_substs(iter::once(Kind::from(content_type))),
scx.tcx().intern_substs(&[]));
- output.push(exchange_free_fn_trans_item);
+ output.push(box_free_fn_trans_item);
}
// If the type implements Drop, also add a translation item for the
// Code relating to drop glue.
use std;
+use std::iter;
use llvm;
use llvm::{ValueRef, get_param};
-use middle::lang_items::ExchangeFreeFnLangItem;
+use middle::lang_items::BoxFreeFnLangItem;
use rustc::ty::subst::{Substs};
use rustc::traits;
use rustc::ty::{self, AdtKind, Ty, TypeFoldable};
+use rustc::ty::subst::Kind;
use adt::{self, MaybeSizedValue};
use base::*;
use callee::Callee;
use syntax_pos::DUMMY_SP;
-pub fn trans_exchange_free_dyn<'a, 'tcx>(
+pub fn trans_exchange_free_ty<'a, 'tcx>(
bcx: &BlockAndBuilder<'a, 'tcx>,
- v: ValueRef,
- size: ValueRef,
- align: ValueRef
+ ptr: MaybeSizedValue,
+ content_ty: Ty<'tcx>
) {
- let def_id = langcall(bcx.tcx(), None, "", ExchangeFreeFnLangItem);
- let args = [bcx.pointercast(v, Type::i8p(bcx.ccx)), size, align];
- let callee = Callee::def(bcx.ccx, def_id, bcx.tcx().intern_substs(&[]));
+ let def_id = langcall(bcx.tcx(), None, "", BoxFreeFnLangItem);
+ let substs = bcx.tcx().mk_substs(iter::once(Kind::from(content_ty)));
+ let callee = Callee::def(bcx.ccx, def_id, substs);
- let ccx = bcx.ccx;
- let fn_ty = callee.direct_fn_type(ccx, &[]);
+ let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
- let llret = bcx.call(callee.reify(ccx), &args[..], None);
+ let llret = bcx.call(callee.reify(bcx.ccx),
+ &[ptr.value, ptr.meta][..1 + ptr.has_meta() as usize], None);
fn_ty.apply_attrs_callsite(llret);
}
-pub fn trans_exchange_free_ty<'a, 'tcx>(
- bcx: &BlockAndBuilder<'a, 'tcx>, ptr: ValueRef, content_ty: Ty<'tcx>
-) {
- assert!(bcx.ccx.shared().type_is_sized(content_ty));
- let sizing_type = sizing_type_of(bcx.ccx, content_ty);
- let content_size = llsize_of_alloc(bcx.ccx, sizing_type);
-
- // `Box<ZeroSizeType>` does not allocate.
- if content_size != 0 {
- let content_align = align_of(bcx.ccx, content_ty);
- let ccx = bcx.ccx;
- trans_exchange_free_dyn(bcx, ptr, C_uint(ccx, content_size), C_uint(ccx, content_align));
- }
-}
-
pub fn get_drop_glue_type<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty<'tcx> {
assert!(t.is_normalized_for_trans());
// special. It may move to library and have Drop impl. As
// a safe-guard, assert TyBox not used with TyContents.
assert!(!skip_dtor);
- if !bcx.ccx.shared().type_is_sized(content_ty) {
+ let ptr = if !bcx.ccx.shared().type_is_sized(content_ty) {
let llbox = bcx.load(get_dataptr(&bcx, ptr.value));
let info = bcx.load(get_meta(&bcx, ptr.value));
- drop_ty(&bcx, MaybeSizedValue::unsized_(llbox, info), content_ty);
- let (llsize, llalign) = size_and_align_of_dst(&bcx, content_ty, info);
-
- // `Box<ZeroSizeType>` does not allocate.
- let needs_free = bcx.icmp(llvm::IntNE, llsize, C_uint(bcx.ccx, 0u64));
- if const_to_opt_uint(needs_free) == Some(0) {
- bcx
- } else {
- let next_cx = bcx.fcx().build_new_block("next");
- let cond_cx = bcx.fcx().build_new_block("cond");
- bcx.cond_br(needs_free, cond_cx.llbb(), next_cx.llbb());
- trans_exchange_free_dyn(&cond_cx, llbox, llsize, llalign);
- cond_cx.br(next_cx.llbb());
- next_cx
- }
+ MaybeSizedValue::unsized_(llbox, info)
} else {
- let llbox = bcx.load(ptr.value);
- drop_ty(&bcx, MaybeSizedValue::sized(llbox), content_ty);
- trans_exchange_free_ty(&bcx, llbox, content_ty);
- bcx
- }
+ MaybeSizedValue::sized(bcx.load(ptr.value))
+ };
+ drop_ty(&bcx, ptr, content_ty);
+ trans_exchange_free_ty(&bcx, ptr, content_ty);
+ bcx
}
ty::TyDynamic(..) => {
// No support in vtable for distinguishing destroying with