Skip to content

Commit 3ba5563

Browse files
Rollup merge of rust-lang#151059 - folkertdev:x86-u128-reg, r=Amanieu
x86: support passing `u128`/`i128` to inline assembly tracking issue: rust-lang#133416 Seems like an oversight. LLVM has supported this since 2019, see llvm/llvm-project#42502. I've put this under `asm_experimental_reg`. cc @taiki-e r? @Amanieu
2 parents 9dfffd6 + c713538 commit 3ba5563

7 files changed

Lines changed: 394 additions & 48 deletions

File tree

compiler/rustc_target/src/asm/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ impl InlineAsmRegClass {
614614
allow_experimental_reg: bool,
615615
) -> &'static [(InlineAsmType, Option<Symbol>)] {
616616
match self {
617-
Self::X86(r) => r.supported_types(arch),
617+
Self::X86(r) => r.supported_types(arch, allow_experimental_reg),
618618
Self::Arm(r) => r.supported_types(arch),
619619
Self::AArch64(r) => r.supported_types(arch),
620620
Self::RiscV(r) => r.supported_types(arch),

compiler/rustc_target/src/asm/x86.rs

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ impl X86InlineAsmRegClass {
105105
pub fn supported_types(
106106
self,
107107
arch: InlineAsmArch,
108+
allow_experimental_reg: bool,
108109
) -> &'static [(InlineAsmType, Option<Symbol>)] {
109110
match self {
110111
Self::reg | Self::reg_abcd => {
@@ -115,21 +116,52 @@ impl X86InlineAsmRegClass {
115116
}
116117
}
117118
Self::reg_byte => types! { _: I8; },
118-
Self::xmm_reg => types! {
119-
sse: I32, I64, F16, F32, F64, F128,
120-
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2);
121-
},
122-
Self::ymm_reg => types! {
123-
avx: I32, I64, F16, F32, F64, F128,
124-
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2),
125-
VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF16(16), VecF32(8), VecF64(4);
126-
},
127-
Self::zmm_reg => types! {
128-
avx512f: I32, I64, F16, F32, F64, F128,
129-
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2),
130-
VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF16(16), VecF32(8), VecF64(4),
131-
VecI8(64), VecI16(32), VecI32(16), VecI64(8), VecF16(32), VecF32(16), VecF64(8);
132-
},
119+
Self::xmm_reg => {
120+
if allow_experimental_reg {
121+
types! {
122+
sse: I32, I64, I128, F16, F32, F64, F128,
123+
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2);
124+
}
125+
} else {
126+
types! {
127+
sse: I32, I64, F16, F32, F64, F128,
128+
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2);
129+
}
130+
}
131+
}
132+
Self::ymm_reg => {
133+
if allow_experimental_reg {
134+
types! {
135+
avx: I32, I64, I128, F16, F32, F64, F128,
136+
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2),
137+
VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF16(16), VecF32(8), VecF64(4);
138+
}
139+
} else {
140+
types! {
141+
avx: I32, I64, F16, F32, F64, F128,
142+
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2),
143+
VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF16(16), VecF32(8), VecF64(4);
144+
}
145+
}
146+
}
147+
Self::zmm_reg => {
148+
if allow_experimental_reg {
149+
types! {
150+
avx512f: I32, I64, I128, F16, F32, F64, F128,
151+
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2),
152+
VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF16(16), VecF32(8), VecF64(4),
153+
VecI8(64), VecI16(32), VecI32(16), VecI64(8), VecF16(32), VecF32(16), VecF64(8);
154+
}
155+
} else {
156+
types! {
157+
avx512f: I32, I64, F16, F32, F64, F128,
158+
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2),
159+
VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF16(16), VecF32(8), VecF64(4),
160+
VecI8(64), VecI16(32), VecI32(16), VecI64(8), VecF16(32), VecF32(16), VecF64(8);
161+
}
162+
}
163+
}
164+
133165
Self::kreg => types! {
134166
avx512f: I8, I16;
135167
avx512bw: I32, I64;

src/doc/unstable-book/src/language-features/asm-experimental-reg.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ This tracks support for additional registers in architectures where inline assem
2222
| Architecture | Register class | Target feature | Allowed types |
2323
| ------------ | -------------- | -------------- | ------------- |
2424
| s390x | `vreg` | `vector` | `i32`, `f32`, `i64`, `f64`, `i128`, `f128`, `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
25+
| x86 | `xmm_reg` | `sse` | `i128` |
26+
| x86 | `ymm_reg` | `avx` | `i128` |
27+
| x86 | `zmm_reg` | `avx512f` | `i128` |
2528

2629
## Register aliases
2730

tests/auxiliary/minicore.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ pub trait MetaSized: PointeeSized {}
6262
)]
6363
pub trait Sized: MetaSized {}
6464

65+
#[lang = "destruct"]
66+
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
67+
pub trait Destruct: PointeeSized {}
68+
6569
#[lang = "legacy_receiver"]
6670
pub trait LegacyReceiver {}
6771
impl<T: PointeeSized> LegacyReceiver for &T {}

tests/ui/asm/x86_64/bad-reg.stderr renamed to tests/ui/asm/x86_64/bad-reg.experimental_reg.stderr

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
error: invalid register class `foo`: unknown register class
2-
--> $DIR/bad-reg.rs:12:20
2+
--> $DIR/bad-reg.rs:20:20
33
|
44
LL | asm!("{}", in(foo) foo);
55
| ^^^^^^^^^^^
66
|
77
= note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg`
88

99
error: invalid register `foo`: unknown register
10-
--> $DIR/bad-reg.rs:14:18
10+
--> $DIR/bad-reg.rs:22:18
1111
|
1212
LL | asm!("", in("foo") foo);
1313
| ^^^^^^^^^^^^^
1414

1515
error: invalid asm template modifier for this register class
16-
--> $DIR/bad-reg.rs:16:15
16+
--> $DIR/bad-reg.rs:24:15
1717
|
1818
LL | asm!("{:z}", in(reg) foo);
1919
| ^^^^ ----------- argument
@@ -23,7 +23,7 @@ LL | asm!("{:z}", in(reg) foo);
2323
= note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, `r`
2424

2525
error: invalid asm template modifier for this register class
26-
--> $DIR/bad-reg.rs:18:15
26+
--> $DIR/bad-reg.rs:26:15
2727
|
2828
LL | asm!("{:r}", in(xmm_reg) foo);
2929
| ^^^^ --------------- argument
@@ -33,183 +33,183 @@ LL | asm!("{:r}", in(xmm_reg) foo);
3333
= note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, `z`
3434

3535
error: asm template modifiers are not allowed for `const` arguments
36-
--> $DIR/bad-reg.rs:20:15
36+
--> $DIR/bad-reg.rs:28:15
3737
|
3838
LL | asm!("{:a}", const 0);
3939
| ^^^^ ------- argument
4040
| |
4141
| template modifier
4242

4343
error: asm template modifiers are not allowed for `sym` arguments
44-
--> $DIR/bad-reg.rs:22:15
44+
--> $DIR/bad-reg.rs:30:15
4545
|
4646
LL | asm!("{:a}", sym main);
4747
| ^^^^ -------- argument
4848
| |
4949
| template modifier
5050

5151
error: invalid register `ebp`: the frame pointer cannot be used as an operand for inline asm
52-
--> $DIR/bad-reg.rs:24:18
52+
--> $DIR/bad-reg.rs:32:18
5353
|
5454
LL | asm!("", in("ebp") foo);
5555
| ^^^^^^^^^^^^^
5656

5757
error: invalid register `rsp`: the stack pointer cannot be used as an operand for inline asm
58-
--> $DIR/bad-reg.rs:26:18
58+
--> $DIR/bad-reg.rs:34:18
5959
|
6060
LL | asm!("", in("rsp") foo);
6161
| ^^^^^^^^^^^^^
6262

6363
error: invalid register `ip`: the instruction pointer cannot be used as an operand for inline asm
64-
--> $DIR/bad-reg.rs:28:18
64+
--> $DIR/bad-reg.rs:36:18
6565
|
6666
LL | asm!("", in("ip") foo);
6767
| ^^^^^^^^^^^^
6868

6969
error: register class `x87_reg` can only be used as a clobber, not as an input or output
70-
--> $DIR/bad-reg.rs:31:18
70+
--> $DIR/bad-reg.rs:39:18
7171
|
7272
LL | asm!("", in("st(2)") foo);
7373
| ^^^^^^^^^^^^^^^
7474

7575
error: register class `mmx_reg` can only be used as a clobber, not as an input or output
76-
--> $DIR/bad-reg.rs:34:18
76+
--> $DIR/bad-reg.rs:42:18
7777
|
7878
LL | asm!("", in("mm0") foo);
7979
| ^^^^^^^^^^^^^
8080

8181
error: register class `kreg0` can only be used as a clobber, not as an input or output
82-
--> $DIR/bad-reg.rs:37:18
82+
--> $DIR/bad-reg.rs:45:18
8383
|
8484
LL | asm!("", in("k0") foo);
8585
| ^^^^^^^^^^^^
8686

8787
error: register class `x87_reg` can only be used as a clobber, not as an input or output
88-
--> $DIR/bad-reg.rs:42:20
88+
--> $DIR/bad-reg.rs:50:20
8989
|
9090
LL | asm!("{}", in(x87_reg) foo);
9191
| ^^^^^^^^^^^^^^^
9292

9393
error: register class `mmx_reg` can only be used as a clobber, not as an input or output
94-
--> $DIR/bad-reg.rs:45:20
94+
--> $DIR/bad-reg.rs:53:20
9595
|
9696
LL | asm!("{}", in(mmx_reg) foo);
9797
| ^^^^^^^^^^^^^^^
9898

9999
error: register class `x87_reg` can only be used as a clobber, not as an input or output
100-
--> $DIR/bad-reg.rs:48:20
100+
--> $DIR/bad-reg.rs:56:20
101101
|
102102
LL | asm!("{}", out(x87_reg) _);
103103
| ^^^^^^^^^^^^^^
104104

105105
error: register class `mmx_reg` can only be used as a clobber, not as an input or output
106-
--> $DIR/bad-reg.rs:50:20
106+
--> $DIR/bad-reg.rs:58:20
107107
|
108108
LL | asm!("{}", out(mmx_reg) _);
109109
| ^^^^^^^^^^^^^^
110110

111111
error: register `al` conflicts with register `eax`
112-
--> $DIR/bad-reg.rs:56:33
112+
--> $DIR/bad-reg.rs:64:33
113113
|
114114
LL | asm!("", in("eax") foo, in("al") bar);
115115
| ------------- ^^^^^^^^^^^^ register `al`
116116
| |
117117
| register `eax`
118118

119119
error: register `rax` conflicts with register `rax`
120-
--> $DIR/bad-reg.rs:59:33
120+
--> $DIR/bad-reg.rs:67:33
121121
|
122122
LL | asm!("", in("rax") foo, out("rax") bar);
123123
| ------------- ^^^^^^^^^^^^^^ register `rax`
124124
| |
125125
| register `rax`
126126
|
127127
help: use `lateout` instead of `out` to avoid conflict
128-
--> $DIR/bad-reg.rs:59:18
128+
--> $DIR/bad-reg.rs:67:18
129129
|
130130
LL | asm!("", in("rax") foo, out("rax") bar);
131131
| ^^^^^^^^^^^^^
132132

133133
error: register `ymm0` conflicts with register `xmm0`
134-
--> $DIR/bad-reg.rs:64:34
134+
--> $DIR/bad-reg.rs:72:34
135135
|
136136
LL | asm!("", in("xmm0") foo, in("ymm0") bar);
137137
| -------------- ^^^^^^^^^^^^^^ register `ymm0`
138138
| |
139139
| register `xmm0`
140140

141141
error: register `ymm0` conflicts with register `xmm0`
142-
--> $DIR/bad-reg.rs:66:34
142+
--> $DIR/bad-reg.rs:74:34
143143
|
144144
LL | asm!("", in("xmm0") foo, out("ymm0") bar);
145145
| -------------- ^^^^^^^^^^^^^^^ register `ymm0`
146146
| |
147147
| register `xmm0`
148148
|
149149
help: use `lateout` instead of `out` to avoid conflict
150-
--> $DIR/bad-reg.rs:66:18
150+
--> $DIR/bad-reg.rs:74:18
151151
|
152152
LL | asm!("", in("xmm0") foo, out("ymm0") bar);
153153
| ^^^^^^^^^^^^^^
154154

155155
error: type `i32` cannot be used with this register class
156-
--> $DIR/bad-reg.rs:31:30
156+
--> $DIR/bad-reg.rs:39:30
157157
|
158158
LL | asm!("", in("st(2)") foo);
159159
| ^^^
160160
|
161161
= note: register class `x87_reg` supports these types:
162162

163163
error: type `i32` cannot be used with this register class
164-
--> $DIR/bad-reg.rs:34:28
164+
--> $DIR/bad-reg.rs:42:28
165165
|
166166
LL | asm!("", in("mm0") foo);
167167
| ^^^
168168
|
169169
= note: register class `mmx_reg` supports these types:
170170

171171
error: type `i32` cannot be used with this register class
172-
--> $DIR/bad-reg.rs:37:27
172+
--> $DIR/bad-reg.rs:45:27
173173
|
174174
LL | asm!("", in("k0") foo);
175175
| ^^^
176176
|
177177
= note: register class `kreg0` supports these types:
178178

179179
error: type `i32` cannot be used with this register class
180-
--> $DIR/bad-reg.rs:42:32
180+
--> $DIR/bad-reg.rs:50:32
181181
|
182182
LL | asm!("{}", in(x87_reg) foo);
183183
| ^^^
184184
|
185185
= note: register class `x87_reg` supports these types:
186186

187187
error: type `i32` cannot be used with this register class
188-
--> $DIR/bad-reg.rs:45:32
188+
--> $DIR/bad-reg.rs:53:32
189189
|
190190
LL | asm!("{}", in(mmx_reg) foo);
191191
| ^^^
192192
|
193193
= note: register class `mmx_reg` supports these types:
194194

195195
error: type `i32` cannot be used with this register class
196-
--> $DIR/bad-reg.rs:56:42
196+
--> $DIR/bad-reg.rs:64:42
197197
|
198198
LL | asm!("", in("eax") foo, in("al") bar);
199199
| ^^^
200200
|
201201
= note: register class `reg_byte` supports these types: i8
202202

203203
error: type `i32` cannot be used with this register class
204-
--> $DIR/bad-reg.rs:61:27
204+
--> $DIR/bad-reg.rs:69:27
205205
|
206206
LL | asm!("", in("al") foo, lateout("al") bar);
207207
| ^^^
208208
|
209209
= note: register class `reg_byte` supports these types: i8
210210

211211
error: type `i32` cannot be used with this register class
212-
--> $DIR/bad-reg.rs:61:46
212+
--> $DIR/bad-reg.rs:69:46
213213
|
214214
LL | asm!("", in("al") foo, lateout("al") bar);
215215
| ^^^

tests/ui/asm/x86_64/bad-reg.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1+
//@ add-minicore
12
//@ only-x86_64
2-
//@ compile-flags: -C target-feature=+avx2
3+
//@ revisions: stable experimental_reg
4+
//@ compile-flags: -C target-feature=+avx2,+avx512f
5+
#![cfg_attr(experimental_reg, feature(asm_experimental_reg))]
36

4-
use std::arch::asm;
7+
#![crate_type = "lib"]
8+
#![feature(no_core)]
9+
#![no_core]
10+
11+
extern crate minicore;
12+
use minicore::*;
513

614
fn main() {
715
let mut foo = 0;
@@ -66,5 +74,23 @@ fn main() {
6674
asm!("", in("xmm0") foo, out("ymm0") bar);
6775
//~^ ERROR register `ymm0` conflicts with register `xmm0`
6876
asm!("", in("xmm0") foo, lateout("ymm0") bar);
77+
78+
// Passing u128/i128 is currently experimental.
79+
let mut xmmword = 0u128;
80+
81+
asm!("/* {:x} */", in(xmm_reg) xmmword); // requires asm_experimental_reg
82+
//[stable]~^ ERROR type `u128` cannot be used with this register class in stable
83+
asm!("/* {:x} */", out(xmm_reg) xmmword); // requires asm_experimental_reg
84+
//[stable]~^ ERROR type `u128` cannot be used with this register class in stable
85+
86+
asm!("/* {:y} */", in(ymm_reg) xmmword); // requires asm_experimental_reg
87+
//[stable]~^ ERROR type `u128` cannot be used with this register class in stable
88+
asm!("/* {:y} */", out(ymm_reg) xmmword); // requires asm_experimental_reg
89+
//[stable]~^ ERROR type `u128` cannot be used with this register class in stable
90+
91+
asm!("/* {:z} */", in(zmm_reg) xmmword); // requires asm_experimental_reg
92+
//[stable]~^ ERROR type `u128` cannot be used with this register class in stable
93+
asm!("/* {:z} */", out(zmm_reg) xmmword); // requires asm_experimental_reg
94+
//[stable]~^ ERROR type `u128` cannot be used with this register class in stable
6995
}
7096
}

0 commit comments

Comments
 (0)