Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions compiler/rustc_codegen_gcc/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,7 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str {
unreachable!("clobber-only")
}
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg_pair) => "R",
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
unreachable!("clobber-only")
Expand Down Expand Up @@ -807,6 +808,13 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
unreachable!("clobber-only")
}
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg_pair) => {
if cx.tcx.sess.asm_arch.unwrap() == InlineAsmArch::RiscV64 {
cx.type_i128()
} else {
cx.type_i64()
}
}
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(),
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
unreachable!("clobber-only")
Expand Down Expand Up @@ -983,6 +991,7 @@ fn modifier_to_gcc(
}
InlineAsmRegClass::PowerPC(_) => None,
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg)
| InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg_pair)
| InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => None,
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
unreachable!("clobber-only")
Expand Down
12 changes: 11 additions & 1 deletion compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
unreachable!("clobber-only")
}
RiscV(RiscVInlineAsmRegClass::reg) => "r",
RiscV(RiscVInlineAsmRegClass::reg_pair) => "R",
RiscV(RiscVInlineAsmRegClass::freg) => "f",
RiscV(RiscVInlineAsmRegClass::vreg) => unreachable!("clobber-only"),
X86(X86InlineAsmRegClass::reg) => "r",
Expand Down Expand Up @@ -756,7 +757,9 @@ fn modifier_to_llvm(
if modifier.is_none() { Some('x') } else { modifier }
}
PowerPC(_) => None,
RiscV(RiscVInlineAsmRegClass::reg) | RiscV(RiscVInlineAsmRegClass::freg) => None,
RiscV(RiscVInlineAsmRegClass::reg)
| RiscV(RiscVInlineAsmRegClass::reg_pair)
| RiscV(RiscVInlineAsmRegClass::freg) => None,
RiscV(RiscVInlineAsmRegClass::vreg) => unreachable!("clobber-only"),
X86(X86InlineAsmRegClass::reg) | X86(X86InlineAsmRegClass::reg_abcd) => match modifier {
None if arch == InlineAsmArch::X86_64 => Some('q'),
Expand Down Expand Up @@ -849,6 +852,13 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
unreachable!("clobber-only")
}
RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
RiscV(RiscVInlineAsmRegClass::reg_pair) => {
if cx.tcx.sess.asm_arch.unwrap() == InlineAsmArch::RiscV64 {
cx.type_i128()
} else {
cx.type_i64()
}
}
RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(),
RiscV(RiscVInlineAsmRegClass::vreg) => unreachable!("clobber-only"),
X86(X86InlineAsmRegClass::reg) | X86(X86InlineAsmRegClass::reg_abcd) => cx.type_i32(),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_target/src/asm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ impl InlineAsmRegClass {
Self::X86(r) => r.supported_types(arch),
Self::Arm(r) => r.supported_types(arch),
Self::AArch64(r) => r.supported_types(arch),
Self::RiscV(r) => r.supported_types(arch),
Self::RiscV(r) => r.supported_types(arch, allow_experimental_reg),
Self::Nvptx(r) => r.supported_types(arch),
Self::PowerPC(r) => r.supported_types(arch),
Self::Hexagon(r) => r.supported_types(arch),
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_target/src/asm/riscv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::spec::{RelocModel, Target};
def_reg_class! {
RiscV RiscVInlineAsmRegClass {
reg,
reg_pair,
freg,
vreg,
}
Expand Down Expand Up @@ -38,6 +39,7 @@ impl RiscVInlineAsmRegClass {
pub fn supported_types(
self,
arch: InlineAsmArch,
allow_experimental_reg: bool,
) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self {
Self::reg => {
Expand All @@ -47,6 +49,18 @@ impl RiscVInlineAsmRegClass {
types! { _: I8, I16, I32, F16, F32; }
}
}
Self::reg_pair => {
if allow_experimental_reg {
// register pair support is unstable.
if arch == InlineAsmArch::RiscV64 {
types! { _: I128; }
} else {
types! { _: I64; }
}
} else {
&[]
}
}
// FIXME(f128): Add `q: F128;` once LLVM support the `Q` extension.
Self::freg => types! { f: F16, F32; d: F64; },
Self::vreg => &[],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ This tracks support for additional registers in architectures where inline assem
| Architecture | Register class | Registers | LLVM constraint code |
| ------------ | -------------- | --------- | -------------------- |
| s390x | `vreg` | `v[0-31]` | `v` |
| RISC-V | `reg_pair` | | `R` |

> **Notes**:
> - s390x `vreg` is clobber-only in stable.
Expand All @@ -22,6 +23,8 @@ This tracks support for additional registers in architectures where inline assem
| Architecture | Register class | Target feature | Allowed types |
| ------------ | -------------- | -------------- | ------------- |
| s390x | `vreg` | `vector` | `i32`, `f32`, `i64`, `f64`, `i128`, `f128`, `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
| RISC-V32 | `reg_pair` | | `i64` |
| RISC-V64 | `reg_pair` | | `i128` |

## Register aliases

Expand All @@ -38,3 +41,4 @@ This tracks support for additional registers in architectures where inline assem
| Architecture | Register class | Modifier | Example output | LLVM modifier |
| ------------ | -------------- | -------- | -------------- | ------------- |
| s390x | `vreg` | None | `%v0` | None |
| RISC-V | `reg_pair` | None | `a0` | None |
16 changes: 15 additions & 1 deletion tests/assembly-llvm/asm/riscv-types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
//@ compile-flags: -C target-feature=+d
//@ compile-flags: -Zmerge-functions=disabled

#![feature(no_core, f16)]
#![feature(no_core, f16, asm_experimental_reg)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register)]
Expand Down Expand Up @@ -136,6 +136,20 @@ check!(reg_f64 f64 reg "mv");
// CHECK: #NO_APP
check!(reg_ptr ptr reg "mv");

// riscv32-LABEL: reg_pair_i64:
// riscv32: #APP
// riscv32: mv {{[a-z0-9]+[02468]}}, {{[a-z0-9]+[02468]}}
// riscv32: #NO_APP
#[cfg(riscv32)]
check!(reg_pair_i64 i64 reg_pair "mv");

// riscv64-LABEL: reg_pair_i128:
// riscv64: #APP
// riscv64: mv {{[a-z0-9]+[02468]}}, {{[a-z0-9]+[02468]}}
// riscv64: #NO_APP
#[cfg(riscv64)]
check!(reg_pair_i128 i128 reg_pair "mv");

// CHECK-LABEL: freg_f16:
// zfhmin-NOT: or
// CHECK: #APP
Expand Down
66 changes: 33 additions & 33 deletions tests/ui/asm/riscv/bad-reg.riscv32e.stderr
Original file line number Diff line number Diff line change
@@ -1,201 +1,201 @@
error: invalid register `s1`: s1 is used internally by LLVM and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:33:18
--> $DIR/bad-reg.rs:43:18
|
LL | asm!("", out("s1") _);
| ^^^^^^^^^^^

error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:35:18
--> $DIR/bad-reg.rs:45:18
|
LL | asm!("", out("fp") _);
| ^^^^^^^^^^^

error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:37:18
--> $DIR/bad-reg.rs:47:18
|
LL | asm!("", out("sp") _);
| ^^^^^^^^^^^

error: invalid register `gp`: the global pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:39:18
--> $DIR/bad-reg.rs:49:18
|
LL | asm!("", out("gp") _);
| ^^^^^^^^^^^

error: invalid register `tp`: the thread pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:41:18
--> $DIR/bad-reg.rs:51:18
|
LL | asm!("", out("tp") _);
| ^^^^^^^^^^^

error: invalid register `zero`: the zero register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:43:18
--> $DIR/bad-reg.rs:53:18
|
LL | asm!("", out("zero") _);
| ^^^^^^^^^^^^^

error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:94:18
--> $DIR/bad-reg.rs:118:18
|
LL | asm!("", in("v0") x);
| ^^^^^^^^^^

error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:97:18
--> $DIR/bad-reg.rs:121:18
|
LL | asm!("", out("v0") x);
| ^^^^^^^^^^^

error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:100:26
--> $DIR/bad-reg.rs:124:26
|
LL | asm!("/* {} */", in(vreg) x);
| ^^^^^^^^^^

error: register class `vreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:103:26
--> $DIR/bad-reg.rs:127:26
|
LL | asm!("/* {} */", out(vreg) _);
| ^^^^^^^^^^^

error: cannot use register `x16`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:46:18
--> $DIR/bad-reg.rs:56:18
|
LL | asm!("", out("x16") _);
| ^^^^^^^^^^^^

error: cannot use register `x17`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:48:18
--> $DIR/bad-reg.rs:58:18
|
LL | asm!("", out("x17") _);
| ^^^^^^^^^^^^

error: cannot use register `x18`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:50:18
--> $DIR/bad-reg.rs:60:18
|
LL | asm!("", out("x18") _);
| ^^^^^^^^^^^^

error: cannot use register `x19`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:52:18
--> $DIR/bad-reg.rs:62:18
|
LL | asm!("", out("x19") _);
| ^^^^^^^^^^^^

error: cannot use register `x20`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:54:18
--> $DIR/bad-reg.rs:64:18
|
LL | asm!("", out("x20") _);
| ^^^^^^^^^^^^

error: cannot use register `x21`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:56:18
--> $DIR/bad-reg.rs:66:18
|
LL | asm!("", out("x21") _);
| ^^^^^^^^^^^^

error: cannot use register `x22`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:58:18
--> $DIR/bad-reg.rs:68:18
|
LL | asm!("", out("x22") _);
| ^^^^^^^^^^^^

error: cannot use register `x23`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:60:18
--> $DIR/bad-reg.rs:70:18
|
LL | asm!("", out("x23") _);
| ^^^^^^^^^^^^

error: cannot use register `x24`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:62:18
--> $DIR/bad-reg.rs:72:18
|
LL | asm!("", out("x24") _);
| ^^^^^^^^^^^^

error: cannot use register `x25`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:64:18
--> $DIR/bad-reg.rs:74:18
|
LL | asm!("", out("x25") _);
| ^^^^^^^^^^^^

error: cannot use register `x26`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:66:18
--> $DIR/bad-reg.rs:76:18
|
LL | asm!("", out("x26") _);
| ^^^^^^^^^^^^

error: cannot use register `x27`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:68:18
--> $DIR/bad-reg.rs:78:18
|
LL | asm!("", out("x27") _);
| ^^^^^^^^^^^^

error: cannot use register `x28`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:70:18
--> $DIR/bad-reg.rs:80:18
|
LL | asm!("", out("x28") _);
| ^^^^^^^^^^^^

error: cannot use register `x29`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:72:18
--> $DIR/bad-reg.rs:82:18
|
LL | asm!("", out("x29") _);
| ^^^^^^^^^^^^

error: cannot use register `x30`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:74:18
--> $DIR/bad-reg.rs:84:18
|
LL | asm!("", out("x30") _);
| ^^^^^^^^^^^^

error: cannot use register `x31`: register can't be used with the `e` target feature
--> $DIR/bad-reg.rs:76:18
--> $DIR/bad-reg.rs:86:18
|
LL | asm!("", out("x31") _);
| ^^^^^^^^^^^^

error: register class `freg` requires at least one of the following target features: d, f
--> $DIR/bad-reg.rs:80:26
--> $DIR/bad-reg.rs:104: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:82:26
--> $DIR/bad-reg.rs:106:26
|
LL | asm!("/* {} */", out(freg) _);
| ^^^^^^^^^^^

error: register class `freg` requires at least one of the following target features: d, f
--> $DIR/bad-reg.rs:84:26
--> $DIR/bad-reg.rs:108: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:87:26
--> $DIR/bad-reg.rs:111:26
|
LL | asm!("/* {} */", out(freg) d);
| ^^^^^^^^^^^

error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:94:27
--> $DIR/bad-reg.rs:118:27
|
LL | asm!("", in("v0") x);
| ^
|
= note: register class `vreg` supports these types:

error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:97:28
--> $DIR/bad-reg.rs:121:28
|
LL | asm!("", out("v0") x);
| ^
|
= note: register class `vreg` supports these types:

error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:100:35
--> $DIR/bad-reg.rs:124:35
|
LL | asm!("/* {} */", in(vreg) x);
| ^
Expand Down
Loading
Loading