Rollup merge of #154719 - androm3da:hexagon-inline-asm-register-classes, r=JohnTitor

Hexagon inline asm: add reg_pair, vreg, vreg_pair, and qreg register classes

Add three new register classes for the Hexagon inline assembly backend:

* `reg_pair`: GPR double registers (r1:0 through r27:26)
* `vreg`: HVX vector registers (v0-v31)
* `qreg`: HVX predicate registers (q0-q3), clobber-only for now
This commit is contained in:
Jonathan Brouwer
2026-04-08 23:04:34 +02:00
committed by GitHub
7 changed files with 623 additions and 2 deletions
+16
View File
@@ -687,9 +687,15 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str {
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg_pair) => "r",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::vreg) => "v",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::vreg_pair) => "v",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::qreg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r",
@@ -779,9 +785,19 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
cx.type_vector(cx.type_i64(), 2)
}
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(),
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg_pair) => cx.type_i64(),
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::vreg) => {
cx.type_vector(cx.type_i32(), 16)
}
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::vreg_pair) => {
cx.type_vector(cx.type_i32(), 32)
}
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::qreg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(),
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(),
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(),
+74
View File
@@ -575,6 +575,52 @@ fn a64_vreg_index(reg: InlineAsmReg) -> Option<u32> {
}
}
/// If the register is a Hexagon register pair then return its LLVM double register index.
/// LLVM uses `d0`, `d1`, ... for Hexagon double registers in inline asm constraints,
/// not the assembly-printed `r1:0`, `r3:2`, ... format.
fn hexagon_reg_pair_index(reg: InlineAsmReg) -> Option<u32> {
match reg {
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r1_0) => Some(0),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r3_2) => Some(1),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r5_4) => Some(2),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r7_6) => Some(3),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r9_8) => Some(4),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r11_10) => Some(5),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r13_12) => Some(6),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r15_14) => Some(7),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r17_16) => Some(8),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r21_20) => Some(10),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r23_22) => Some(11),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r25_24) => Some(12),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r27_26) => Some(13),
_ => None,
}
}
/// If the register is a Hexagon HVX vector pair then return its LLVM W-register index.
/// LLVM uses `w0`, `w1`, ... for Hexagon vector pair registers in inline asm constraints.
fn hexagon_vreg_pair_index(reg: InlineAsmReg) -> Option<u32> {
match reg {
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v1_0) => Some(0),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v3_2) => Some(1),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v5_4) => Some(2),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v7_6) => Some(3),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v9_8) => Some(4),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v11_10) => Some(5),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v13_12) => Some(6),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v15_14) => Some(7),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v17_16) => Some(8),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v19_18) => Some(9),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v21_20) => Some(10),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v23_22) => Some(11),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v25_24) => Some(12),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v27_26) => Some(13),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v29_28) => Some(14),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v31_30) => Some(15),
_ => None,
}
}
/// Converts a register class to an LLVM constraint code.
fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> String {
use InlineAsmRegClass::*;
@@ -624,6 +670,12 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
'q'
};
format!("{{{}{}}}", class, idx)
} else if let Some(idx) = hexagon_reg_pair_index(reg) {
// LLVM uses `dN` for Hexagon double registers, not the `rN+1:N` asm syntax.
format!("{{d{}}}", idx)
} else if let Some(idx) = hexagon_vreg_pair_index(reg) {
// LLVM uses `wN` for Hexagon HVX vector pair registers.
format!("{{w{}}}", idx)
} else if reg == InlineAsmReg::Arm(ArmInlineAsmReg::r14) {
// LLVM doesn't recognize r14
"{lr}".to_string()
@@ -647,7 +699,11 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
| Arm(ArmInlineAsmRegClass::qreg_low4) => "x",
Arm(ArmInlineAsmRegClass::dreg) | Arm(ArmInlineAsmRegClass::qreg) => "w",
Hexagon(HexagonInlineAsmRegClass::reg) => "r",
Hexagon(HexagonInlineAsmRegClass::reg_pair) => "r",
Hexagon(HexagonInlineAsmRegClass::preg) => unreachable!("clobber-only"),
Hexagon(HexagonInlineAsmRegClass::vreg) => "v",
Hexagon(HexagonInlineAsmRegClass::vreg_pair) => "v",
Hexagon(HexagonInlineAsmRegClass::qreg) => unreachable!("clobber-only"),
LoongArch(LoongArchInlineAsmRegClass::reg) => "r",
LoongArch(LoongArchInlineAsmRegClass::freg) => "f",
Mips(MipsInlineAsmRegClass::reg) => "r",
@@ -828,7 +884,25 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
| Arm(ArmInlineAsmRegClass::qreg_low8)
| Arm(ArmInlineAsmRegClass::qreg_low4) => cx.type_vector(cx.type_i64(), 2),
Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(),
Hexagon(HexagonInlineAsmRegClass::reg_pair) => cx.type_i64(),
Hexagon(HexagonInlineAsmRegClass::preg) => unreachable!("clobber-only"),
Hexagon(HexagonInlineAsmRegClass::vreg) => {
// HVX vector register size depends on the HVX mode.
// LLVM's "v" constraint requires the exact vector width.
if cx.tcx.sess.unstable_target_features.contains(&sym::hvx_length128b) {
cx.type_vector(cx.type_i32(), 32) // 1024-bit for 128B mode
} else {
cx.type_vector(cx.type_i32(), 16) // 512-bit for 64B mode
}
}
Hexagon(HexagonInlineAsmRegClass::vreg_pair) => {
if cx.tcx.sess.unstable_target_features.contains(&sym::hvx_length128b) {
cx.type_vector(cx.type_i32(), 64) // 2048-bit for 128B mode
} else {
cx.type_vector(cx.type_i32(), 32) // 1024-bit for 64B mode
}
}
Hexagon(HexagonInlineAsmRegClass::qreg) => unreachable!("clobber-only"),
LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(),
LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(),
Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(),
+4
View File
@@ -1042,6 +1042,9 @@
html_no_source,
html_playground_url,
html_root_url,
hvx,
hvx_length64b: "hvx-length64b",
hvx_length128b: "hvx-length128b",
hwaddress,
i8,
i16,
@@ -2221,6 +2224,7 @@
volatile_store,
vreg,
vreg_low16,
vreg_pair,
vsreg,
vsx,
vtable_align,
+149 -1
View File
@@ -7,7 +7,11 @@
def_reg_class! {
Hexagon HexagonInlineAsmRegClass {
reg,
reg_pair,
preg,
vreg,
vreg_pair,
qreg,
}
}
@@ -38,7 +42,17 @@ pub fn supported_types(
) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self {
Self::reg => types! { _: I8, I16, I32, F32; },
Self::reg_pair => types! { _: I64, F64; },
Self::preg => &[],
Self::vreg => types! {
hvx_length64b: VecI32(16);
hvx_length128b: VecI32(32);
},
Self::vreg_pair => types! {
hvx_length64b: VecI32(32);
hvx_length128b: VecI32(64);
},
Self::qreg => &[],
}
}
}
@@ -73,18 +87,89 @@ pub fn supported_types(
r26: reg = ["r26"],
r27: reg = ["r27"],
r28: reg = ["r28"],
r1_0: reg_pair = ["r1:0"],
r3_2: reg_pair = ["r3:2"],
r5_4: reg_pair = ["r5:4"],
r7_6: reg_pair = ["r7:6"],
r9_8: reg_pair = ["r9:8"],
r11_10: reg_pair = ["r11:10"],
r13_12: reg_pair = ["r13:12"],
r15_14: reg_pair = ["r15:14"],
r17_16: reg_pair = ["r17:16"],
r21_20: reg_pair = ["r21:20"],
r23_22: reg_pair = ["r23:22"],
r25_24: reg_pair = ["r25:24"],
r27_26: reg_pair = ["r27:26"],
p0: preg = ["p0"],
p1: preg = ["p1"],
p2: preg = ["p2"],
p3: preg = ["p3"],
v0: vreg = ["v0"],
v1: vreg = ["v1"],
v2: vreg = ["v2"],
v3: vreg = ["v3"],
v4: vreg = ["v4"],
v5: vreg = ["v5"],
v6: vreg = ["v6"],
v7: vreg = ["v7"],
v8: vreg = ["v8"],
v9: vreg = ["v9"],
v10: vreg = ["v10"],
v11: vreg = ["v11"],
v12: vreg = ["v12"],
v13: vreg = ["v13"],
v14: vreg = ["v14"],
v15: vreg = ["v15"],
v16: vreg = ["v16"],
v17: vreg = ["v17"],
v18: vreg = ["v18"],
v19: vreg = ["v19"],
v20: vreg = ["v20"],
v21: vreg = ["v21"],
v22: vreg = ["v22"],
v23: vreg = ["v23"],
v24: vreg = ["v24"],
v25: vreg = ["v25"],
v26: vreg = ["v26"],
v27: vreg = ["v27"],
v28: vreg = ["v28"],
v29: vreg = ["v29"],
v30: vreg = ["v30"],
v31: vreg = ["v31"],
v1_0: vreg_pair = ["v1:0"],
v3_2: vreg_pair = ["v3:2"],
v5_4: vreg_pair = ["v5:4"],
v7_6: vreg_pair = ["v7:6"],
v9_8: vreg_pair = ["v9:8"],
v11_10: vreg_pair = ["v11:10"],
v13_12: vreg_pair = ["v13:12"],
v15_14: vreg_pair = ["v15:14"],
v17_16: vreg_pair = ["v17:16"],
v19_18: vreg_pair = ["v19:18"],
v21_20: vreg_pair = ["v21:20"],
v23_22: vreg_pair = ["v23:22"],
v25_24: vreg_pair = ["v25:24"],
v27_26: vreg_pair = ["v27:26"],
v29_28: vreg_pair = ["v29:28"],
v31_30: vreg_pair = ["v31:30"],
q0: qreg = ["q0"],
q1: qreg = ["q1"],
q2: qreg = ["q2"],
q3: qreg = ["q3"],
#error = ["r19"] =>
"r19 is used internally by LLVM and cannot be used as an operand for inline asm",
#error = ["r19:18"] =>
"r19 is used internally by LLVM and cannot be used as an operand for inline asm",
#error = ["r29", "sp"] =>
"the stack pointer cannot be used as an operand for inline asm",
#error = ["r29:28"] =>
"the stack pointer cannot be used as an operand for inline asm",
#error = ["r30", "fr"] =>
"the frame register cannot be used as an operand for inline asm",
#error = ["r31", "lr"] =>
"the link register cannot be used as an operand for inline asm",
#error = ["r31:30"] =>
"the frame register and link register cannot be used as an operand for inline asm",
}
}
@@ -98,5 +183,68 @@ pub fn emit(
out.write_str(self.name())
}
pub fn overlapping_regs(self, mut _cb: impl FnMut(HexagonInlineAsmReg)) {}
pub fn overlapping_regs(self, mut cb: impl FnMut(HexagonInlineAsmReg)) {
cb(self);
macro_rules! reg_pair_conflicts {
(
$(
$pair:ident : $hi:ident $lo:ident,
)*
) => {
match self {
$(
Self::$pair => {
cb(Self::$hi);
cb(Self::$lo);
}
Self::$hi => {
cb(Self::$pair);
}
Self::$lo => {
cb(Self::$pair);
}
)*
_ => {}
}
};
}
// GPR pair ↔ single GPR conflicts
reg_pair_conflicts! {
r1_0 : r1 r0,
r3_2 : r3 r2,
r5_4 : r5 r4,
r7_6 : r7 r6,
r9_8 : r9 r8,
r11_10 : r11 r10,
r13_12 : r13 r12,
r15_14 : r15 r14,
r17_16 : r17 r16,
r21_20 : r21 r20,
r23_22 : r23 r22,
r25_24 : r25 r24,
r27_26 : r27 r26,
}
// HVX vector pair ↔ single vector conflicts
reg_pair_conflicts! {
v1_0 : v1 v0,
v3_2 : v3 v2,
v5_4 : v5 v4,
v7_6 : v7 v6,
v9_8 : v9 v8,
v11_10 : v11 v10,
v13_12 : v13 v12,
v15_14 : v15 v14,
v17_16 : v17 v16,
v19_18 : v19 v18,
v21_20 : v21 v20,
v23_22 : v23 v22,
v25_24 : v25 v24,
v27_26 : v27 v26,
v29_28 : v29 v28,
v31_30 : v31 v30,
}
}
}
+64 -1
View File
@@ -1,10 +1,11 @@
//@ add-minicore
//@ assembly-output: emit-asm
//@ compile-flags: --target hexagon-unknown-linux-musl
//@ compile-flags: -C target-feature=+hvx-length128b
//@ compile-flags: -Zmerge-functions=disabled
//@ needs-llvm-components: hexagon
#![feature(no_core, asm_experimental_arch)]
#![feature(no_core, repr_simd, asm_experimental_arch)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
@@ -14,6 +15,14 @@
type ptr = *const i32;
#[repr(simd)]
pub struct i32x32([i32; 32]); // 1024-bit HVX vector (128B mode)
impl Copy for i32x32 {}
#[repr(simd)]
pub struct i32x64([i32; 64]); // 2048-bit HVX vector pair (128B mode)
impl Copy for i32x64 {}
extern "C" {
fn extern_func();
static extern_static: u8;
@@ -137,3 +146,57 @@ pub unsafe fn packet() {
// CHECK: r0 = r0
// CHECK: InlineAsm End
check_reg!(r0_i16 i16 "r0");
// ===== Register pair (reg_pair) tests =====
// CHECK-LABEL: reg_pair_i64:
// CHECK: InlineAsm Start
// CHECK: r{{[0-9]+}}:{{[0-9]+}} = combine(r{{[0-9]+}},r{{[0-9]+}})
// CHECK: InlineAsm End
check!(reg_pair_i64 i64 reg_pair);
// CHECK-LABEL: reg_pair_f64:
// CHECK: InlineAsm Start
// CHECK: r{{[0-9]+}}:{{[0-9]+}} = combine(r{{[0-9]+}},r{{[0-9]+}})
// CHECK: InlineAsm End
check!(reg_pair_f64 f64 reg_pair);
// CHECK-LABEL: r1_0_i64:
// CHECK: InlineAsm Start
// CHECK: r1:0 = combine(r1,r0)
// CHECK: InlineAsm End
check_reg!(r1_0_i64 i64 "r1:0");
// CHECK-LABEL: r1_0_f64:
// CHECK: InlineAsm Start
// CHECK: r1:0 = combine(r1,r0)
// CHECK: InlineAsm End
check_reg!(r1_0_f64 f64 "r1:0");
// ===== HVX vector register (vreg) tests =====
// CHECK-LABEL: vreg_i32x32:
// CHECK: InlineAsm Start
// CHECK: v{{[0-9]+}} = v{{[0-9]+}}
// CHECK: InlineAsm End
check!(vreg_i32x32 i32x32 vreg);
// CHECK-LABEL: v0_i32x32:
// CHECK: InlineAsm Start
// CHECK: v0 = v0
// CHECK: InlineAsm End
check_reg!(v0_i32x32 i32x32 "v0");
// ===== HVX vector pair (vreg_pair) tests =====
// CHECK-LABEL: vreg_pair_i32x64:
// CHECK: InlineAsm Start
// CHECK: v{{[0-9]+}}:{{[0-9]+}} = vcombine(r{{[0-9]+}},r{{[0-9]+}})
// CHECK: InlineAsm End
check!(vreg_pair_i32x64 i32x64 vreg_pair);
// CHECK-LABEL: v1_0_i32x64:
// CHECK: InlineAsm Start
// CHECK: v1:0 = vcombine(r1,r0)
// CHECK: InlineAsm End
check_reg!(v1_0_i32x64 i32x64 "v1:0");
+114
View File
@@ -0,0 +1,114 @@
//@ add-minicore
//@ compile-flags: --target hexagon-unknown-linux-musl -C target-feature=+hvx-length128b
//@ needs-llvm-components: hexagon
//@ ignore-backends: gcc
//~? WARN unstable feature specified for `-Ctarget-feature`: `hvx-length128b`
#![crate_type = "lib"]
#![feature(no_core, asm_experimental_arch)]
#![no_core]
extern crate minicore;
use minicore::*;
fn f() {
let mut x: i32 = 0;
let mut y: i64 = 0;
unsafe {
// Blocked registers
asm!("", out("r19") _);
//~^ ERROR invalid register `r19`: r19 is used internally by LLVM and cannot be used as an operand for inline asm
asm!("", out("sp") _);
//~^ ERROR invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
asm!("", out("r29") _);
//~^ ERROR invalid register `r29`: the stack pointer cannot be used as an operand for inline asm
asm!("", out("r30") _);
//~^ ERROR invalid register `r30`: the frame register cannot be used as an operand for inline asm
asm!("", out("fr") _);
//~^ ERROR invalid register `fr`: the frame register cannot be used as an operand for inline asm
asm!("", out("r31") _);
//~^ ERROR invalid register `r31`: the link register cannot be used as an operand for inline asm
asm!("", out("lr") _);
//~^ ERROR invalid register `lr`: the link register cannot be used as an operand for inline asm
// Blocked register pairs
asm!("", out("r19:18") _);
//~^ ERROR invalid register `r19:18`: r19 is used internally by LLVM and cannot be used as an operand for inline asm
asm!("", out("r29:28") _);
//~^ ERROR invalid register `r29:28`: the stack pointer cannot be used as an operand for inline asm
asm!("", out("r31:30") _);
//~^ ERROR invalid register `r31:30`: the frame register and link register cannot be used as an operand for inline asm
// Clobber-only: preg
asm!("", out("p0") _); // ok (clobber)
asm!("", in("p0") x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
asm!("", out("p0") x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
// Clobber-only: qreg
asm!("", out("q0") _); // ok (clobber)
asm!("", in("q0") x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
asm!("", out("q0") x);
//~^ ERROR can only be used as a clobber
//~| ERROR type `i32` cannot be used with this register class
// Type mismatches: reg (supports i8, i16, i32, f32)
asm!("/* {} */", in(reg) y);
//~^ ERROR type `i64` cannot be used with this register class
// Type mismatches: reg_pair (supports i64, f64)
asm!("/* {} */", in(reg_pair) x);
//~^ ERROR type `i32` cannot be used with this register class
// Type mismatches: vreg (supports vector types only)
asm!("/* {} */", in(vreg) x);
//~^ ERROR type `i32` cannot be used with this register class
asm!("/* {} */", in(vreg) y);
//~^ ERROR type `i64` cannot be used with this register class
// Type mismatches: vreg_pair (supports vector types only)
asm!("/* {} */", in(vreg_pair) x);
//~^ ERROR type `i32` cannot be used with this register class
asm!("/* {} */", in(vreg_pair) y);
//~^ ERROR type `i64` cannot be used with this register class
// Valid usage: reg
asm!("", out("r0") _);
asm!("/* {} */", in(reg) x);
// Valid usage: reg_pair
asm!("", out("r1:0") _);
asm!("/* {} */", in(reg_pair) y);
// Valid usage: vreg clobber
asm!("", out("v0") _);
// Valid usage: vreg_pair clobber
asm!("", out("v1:0") _);
// Valid usage: qreg clobber
asm!("", out("q0") _);
// Register pair overlap: r0 and r1:0 conflict
asm!("", out("r0") _, out("r1:0") _);
//~^ ERROR register `r1:0` conflicts with register `r0`
asm!("", out("r1") _, out("r1:0") _);
//~^ ERROR register `r1:0` conflicts with register `r1`
// HVX vector pair overlap: v0 and v1:0 conflict
asm!("", out("v0") _, out("v1:0") _);
//~^ ERROR register `v1:0` conflicts with register `v0`
asm!("", out("v1") _, out("v1:0") _);
//~^ ERROR register `v1:0` conflicts with register `v1`
// Non-overlapping pair and single: no conflict
asm!("", out("r0") _, out("r3:2") _);
asm!("", out("v0") _, out("v3:2") _);
}
}
+202
View File
@@ -0,0 +1,202 @@
warning: unstable feature specified for `-Ctarget-feature`: `hvx-length128b`
|
= note: this feature is not stably supported; its behavior can change in the future
error: invalid register `r19`: r19 is used internally by LLVM and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:20:18
|
LL | asm!("", out("r19") _);
| ^^^^^^^^^^^^
error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:22:18
|
LL | asm!("", out("sp") _);
| ^^^^^^^^^^^
error: invalid register `r29`: the stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:24:18
|
LL | asm!("", out("r29") _);
| ^^^^^^^^^^^^
error: invalid register `r30`: the frame register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:26:18
|
LL | asm!("", out("r30") _);
| ^^^^^^^^^^^^
error: invalid register `fr`: the frame register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:28:18
|
LL | asm!("", out("fr") _);
| ^^^^^^^^^^^
error: invalid register `r31`: the link register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:30:18
|
LL | asm!("", out("r31") _);
| ^^^^^^^^^^^^
error: invalid register `lr`: the link register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:32:18
|
LL | asm!("", out("lr") _);
| ^^^^^^^^^^^
error: invalid register `r19:18`: r19 is used internally by LLVM and cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:36:18
|
LL | asm!("", out("r19:18") _);
| ^^^^^^^^^^^^^^^
error: invalid register `r29:28`: the stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:38:18
|
LL | asm!("", out("r29:28") _);
| ^^^^^^^^^^^^^^^
error: invalid register `r31:30`: the frame register and link register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:40:18
|
LL | asm!("", out("r31:30") _);
| ^^^^^^^^^^^^^^^
error: register class `preg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:45:18
|
LL | asm!("", in("p0") x);
| ^^^^^^^^^^
error: register class `preg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:48:18
|
LL | asm!("", out("p0") x);
| ^^^^^^^^^^^
error: register class `qreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:54:18
|
LL | asm!("", in("q0") x);
| ^^^^^^^^^^
error: register class `qreg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:57:18
|
LL | asm!("", out("q0") x);
| ^^^^^^^^^^^
error: register `r1:0` conflicts with register `r0`
--> $DIR/bad-reg.rs:99:31
|
LL | asm!("", out("r0") _, out("r1:0") _);
| ----------- ^^^^^^^^^^^^^ register `r1:0`
| |
| register `r0`
error: register `r1:0` conflicts with register `r1`
--> $DIR/bad-reg.rs:101:31
|
LL | asm!("", out("r1") _, out("r1:0") _);
| ----------- ^^^^^^^^^^^^^ register `r1:0`
| |
| register `r1`
error: register `v1:0` conflicts with register `v0`
--> $DIR/bad-reg.rs:105:31
|
LL | asm!("", out("v0") _, out("v1:0") _);
| ----------- ^^^^^^^^^^^^^ register `v1:0`
| |
| register `v0`
error: register `v1:0` conflicts with register `v1`
--> $DIR/bad-reg.rs:107:31
|
LL | asm!("", out("v1") _, out("v1:0") _);
| ----------- ^^^^^^^^^^^^^ register `v1:0`
| |
| register `v1`
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:45:27
|
LL | asm!("", in("p0") x);
| ^
|
= note: register class `preg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:48:28
|
LL | asm!("", out("p0") x);
| ^
|
= note: register class `preg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:54:27
|
LL | asm!("", in("q0") x);
| ^
|
= note: register class `qreg` supports these types:
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:57:28
|
LL | asm!("", out("q0") x);
| ^
|
= note: register class `qreg` supports these types:
error: type `i64` cannot be used with this register class
--> $DIR/bad-reg.rs:62:34
|
LL | asm!("/* {} */", in(reg) y);
| ^
|
= note: register class `reg` supports these types: i8, i16, i32, f32
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:66:39
|
LL | asm!("/* {} */", in(reg_pair) x);
| ^
|
= note: register class `reg_pair` supports these types: i64, f64
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:70:35
|
LL | asm!("/* {} */", in(vreg) x);
| ^
|
= note: register class `vreg` supports these types: i32x16, i32x32
error: type `i64` cannot be used with this register class
--> $DIR/bad-reg.rs:72:35
|
LL | asm!("/* {} */", in(vreg) y);
| ^
|
= note: register class `vreg` supports these types: i32x16, i32x32
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:76:40
|
LL | asm!("/* {} */", in(vreg_pair) x);
| ^
|
= note: register class `vreg_pair` supports these types: i32x32, i32x64
error: type `i64` cannot be used with this register class
--> $DIR/bad-reg.rs:78:40
|
LL | asm!("/* {} */", in(vreg_pair) y);
| ^
|
= note: register class `vreg_pair` supports these types: i32x32, i32x64
error: aborting due to 28 previous errors; 1 warning emitted