Skip to content

Commit 0e58a5d

Browse files
Feature gate the sysv64 abi as feature(abi_sysv64) and add tests
1 parent 30c4173 commit 0e58a5d

File tree

4 files changed

+184
-7
lines changed

4 files changed

+184
-7
lines changed

src/libsyntax/feature_gate.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,11 @@ declare_features! (
281281
(active, never_type, "1.13.0", Some(35121)),
282282

283283
// Allows all literals in attribute lists and values of key-value pairs.
284-
(active, attr_literals, "1.13.0", Some(34981))
284+
(active, attr_literals, "1.13.0", Some(34981)),
285+
286+
// Allows the sysV64 ABI to be specified on all platforms
287+
// instead of just the platforms on which it is the C ABI
288+
(active, abi_sysv64, "1.13.0", None)
285289
);
286290

287291
declare_features! (
@@ -811,21 +815,26 @@ macro_rules! gate_feature_post {
811815
impl<'a> PostExpansionVisitor<'a> {
812816
fn check_abi(&self, abi: Abi, span: Span) {
813817
match abi {
814-
Abi::RustIntrinsic =>
818+
Abi::RustIntrinsic => {
815819
gate_feature_post!(&self, intrinsics, span,
816-
"intrinsics are subject to change"),
820+
"intrinsics are subject to change");
821+
},
817822
Abi::PlatformIntrinsic => {
818823
gate_feature_post!(&self, platform_intrinsics, span,
819-
"platform intrinsics are experimental and possibly buggy")
824+
"platform intrinsics are experimental and possibly buggy");
820825
},
821826
Abi::Vectorcall => {
822827
gate_feature_post!(&self, abi_vectorcall, span,
823-
"vectorcall is experimental and subject to change")
824-
}
828+
"vectorcall is experimental and subject to change");
829+
},
825830
Abi::RustCall => {
826831
gate_feature_post!(&self, unboxed_closures, span,
827832
"rust-call ABI is subject to change");
828-
}
833+
},
834+
Abi::SysV64 => {
835+
gate_feature_post!(&self, abi_sysv64, span,
836+
"sysv64 ABI is experimental and subject to change");
837+
},
829838
_ => {}
830839
}
831840
}

src/test/codegen/abi-sysv64.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Checks if the correct annotation for the sysv64 ABI is passed to
12+
// llvm. Also checks that the abi-sysv64 feature gate allows usage
13+
// of the sysv64 abi.
14+
15+
// compile-flags: -C no-prepopulate-passes
16+
17+
#![crate_type = "lib"]
18+
#![feature(abi_sysv64)]
19+
20+
// CHECK: define x86_64_sysvcc i64 @has_sysv64_abi
21+
#[no_mangle]
22+
pub extern "sysv64" fn has_sysv64_abi(a: i64) -> i64 {
23+
a * 2
24+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that the sysv64 ABI cannot be used when abi-sysv64 feature
12+
// gate is not used.
13+
14+
extern "sysv64" fn foo() {}
15+
//~^ ERROR sysv64 ABI is experimental and subject to change
16+
17+
fn main() {
18+
foo();
19+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Checks if the correct registers are being used to pass arguments
12+
// when the sysv64 ABI is specified.
13+
14+
#![feature(abi_sysv64)]
15+
#![feature(naked_functions)]
16+
#![feature(asm)]
17+
18+
#[naked]
19+
#[inline(never)]
20+
#[allow(unused_variables)]
21+
pub unsafe extern "sysv64" fn all_the_registers(rdi: i64, rsi: i64, rdx: i64,
22+
rcx: i64, r8 : i64, r9 : i64,
23+
xmm0: f32, xmm1: f32, xmm2: f32,
24+
xmm3: f32, xmm4: f32, xmm5: f32,
25+
xmm6: f32, xmm7: f32) -> i64 {
26+
// this assembly checks all registers for specific values, and puts in rax
27+
// how many values were correct.
28+
asm!("cmp rdi, 0x1;
29+
xor rax, rax;
30+
setz al;
31+
32+
cmp rsi, 0x2;
33+
xor rdi, rdi
34+
setz dil;
35+
add rax, rdi;
36+
37+
cmp rdx, 0x3;
38+
setz dil;
39+
add rax, rdi;
40+
41+
cmp rcx, 0x4;
42+
setz dil;
43+
add rax, rdi;
44+
45+
cmp r8, 0x5;
46+
setz dil;
47+
add rax, rdi;
48+
49+
cmp r9, 0x6;
50+
setz dil;
51+
add rax, rdi;
52+
53+
movd esi, xmm0;
54+
cmp rsi, 0x3F800000;
55+
setz dil;
56+
add rax, rdi;
57+
58+
movd esi, xmm1;
59+
cmp rsi, 0x40000000;
60+
setz dil;
61+
add rax, rdi;
62+
63+
movd esi, xmm2;
64+
cmp rsi, 0x40800000;
65+
setz dil;
66+
add rax, rdi;
67+
68+
movd esi, xmm3;
69+
cmp rsi, 0x41000000;
70+
setz dil;
71+
add rax, rdi;
72+
73+
movd esi, xmm4;
74+
cmp rsi, 0x41800000;
75+
setz dil;
76+
add rax, rdi;
77+
78+
movd esi, xmm5;
79+
cmp rsi, 0x42000000;
80+
setz dil;
81+
add rax, rdi;
82+
83+
movd esi, xmm6;
84+
cmp rsi, 0x42800000;
85+
setz dil;
86+
add rax, rdi;
87+
88+
movd esi, xmm7;
89+
cmp rsi, 0x43000000;
90+
setz dil;
91+
add rax, rdi;
92+
ret
93+
" :::: "intel");
94+
unreachable!();
95+
}
96+
97+
// this struct contains 8 i64's, while only 6 can be passed in registers.
98+
#[derive(PartialEq, Eq, Debug)]
99+
pub struct LargeStruct(i64, i64, i64, i64, i64, i64, i64, i64);
100+
101+
#[inline(never)]
102+
pub extern "sysv64" fn large_struct_by_val(mut foo: LargeStruct) -> LargeStruct {
103+
foo.0 *= 1;
104+
foo.1 *= 2;
105+
foo.2 *= 3;
106+
foo.3 *= 4;
107+
foo.4 *= 5;
108+
foo.5 *= 6;
109+
foo.6 *= 7;
110+
foo.7 *= 8;
111+
foo
112+
}
113+
114+
pub fn main() {
115+
assert_eq!(unsafe {
116+
all_the_registers(1, 2, 3, 4, 5, 6,
117+
1.0, 2.0, 4.0, 8.0,
118+
16.0, 32.0, 64.0, 128.0)
119+
}, 14);
120+
121+
assert_eq!(
122+
large_struct_by_val(LargeStruct(1, 2, 3, 4, 5, 6, 7, 8)),
123+
LargeStruct(1, 4, 9, 16, 25, 36, 49, 64)
124+
);
125+
}

0 commit comments

Comments
 (0)