use llvm::{self, ValueRef, get_params};
use rustc::hir::def_id::DefId;
-use rustc::ty::subst::Substs;
+use rustc::ty::subst::{Substs, Subst};
use rustc::traits;
use abi::{Abi, FnType};
use attributes;
-use base;
use builder::Builder;
-use common::{self, CrateContext, SharedCrateContext};
+use common::{self, CrateContext};
use cleanup::CleanupScope;
use mir::lvalue::LvalueRef;
use consts;
+use common::instance_ty;
use declare;
use value::Value;
use meth;
-use monomorphize::{self, Instance};
+use monomorphize::Instance;
+use back::symbol_names::symbol_name;
use trans_item::TransItem;
use type_of;
-use Disr;
use rustc::ty::{self, Ty, TypeFoldable};
use rustc::hir;
use std::iter;
#[derive(Debug)]
pub enum CalleeData {
- /// Constructor for enum variant/tuple-like-struct.
- NamedTupleConstructor(Disr),
-
/// Function pointer.
Fn(ValueRef),
return Callee::trait_method(ccx, trait_id, def_id, substs);
}
- let fn_ty = def_ty(ccx.shared(), def_id, substs);
+ let instance = ty::Instance::new(def_id, substs);
+ let fn_ty = instance_ty(ccx.shared(), &instance);
if let ty::TyFnDef(.., f) = fn_ty.sty {
- if f.abi == Abi::RustIntrinsic || f.abi == Abi::PlatformIntrinsic {
+ if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic {
return Callee {
data: Intrinsic,
ty: fn_ty
}
}
- // FIXME(eddyb) Detect ADT constructors more efficiently.
- if let Some(adt_def) = fn_ty.fn_ret().skip_binder().ty_adt_def() {
- if let Some(v) = adt_def.variants.iter().find(|v| def_id == v.did) {
- return Callee {
- data: NamedTupleConstructor(Disr::from(v.disr_val)),
- ty: fn_ty
- };
- }
- }
-
- let (llfn, ty) = get_fn(ccx, def_id, substs);
+ let (llfn, ty) = get_fn(ccx, instance);
Callee::ptr(llfn, ty)
}
match common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref) {
traits::VtableImpl(vtable_impl) => {
let name = tcx.item_name(def_id);
- let (def_id, substs) = traits::find_method(tcx, name, substs, &vtable_impl);
+ let instance = common::find_method(tcx, name, substs, &vtable_impl);
// Translate the function, bypassing Callee::def.
// That is because default methods have the same ID as the
// trait method used to look up the impl method that ended
// up here, so calling Callee::def would infinitely recurse.
- let (llfn, ty) = get_fn(ccx, def_id, substs);
+ let (llfn, ty) = get_fn(ccx, instance);
Callee::ptr(llfn, ty)
}
traits::VtableClosure(vtable_closure) => {
instance,
trait_closure_kind);
- let method_ty = def_ty(ccx.shared(), def_id, substs);
+ let method_ty = instance_ty(ccx.shared(), &instance);
Callee::ptr(llfn, method_ty)
}
traits::VtableFnPointer(vtable_fn_pointer) => {
trait_closure_kind,
vtable_fn_pointer.fn_ty);
- let method_ty = def_ty(ccx.shared(), def_id, substs);
+ let method_ty = instance_ty(ccx.shared(), &instance);
Callee::ptr(llfn, method_ty)
}
traits::VtableObject(ref data) => {
Callee {
data: Virtual(tcx.get_vtable_index_of_object_method(data, def_id)),
- ty: def_ty(ccx.shared(), def_id, substs)
+ ty: instance_ty(ccx.shared(), &Instance::new(def_id, substs))
}
}
vtable => {
/// The extra argument types are for variadic (extern "C") functions.
pub fn direct_fn_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>,
extra_args: &[Ty<'tcx>]) -> FnType {
- let abi = self.ty.fn_abi();
- let sig = ccx.tcx().erase_late_bound_regions_and_normalize(self.ty.fn_sig());
- let mut fn_ty = FnType::unadjusted(ccx, abi, &sig, extra_args);
+ let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&self.ty.fn_sig());
+ let mut fn_ty = FnType::unadjusted(ccx, sig, extra_args);
if let Virtual(_) = self.data {
// Don't pass the vtable, it's not an argument of the virtual fn.
fn_ty.args[1].ignore();
}
- fn_ty.adjust_for_abi(ccx, abi, &sig);
+ fn_ty.adjust_for_abi(ccx, sig);
fn_ty
}
match self.data {
Fn(llfn) => llfn,
Virtual(_) => meth::trans_object_shim(ccx, self),
- NamedTupleConstructor(disr) => match self.ty.sty {
- ty::TyFnDef(def_id, substs, _) => {
- let instance = Instance::new(def_id, substs);
- if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
- return llfn;
- }
-
- let sym = ccx.symbol_map().get_or_compute(ccx.shared(),
- TransItem::Fn(instance));
- assert!(!ccx.codegen_unit().contains_item(&TransItem::Fn(instance)));
- let lldecl = declare::define_internal_fn(ccx, &sym, self.ty);
- base::trans_ctor_shim(ccx, def_id, substs, disr, lldecl);
- ccx.instances().borrow_mut().insert(instance, lldecl);
-
- lldecl
- }
- _ => bug!("expected fn item type, found {}", self.ty)
- },
Intrinsic => bug!("intrinsic {} getting reified", self.ty)
}
}
}
-/// Given a DefId and some Substs, produces the monomorphic item type.
-fn def_ty<'a, 'tcx>(shared: &SharedCrateContext<'a, 'tcx>,
- def_id: DefId,
- substs: &'tcx Substs<'tcx>)
- -> Ty<'tcx> {
- let ty = shared.tcx().item_type(def_id);
- monomorphize::apply_param_substs(shared, substs, &ty)
-}
-
-
fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
def_id: DefId,
substs: ty::ClosureSubsts<'tcx>,
-> ValueRef
{
// If this is a closure, redirect to it.
- let (llfn, _) = get_fn(ccx, def_id, substs.substs);
+ let (llfn, _) = get_fn(ccx, Instance::new(def_id, substs.substs));
// If the closure is a Fn closure, but a FnOnce is needed (etc),
// then adapt the self type
let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), closure_ty);
// Make a version with the type of by-ref closure.
- let ty::ClosureTy { unsafety, abi, mut sig } = tcx.closure_type(def_id, substs);
- sig.0 = tcx.mk_fn_sig(
- iter::once(ref_closure_ty).chain(sig.0.inputs().iter().cloned()),
- sig.0.output(),
- sig.0.variadic
- );
- let llref_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
- unsafety: unsafety,
- abi: abi,
- sig: sig.clone()
- }));
+ let sig = tcx.closure_type(def_id).subst(tcx, substs.substs);
+ let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
+ assert_eq!(sig.abi, Abi::RustCall);
+ let llref_fn_ty = tcx.mk_fn_ptr(ty::Binder(tcx.mk_fn_sig(
+ iter::once(ref_closure_ty).chain(sig.inputs().iter().cloned()),
+ sig.output(),
+ sig.variadic,
+ sig.unsafety,
+ Abi::RustCall
+ )));
debug!("trans_fn_once_adapter_shim: llref_fn_ty={:?}",
llref_fn_ty);
// Make a version of the closure type with the same arguments, but
// with argument #0 being by value.
- assert_eq!(abi, Abi::RustCall);
- sig.0 = tcx.mk_fn_sig(
- iter::once(closure_ty).chain(sig.0.inputs().iter().skip(1).cloned()),
- sig.0.output(),
- sig.0.variadic
+ let sig = tcx.mk_fn_sig(
+ iter::once(closure_ty).chain(sig.inputs().iter().cloned()),
+ sig.output(),
+ sig.variadic,
+ sig.unsafety,
+ Abi::RustCall
);
- let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
- let fn_ty = FnType::new(ccx, abi, &sig, &[]);
-
- let llonce_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
- unsafety: unsafety,
- abi: abi,
- sig: ty::Binder(sig)
- }));
+ let fn_ty = FnType::new(ccx, sig, &[]);
+ let llonce_fn_ty = tcx.mk_fn_ptr(ty::Binder(sig));
// Create the by-value helper.
- let function_name = method_instance.symbol_name(ccx.shared());
+ let function_name = symbol_name(method_instance, ccx.shared());
let lloncefn = declare::define_internal_fn(ccx, &function_name, llonce_fn_ty);
attributes::set_frame_pointer_elimination(ccx, lloncefn);
// Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`,
// which is the fn pointer, and `args`, which is the arguments tuple.
- let sig = match bare_fn_ty.sty {
- ty::TyFnDef(..,
- &ty::BareFnTy { unsafety: hir::Unsafety::Normal,
- abi: Abi::Rust,
- ref sig }) |
- ty::TyFnPtr(&ty::BareFnTy { unsafety: hir::Unsafety::Normal,
- abi: Abi::Rust,
- ref sig }) => sig,
-
- _ => {
- bug!("trans_fn_pointer_shim invoked on invalid type: {}",
- bare_fn_ty);
- }
- };
- let sig = tcx.erase_late_bound_regions_and_normalize(sig);
+ let sig = bare_fn_ty.fn_sig();
+ let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
+ assert_eq!(sig.unsafety, hir::Unsafety::Normal);
+ assert_eq!(sig.abi, Abi::Rust);
let tuple_input_ty = tcx.intern_tup(sig.inputs(), false);
let sig = tcx.mk_fn_sig(
[bare_fn_ty_maybe_ref, tuple_input_ty].iter().cloned(),
sig.output(),
- false
+ false,
+ hir::Unsafety::Normal,
+ Abi::RustCall
);
- let fn_ty = FnType::new(ccx, Abi::RustCall, &sig, &[]);
- let tuple_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
- unsafety: hir::Unsafety::Normal,
- abi: Abi::RustCall,
- sig: ty::Binder(sig)
- }));
+ let fn_ty = FnType::new(ccx, sig, &[]);
+ let tuple_fn_ty = tcx.mk_fn_ptr(ty::Binder(sig));
debug!("tuple_fn_ty: {:?}", tuple_fn_ty);
//
- let function_name = method_instance.symbol_name(ccx.shared());
+ let function_name = symbol_name(method_instance, ccx.shared());
let llfn = declare::define_internal_fn(ccx, &function_name, tuple_fn_ty);
attributes::set_frame_pointer_elimination(ccx, llfn);
//
/// - `def_id`: def id of the fn or method item being referenced
/// - `substs`: values for each of the fn/method's parameters
fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
- def_id: DefId,
- substs: &'tcx Substs<'tcx>)
+ instance: Instance<'tcx>)
-> (ValueRef, Ty<'tcx>) {
let tcx = ccx.tcx();
- debug!("get_fn(def_id={:?}, substs={:?})", def_id, substs);
-
- assert!(!substs.needs_infer());
- assert!(!substs.has_escaping_regions());
- assert!(!substs.has_param_types());
+ debug!("get_fn(instance={:?})", instance);
- let substs = tcx.normalize_associated_type(&substs);
- let instance = Instance::new(def_id, substs);
- let item_ty = ccx.tcx().item_type(def_id);
- let fn_ty = monomorphize::apply_param_substs(ccx.shared(), substs, &item_ty);
+ assert!(!instance.substs.needs_infer());
+ assert!(!instance.substs.has_escaping_regions());
+ assert!(!instance.substs.has_param_types());
+ let fn_ty = common::instance_ty(ccx.shared(), &instance);
if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
return (llfn, fn_ty);
}
// other weird situations. Annoying.
// Create a fn pointer with the substituted signature.
- let fn_ptr_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(common::ty_fn_ty(ccx, fn_ty).into_owned()));
+ let fn_ptr_ty = tcx.mk_fn_ptr(common::ty_fn_sig(ccx, fn_ty));
let llptrty = type_of::type_of(ccx, fn_ptr_ty);
let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
assert_eq!(common::val_ty(llfn), llptrty);
debug!("get_fn: not casting pointer!");
- let attrs = ccx.tcx().get_attrs(def_id);
+ let attrs = instance.def.attrs(ccx.tcx());
attributes::from_fn_attrs(ccx, &attrs, llfn);
let is_local_def = ccx.shared().translation_items().borrow()
llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
}
}
- if ccx.use_dll_storage_attrs() && ccx.sess().cstore.is_dllimport_foreign_item(def_id) {
+ if ccx.use_dll_storage_attrs() &&
+ ccx.sess().cstore.is_dllimport_foreign_item(instance.def_id())
+ {
unsafe {
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
}