From 5a8ef029fd52347d991b029e1b10e8f293ed631c Mon Sep 17 00:00:00 2001 From: beetrees Date: Tue, 11 Aug 2026 22:37:26 +0100 Subject: [PATCH] Add floating point inline ASM support for SPARC --- compiler/rustc_codegen_gcc/src/asm.rs | 6 + compiler/rustc_codegen_llvm/src/asm.rs | 15 ++ compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/asm/mod.rs | 2 +- compiler/rustc_target/src/asm/sparc.rs | 200 +++++++++++++++++- tests/assembly-llvm/asm/sparc-types.rs | 93 ++++++-- tests/ui/asm/sparc/bad-reg.rs | 6 +- tests/ui/asm/sparc/bad-reg.sparc.stderr | 14 +- tests/ui/asm/sparc/reg-conflict.rs | 41 ++++ tests/ui/asm/sparc/reg-conflict.sparc.stderr | 82 +++++++ .../ui/asm/sparc/reg-conflict.sparc64.stderr | 82 +++++++ .../asm/sparc/reg-conflict.sparcv8plus.stderr | 82 +++++++ 12 files changed, 608 insertions(+), 16 deletions(-) create mode 100644 tests/ui/asm/sparc/reg-conflict.rs create mode 100644 tests/ui/asm/sparc/reg-conflict.sparc.stderr create mode 100644 tests/ui/asm/sparc/reg-conflict.sparc64.stderr create mode 100644 tests/ui/asm/sparc/reg-conflict.sparcv8plus.stderr diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index ee0cef350b42f..ac86fbe7428b0 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -790,6 +790,9 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str { unreachable!("clobber-only") } InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::dreg) => "e", + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::qreg) => "e", InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"), InlineAsmRegClass::Err => unreachable!(), } @@ -896,6 +899,9 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl unreachable!("clobber-only") } InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::freg) => cx.type_f32(), + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::dreg) => cx.type_f64(), + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::qreg) => cx.type_f128(), InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"), InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index fba43bba737e0..b4d3e8206cc07 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -733,6 +733,16 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> } else if reg == InlineAsmReg::Arm(ArmInlineAsmReg::r14) { // LLVM doesn't recognize r14 "{lr}".to_string() + } else if let InlineAsmReg::Sparc(reg) = reg + && let Some(num) = reg.dreg_number() + { + // LLVM numbers d registers sequentially (d0 => d0, d2 => d1, d4 => d2 etc.) + format!("{{d{}}}", num / 2) + } else if let InlineAsmReg::Sparc(reg) = reg + && let Some(num) = reg.qreg_number() + { + // LLVM numbers q registers sequentially (q0 => q0, q4 => q1, q8 => q2 etc.) + format!("{{q{}}}", num / 4) } else { format!("{{{}}}", reg.name()) } @@ -819,6 +829,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> unreachable!("clobber-only") } Sparc(SparcInlineAsmRegClass::reg) => "r", + Sparc(SparcInlineAsmRegClass::freg) => "f", + Sparc(SparcInlineAsmRegClass::dreg | SparcInlineAsmRegClass::qreg) => "e", Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"), Msp430(Msp430InlineAsmRegClass::reg) => "r", M68k(M68kInlineAsmRegClass::reg) => "r", @@ -1042,6 +1054,9 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' unreachable!("clobber-only") } Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(), + Sparc(SparcInlineAsmRegClass::freg) => cx.type_f32(), + Sparc(SparcInlineAsmRegClass::dreg) => cx.type_f64(), + Sparc(SparcInlineAsmRegClass::qreg) => cx.type_f128(), Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"), Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(), M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 07d6eb03ae8da..5a1636ac849b5 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2306,6 +2306,7 @@ symbols! { usize_legacy_mod, v1, v8plus, + v9, va_arg, va_arg_safe, va_copy, diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 8d99035fd0db4..3b594253082b7 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -477,7 +477,7 @@ impl InlineAsmReg { Self::LoongArch(r) => r.overlapping_regs(|r| cb(Self::LoongArch(r))), Self::Mips(_) => cb(self), Self::S390x(r) => r.overlapping_regs(|r| cb(Self::S390x(r))), - Self::Sparc(_) => cb(self), + Self::Sparc(r) => r.overlapping_regs(|r| cb(Self::Sparc(r))), Self::Xtensa(_) => cb(self), Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))), Self::Avr(r) => r.overlapping_regs(|r| cb(Self::Avr(r))), diff --git a/compiler/rustc_target/src/asm/sparc.rs b/compiler/rustc_target/src/asm/sparc.rs index 6261708642b28..2e79d995ab10b 100644 --- a/compiler/rustc_target/src/asm/sparc.rs +++ b/compiler/rustc_target/src/asm/sparc.rs @@ -1,7 +1,7 @@ use std::fmt; use rustc_data_structures::fx::FxIndexSet; -use rustc_span::Symbol; +use rustc_span::{Symbol, sym}; use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; use crate::spec::{RelocModel, Target}; @@ -9,6 +9,9 @@ use crate::spec::{RelocModel, Target}; def_reg_class! { Sparc SparcInlineAsmRegClass { reg, + freg, + dreg, + qreg, yreg, } } @@ -51,6 +54,9 @@ impl SparcInlineAsmRegClass { types! { _: I8, I16, I32, I64; } } } + Self::freg => types! { _: F32; }, + Self::dreg => types! { _: F64; }, + Self::qreg => types! { _: F128; }, Self::yreg => &[], } } @@ -75,6 +81,20 @@ fn reserved_g5( } } +fn v9_only( + _arch: InlineAsmArch, + _reloc_model: RelocModel, + target_features: &FxIndexSet, + _target: &Target, + _is_clobber: bool, +) -> Result<(), &'static str> { + if !target_features.contains(&sym::v9) { + Err("floating point registers in the upper half can only be used on SPARCv9") + } else { + Ok(()) + } +} + def_regs! { Sparc SparcInlineAsmReg SparcInlineAsmRegClass { // FIXME: @@ -107,6 +127,86 @@ def_regs! { r27: reg = ["r27", "i3"], // % reserved_i3 r28: reg = ["r28", "i4"], // % reserved_i4 r29: reg = ["r29", "i5"], // % reserved_i5 + f0: freg = ["f0"], + f1: freg = ["f1"], + f2: freg = ["f2"], + f3: freg = ["f3"], + f4: freg = ["f4"], + f5: freg = ["f5"], + f6: freg = ["f6"], + f7: freg = ["f7"], + f8: freg = ["f8"], + f9: freg = ["f9"], + f10: freg = ["f10"], + f11: freg = ["f11"], + f12: freg = ["f12"], + f13: freg = ["f13"], + f14: freg = ["f14"], + f15: freg = ["f15"], + f16: freg = ["f16"], + f17: freg = ["f17"], + f18: freg = ["f18"], + f19: freg = ["f19"], + f20: freg = ["f20"], + f21: freg = ["f21"], + f22: freg = ["f22"], + f23: freg = ["f23"], + f24: freg = ["f24"], + f25: freg = ["f25"], + f26: freg = ["f26"], + f27: freg = ["f27"], + f28: freg = ["f28"], + f29: freg = ["f29"], + f30: freg = ["f30"], + f31: freg = ["f31"], + d0: dreg = ["d0"], + d2: dreg = ["d2"], + d4: dreg = ["d4"], + d6: dreg = ["d6"], + d8: dreg = ["d8"], + d10: dreg = ["d10"], + d12: dreg = ["d12"], + d14: dreg = ["d14"], + d16: dreg = ["d16"], + d18: dreg = ["d18"], + d20: dreg = ["d20"], + d22: dreg = ["d22"], + d24: dreg = ["d24"], + d26: dreg = ["d26"], + d28: dreg = ["d28"], + d30: dreg = ["d30"], + d32: dreg = ["d32"] % v9_only, + d34: dreg = ["d34"] % v9_only, + d36: dreg = ["d36"] % v9_only, + d38: dreg = ["d38"] % v9_only, + d40: dreg = ["d40"] % v9_only, + d42: dreg = ["d42"] % v9_only, + d44: dreg = ["d44"] % v9_only, + d46: dreg = ["d46"] % v9_only, + d48: dreg = ["d48"] % v9_only, + d50: dreg = ["d50"] % v9_only, + d52: dreg = ["d52"] % v9_only, + d54: dreg = ["d54"] % v9_only, + d56: dreg = ["d56"] % v9_only, + d58: dreg = ["d58"] % v9_only, + d60: dreg = ["d60"] % v9_only, + d62: dreg = ["d62"] % v9_only, + q0: qreg = ["q0"], + q4: qreg = ["q4"], + q8: qreg = ["q8"], + q12: qreg = ["q12"], + q16: qreg = ["q16"], + q20: qreg = ["q20"], + q24: qreg = ["q24"], + q28: qreg = ["q28"], + q32: qreg = ["q32"] % v9_only, + q36: qreg = ["q36"] % v9_only, + q40: qreg = ["q40"] % v9_only, + q44: qreg = ["q44"] % v9_only, + q48: qreg = ["q48"] % v9_only, + q52: qreg = ["q52"] % v9_only, + q56: qreg = ["q56"] % v9_only, + q60: qreg = ["q60"] % v9_only, y: yreg = ["y"], #error = ["r0", "g0"] => "g0 is always zero and cannot be used as an operand for inline asm", @@ -135,4 +235,102 @@ impl SparcInlineAsmReg { ) -> fmt::Result { write!(out, "%{}", self.name()) } + + pub fn overlapping_regs(self, mut cb: impl FnMut(SparcInlineAsmReg)) { + cb(self); + + macro_rules! reg_conflicts { + ( + $( + $q:ident : $d0:ident $d1:ident : $f0:ident $f1:ident $f2:ident $f3:ident + ),*; + $( + $q_high:ident : $d0_high:ident $d1_high:ident + ),*; + ) => { + match self { + $( + Self::$q => { + cb(Self::$d0); + cb(Self::$d1); + cb(Self::$f0); + cb(Self::$f1); + cb(Self::$f2); + cb(Self::$f3); + } + Self::$d0 => { + cb(Self::$q); + cb(Self::$f0); + cb(Self::$f1); + } + Self::$d1 => { + cb(Self::$q); + cb(Self::$f2); + cb(Self::$f3); + } + Self::$f0 | Self::$f1 => { + cb(Self::$q); + cb(Self::$d0); + } + Self::$f2 | Self::$f3 => { + cb(Self::$q); + cb(Self::$d1); + } + )* + $( + Self::$q_high => { + cb(Self::$d0_high); + cb(Self::$d1_high); + } + Self::$d0_high | Self::$d1_high => { + cb(Self::$q_high); + } + )* + _ => {}, + } + }; + } + + // SPARC's floating-point register file is interesting in that it can be + // viewed as 16 128-bit registers, 32 64-bit registers or 32 32-bit + // registers. Because these views overlap, the registers of different + // widths will conflict (e.g. d0 overlaps with f0 and f1, and q1 + // overlaps with d2 and d3). + // + // See section 3.1.2 of The SPARC Architecture Manual: Version 9 for details. + reg_conflicts! { + q0 : d0 d2 : f0 f1 f2 f3, + q4 : d4 d6 : f4 f5 f6 f7, + q8 : d8 d10 : f8 f9 f10 f11, + q12 : d12 d14 : f12 f13 f14 f15, + q16 : d16 d18 : f16 f17 f18 f19, + q20 : d20 d22 : f20 f21 f22 f23, + q24 : d24 d26 : f24 f25 f26 f27, + q28 : d28 d30 : f28 f29 f30 f31; + q32 : d32 d34, + q36 : d36 d38, + q40 : d40 d42, + q44 : d44 d46, + q48 : d48 d50, + q52 : d52 d54, + q56 : d56 d58, + q60 : d60 d62; + } + } + + pub fn dreg_number(self) -> Option { + if self >= Self::d0 && self <= Self::d62 { + Some((self as u32 - Self::d0 as u32) * 2) + } else { + None + } + } + + pub fn qreg_number(self) -> Option { + if self >= Self::q0 && self <= Self::q60 { + Some((self as u32 - Self::q0 as u32) * 4) + } else { + None + } + } } diff --git a/tests/assembly-llvm/asm/sparc-types.rs b/tests/assembly-llvm/asm/sparc-types.rs index 3eb3528991efd..f4e3bb86ee5bc 100644 --- a/tests/assembly-llvm/asm/sparc-types.rs +++ b/tests/assembly-llvm/asm/sparc-types.rs @@ -3,17 +3,26 @@ //@ assembly-output: emit-asm //@[sparc] compile-flags: --target sparc-unknown-none-elf //@[sparc] needs-llvm-components: sparc -//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu +//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu --cfg v9 //@[sparcv8plus] needs-llvm-components: sparc -//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu +//@[sparcv8plus] filecheck-flags: --check-prefix v9 +//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu --cfg v9 //@[sparc64] needs-llvm-components: sparc +//@[sparc64] filecheck-flags: --check-prefix v9 //@ compile-flags: -Zmerge-functions=disabled +//@ compile-flags: --check-cfg=cfg(v9) +//@ min-llvm-version: 22 -#![feature(no_core, asm_experimental_arch)] +#![deny(unexpected_cfgs)] +#![feature(no_core, asm_experimental_arch, f128)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] +#[cfg_attr(v9, cfg(not(target_feature = "v9")))] +#[cfg_attr(not(v9), cfg(target_feature = "v9"))] +compile_error!("v9 cfg mismatch"); + extern crate minicore; use minicore::*; @@ -25,7 +34,7 @@ extern "C" { } macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { - #[no_mangle] + #[unsafe(no_mangle)] pub unsafe fn $func(x: $ty) -> $ty { let y; asm!(concat!($mov," {}, {}"), in($class) x, out($class) y); @@ -33,14 +42,24 @@ macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { } };} -macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { - #[no_mangle] - pub unsafe fn $func(x: $ty) -> $ty { - let y; - asm!(concat!($mov, " %", $reg, ", %", $reg), in($reg) x, lateout($reg) y); - y - } -};} +macro_rules! check_reg { + ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { + #[unsafe(no_mangle)] + pub unsafe fn $func(x: $ty) -> $ty { + let y; + asm!(concat!($mov, " %", $reg, ", %", $reg), in($reg) x, lateout($reg) y); + y + } + }; + ($func:ident, $ty:ty, $reg:tt, $asm_reg:tt, $mov:literal) => { + #[unsafe(no_mangle)] + pub unsafe fn $func(x: $ty) -> $ty { + let y; + asm!(concat!($mov, " %", $asm_reg, ", %", $asm_reg), in($reg) x, lateout($reg) y); + y + } + }; +} // CHECK-LABEL: sym_fn_32: // CHECK: !APP @@ -143,3 +162,53 @@ check_reg!(r9_i32, i32, "r9", "mov"); // sparc64-NEXT: !NO_APP #[cfg(sparc64)] check_reg!(r9_i64, i64, "r9", "mov"); + +// CHECK-LABEL: freg_f32: +// CHECK: !APP +// CHECK-NEXT: fmovs %f{{[0-9]+}}, %f{{[0-9]+}} +// CHECK-NEXT: !NO_APP +check!(freg_f32, f32, freg, "fmovs"); + +// CHECK-LABEL: dreg_f64: +// CHECK: !APP +// CHECK-NEXT: fmovs %f{{[0-9]+}}, %f{{[0-9]+}} +// CHECK-NEXT: !NO_APP +check!(dreg_f64, f64, dreg, "fmovs"); + +// CHECK-LABEL: qreg_f128: +// CHECK: !APP +// CHECK-NEXT: fmovs %f{{[0-9]+}}, %f{{[0-9]+}} +// CHECK-NEXT: !NO_APP +check!(qreg_f128, f128, qreg, "fmovs"); + +// CHECK-LABEL: f0_f32: +// CHECK: !APP +// CHECK-NEXT: fmovs %f0, %f0 +// CHECK-NEXT: !NO_APP +check_reg!(f0_f32, f32, "f0", "fmovs"); + +// CHECK-LABEL: d0_f64: +// CHECK: !APP +// CHECK-NEXT: fmovs %f0, %f0 +// CHECK-NEXT: !NO_APP +check_reg!(d0_f64, f64, "d0", "f0", "fmovs"); + +// CHECK-LABEL: q0_f128: +// CHECK: !APP +// CHECK-NEXT: fmovs %f0, %f0 +// CHECK-NEXT: !NO_APP +check_reg!(q0_f128, f128, "q0", "f0", "fmovs"); + +// v9-LABEL: d62_f64: +// v9: !APP +// v9-NEXT: fmovd %f62, %f62 +// v9-NEXT: !NO_APP +#[cfg(v9)] +check_reg!(d62_f64, f64, "d62", "f62", "fmovd"); + +// v9-LABEL: q60_f128: +// v9: !APP +// v9-NEXT: fmovd %f60, %f60 +// v9-NEXT: !NO_APP +#[cfg(v9)] +check_reg!(q60_f128, f128, "q60", "f60", "fmovd"); diff --git a/tests/ui/asm/sparc/bad-reg.rs b/tests/ui/asm/sparc/bad-reg.rs index c44f6c5790bf9..8cac5eb6b4ad0 100644 --- a/tests/ui/asm/sparc/bad-reg.rs +++ b/tests/ui/asm/sparc/bad-reg.rs @@ -9,7 +9,7 @@ //@ ignore-backends: gcc #![crate_type = "rlib"] -#![feature(no_core, asm_experimental_arch)] +#![feature(no_core, asm_experimental_arch, f128)] #![no_core] extern crate minicore; @@ -54,5 +54,9 @@ fn f() { //~| ERROR type `i32` cannot be used with this register class asm!("/* {} */", out(yreg) _); //~^ ERROR can only be used as a clobber + asm!("", in("d62") 0.0_f64); + //[sparc]~^ ERROR cannot use register `d62` + asm!("", in("q60") 0.0_f128); + //[sparc]~^ ERROR cannot use register `q60` } } diff --git a/tests/ui/asm/sparc/bad-reg.sparc.stderr b/tests/ui/asm/sparc/bad-reg.sparc.stderr index e0580ad3232f5..06b607ff007ac 100644 --- a/tests/ui/asm/sparc/bad-reg.sparc.stderr +++ b/tests/ui/asm/sparc/bad-reg.sparc.stderr @@ -94,5 +94,17 @@ LL | asm!("/* {} */", in(yreg) x); | = note: register class `yreg` supports these types: -error: aborting due to 15 previous errors +error: cannot use register `d62`: floating point registers in the upper half can only be used on SPARCv9 + --> $DIR/bad-reg.rs:57:18 + | +LL | asm!("", in("d62") 0.0_f64); + | ^^^^^^^^^^^^^^^^^ + +error: cannot use register `q60`: floating point registers in the upper half can only be used on SPARCv9 + --> $DIR/bad-reg.rs:59:18 + | +LL | asm!("", in("q60") 0.0_f128); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 17 previous errors diff --git a/tests/ui/asm/sparc/reg-conflict.rs b/tests/ui/asm/sparc/reg-conflict.rs new file mode 100644 index 0000000000000..70e138733042c --- /dev/null +++ b/tests/ui/asm/sparc/reg-conflict.rs @@ -0,0 +1,41 @@ +//@ add-minicore +//@ revisions: sparc sparcv8plus sparc64 +//@[sparc] compile-flags: --target sparc-unknown-none-elf +//@[sparc] needs-llvm-components: sparc +//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu +//@[sparcv8plus] needs-llvm-components: sparc +//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu +//@[sparc64] needs-llvm-components: sparc +//@ ignore-backends: gcc + +#![crate_type = "rlib"] +#![feature(no_core, asm_experimental_arch, f128)] +#![no_core] + +extern crate minicore; +use minicore::*; + +fn f() { + unsafe { + asm!("", in("f6") 0.0_f32, in("d6") 0.0_f64); + //~^ ERROR register `d6` conflicts with register `f6` + asm!("", in("f7") 0.0_f32, in("d6") 0.0_f64); + //~^ ERROR register `d6` conflicts with register `f7` + asm!("", in("f8") 0.0_f32, in("q8") 0.0_f128); + //~^ ERROR register `q8` conflicts with register `f8` + asm!("", in("f9") 0.0_f32, in("q8") 0.0_f128); + //~^ ERROR register `q8` conflicts with register `f9` + asm!("", in("f10") 0.0_f32, in("q8") 0.0_f128); + //~^ ERROR register `q8` conflicts with register `f10` + asm!("", in("f11") 0.0_f32, in("q8") 0.0_f128); + //~^ ERROR register `q8` conflicts with register `f11` + asm!("", in("d12") 0.0_f64, in("q12") 0.0_f128); + //~^ ERROR register `q12` conflicts with register `d12` + asm!("", in("d12") 0.0_f64, in("q12") 0.0_f128); + //~^ ERROR register `q12` conflicts with register `d12` + asm!("", in("d14") 0.0_f64, in("q12") 0.0_f128); + //~^ ERROR register `q12` conflicts with register `d14` + asm!("", in("d14") 0.0_f64, in("q12") 0.0_f128); + //~^ ERROR register `q12` conflicts with register `d14` + } +} diff --git a/tests/ui/asm/sparc/reg-conflict.sparc.stderr b/tests/ui/asm/sparc/reg-conflict.sparc.stderr new file mode 100644 index 0000000000000..fef74ef77b36d --- /dev/null +++ b/tests/ui/asm/sparc/reg-conflict.sparc.stderr @@ -0,0 +1,82 @@ +error: register `d6` conflicts with register `f6` + --> $DIR/reg-conflict.rs:20:36 + | +LL | asm!("", in("f6") 0.0_f32, in("d6") 0.0_f64); + | ---------------- ^^^^^^^^^^^^^^^^ register `d6` + | | + | register `f6` + +error: register `d6` conflicts with register `f7` + --> $DIR/reg-conflict.rs:22:36 + | +LL | asm!("", in("f7") 0.0_f32, in("d6") 0.0_f64); + | ---------------- ^^^^^^^^^^^^^^^^ register `d6` + | | + | register `f7` + +error: register `q8` conflicts with register `f8` + --> $DIR/reg-conflict.rs:24:36 + | +LL | asm!("", in("f8") 0.0_f32, in("q8") 0.0_f128); + | ---------------- ^^^^^^^^^^^^^^^^^ register `q8` + | | + | register `f8` + +error: register `q8` conflicts with register `f9` + --> $DIR/reg-conflict.rs:26:36 + | +LL | asm!("", in("f9") 0.0_f32, in("q8") 0.0_f128); + | ---------------- ^^^^^^^^^^^^^^^^^ register `q8` + | | + | register `f9` + +error: register `q8` conflicts with register `f10` + --> $DIR/reg-conflict.rs:28:37 + | +LL | asm!("", in("f10") 0.0_f32, in("q8") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^ register `q8` + | | + | register `f10` + +error: register `q8` conflicts with register `f11` + --> $DIR/reg-conflict.rs:30:37 + | +LL | asm!("", in("f11") 0.0_f32, in("q8") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^ register `q8` + | | + | register `f11` + +error: register `q12` conflicts with register `d12` + --> $DIR/reg-conflict.rs:32:37 + | +LL | asm!("", in("d12") 0.0_f64, in("q12") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^^ register `q12` + | | + | register `d12` + +error: register `q12` conflicts with register `d12` + --> $DIR/reg-conflict.rs:34:37 + | +LL | asm!("", in("d12") 0.0_f64, in("q12") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^^ register `q12` + | | + | register `d12` + +error: register `q12` conflicts with register `d14` + --> $DIR/reg-conflict.rs:36:37 + | +LL | asm!("", in("d14") 0.0_f64, in("q12") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^^ register `q12` + | | + | register `d14` + +error: register `q12` conflicts with register `d14` + --> $DIR/reg-conflict.rs:38:37 + | +LL | asm!("", in("d14") 0.0_f64, in("q12") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^^ register `q12` + | | + | register `d14` + +error: aborting due to 10 previous errors + diff --git a/tests/ui/asm/sparc/reg-conflict.sparc64.stderr b/tests/ui/asm/sparc/reg-conflict.sparc64.stderr new file mode 100644 index 0000000000000..fef74ef77b36d --- /dev/null +++ b/tests/ui/asm/sparc/reg-conflict.sparc64.stderr @@ -0,0 +1,82 @@ +error: register `d6` conflicts with register `f6` + --> $DIR/reg-conflict.rs:20:36 + | +LL | asm!("", in("f6") 0.0_f32, in("d6") 0.0_f64); + | ---------------- ^^^^^^^^^^^^^^^^ register `d6` + | | + | register `f6` + +error: register `d6` conflicts with register `f7` + --> $DIR/reg-conflict.rs:22:36 + | +LL | asm!("", in("f7") 0.0_f32, in("d6") 0.0_f64); + | ---------------- ^^^^^^^^^^^^^^^^ register `d6` + | | + | register `f7` + +error: register `q8` conflicts with register `f8` + --> $DIR/reg-conflict.rs:24:36 + | +LL | asm!("", in("f8") 0.0_f32, in("q8") 0.0_f128); + | ---------------- ^^^^^^^^^^^^^^^^^ register `q8` + | | + | register `f8` + +error: register `q8` conflicts with register `f9` + --> $DIR/reg-conflict.rs:26:36 + | +LL | asm!("", in("f9") 0.0_f32, in("q8") 0.0_f128); + | ---------------- ^^^^^^^^^^^^^^^^^ register `q8` + | | + | register `f9` + +error: register `q8` conflicts with register `f10` + --> $DIR/reg-conflict.rs:28:37 + | +LL | asm!("", in("f10") 0.0_f32, in("q8") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^ register `q8` + | | + | register `f10` + +error: register `q8` conflicts with register `f11` + --> $DIR/reg-conflict.rs:30:37 + | +LL | asm!("", in("f11") 0.0_f32, in("q8") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^ register `q8` + | | + | register `f11` + +error: register `q12` conflicts with register `d12` + --> $DIR/reg-conflict.rs:32:37 + | +LL | asm!("", in("d12") 0.0_f64, in("q12") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^^ register `q12` + | | + | register `d12` + +error: register `q12` conflicts with register `d12` + --> $DIR/reg-conflict.rs:34:37 + | +LL | asm!("", in("d12") 0.0_f64, in("q12") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^^ register `q12` + | | + | register `d12` + +error: register `q12` conflicts with register `d14` + --> $DIR/reg-conflict.rs:36:37 + | +LL | asm!("", in("d14") 0.0_f64, in("q12") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^^ register `q12` + | | + | register `d14` + +error: register `q12` conflicts with register `d14` + --> $DIR/reg-conflict.rs:38:37 + | +LL | asm!("", in("d14") 0.0_f64, in("q12") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^^ register `q12` + | | + | register `d14` + +error: aborting due to 10 previous errors + diff --git a/tests/ui/asm/sparc/reg-conflict.sparcv8plus.stderr b/tests/ui/asm/sparc/reg-conflict.sparcv8plus.stderr new file mode 100644 index 0000000000000..fef74ef77b36d --- /dev/null +++ b/tests/ui/asm/sparc/reg-conflict.sparcv8plus.stderr @@ -0,0 +1,82 @@ +error: register `d6` conflicts with register `f6` + --> $DIR/reg-conflict.rs:20:36 + | +LL | asm!("", in("f6") 0.0_f32, in("d6") 0.0_f64); + | ---------------- ^^^^^^^^^^^^^^^^ register `d6` + | | + | register `f6` + +error: register `d6` conflicts with register `f7` + --> $DIR/reg-conflict.rs:22:36 + | +LL | asm!("", in("f7") 0.0_f32, in("d6") 0.0_f64); + | ---------------- ^^^^^^^^^^^^^^^^ register `d6` + | | + | register `f7` + +error: register `q8` conflicts with register `f8` + --> $DIR/reg-conflict.rs:24:36 + | +LL | asm!("", in("f8") 0.0_f32, in("q8") 0.0_f128); + | ---------------- ^^^^^^^^^^^^^^^^^ register `q8` + | | + | register `f8` + +error: register `q8` conflicts with register `f9` + --> $DIR/reg-conflict.rs:26:36 + | +LL | asm!("", in("f9") 0.0_f32, in("q8") 0.0_f128); + | ---------------- ^^^^^^^^^^^^^^^^^ register `q8` + | | + | register `f9` + +error: register `q8` conflicts with register `f10` + --> $DIR/reg-conflict.rs:28:37 + | +LL | asm!("", in("f10") 0.0_f32, in("q8") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^ register `q8` + | | + | register `f10` + +error: register `q8` conflicts with register `f11` + --> $DIR/reg-conflict.rs:30:37 + | +LL | asm!("", in("f11") 0.0_f32, in("q8") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^ register `q8` + | | + | register `f11` + +error: register `q12` conflicts with register `d12` + --> $DIR/reg-conflict.rs:32:37 + | +LL | asm!("", in("d12") 0.0_f64, in("q12") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^^ register `q12` + | | + | register `d12` + +error: register `q12` conflicts with register `d12` + --> $DIR/reg-conflict.rs:34:37 + | +LL | asm!("", in("d12") 0.0_f64, in("q12") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^^ register `q12` + | | + | register `d12` + +error: register `q12` conflicts with register `d14` + --> $DIR/reg-conflict.rs:36:37 + | +LL | asm!("", in("d14") 0.0_f64, in("q12") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^^ register `q12` + | | + | register `d14` + +error: register `q12` conflicts with register `d14` + --> $DIR/reg-conflict.rs:38:37 + | +LL | asm!("", in("d14") 0.0_f64, in("q12") 0.0_f128); + | ----------------- ^^^^^^^^^^^^^^^^^^ register `q12` + | | + | register `d14` + +error: aborting due to 10 previous errors +