Skip to content

Commit

Permalink
Unrolled build for rust-lang#133587
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#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
  • Loading branch information
rust-timer authored Nov 30, 2024
2 parents e48ddd8 + 0c8e36b commit 6fdace1
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 1 deletion.
2 changes: 1 addition & 1 deletion compiler/rustc_target/src/asm/loongarch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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; },
}
}
}
Expand Down
38 changes: 38 additions & 0 deletions tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr
Original file line number Diff line number Diff line change
@@ -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

62 changes: 62 additions & 0 deletions tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr
Original file line number Diff line number Diff line change
@@ -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

45 changes: 45 additions & 0 deletions tests/ui/asm/loongarch/bad-reg.rs
Original file line number Diff line number Diff line change
@@ -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
}
}

0 comments on commit 6fdace1

Please sign in to comment.