]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_trans/callee.rs
move Instance to rustc and use it in the collector
[rust.git] / src / librustc_trans / callee.rs
index 4a8658dd2e308a86d2bec71d3c0a890102c6979a..19fc4e013fae1f7f401f534894c78223a9723005 100644 (file)
 
 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;
@@ -45,9 +45,6 @@
 
 #[derive(Debug)]
 pub enum CalleeData {
-    /// Constructor for enum variant/tuple-like-struct.
-    NamedTupleConstructor(Disr),
-
     /// Function pointer.
     Fn(ValueRef),
 
@@ -81,9 +78,10 @@ pub fn def<'a>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId, substs: &'tcx Substs
             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
@@ -91,17 +89,7 @@ pub fn def<'a>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId, substs: &'tcx Substs
             }
         }
 
-        // 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)
     }
 
@@ -118,13 +106,13 @@ pub fn trait_method<'a>(ccx: &CrateContext<'a, 'tcx>,
         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) => {
@@ -139,7 +127,7 @@ pub fn trait_method<'a>(ccx: &CrateContext<'a, 'tcx>,
                     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) => {
@@ -149,13 +137,13 @@ pub fn trait_method<'a>(ccx: &CrateContext<'a, 'tcx>,
                                                  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 => {
@@ -169,14 +157,13 @@ pub fn trait_method<'a>(ccx: &CrateContext<'a, 'tcx>,
     /// 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
     }
 
@@ -185,39 +172,11 @@ pub fn reify<'a>(self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
         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>,
@@ -226,7 +185,7 @@ fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, '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
@@ -307,41 +266,35 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
     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);
 
@@ -470,37 +423,24 @@ fn trans_fn_pointer_shim<'a, 'tcx>(
 
     // 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);
     //
@@ -551,22 +491,17 @@ fn trans_fn_pointer_shim<'a, 'tcx>(
 /// - `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);
     }
@@ -600,7 +535,7 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     // 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) {
@@ -616,7 +551,7 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         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()
@@ -628,7 +563,9 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 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);
             }