Skip to content

Commit ab4588a

Browse files
authored
Rollup merge of #133587 - taiki-e:loongarch-asm-freg, r=Amanieu
Fix target_feature handling in freg of LoongArch inline assembly In LoongArch inline assembly, freg currently always accepts f32/f64 as input/output. https://github.com/rust-lang/rust/blob/9b4d7c6a40b328d212095c28670c629facf1557d/compiler/rustc_target/src/asm/loongarch.rs#L41 However, these types actually require f/d target features as in RISC-V. Otherwise, an (ugly) compile error will occur: https://godbolt.org/z/K61Gq1E9E f32/f64 without f: ``` error: couldn't allocate output register for constraint '{$f1}' --> <source>:12:11 | 12 | asm!("", in("$f1") x, lateout("$f1") y); | ^ ``` f64 with f but without d: ``` error: scalar-to-vector conversion failed, possible invalid constraint for vector type --> <source>:19:11 | 19 | asm!("", in("$f1") x, lateout("$f1") y); | ^ ``` cc ``@heiher`` r? ``@Amanieu`` ``@rustbot`` label +O-LoongArch +A-inline-assembly
2 parents 70e71f5 + 0c8e36b commit ab4588a

File tree

4 files changed

+146
-1
lines changed

4 files changed

+146
-1
lines changed

Diff for: compiler/rustc_target/src/asm/loongarch.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl LoongArchInlineAsmRegClass {
3838
) -> &'static [(InlineAsmType, Option<Symbol>)] {
3939
match self {
4040
Self::reg => types! { _: I8, I16, I32, I64, F32, F64; },
41-
Self::freg => types! { _: F32, F64; },
41+
Self::freg => types! { f: F32; d: F64; },
4242
}
4343
}
4444
}
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
2+
--> $DIR/bad-reg.rs:22:18
3+
|
4+
LL | asm!("", out("$r0") _);
5+
| ^^^^^^^^^^^^
6+
7+
error: invalid register `$tp`: reserved for TLS
8+
--> $DIR/bad-reg.rs:24:18
9+
|
10+
LL | asm!("", out("$tp") _);
11+
| ^^^^^^^^^^^^
12+
13+
error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
14+
--> $DIR/bad-reg.rs:26:18
15+
|
16+
LL | asm!("", out("$sp") _);
17+
| ^^^^^^^^^^^^
18+
19+
error: invalid register `$r21`: reserved by the ABI
20+
--> $DIR/bad-reg.rs:28:18
21+
|
22+
LL | asm!("", out("$r21") _);
23+
| ^^^^^^^^^^^^^
24+
25+
error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
26+
--> $DIR/bad-reg.rs:30:18
27+
|
28+
LL | asm!("", out("$fp") _);
29+
| ^^^^^^^^^^^^
30+
31+
error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
32+
--> $DIR/bad-reg.rs:32:18
33+
|
34+
LL | asm!("", out("$r31") _);
35+
| ^^^^^^^^^^^^^
36+
37+
error: aborting due to 6 previous errors
38+
+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
2+
--> $DIR/bad-reg.rs:22:18
3+
|
4+
LL | asm!("", out("$r0") _);
5+
| ^^^^^^^^^^^^
6+
7+
error: invalid register `$tp`: reserved for TLS
8+
--> $DIR/bad-reg.rs:24:18
9+
|
10+
LL | asm!("", out("$tp") _);
11+
| ^^^^^^^^^^^^
12+
13+
error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
14+
--> $DIR/bad-reg.rs:26:18
15+
|
16+
LL | asm!("", out("$sp") _);
17+
| ^^^^^^^^^^^^
18+
19+
error: invalid register `$r21`: reserved by the ABI
20+
--> $DIR/bad-reg.rs:28:18
21+
|
22+
LL | asm!("", out("$r21") _);
23+
| ^^^^^^^^^^^^^
24+
25+
error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
26+
--> $DIR/bad-reg.rs:30:18
27+
|
28+
LL | asm!("", out("$fp") _);
29+
| ^^^^^^^^^^^^
30+
31+
error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
32+
--> $DIR/bad-reg.rs:32:18
33+
|
34+
LL | asm!("", out("$r31") _);
35+
| ^^^^^^^^^^^^^
36+
37+
error: register class `freg` requires at least one of the following target features: d, f
38+
--> $DIR/bad-reg.rs:36:26
39+
|
40+
LL | asm!("/* {} */", in(freg) f);
41+
| ^^^^^^^^^^
42+
43+
error: register class `freg` requires at least one of the following target features: d, f
44+
--> $DIR/bad-reg.rs:38:26
45+
|
46+
LL | asm!("/* {} */", out(freg) _);
47+
| ^^^^^^^^^^^
48+
49+
error: register class `freg` requires at least one of the following target features: d, f
50+
--> $DIR/bad-reg.rs:40:26
51+
|
52+
LL | asm!("/* {} */", in(freg) d);
53+
| ^^^^^^^^^^
54+
55+
error: register class `freg` requires at least one of the following target features: d, f
56+
--> $DIR/bad-reg.rs:42:26
57+
|
58+
LL | asm!("/* {} */", out(freg) d);
59+
| ^^^^^^^^^^^
60+
61+
error: aborting due to 10 previous errors
62+

Diff for: tests/ui/asm/loongarch/bad-reg.rs

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//@ add-core-stubs
2+
//@ needs-asm-support
3+
//@ revisions: loongarch64_lp64d loongarch64_lp64s
4+
//@[loongarch64_lp64d] compile-flags: --target loongarch64-unknown-linux-gnu
5+
//@[loongarch64_lp64d] needs-llvm-components: loongarch
6+
//@[loongarch64_lp64s] compile-flags: --target loongarch64-unknown-none-softfloat
7+
//@[loongarch64_lp64s] needs-llvm-components: loongarch
8+
9+
#![crate_type = "lib"]
10+
#![feature(no_core, rustc_attrs)]
11+
#![no_core]
12+
13+
extern crate minicore;
14+
use minicore::*;
15+
16+
fn f() {
17+
let mut x = 0;
18+
let mut f = 0.0_f32;
19+
let mut d = 0.0_f64;
20+
unsafe {
21+
// Unsupported registers
22+
asm!("", out("$r0") _);
23+
//~^ ERROR constant zero cannot be used as an operand for inline asm
24+
asm!("", out("$tp") _);
25+
//~^ ERROR invalid register `$tp`: reserved for TLS
26+
asm!("", out("$sp") _);
27+
//~^ ERROR invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
28+
asm!("", out("$r21") _);
29+
//~^ ERROR invalid register `$r21`: reserved by the ABI
30+
asm!("", out("$fp") _);
31+
//~^ ERROR invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
32+
asm!("", out("$r31") _);
33+
//~^ ERROR invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
34+
35+
asm!("", out("$f0") _); // ok
36+
asm!("/* {} */", in(freg) f);
37+
//[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
38+
asm!("/* {} */", out(freg) _);
39+
//[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
40+
asm!("/* {} */", in(freg) d);
41+
//[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
42+
asm!("/* {} */", out(freg) d);
43+
//[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
44+
}
45+
}

0 commit comments

Comments
 (0)