about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_trans/cabi_x86.rs55
-rw-r--r--src/test/codegen/fastcall-inreg.rs85
2 files changed, 110 insertions, 30 deletions
diff --git a/src/librustc_trans/cabi_x86.rs b/src/librustc_trans/cabi_x86.rs
index ae8b610882b..fea005f3d77 100644
--- a/src/librustc_trans/cabi_x86.rs
+++ b/src/librustc_trans/cabi_x86.rs
@@ -61,46 +61,41 @@ pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType, flavor: Flavor) {
     if flavor == Flavor::Fastcall {
         // Mark arguments as InReg like clang does it,
         // so our fastcall is compatible with C/C++ fastcall.
-        // Clang reference: ib/CodeGen/TargetInfo.cpp
-        let is_mcu_abi = ccx.sess().target.target.target_os.eq("elfiamcu");
-        let is_soft_float_abi = ccx.sess().target.target.options.features.contains("+soft-float");
+
+        // Clang reference: lib/CodeGen/TargetInfo.cpp
+        // See X86_32ABIInfo::shouldPrimitiveUseInReg(), X86_32ABIInfo::updateFreeRegs()
+
+        // IsSoftFloatABI is only set to true on ARM platforms,
+        // which in turn can't be x86?
 
         let mut free_regs = 2;
 
         for arg in &mut fty.args {
-            if !arg.is_ignore() && !arg.is_indirect() {
-                if !is_soft_float_abi {
-                    if arg.ty.kind() == Float {
-                        continue;
-                    }
-                }
+            if arg.is_ignore() || arg.is_indirect() { continue; }
 
-                let size = llbitsize_of_real(ccx, arg.ty);
-                let size_in_regs = (size + 31) / 32;
+            if arg.ty.kind() == Float {
+                continue;
+            }
 
-                if size_in_regs == 0 {
-                    continue;
-                }
+            let size = llbitsize_of_real(ccx, arg.ty);
+            let size_in_regs = (size + 31) / 32;
 
-                if !is_mcu_abi {
-                    if size_in_regs > free_regs {
-                        break;
-                    }
-                } else {
-                    if size_in_regs > free_regs || size_in_regs > 2 {
-                        continue;
-                    }
-                }
+            if size_in_regs == 0 {
+                continue;
+            }
 
-                free_regs -= size_in_regs;
+            if size_in_regs > free_regs {
+                break;
+            }
 
-                if !is_mcu_abi && size <= 32 && (arg.ty.kind() == Pointer || arg.ty.kind() == Integer) {
-                    arg.attrs.set(ArgAttribute::InReg);
-                }
+            free_regs -= size_in_regs;
 
-                if free_regs == 0 {
-                    break;
-                }
+            if size <= 32 && (arg.ty.kind() == Pointer || arg.ty.kind() == Integer) {
+                arg.attrs.set(ArgAttribute::InReg);
+            }
+
+            if free_regs == 0 {
+                break;
             }
         }
     }
diff --git a/src/test/codegen/fastcall-inreg.rs b/src/test/codegen/fastcall-inreg.rs
new file mode 100644
index 00000000000..e1dda4d2be0
--- /dev/null
+++ b/src/test/codegen/fastcall-inreg.rs
@@ -0,0 +1,85 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Checks if the "fastcall" calling convention marks function arguments
+// as "inreg" like the C/C++ compilers for the platforms.
+// x86 only.
+
+// ignore-aarch64
+// ignore-aarch64_be
+// ignore-arm
+// ignore-armeb
+// ignore-avr
+// ignore-bpfel
+// ignore-bpfeb
+// ignore-hexagon
+// ignore-mips
+// ignore-mipsel
+// ignore-mips64
+// ignore-mips64el
+// ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-powerpc
+// ignore-r600
+// ignore-amdgcn
+// ignore-sparc
+// ignore-sparcv9
+// ignore-sparcel
+// ignore-s390x
+// ignore-tce
+// ignore-thumb
+// ignore-thumbeb
+// ignore-x86_64 no-ignore-x86
+// ignore-xcore
+// ignore-nvptx
+// ignore-nvptx64
+// ignore-le32
+// ignore-le64
+// ignore-amdil
+// ignore-amdil64
+// ignore-hsail
+// ignore-hsail64
+// ignore-spir
+// ignore-spir64
+// ignore-kalimba
+// ignore-shave
+// ignore-wasm32
+// ignore-wasm64
+
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+mod tests {
+    // CHECK: @f1(i32 inreg, i32 inreg, i32)
+    #[no_mangle]
+    extern "fastcall" fn f1(_: i32, _: i32, _: i32) {}
+
+    // CHECK: @f2(i32* inreg, i32* inreg, i32*)
+    #[no_mangle]
+    extern "fastcall" fn f2(_: *const i32, _: *const i32, _: *const i32) {}
+
+    // CHECK: @f3(float, i32 inreg, i32 inreg, i32)
+    #[no_mangle]
+    extern "fastcall" fn f3(_: f32, _: i32, _: i32, _: i32) {}
+
+    // CHECK: @f4(i32 inreg, float, i32 inreg, i32)
+    #[no_mangle]
+    extern "fastcall" fn f4(_: i32, _: f32, _: i32, _: i32) {}
+
+    // CHECK: @f5(i64, i32)
+    #[no_mangle]
+    extern "fastcall" fn f5(_: i64, _: i32) {}
+
+    // CHECK: @f6(i1 inreg zeroext, i32 inreg, i32)
+    #[no_mangle]
+    extern "fastcall" fn f6(_: bool, _: i32, _: i32) {}
+}