1
Fork 0

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.

9b4d7c6a40/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
This commit is contained in:
许杰友 Jieyou Xu (Joe) 2024-11-30 12:56:53 +08:00 committed by GitHub
commit ab4588a619
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 146 additions and 1 deletions

View file

@ -38,7 +38,7 @@ impl LoongArchInlineAsmRegClass {
) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self {
Self::reg => types! { _: I8, I16, I32, I64, F32, F64; },
Self::freg => types! { _: F32, F64; },
Self::freg => types! { f: F32; d: F64; },
}
}
}

View file

@ -0,0 +1,38 @@
error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:22:18
|
LL | asm!("", out("$r0") _);
| ^^^^^^^^^^^^
error: invalid register `$tp`: reserved for TLS
--> $DIR/bad-reg.rs:24:18
|
LL | asm!("", out("$tp") _);
| ^^^^^^^^^^^^
error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:26:18
|
LL | asm!("", out("$sp") _);
| ^^^^^^^^^^^^
error: invalid register `$r21`: reserved by the ABI
--> $DIR/bad-reg.rs:28:18
|
LL | asm!("", out("$r21") _);
| ^^^^^^^^^^^^^
error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:30:18
|
LL | asm!("", out("$fp") _);
| ^^^^^^^^^^^^
error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:32:18
|
LL | asm!("", out("$r31") _);
| ^^^^^^^^^^^^^
error: aborting due to 6 previous errors

View file

@ -0,0 +1,62 @@
error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:22:18
|
LL | asm!("", out("$r0") _);
| ^^^^^^^^^^^^
error: invalid register `$tp`: reserved for TLS
--> $DIR/bad-reg.rs:24:18
|
LL | asm!("", out("$tp") _);
| ^^^^^^^^^^^^
error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:26:18
|
LL | asm!("", out("$sp") _);
| ^^^^^^^^^^^^
error: invalid register `$r21`: reserved by the ABI
--> $DIR/bad-reg.rs:28:18
|
LL | asm!("", out("$r21") _);
| ^^^^^^^^^^^^^
error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:30:18
|
LL | asm!("", out("$fp") _);
| ^^^^^^^^^^^^
error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:32:18
|
LL | asm!("", out("$r31") _);
| ^^^^^^^^^^^^^
error: register class `freg` requires at least one of the following target features: d, f
--> $DIR/bad-reg.rs:36:26
|
LL | asm!("/* {} */", in(freg) f);
| ^^^^^^^^^^
error: register class `freg` requires at least one of the following target features: d, f
--> $DIR/bad-reg.rs:38:26
|
LL | asm!("/* {} */", out(freg) _);
| ^^^^^^^^^^^
error: register class `freg` requires at least one of the following target features: d, f
--> $DIR/bad-reg.rs:40:26
|
LL | asm!("/* {} */", in(freg) d);
| ^^^^^^^^^^
error: register class `freg` requires at least one of the following target features: d, f
--> $DIR/bad-reg.rs:42:26
|
LL | asm!("/* {} */", out(freg) d);
| ^^^^^^^^^^^
error: aborting due to 10 previous errors

View file

@ -0,0 +1,45 @@
//@ add-core-stubs
//@ needs-asm-support
//@ revisions: loongarch64_lp64d loongarch64_lp64s
//@[loongarch64_lp64d] compile-flags: --target loongarch64-unknown-linux-gnu
//@[loongarch64_lp64d] needs-llvm-components: loongarch
//@[loongarch64_lp64s] compile-flags: --target loongarch64-unknown-none-softfloat
//@[loongarch64_lp64s] needs-llvm-components: loongarch
#![crate_type = "lib"]
#![feature(no_core, rustc_attrs)]
#![no_core]
extern crate minicore;
use minicore::*;
fn f() {
let mut x = 0;
let mut f = 0.0_f32;
let mut d = 0.0_f64;
unsafe {
// Unsupported registers
asm!("", out("$r0") _);
//~^ ERROR constant zero cannot be used as an operand for inline asm
asm!("", out("$tp") _);
//~^ ERROR invalid register `$tp`: reserved for TLS
asm!("", out("$sp") _);
//~^ ERROR invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
asm!("", out("$r21") _);
//~^ ERROR invalid register `$r21`: reserved by the ABI
asm!("", out("$fp") _);
//~^ ERROR invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
asm!("", out("$r31") _);
//~^ ERROR invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
asm!("", out("$f0") _); // ok
asm!("/* {} */", in(freg) f);
//[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
asm!("/* {} */", out(freg) _);
//[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
asm!("/* {} */", in(freg) d);
//[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
asm!("/* {} */", out(freg) d);
//[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
}
}