about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCensoredUsername <cens.username@gmail.com>2016-08-27 15:14:51 +0200
committerCensoredUsername <cens.username@gmail.com>2016-08-30 16:03:06 +0200
commit0e58a5d139772404ab936b6c7679e9ff936101c4 (patch)
tree2453b34c80fde922db92e9fb212730d6f5bba2a7
parent30c4173cb8f942afbb1588174e5867eb780cdaa0 (diff)
downloadrust-0e58a5d139772404ab936b6c7679e9ff936101c4.tar.gz
rust-0e58a5d139772404ab936b6c7679e9ff936101c4.zip
Feature gate the sysv64 abi as feature(abi_sysv64) and add tests
-rw-r--r--src/libsyntax/feature_gate.rs23
-rw-r--r--src/test/codegen/abi-sysv64.rs24
-rw-r--r--src/test/compile-fail/feature-gate-abi-sysv64.rs19
-rw-r--r--src/test/run-pass/abi-sysv64-register-usage.rs125
4 files changed, 184 insertions, 7 deletions
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 1e15c156356..18924a3dc25 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -281,7 +281,11 @@ declare_features! (
     (active, never_type, "1.13.0", Some(35121)),
 
     // Allows all literals in attribute lists and values of key-value pairs.
-    (active, attr_literals, "1.13.0", Some(34981))
+    (active, attr_literals, "1.13.0", Some(34981)),
+
+    // Allows the sysV64 ABI to be specified on all platforms
+    // instead of just the platforms on which it is the C ABI
+    (active, abi_sysv64, "1.13.0", None)
 );
 
 declare_features! (
@@ -811,21 +815,26 @@ macro_rules! gate_feature_post {
 impl<'a> PostExpansionVisitor<'a> {
     fn check_abi(&self, abi: Abi, span: Span) {
         match abi {
-            Abi::RustIntrinsic =>
+            Abi::RustIntrinsic => {
                 gate_feature_post!(&self, intrinsics, span,
-                                   "intrinsics are subject to change"),
+                                   "intrinsics are subject to change");
+            },
             Abi::PlatformIntrinsic => {
                 gate_feature_post!(&self, platform_intrinsics, span,
-                                   "platform intrinsics are experimental and possibly buggy")
+                                   "platform intrinsics are experimental and possibly buggy");
             },
             Abi::Vectorcall => {
                 gate_feature_post!(&self, abi_vectorcall, span,
-                                   "vectorcall is experimental and subject to change")
-            }
+                                   "vectorcall is experimental and subject to change");
+            },
             Abi::RustCall => {
                 gate_feature_post!(&self, unboxed_closures, span,
                                    "rust-call ABI is subject to change");
-            }
+            },
+            Abi::SysV64 => {
+                gate_feature_post!(&self, abi_sysv64, span,
+                                   "sysv64 ABI is experimental and subject to change");
+            },
             _ => {}
         }
     }
diff --git a/src/test/codegen/abi-sysv64.rs b/src/test/codegen/abi-sysv64.rs
new file mode 100644
index 00000000000..2b8e8a1b6b2
--- /dev/null
+++ b/src/test/codegen/abi-sysv64.rs
@@ -0,0 +1,24 @@
+// 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 correct annotation for the sysv64 ABI is passed to
+// llvm. Also checks that the abi-sysv64 feature gate allows usage
+// of the sysv64 abi.
+
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(abi_sysv64)]
+
+// CHECK: define x86_64_sysvcc i64 @has_sysv64_abi
+#[no_mangle]
+pub extern "sysv64" fn has_sysv64_abi(a: i64) -> i64 {
+    a * 2
+}
diff --git a/src/test/compile-fail/feature-gate-abi-sysv64.rs b/src/test/compile-fail/feature-gate-abi-sysv64.rs
new file mode 100644
index 00000000000..2a4aae8c06b
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-abi-sysv64.rs
@@ -0,0 +1,19 @@
+// 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.
+
+// Test that the sysv64 ABI cannot be used when abi-sysv64 feature
+// gate is not used.
+
+extern "sysv64" fn foo() {}
+//~^ ERROR sysv64 ABI is experimental and subject to change
+
+fn main() {
+    foo();
+}
diff --git a/src/test/run-pass/abi-sysv64-register-usage.rs b/src/test/run-pass/abi-sysv64-register-usage.rs
new file mode 100644
index 00000000000..5e58240359e
--- /dev/null
+++ b/src/test/run-pass/abi-sysv64-register-usage.rs
@@ -0,0 +1,125 @@
+// 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 correct registers are being used to pass arguments
+// when the sysv64 ABI is specified.
+
+#![feature(abi_sysv64)]
+#![feature(naked_functions)]
+#![feature(asm)]
+
+#[naked]
+#[inline(never)]
+#[allow(unused_variables)]
+pub unsafe extern "sysv64" fn all_the_registers(rdi: i64, rsi: i64, rdx: i64,
+                                                rcx: i64, r8 : i64, r9 : i64,
+                                                xmm0: f32, xmm1: f32, xmm2: f32,
+                                                xmm3: f32, xmm4: f32, xmm5: f32,
+                                                xmm6: f32, xmm7: f32) -> i64 {
+    // this assembly checks all registers for specific values, and puts in rax
+    // how many values were correct.
+    asm!("cmp rdi, 0x1;
+          xor rax, rax;
+          setz al;
+
+          cmp rsi, 0x2;
+          xor rdi, rdi
+          setz dil;
+          add rax, rdi;
+
+          cmp rdx, 0x3;
+          setz dil;
+          add rax, rdi;
+
+          cmp rcx, 0x4;
+          setz dil;
+          add rax, rdi;
+
+          cmp r8, 0x5;
+          setz dil;
+          add rax, rdi;
+
+          cmp r9, 0x6;
+          setz dil;
+          add rax, rdi;
+
+          movd esi, xmm0;
+          cmp rsi, 0x3F800000;
+          setz dil;
+          add rax, rdi;
+
+          movd esi, xmm1;
+          cmp rsi, 0x40000000;
+          setz dil;
+          add rax, rdi;
+
+          movd esi, xmm2;
+          cmp rsi, 0x40800000;
+          setz dil;
+          add rax, rdi;
+
+          movd esi, xmm3;
+          cmp rsi, 0x41000000;
+          setz dil;
+          add rax, rdi;
+
+          movd esi, xmm4;
+          cmp rsi, 0x41800000;
+          setz dil;
+          add rax, rdi;
+
+          movd esi, xmm5;
+          cmp rsi, 0x42000000;
+          setz dil;
+          add rax, rdi;
+
+          movd esi, xmm6;
+          cmp rsi, 0x42800000;
+          setz dil;
+          add rax, rdi;
+
+          movd esi, xmm7;
+          cmp rsi, 0x43000000;
+          setz dil;
+          add rax, rdi;
+          ret
+         " :::: "intel");
+    unreachable!();
+}
+
+// this struct contains 8 i64's, while only 6 can be passed in registers.
+#[derive(PartialEq, Eq, Debug)]
+pub struct LargeStruct(i64, i64, i64, i64, i64, i64, i64, i64);
+
+#[inline(never)]
+pub extern "sysv64" fn large_struct_by_val(mut foo: LargeStruct) -> LargeStruct {
+    foo.0 *= 1;
+    foo.1 *= 2;
+    foo.2 *= 3;
+    foo.3 *= 4;
+    foo.4 *= 5;
+    foo.5 *= 6;
+    foo.6 *= 7;
+    foo.7 *= 8;
+    foo
+}
+
+pub fn main() {
+    assert_eq!(unsafe {
+        all_the_registers(1, 2, 3, 4, 5, 6,
+                          1.0, 2.0, 4.0, 8.0,
+                          16.0, 32.0, 64.0, 128.0)
+    }, 14);
+
+    assert_eq!(
+        large_struct_by_val(LargeStruct(1, 2, 3, 4, 5, 6, 7, 8)),
+        LargeStruct(1, 4, 9, 16, 25, 36, 49, 64)
+    );
+}