about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2016-03-06 12:38:46 +0200
committerEduard Burtescu <edy.burt@gmail.com>2016-03-17 21:51:52 +0200
commit9e036c0ff0e8ba6018f9e0240064f7f7cf26885f (patch)
treeee3726ffd2f486fed3a0dc760e0ef5c5eea24537
parent80d939fd22361cc8652cd4d7006fd1964d9ab699 (diff)
trans: Provide the FnType for a direct call via Callee::direct_fn_type.
-rw-r--r--src/librustc_trans/trans/abi.rs70
-rw-r--r--src/librustc_trans/trans/callee.rs17
2 files changed, 55 insertions, 32 deletions
diff --git a/src/librustc_trans/trans/abi.rs b/src/librustc_trans/trans/abi.rs
index bd5de8efc19..6345395d441 100644
--- a/src/librustc_trans/trans/abi.rs
+++ b/src/librustc_trans/trans/abi.rs
@@ -150,17 +150,18 @@ impl FnType {
                          abi: Abi,
                          sig: &ty::FnSig<'tcx>,
                          extra_args: &[Ty<'tcx>]) -> FnType {
+        let mut fn_ty = FnType::unadjusted(ccx, abi, sig, extra_args);
+        fn_ty.adjust_for_abi(ccx, abi, sig);
+        fn_ty
+    }
+
+    pub fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                abi: Abi,
+                                sig: &ty::FnSig<'tcx>,
+                                extra_args: &[Ty<'tcx>]) -> FnType {
         use self::Abi::*;
         let cconv = match ccx.sess().target.target.adjust_abi(abi) {
-            RustIntrinsic => {
-                // Intrinsics are emitted at the call site
-                ccx.sess().bug("asked to compute FnType of intrinsic");
-            }
-            PlatformIntrinsic => {
-                // Intrinsics are emitted at the call site
-                ccx.sess().bug("asked to compute FnType of platform intrinsic");
-            }
-
+            RustIntrinsic | PlatformIntrinsic |
             Rust | RustCall => llvm::CCallConv,
 
             // It's the ABI's job to select this, not us.
@@ -309,14 +310,20 @@ impl FnType {
             }
         }
 
-        let mut fty = FnType {
+        FnType {
             args: args,
             ret: ret,
             variadic: sig.variadic,
             cconv: cconv
-        };
+        }
+    }
 
-        if abi == Rust || abi == RustCall {
+    pub fn adjust_for_abi<'a, 'tcx>(&mut self,
+                                    ccx: &CrateContext<'a, 'tcx>,
+                                    abi: Abi,
+                                    sig: &ty::FnSig<'tcx>) {
+        if abi == Abi::Rust || abi == Abi::RustCall ||
+           abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
             let fixup = |arg: &mut ArgType| {
                 if !arg.ty.is_aggregate() {
                     // Scalars and vectors, always immediate.
@@ -332,49 +339,48 @@ impl FnType {
                     arg.cast = Some(Type::ix(ccx, size * 8));
                 }
             };
-            if fty.ret.ty != Type::void(ccx) {
-                // Fat pointers are returned by-value.
+            // Fat pointers are returned by-value.
+            if !self.ret.is_ignore() {
                 if !type_is_fat_ptr(ccx.tcx(), sig.output.unwrap()) {
-                    fixup(&mut fty.ret);
+                    fixup(&mut self.ret);
                 }
             }
-            for arg in &mut fty.args {
+            for arg in &mut self.args {
+                if arg.is_ignore() { continue; }
                 fixup(arg);
             }
-            if fty.ret.is_indirect() {
-                fty.ret.attrs.set(llvm::Attribute::StructRet);
+            if self.ret.is_indirect() {
+                self.ret.attrs.set(llvm::Attribute::StructRet);
             }
-            return fty;
+            return;
         }
 
         match &ccx.sess().target.target.arch[..] {
-            "x86" => cabi_x86::compute_abi_info(ccx, &mut fty),
+            "x86" => cabi_x86::compute_abi_info(ccx, self),
             "x86_64" => if ccx.sess().target.target.options.is_like_windows {
-                cabi_x86_win64::compute_abi_info(ccx, &mut fty);
+                cabi_x86_win64::compute_abi_info(ccx, self);
             } else {
-                cabi_x86_64::compute_abi_info(ccx, &mut fty);
+                cabi_x86_64::compute_abi_info(ccx, self);
             },
-            "aarch64" => cabi_aarch64::compute_abi_info(ccx, &mut fty),
+            "aarch64" => cabi_aarch64::compute_abi_info(ccx, self),
             "arm" => {
                 let flavor = if ccx.sess().target.target.target_os == "ios" {
                     cabi_arm::Flavor::Ios
                 } else {
                     cabi_arm::Flavor::General
                 };
-                cabi_arm::compute_abi_info(ccx, &mut fty, flavor);
+                cabi_arm::compute_abi_info(ccx, self, flavor);
             },
-            "mips" => cabi_mips::compute_abi_info(ccx, &mut fty),
-            "powerpc" => cabi_powerpc::compute_abi_info(ccx, &mut fty),
-            "powerpc64" => cabi_powerpc64::compute_abi_info(ccx, &mut fty),
-            "asmjs" => cabi_asmjs::compute_abi_info(ccx, &mut fty),
+            "mips" => cabi_mips::compute_abi_info(ccx, self),
+            "powerpc" => cabi_powerpc::compute_abi_info(ccx, self),
+            "powerpc64" => cabi_powerpc64::compute_abi_info(ccx, self),
+            "asmjs" => cabi_asmjs::compute_abi_info(ccx, self),
             a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
         }
 
-        if fty.ret.is_indirect() {
-            fty.ret.attrs.set(llvm::Attribute::StructRet);
+        if self.ret.is_indirect() {
+            self.ret.attrs.set(llvm::Attribute::StructRet);
         }
-
-        fty
     }
 
     pub fn llvm_type(&self, ccx: &CrateContext) -> Type {
diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs
index 9236d29ca72..1d302b65f9c 100644
--- a/src/librustc_trans/trans/callee.rs
+++ b/src/librustc_trans/trans/callee.rs
@@ -210,6 +210,23 @@ impl<'tcx> Callee<'tcx> {
         }
     }
 
+    /// Get the abi::FnType for a direct call. Mainly deals with the fact
+    /// that a Virtual call doesn't take the vtable, like its shim does.
+    /// 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(self.ty.fn_sig());
+        let sig = infer::normalize_associated_type(ccx.tcx(), &sig);
+        let mut fn_ty = FnType::unadjusted(ccx, abi, &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
+    }
+
     /// This behemoth of a function translates function calls. Unfortunately, in
     /// order to generate more efficient LLVM output at -O0, it has quite a complex
     /// signature (refactoring this into two functions seems like a good idea).