Auto merge of #132472 - taiki-e:sparc-asm, r=Amanieu
Basic inline assembly support for SPARC and SPARC64
This implements asm_experimental_arch (tracking issue https://github.com/rust-lang/rust/issues/93335) for SPARC and SPARC64.
This PR includes:
- General-purpose registers `r[0-31]` (`reg` register class, LLVM/GCC constraint `r`)
Supported types: i8, i16, i32, i64 (SPARC64-only)
Aliases: `g[0-7]` (`r[0-7]`), `o[0-7]` (`r[8-15]`), `l[0-7]` (`r[16-23]`), `i[0-7]` (`r[24-31]`)
- `y` register (clobber-only, needed for clobber_abi)
- preserves_flags: Integer condition codes (`icc`, `xcc`) and floating-point condition codes (`fcc*`)
The following are *not* included:
- 64-bit integer support on SPARC-V8+'s global or out registers (`g[0-7]`, `o[0-7]`): GCC's `h` constraint (it seems that there is no corresponding constraint in LLVM?)
- Floating-point registers (LLVM/GCC constraint `e`/`f`):
I initially tried to implement this, but postponed it for now because there seemed to be several parts in LLVM that behaved differently than in the LangRef's description.
- clobber_abi: Support for floating-point registers is needed.
Refs:
- LLVM
- Reserved registers https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp#L52
- Register definitions https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.td
- Supported constraints https://llvm.org/docs/LangRef.html#supported-constraint-code-list
- GCC
- Reserved registers 63b6967b06/gcc/config/sparc/sparc.h (L633-L658)
- Supported constraints https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
- SPARC ISA/ABI
- (64-bit ISA) The SPARC Architecture Manual, Version 9
(32-bit ISA) The SPARC Architecture Manual, Version 8
(64-bit ABI) System V Application Binary Interface SPARC Version 9 Processor Supplement, Rev 1.35
(32-bit ABI) System V Application Binary Interface SPARC Processor Supplement, Third Edition
The above docs can be downloaded from https://sparc.org/technical-documents
- (32-bit V8+ ABI) The V8+ Technical Specification
https://temlib.org/pub/SparcStation/Standards/V8plus.pdf
cc `@thejpster` (sparc-unknown-none-elf target maintainer)
(AFAIK, other sparc/sprac64 targets don't have target maintainers)
r? `@Amanieu`
`@rustbot` label +O-SPARC +A-inline-assembly
This commit is contained in:
commit
b91a3a0560
@ -688,6 +688,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
|
|||||||
) => {
|
) => {
|
||||||
unreachable!("clobber-only")
|
unreachable!("clobber-only")
|
||||||
}
|
}
|
||||||
|
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r",
|
||||||
|
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
|
||||||
InlineAsmRegClass::Err => unreachable!(),
|
InlineAsmRegClass::Err => unreachable!(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -767,6 +769,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
|
|||||||
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => {
|
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => {
|
||||||
unreachable!("clobber-only")
|
unreachable!("clobber-only")
|
||||||
}
|
}
|
||||||
|
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(),
|
||||||
|
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
|
||||||
InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(),
|
InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(),
|
||||||
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(),
|
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(),
|
||||||
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(),
|
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(),
|
||||||
@ -946,6 +950,7 @@ fn modifier_to_gcc(
|
|||||||
},
|
},
|
||||||
InlineAsmRegClass::Avr(_) => None,
|
InlineAsmRegClass::Avr(_) => None,
|
||||||
InlineAsmRegClass::S390x(_) => None,
|
InlineAsmRegClass::S390x(_) => None,
|
||||||
|
InlineAsmRegClass::Sparc(_) => None,
|
||||||
InlineAsmRegClass::Msp430(_) => None,
|
InlineAsmRegClass::Msp430(_) => None,
|
||||||
InlineAsmRegClass::M68k(_) => None,
|
InlineAsmRegClass::M68k(_) => None,
|
||||||
InlineAsmRegClass::CSKY(_) => None,
|
InlineAsmRegClass::CSKY(_) => None,
|
||||||
|
@ -268,6 +268,15 @@ fn codegen_inline_asm(
|
|||||||
InlineAsmArch::S390x => {
|
InlineAsmArch::S390x => {
|
||||||
constraints.push("~{cc}".to_string());
|
constraints.push("~{cc}".to_string());
|
||||||
}
|
}
|
||||||
|
InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => {
|
||||||
|
// In LLVM, ~{icc} represents icc and xcc in 64-bit code.
|
||||||
|
// https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.td#L64
|
||||||
|
constraints.push("~{icc}".to_string());
|
||||||
|
constraints.push("~{fcc0}".to_string());
|
||||||
|
constraints.push("~{fcc1}".to_string());
|
||||||
|
constraints.push("~{fcc2}".to_string());
|
||||||
|
constraints.push("~{fcc3}".to_string());
|
||||||
|
}
|
||||||
InlineAsmArch::SpirV => {}
|
InlineAsmArch::SpirV => {}
|
||||||
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {}
|
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {}
|
||||||
InlineAsmArch::Bpf => {}
|
InlineAsmArch::Bpf => {}
|
||||||
@ -672,6 +681,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
|
|||||||
S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => {
|
S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => {
|
||||||
unreachable!("clobber-only")
|
unreachable!("clobber-only")
|
||||||
}
|
}
|
||||||
|
Sparc(SparcInlineAsmRegClass::reg) => "r",
|
||||||
|
Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
|
||||||
Msp430(Msp430InlineAsmRegClass::reg) => "r",
|
Msp430(Msp430InlineAsmRegClass::reg) => "r",
|
||||||
M68k(M68kInlineAsmRegClass::reg) => "r",
|
M68k(M68kInlineAsmRegClass::reg) => "r",
|
||||||
M68k(M68kInlineAsmRegClass::reg_addr) => "a",
|
M68k(M68kInlineAsmRegClass::reg_addr) => "a",
|
||||||
@ -765,6 +776,7 @@ fn modifier_to_llvm(
|
|||||||
},
|
},
|
||||||
Avr(_) => None,
|
Avr(_) => None,
|
||||||
S390x(_) => None,
|
S390x(_) => None,
|
||||||
|
Sparc(_) => None,
|
||||||
Msp430(_) => None,
|
Msp430(_) => None,
|
||||||
SpirV(SpirVInlineAsmRegClass::reg) => bug!("LLVM backend does not support SPIR-V"),
|
SpirV(SpirVInlineAsmRegClass::reg) => bug!("LLVM backend does not support SPIR-V"),
|
||||||
M68k(_) => None,
|
M68k(_) => None,
|
||||||
@ -835,6 +847,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
|
|||||||
S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => {
|
S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => {
|
||||||
unreachable!("clobber-only")
|
unreachable!("clobber-only")
|
||||||
}
|
}
|
||||||
|
Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(),
|
||||||
|
Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
|
||||||
Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(),
|
Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(),
|
||||||
M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(),
|
M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(),
|
||||||
M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(),
|
M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(),
|
||||||
|
@ -2175,6 +2175,7 @@
|
|||||||
yes,
|
yes,
|
||||||
yield_expr,
|
yield_expr,
|
||||||
ymm_reg,
|
ymm_reg,
|
||||||
|
yreg,
|
||||||
zfh,
|
zfh,
|
||||||
zfhmin,
|
zfhmin,
|
||||||
zmm_reg,
|
zmm_reg,
|
||||||
|
@ -191,6 +191,7 @@ macro_rules! types {
|
|||||||
mod powerpc;
|
mod powerpc;
|
||||||
mod riscv;
|
mod riscv;
|
||||||
mod s390x;
|
mod s390x;
|
||||||
|
mod sparc;
|
||||||
mod spirv;
|
mod spirv;
|
||||||
mod wasm;
|
mod wasm;
|
||||||
mod x86;
|
mod x86;
|
||||||
@ -209,6 +210,7 @@ macro_rules! types {
|
|||||||
pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass};
|
pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass};
|
||||||
pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
|
pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
|
||||||
pub use s390x::{S390xInlineAsmReg, S390xInlineAsmRegClass};
|
pub use s390x::{S390xInlineAsmReg, S390xInlineAsmRegClass};
|
||||||
|
pub use sparc::{SparcInlineAsmReg, SparcInlineAsmRegClass};
|
||||||
pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass};
|
pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass};
|
||||||
pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass};
|
pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass};
|
||||||
pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass};
|
pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass};
|
||||||
@ -230,6 +232,8 @@ pub enum InlineAsmArch {
|
|||||||
PowerPC,
|
PowerPC,
|
||||||
PowerPC64,
|
PowerPC64,
|
||||||
S390x,
|
S390x,
|
||||||
|
Sparc,
|
||||||
|
Sparc64,
|
||||||
SpirV,
|
SpirV,
|
||||||
Wasm32,
|
Wasm32,
|
||||||
Wasm64,
|
Wasm64,
|
||||||
@ -260,6 +264,8 @@ fn from_str(s: &str) -> Result<InlineAsmArch, ()> {
|
|||||||
"mips" | "mips32r6" => Ok(Self::Mips),
|
"mips" | "mips32r6" => Ok(Self::Mips),
|
||||||
"mips64" | "mips64r6" => Ok(Self::Mips64),
|
"mips64" | "mips64r6" => Ok(Self::Mips64),
|
||||||
"s390x" => Ok(Self::S390x),
|
"s390x" => Ok(Self::S390x),
|
||||||
|
"sparc" => Ok(Self::Sparc),
|
||||||
|
"sparc64" => Ok(Self::Sparc64),
|
||||||
"spirv" => Ok(Self::SpirV),
|
"spirv" => Ok(Self::SpirV),
|
||||||
"wasm32" => Ok(Self::Wasm32),
|
"wasm32" => Ok(Self::Wasm32),
|
||||||
"wasm64" => Ok(Self::Wasm64),
|
"wasm64" => Ok(Self::Wasm64),
|
||||||
@ -286,6 +292,7 @@ pub enum InlineAsmReg {
|
|||||||
LoongArch(LoongArchInlineAsmReg),
|
LoongArch(LoongArchInlineAsmReg),
|
||||||
Mips(MipsInlineAsmReg),
|
Mips(MipsInlineAsmReg),
|
||||||
S390x(S390xInlineAsmReg),
|
S390x(S390xInlineAsmReg),
|
||||||
|
Sparc(SparcInlineAsmReg),
|
||||||
SpirV(SpirVInlineAsmReg),
|
SpirV(SpirVInlineAsmReg),
|
||||||
Wasm(WasmInlineAsmReg),
|
Wasm(WasmInlineAsmReg),
|
||||||
Bpf(BpfInlineAsmReg),
|
Bpf(BpfInlineAsmReg),
|
||||||
@ -309,6 +316,7 @@ pub fn name(self) -> &'static str {
|
|||||||
Self::LoongArch(r) => r.name(),
|
Self::LoongArch(r) => r.name(),
|
||||||
Self::Mips(r) => r.name(),
|
Self::Mips(r) => r.name(),
|
||||||
Self::S390x(r) => r.name(),
|
Self::S390x(r) => r.name(),
|
||||||
|
Self::Sparc(r) => r.name(),
|
||||||
Self::Bpf(r) => r.name(),
|
Self::Bpf(r) => r.name(),
|
||||||
Self::Avr(r) => r.name(),
|
Self::Avr(r) => r.name(),
|
||||||
Self::Msp430(r) => r.name(),
|
Self::Msp430(r) => r.name(),
|
||||||
@ -329,6 +337,7 @@ pub fn reg_class(self) -> InlineAsmRegClass {
|
|||||||
Self::LoongArch(r) => InlineAsmRegClass::LoongArch(r.reg_class()),
|
Self::LoongArch(r) => InlineAsmRegClass::LoongArch(r.reg_class()),
|
||||||
Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
|
Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
|
||||||
Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()),
|
Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()),
|
||||||
|
Self::Sparc(r) => InlineAsmRegClass::Sparc(r.reg_class()),
|
||||||
Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()),
|
Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()),
|
||||||
Self::Avr(r) => InlineAsmRegClass::Avr(r.reg_class()),
|
Self::Avr(r) => InlineAsmRegClass::Avr(r.reg_class()),
|
||||||
Self::Msp430(r) => InlineAsmRegClass::Msp430(r.reg_class()),
|
Self::Msp430(r) => InlineAsmRegClass::Msp430(r.reg_class()),
|
||||||
@ -361,6 +370,9 @@ pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str> {
|
|||||||
Self::Mips(MipsInlineAsmReg::parse(name)?)
|
Self::Mips(MipsInlineAsmReg::parse(name)?)
|
||||||
}
|
}
|
||||||
InlineAsmArch::S390x => Self::S390x(S390xInlineAsmReg::parse(name)?),
|
InlineAsmArch::S390x => Self::S390x(S390xInlineAsmReg::parse(name)?),
|
||||||
|
InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => {
|
||||||
|
Self::Sparc(SparcInlineAsmReg::parse(name)?)
|
||||||
|
}
|
||||||
InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmReg::parse(name)?),
|
InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmReg::parse(name)?),
|
||||||
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
|
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
|
||||||
Self::Wasm(WasmInlineAsmReg::parse(name)?)
|
Self::Wasm(WasmInlineAsmReg::parse(name)?)
|
||||||
@ -393,6 +405,7 @@ pub fn validate(
|
|||||||
}
|
}
|
||||||
Self::Mips(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
|
Self::Mips(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
|
||||||
Self::S390x(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
|
Self::S390x(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
|
||||||
|
Self::Sparc(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
|
||||||
Self::Bpf(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
|
Self::Bpf(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
|
||||||
Self::Avr(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
|
Self::Avr(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
|
||||||
Self::Msp430(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
|
Self::Msp430(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
|
||||||
@ -420,6 +433,7 @@ pub fn emit(
|
|||||||
Self::LoongArch(r) => r.emit(out, arch, modifier),
|
Self::LoongArch(r) => r.emit(out, arch, modifier),
|
||||||
Self::Mips(r) => r.emit(out, arch, modifier),
|
Self::Mips(r) => r.emit(out, arch, modifier),
|
||||||
Self::S390x(r) => r.emit(out, arch, modifier),
|
Self::S390x(r) => r.emit(out, arch, modifier),
|
||||||
|
Self::Sparc(r) => r.emit(out, arch, modifier),
|
||||||
Self::Bpf(r) => r.emit(out, arch, modifier),
|
Self::Bpf(r) => r.emit(out, arch, modifier),
|
||||||
Self::Avr(r) => r.emit(out, arch, modifier),
|
Self::Avr(r) => r.emit(out, arch, modifier),
|
||||||
Self::Msp430(r) => r.emit(out, arch, modifier),
|
Self::Msp430(r) => r.emit(out, arch, modifier),
|
||||||
@ -440,6 +454,7 @@ pub fn overlapping_regs(self, mut cb: impl FnMut(InlineAsmReg)) {
|
|||||||
Self::LoongArch(_) => cb(self),
|
Self::LoongArch(_) => cb(self),
|
||||||
Self::Mips(_) => cb(self),
|
Self::Mips(_) => cb(self),
|
||||||
Self::S390x(r) => r.overlapping_regs(|r| cb(Self::S390x(r))),
|
Self::S390x(r) => r.overlapping_regs(|r| cb(Self::S390x(r))),
|
||||||
|
Self::Sparc(_) => cb(self),
|
||||||
Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),
|
Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),
|
||||||
Self::Avr(r) => r.overlapping_regs(|r| cb(Self::Avr(r))),
|
Self::Avr(r) => r.overlapping_regs(|r| cb(Self::Avr(r))),
|
||||||
Self::Msp430(_) => cb(self),
|
Self::Msp430(_) => cb(self),
|
||||||
@ -463,6 +478,7 @@ pub enum InlineAsmRegClass {
|
|||||||
LoongArch(LoongArchInlineAsmRegClass),
|
LoongArch(LoongArchInlineAsmRegClass),
|
||||||
Mips(MipsInlineAsmRegClass),
|
Mips(MipsInlineAsmRegClass),
|
||||||
S390x(S390xInlineAsmRegClass),
|
S390x(S390xInlineAsmRegClass),
|
||||||
|
Sparc(SparcInlineAsmRegClass),
|
||||||
SpirV(SpirVInlineAsmRegClass),
|
SpirV(SpirVInlineAsmRegClass),
|
||||||
Wasm(WasmInlineAsmRegClass),
|
Wasm(WasmInlineAsmRegClass),
|
||||||
Bpf(BpfInlineAsmRegClass),
|
Bpf(BpfInlineAsmRegClass),
|
||||||
@ -487,6 +503,7 @@ pub fn name(self) -> Symbol {
|
|||||||
Self::LoongArch(r) => r.name(),
|
Self::LoongArch(r) => r.name(),
|
||||||
Self::Mips(r) => r.name(),
|
Self::Mips(r) => r.name(),
|
||||||
Self::S390x(r) => r.name(),
|
Self::S390x(r) => r.name(),
|
||||||
|
Self::Sparc(r) => r.name(),
|
||||||
Self::SpirV(r) => r.name(),
|
Self::SpirV(r) => r.name(),
|
||||||
Self::Wasm(r) => r.name(),
|
Self::Wasm(r) => r.name(),
|
||||||
Self::Bpf(r) => r.name(),
|
Self::Bpf(r) => r.name(),
|
||||||
@ -513,6 +530,7 @@ pub fn suggest_class(self, arch: InlineAsmArch, ty: InlineAsmType) -> Option<Sel
|
|||||||
Self::LoongArch(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::LoongArch),
|
Self::LoongArch(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::LoongArch),
|
||||||
Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
|
Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
|
||||||
Self::S390x(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::S390x),
|
Self::S390x(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::S390x),
|
||||||
|
Self::Sparc(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Sparc),
|
||||||
Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
|
Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
|
||||||
Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
|
Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
|
||||||
Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf),
|
Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf),
|
||||||
@ -542,6 +560,7 @@ pub fn suggest_modifier(self, arch: InlineAsmArch, ty: InlineAsmType) -> Option<
|
|||||||
Self::LoongArch(r) => r.suggest_modifier(arch, ty),
|
Self::LoongArch(r) => r.suggest_modifier(arch, ty),
|
||||||
Self::Mips(r) => r.suggest_modifier(arch, ty),
|
Self::Mips(r) => r.suggest_modifier(arch, ty),
|
||||||
Self::S390x(r) => r.suggest_modifier(arch, ty),
|
Self::S390x(r) => r.suggest_modifier(arch, ty),
|
||||||
|
Self::Sparc(r) => r.suggest_modifier(arch, ty),
|
||||||
Self::SpirV(r) => r.suggest_modifier(arch, ty),
|
Self::SpirV(r) => r.suggest_modifier(arch, ty),
|
||||||
Self::Wasm(r) => r.suggest_modifier(arch, ty),
|
Self::Wasm(r) => r.suggest_modifier(arch, ty),
|
||||||
Self::Bpf(r) => r.suggest_modifier(arch, ty),
|
Self::Bpf(r) => r.suggest_modifier(arch, ty),
|
||||||
@ -571,6 +590,7 @@ pub fn default_modifier(self, arch: InlineAsmArch) -> Option<ModifierInfo> {
|
|||||||
Self::LoongArch(r) => r.default_modifier(arch),
|
Self::LoongArch(r) => r.default_modifier(arch),
|
||||||
Self::Mips(r) => r.default_modifier(arch),
|
Self::Mips(r) => r.default_modifier(arch),
|
||||||
Self::S390x(r) => r.default_modifier(arch),
|
Self::S390x(r) => r.default_modifier(arch),
|
||||||
|
Self::Sparc(r) => r.default_modifier(arch),
|
||||||
Self::SpirV(r) => r.default_modifier(arch),
|
Self::SpirV(r) => r.default_modifier(arch),
|
||||||
Self::Wasm(r) => r.default_modifier(arch),
|
Self::Wasm(r) => r.default_modifier(arch),
|
||||||
Self::Bpf(r) => r.default_modifier(arch),
|
Self::Bpf(r) => r.default_modifier(arch),
|
||||||
@ -599,6 +619,7 @@ pub fn supported_types(
|
|||||||
Self::LoongArch(r) => r.supported_types(arch),
|
Self::LoongArch(r) => r.supported_types(arch),
|
||||||
Self::Mips(r) => r.supported_types(arch),
|
Self::Mips(r) => r.supported_types(arch),
|
||||||
Self::S390x(r) => r.supported_types(arch),
|
Self::S390x(r) => r.supported_types(arch),
|
||||||
|
Self::Sparc(r) => r.supported_types(arch),
|
||||||
Self::SpirV(r) => r.supported_types(arch),
|
Self::SpirV(r) => r.supported_types(arch),
|
||||||
Self::Wasm(r) => r.supported_types(arch),
|
Self::Wasm(r) => r.supported_types(arch),
|
||||||
Self::Bpf(r) => r.supported_types(arch),
|
Self::Bpf(r) => r.supported_types(arch),
|
||||||
@ -632,6 +653,9 @@ pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str> {
|
|||||||
Self::Mips(MipsInlineAsmRegClass::parse(name)?)
|
Self::Mips(MipsInlineAsmRegClass::parse(name)?)
|
||||||
}
|
}
|
||||||
InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(name)?),
|
InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(name)?),
|
||||||
|
InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => {
|
||||||
|
Self::Sparc(SparcInlineAsmRegClass::parse(name)?)
|
||||||
|
}
|
||||||
InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(name)?),
|
InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(name)?),
|
||||||
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
|
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
|
||||||
Self::Wasm(WasmInlineAsmRegClass::parse(name)?)
|
Self::Wasm(WasmInlineAsmRegClass::parse(name)?)
|
||||||
@ -658,6 +682,7 @@ pub fn valid_modifiers(self, arch: InlineAsmArch) -> &'static [char] {
|
|||||||
Self::LoongArch(r) => r.valid_modifiers(arch),
|
Self::LoongArch(r) => r.valid_modifiers(arch),
|
||||||
Self::Mips(r) => r.valid_modifiers(arch),
|
Self::Mips(r) => r.valid_modifiers(arch),
|
||||||
Self::S390x(r) => r.valid_modifiers(arch),
|
Self::S390x(r) => r.valid_modifiers(arch),
|
||||||
|
Self::Sparc(r) => r.valid_modifiers(arch),
|
||||||
Self::SpirV(r) => r.valid_modifiers(arch),
|
Self::SpirV(r) => r.valid_modifiers(arch),
|
||||||
Self::Wasm(r) => r.valid_modifiers(arch),
|
Self::Wasm(r) => r.valid_modifiers(arch),
|
||||||
Self::Bpf(r) => r.valid_modifiers(arch),
|
Self::Bpf(r) => r.valid_modifiers(arch),
|
||||||
@ -843,6 +868,11 @@ pub fn allocatable_registers(
|
|||||||
s390x::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
|
s390x::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
|
||||||
map
|
map
|
||||||
}
|
}
|
||||||
|
InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => {
|
||||||
|
let mut map = sparc::regclass_map();
|
||||||
|
sparc::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
|
||||||
|
map
|
||||||
|
}
|
||||||
InlineAsmArch::SpirV => {
|
InlineAsmArch::SpirV => {
|
||||||
let mut map = spirv::regclass_map();
|
let mut map = spirv::regclass_map();
|
||||||
spirv::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
|
spirv::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
|
||||||
|
138
compiler/rustc_target/src/asm/sparc.rs
Normal file
138
compiler/rustc_target/src/asm/sparc.rs
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
|
use rustc_span::Symbol;
|
||||||
|
|
||||||
|
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
|
||||||
|
use crate::spec::{RelocModel, Target};
|
||||||
|
|
||||||
|
def_reg_class! {
|
||||||
|
Sparc SparcInlineAsmRegClass {
|
||||||
|
reg,
|
||||||
|
yreg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SparcInlineAsmRegClass {
|
||||||
|
pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] {
|
||||||
|
&[]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn suggest_modifier(
|
||||||
|
self,
|
||||||
|
_arch: InlineAsmArch,
|
||||||
|
_ty: InlineAsmType,
|
||||||
|
) -> Option<ModifierInfo> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn supported_types(
|
||||||
|
self,
|
||||||
|
arch: InlineAsmArch,
|
||||||
|
) -> &'static [(InlineAsmType, Option<Symbol>)] {
|
||||||
|
match self {
|
||||||
|
Self::reg => {
|
||||||
|
if arch == InlineAsmArch::Sparc {
|
||||||
|
types! {
|
||||||
|
_: I8, I16, I32;
|
||||||
|
// FIXME: i64 is ok for g*/o* registers on SPARC-V8+ ("h" constraint in GCC),
|
||||||
|
// but not yet supported in LLVM.
|
||||||
|
// v8plus: I64;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
types! { _: I8, I16, I32, I64; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self::yreg => &[],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reserved_g5(
|
||||||
|
arch: InlineAsmArch,
|
||||||
|
_reloc_model: RelocModel,
|
||||||
|
_target_features: &FxIndexSet<Symbol>,
|
||||||
|
_target: &Target,
|
||||||
|
_is_clobber: bool,
|
||||||
|
) -> Result<(), &'static str> {
|
||||||
|
if arch == InlineAsmArch::Sparc {
|
||||||
|
// FIXME: Section 2.1.5 "Function Registers with Unassigned Roles" of the V8+ Technical
|
||||||
|
// Specification says "%g5; no longer reserved for system software" [1], but LLVM always
|
||||||
|
// reserves it on SPARC32 [2].
|
||||||
|
// [1]: https://temlib.org/pub/SparcStation/Standards/V8plus.pdf
|
||||||
|
// [2]: https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp#L64-L66
|
||||||
|
Err("g5 is reserved for system on SPARC32")
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def_regs! {
|
||||||
|
Sparc SparcInlineAsmReg SparcInlineAsmRegClass {
|
||||||
|
// FIXME:
|
||||||
|
// - LLVM has reserve-{g,o,l,i}N feature to reserve each general-purpose registers.
|
||||||
|
// - g2-g4 are reserved for application (optional in both LLVM and GCC, and GCC has -mno-app-regs option to reserve them).
|
||||||
|
// There are currently no builtin targets that use them, but in the future they may need to
|
||||||
|
// be supported via options similar to AArch64's -Z fixed-x18.
|
||||||
|
r2: reg = ["r2", "g2"], // % reserved_g2
|
||||||
|
r3: reg = ["r3", "g3"], // % reserved_g3
|
||||||
|
r4: reg = ["r4", "g4"], // % reserved_g4
|
||||||
|
r5: reg = ["r5", "g5"] % reserved_g5,
|
||||||
|
r8: reg = ["r8", "o0"], // % reserved_o0
|
||||||
|
r9: reg = ["r9", "o1"], // % reserved_o1
|
||||||
|
r10: reg = ["r10", "o2"], // % reserved_o2
|
||||||
|
r11: reg = ["r11", "o3"], // % reserved_o3
|
||||||
|
r12: reg = ["r12", "o4"], // % reserved_o4
|
||||||
|
r13: reg = ["r13", "o5"], // % reserved_o5
|
||||||
|
r15: reg = ["r15", "o7"], // % reserved_o7
|
||||||
|
r16: reg = ["r16", "l0"], // % reserved_l0
|
||||||
|
r17: reg = ["r17", "l1"], // % reserved_l1
|
||||||
|
r18: reg = ["r18", "l2"], // % reserved_l2
|
||||||
|
r19: reg = ["r19", "l3"], // % reserved_l3
|
||||||
|
r20: reg = ["r20", "l4"], // % reserved_l4
|
||||||
|
r21: reg = ["r21", "l5"], // % reserved_l5
|
||||||
|
r22: reg = ["r22", "l6"], // % reserved_l6
|
||||||
|
r23: reg = ["r23", "l7"], // % reserved_l7
|
||||||
|
r24: reg = ["r24", "i0"], // % reserved_i0
|
||||||
|
r25: reg = ["r25", "i1"], // % reserved_i1
|
||||||
|
r26: reg = ["r26", "i2"], // % reserved_i2
|
||||||
|
r27: reg = ["r27", "i3"], // % reserved_i3
|
||||||
|
r28: reg = ["r28", "i4"], // % reserved_i4
|
||||||
|
r29: reg = ["r29", "i5"], // % reserved_i5
|
||||||
|
y: yreg = ["y"],
|
||||||
|
#error = ["r0", "g0"] =>
|
||||||
|
"g0 is always zero and cannot be used as an operand for inline asm",
|
||||||
|
// FIXME: %g1 is volatile in ABI, but used internally by LLVM.
|
||||||
|
// https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp#L55-L56
|
||||||
|
// > FIXME: G1 reserved for now for large imm generation by frame code.
|
||||||
|
#error = ["r1", "g1"] =>
|
||||||
|
"reserved by LLVM and cannot be used as an operand for inline asm",
|
||||||
|
#error = ["r6", "g6", "r7", "g7"] =>
|
||||||
|
"reserved for system and cannot be used as an operand for inline asm",
|
||||||
|
#error = ["sp", "r14", "o6"] =>
|
||||||
|
"the stack pointer cannot be used as an operand for inline asm",
|
||||||
|
#error = ["fp", "r30", "i6"] =>
|
||||||
|
"the frame pointer cannot be used as an operand for inline asm",
|
||||||
|
#error = ["r31", "i7"] =>
|
||||||
|
"the return address register cannot be used as an operand for inline asm",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SparcInlineAsmReg {
|
||||||
|
pub fn emit(
|
||||||
|
self,
|
||||||
|
out: &mut dyn fmt::Write,
|
||||||
|
_arch: InlineAsmArch,
|
||||||
|
_modifier: Option<char>,
|
||||||
|
) -> fmt::Result {
|
||||||
|
write!(out, "%{}", self.name())
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
|
|||||||
- CSKY
|
- CSKY
|
||||||
- s390x
|
- s390x
|
||||||
- Arm64EC
|
- Arm64EC
|
||||||
|
- SPARC
|
||||||
|
|
||||||
## Register classes
|
## Register classes
|
||||||
|
|
||||||
@ -56,6 +57,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
|
|||||||
| s390x | `freg` | `f[0-15]` | `f` |
|
| s390x | `freg` | `f[0-15]` | `f` |
|
||||||
| s390x | `vreg` | `v[0-31]` | Only clobbers |
|
| s390x | `vreg` | `v[0-31]` | Only clobbers |
|
||||||
| s390x | `areg` | `a[2-15]` | Only clobbers |
|
| s390x | `areg` | `a[2-15]` | Only clobbers |
|
||||||
|
| SPARC | `reg` | `r[2-29]` | `r` |
|
||||||
|
| SPARC | `yreg` | `y` | Only clobbers |
|
||||||
| Arm64EC | `reg` | `x[0-12]`, `x[15-22]`, `x[25-27]`, `x30` | `r` |
|
| Arm64EC | `reg` | `x[0-12]`, `x[15-22]`, `x[25-27]`, `x30` | `r` |
|
||||||
| Arm64EC | `vreg` | `v[0-15]` | `w` |
|
| Arm64EC | `vreg` | `v[0-15]` | `w` |
|
||||||
| Arm64EC | `vreg_low16` | `v[0-15]` | `x` |
|
| Arm64EC | `vreg_low16` | `v[0-15]` | `x` |
|
||||||
@ -97,6 +100,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
|
|||||||
| s390x | `freg` | None | `f32`, `f64` |
|
| s390x | `freg` | None | `f32`, `f64` |
|
||||||
| s390x | `vreg` | N/A | Only clobbers |
|
| s390x | `vreg` | N/A | Only clobbers |
|
||||||
| s390x | `areg` | N/A | Only clobbers |
|
| s390x | `areg` | N/A | Only clobbers |
|
||||||
|
| SPARC | `reg` | None | `i8`, `i16`, `i32`, `i64` (SPARC64 only) |
|
||||||
|
| SPARC | `yreg` | N/A | Only clobbers |
|
||||||
| Arm64EC | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
|
| Arm64EC | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
|
||||||
| Arm64EC | `vreg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`, <br> `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
|
| Arm64EC | `vreg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`, <br> `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
|
||||||
|
|
||||||
@ -135,6 +140,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
|
|||||||
| CSKY | `r29` | `rtb` |
|
| CSKY | `r29` | `rtb` |
|
||||||
| CSKY | `r30` | `svbr` |
|
| CSKY | `r30` | `svbr` |
|
||||||
| CSKY | `r31` | `tls` |
|
| CSKY | `r31` | `tls` |
|
||||||
|
| SPARC | `r[0-7]` | `g[0-7]` |
|
||||||
|
| SPARC | `r[8-15]` | `o[0-7]` |
|
||||||
|
| SPARC | `r[16-23]` | `l[0-7]` |
|
||||||
|
| SPARC | `r[24-31]` | `i[0-7]` |
|
||||||
| Arm64EC | `x[0-30]` | `w[0-30]` |
|
| Arm64EC | `x[0-30]` | `w[0-30]` |
|
||||||
| Arm64EC | `x29` | `fp` |
|
| Arm64EC | `x29` | `fp` |
|
||||||
| Arm64EC | `x30` | `lr` |
|
| Arm64EC | `x30` | `lr` |
|
||||||
@ -150,8 +159,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
|
|||||||
|
|
||||||
| Architecture | Unsupported register | Reason |
|
| Architecture | Unsupported register | Reason |
|
||||||
| ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| All | `sp`, `r15` (s390x) | The stack pointer must be restored to its original value at the end of an asm code block. |
|
| All | `sp`, `r15` (s390x), `r14`/`o6` (SPARC) | The stack pointer must be restored to its original value at the end of an asm code block. |
|
||||||
| All | `fr` (Hexagon), `fp` (PowerPC), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x), `x29` (Arm64EC) | The frame pointer cannot be used as an input or output. |
|
| All | `fr` (Hexagon), `fp` (PowerPC), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x), `r30`/`i6` (SPARC), `x29` (Arm64EC) | The frame pointer cannot be used as an input or output. |
|
||||||
| All | `r19` (Hexagon), `r29` (PowerPC), `r30` (PowerPC), `x19` (Arm64EC) | These are used internally by LLVM as "base pointer" for functions with complex stack frames. |
|
| All | `r19` (Hexagon), `r29` (PowerPC), `r30` (PowerPC), `x19` (Arm64EC) | These are used internally by LLVM as "base pointer" for functions with complex stack frames. |
|
||||||
| MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. |
|
| MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. |
|
||||||
| MIPS | `$1` or `$at` | Reserved for assembler. |
|
| MIPS | `$1` or `$at` | Reserved for assembler. |
|
||||||
@ -174,6 +183,11 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
|
|||||||
| CSKY | `r31` | This is the TLS register. |
|
| CSKY | `r31` | This is the TLS register. |
|
||||||
| s390x | `c[0-15]` | Reserved by the kernel. |
|
| s390x | `c[0-15]` | Reserved by the kernel. |
|
||||||
| s390x | `a[0-1]` | Reserved for system use. |
|
| s390x | `a[0-1]` | Reserved for system use. |
|
||||||
|
| SPARC | `r0`/`g0` | This is always zero and cannot be used as inputs or outputs. |
|
||||||
|
| SPARC | `r1`/`g1` | Used internally by LLVM. |
|
||||||
|
| SPARC | `r5`/`g5` | Reserved for system. (SPARC32 only) |
|
||||||
|
| SPARC | `r6`/`g6`, `r7`/`g7` | Reserved for system. |
|
||||||
|
| SPARC | `r31`/`i7` | Return address cannot be used as inputs or outputs. |
|
||||||
| Arm64EC | `xzr` | This is a constant zero register which can't be modified. |
|
| Arm64EC | `xzr` | This is a constant zero register which can't be modified. |
|
||||||
| Arm64EC | `x18` | This is an OS-reserved register. |
|
| Arm64EC | `x18` | This is an OS-reserved register. |
|
||||||
| Arm64EC | `x13`, `x14`, `x23`, `x24`, `x28`, `v[16-31]` | These are AArch64 registers that are not supported for Arm64EC. |
|
| Arm64EC | `x13`, `x14`, `x23`, `x24`, `x28`, `v[16-31]` | These are AArch64 registers that are not supported for Arm64EC. |
|
||||||
@ -195,6 +209,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
|
|||||||
| s390x | `reg` | None | `%r0` | None |
|
| s390x | `reg` | None | `%r0` | None |
|
||||||
| s390x | `reg_addr` | None | `%r1` | None |
|
| s390x | `reg_addr` | None | `%r1` | None |
|
||||||
| s390x | `freg` | None | `%f0` | None |
|
| s390x | `freg` | None | `%f0` | None |
|
||||||
|
| SPARC | `reg` | None | `%o0` | None |
|
||||||
| CSKY | `reg` | None | `r0` | None |
|
| CSKY | `reg` | None | `r0` | None |
|
||||||
| CSKY | `freg` | None | `f0` | None |
|
| CSKY | `freg` | None | `f0` | None |
|
||||||
| Arm64EC | `reg` | None | `x0` | `x` |
|
| Arm64EC | `reg` | None | `x0` | `x` |
|
||||||
@ -219,6 +234,9 @@ These flags registers must be restored upon exiting the asm block if the `preser
|
|||||||
- The condition code register `ccr`.
|
- The condition code register `ccr`.
|
||||||
- s390x
|
- s390x
|
||||||
- The condition code register `cc`.
|
- The condition code register `cc`.
|
||||||
|
- SPARC
|
||||||
|
- Integer condition codes (`icc` and `xcc`)
|
||||||
|
- Floating-point condition codes (`fcc[0-3]`)
|
||||||
- Arm64EC
|
- Arm64EC
|
||||||
- Condition flags (`NZCV` register).
|
- Condition flags (`NZCV` register).
|
||||||
- Floating-point status (`FPSR` register).
|
- Floating-point status (`FPSR` register).
|
||||||
|
168
tests/assembly/asm/sparc-types.rs
Normal file
168
tests/assembly/asm/sparc-types.rs
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
//@ revisions: sparc sparcv8plus sparc64
|
||||||
|
//@ 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] needs-llvm-components: sparc
|
||||||
|
//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu
|
||||||
|
//@[sparc64] needs-llvm-components: sparc
|
||||||
|
//@ compile-flags: -Zmerge-functions=disabled
|
||||||
|
|
||||||
|
#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
|
||||||
|
#![crate_type = "rlib"]
|
||||||
|
#![no_core]
|
||||||
|
#![allow(asm_sub_register, non_camel_case_types)]
|
||||||
|
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
macro_rules! asm {
|
||||||
|
() => {};
|
||||||
|
}
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
macro_rules! concat {
|
||||||
|
() => {};
|
||||||
|
}
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
macro_rules! stringify {
|
||||||
|
() => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[lang = "sized"]
|
||||||
|
trait Sized {}
|
||||||
|
#[lang = "copy"]
|
||||||
|
trait Copy {}
|
||||||
|
|
||||||
|
type ptr = *const i32;
|
||||||
|
|
||||||
|
impl Copy for i8 {}
|
||||||
|
impl Copy for u8 {}
|
||||||
|
impl Copy for i16 {}
|
||||||
|
impl Copy for i32 {}
|
||||||
|
impl Copy for i64 {}
|
||||||
|
impl Copy for f32 {}
|
||||||
|
impl Copy for f64 {}
|
||||||
|
impl Copy for ptr {}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn extern_func();
|
||||||
|
static extern_static: u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn $func(x: $ty) -> $ty {
|
||||||
|
let y;
|
||||||
|
asm!(concat!($mov," {}, {}"), in($class) x, out($class) y);
|
||||||
|
y
|
||||||
|
}
|
||||||
|
};}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
};}
|
||||||
|
|
||||||
|
// CHECK-LABEL: sym_fn_32:
|
||||||
|
// CHECK: !APP
|
||||||
|
// CHECK-NEXT: call extern_func
|
||||||
|
// CHECK-NEXT: !NO_APP
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn sym_fn_32() {
|
||||||
|
asm!("call {}", sym extern_func);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: sym_static:
|
||||||
|
// CHECK: !APP
|
||||||
|
// CHECK-NEXT: call extern_static
|
||||||
|
// CHECK-NEXT: !NO_APP
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn sym_static() {
|
||||||
|
asm!("call {}", sym extern_static);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_i8:
|
||||||
|
// CHECK: !APP
|
||||||
|
// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
|
||||||
|
// CHECK-NEXT: !NO_APP
|
||||||
|
check!(reg_i8, i8, reg, "mov");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_i16:
|
||||||
|
// CHECK: !APP
|
||||||
|
// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
|
||||||
|
// CHECK-NEXT: !NO_APP
|
||||||
|
check!(reg_i16, i16, reg, "mov");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_i32:
|
||||||
|
// CHECK: !APP
|
||||||
|
// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
|
||||||
|
// CHECK-NEXT: !NO_APP
|
||||||
|
check!(reg_i32, i32, reg, "mov");
|
||||||
|
|
||||||
|
// FIXME: should be allowed for sparcv8plus but not yet supported in LLVM
|
||||||
|
// sparc64-LABEL: reg_i64:
|
||||||
|
// sparc64: !APP
|
||||||
|
// sparc64-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
|
||||||
|
// sparc64-NEXT: !NO_APP
|
||||||
|
#[cfg(sparc64)]
|
||||||
|
check!(reg_i64, i64, reg, "mov");
|
||||||
|
|
||||||
|
// CHECK-LABEL: reg_ptr:
|
||||||
|
// CHECK: !APP
|
||||||
|
// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
|
||||||
|
// CHECK-NEXT: !NO_APP
|
||||||
|
check!(reg_ptr, ptr, reg, "mov");
|
||||||
|
|
||||||
|
// CHECK-LABEL: o0_i8:
|
||||||
|
// CHECK: !APP
|
||||||
|
// CHECK-NEXT: mov %o0, %o0
|
||||||
|
// CHECK-NEXT: !NO_APP
|
||||||
|
check_reg!(o0_i8, i8, "o0", "mov");
|
||||||
|
|
||||||
|
// CHECK-LABEL: o0_i16:
|
||||||
|
// CHECK: !APP
|
||||||
|
// CHECK-NEXT: mov %o0, %o0
|
||||||
|
// CHECK-NEXT: !NO_APP
|
||||||
|
check_reg!(o0_i16, i16, "o0", "mov");
|
||||||
|
|
||||||
|
// CHECK-LABEL: o0_i32:
|
||||||
|
// CHECK: !APP
|
||||||
|
// CHECK-NEXT: mov %o0, %o0
|
||||||
|
// CHECK-NEXT: !NO_APP
|
||||||
|
check_reg!(o0_i32, i32, "o0", "mov");
|
||||||
|
|
||||||
|
// FIXME: should be allowed for sparcv8plus but not yet supported in LLVM
|
||||||
|
// sparc64-LABEL: o0_i64:
|
||||||
|
// sparc64: !APP
|
||||||
|
// sparc64-NEXT: mov %o0, %o0
|
||||||
|
// sparc64-NEXT: !NO_APP
|
||||||
|
#[cfg(sparc64)]
|
||||||
|
check_reg!(o0_i64, i64, "o0", "mov");
|
||||||
|
|
||||||
|
// CHECK-LABEL: r9_i8:
|
||||||
|
// CHECK: !APP
|
||||||
|
// CHECK-NEXT: mov %o1, %o1
|
||||||
|
// CHECK-NEXT: !NO_APP
|
||||||
|
check_reg!(r9_i8, i8, "r9", "mov");
|
||||||
|
|
||||||
|
// CHECK-LABEL: r9_i16:
|
||||||
|
// CHECK: !APP
|
||||||
|
// CHECK-NEXT: mov %o1, %o1
|
||||||
|
// CHECK-NEXT: !NO_APP
|
||||||
|
check_reg!(r9_i16, i16, "r9", "mov");
|
||||||
|
|
||||||
|
// CHECK-LABEL: r9_i32:
|
||||||
|
// CHECK: !APP
|
||||||
|
// CHECK-NEXT: mov %o1, %o1
|
||||||
|
// CHECK-NEXT: !NO_APP
|
||||||
|
check_reg!(r9_i32, i32, "r9", "mov");
|
||||||
|
|
||||||
|
// FIXME: should be allowed for sparcv8plus but not yet supported in LLVM
|
||||||
|
// sparc64-LABEL: r9_i64:
|
||||||
|
// sparc64: !APP
|
||||||
|
// sparc64-NEXT: mov %o1, %o1
|
||||||
|
// sparc64-NEXT: !NO_APP
|
||||||
|
#[cfg(sparc64)]
|
||||||
|
check_reg!(r9_i64, i64, "r9", "mov");
|
40
tests/codegen/asm/sparc-clobbers.rs
Normal file
40
tests/codegen/asm/sparc-clobbers.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
//@ 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
|
||||||
|
|
||||||
|
#![crate_type = "rlib"]
|
||||||
|
#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
|
||||||
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "sized"]
|
||||||
|
trait Sized {}
|
||||||
|
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
macro_rules! asm {
|
||||||
|
() => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: @cc_clobber
|
||||||
|
// CHECK: call void asm sideeffect "", "~{icc},~{fcc0},~{fcc1},~{fcc2},~{fcc3}"()
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn cc_clobber() {
|
||||||
|
asm!("", options(nostack, nomem));
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: @no_clobber
|
||||||
|
// CHECK: call void asm sideeffect "", ""()
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn no_clobber() {
|
||||||
|
asm!("", options(nostack, nomem, preserves_flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: @y_clobber
|
||||||
|
// CHECK: call void asm sideeffect "", "~{y}"()
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe fn y_clobber() {
|
||||||
|
asm!("", out("y") _, options(nostack, nomem, preserves_flags));
|
||||||
|
}
|
@ -1,26 +0,0 @@
|
|||||||
//@ compile-flags: --target sparc-unknown-linux-gnu
|
|
||||||
//@ needs-llvm-components: sparc
|
|
||||||
|
|
||||||
#![feature(no_core, lang_items, rustc_attrs)]
|
|
||||||
#![no_core]
|
|
||||||
|
|
||||||
#[rustc_builtin_macro]
|
|
||||||
macro_rules! asm {
|
|
||||||
() => {};
|
|
||||||
}
|
|
||||||
#[rustc_builtin_macro]
|
|
||||||
macro_rules! global_asm {
|
|
||||||
() => {};
|
|
||||||
}
|
|
||||||
#[lang = "sized"]
|
|
||||||
trait Sized {}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
unsafe {
|
|
||||||
asm!("");
|
|
||||||
//~^ ERROR inline assembly is unsupported on this target
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
global_asm!("");
|
|
||||||
//~^ ERROR inline assembly is unsupported on this target
|
|
@ -1,15 +0,0 @@
|
|||||||
error[E0472]: inline assembly is unsupported on this target
|
|
||||||
--> $DIR/bad-arch.rs:20:9
|
|
||||||
|
|
|
||||||
LL | asm!("");
|
|
||||||
| ^^^^^^^^
|
|
||||||
|
|
||||||
error[E0472]: inline assembly is unsupported on this target
|
|
||||||
--> $DIR/bad-arch.rs:25:1
|
|
||||||
|
|
|
||||||
LL | global_asm!("");
|
|
||||||
| ^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0472`.
|
|
66
tests/ui/asm/sparc/bad-reg.rs
Normal file
66
tests/ui/asm/sparc/bad-reg.rs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
//@ 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
|
||||||
|
//@ needs-asm-support
|
||||||
|
|
||||||
|
#![crate_type = "rlib"]
|
||||||
|
#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
|
||||||
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "sized"]
|
||||||
|
trait Sized {}
|
||||||
|
#[lang = "copy"]
|
||||||
|
trait Copy {}
|
||||||
|
|
||||||
|
impl Copy for i32 {}
|
||||||
|
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
macro_rules! asm {
|
||||||
|
() => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() {
|
||||||
|
let mut x = 0;
|
||||||
|
unsafe {
|
||||||
|
// Unsupported registers
|
||||||
|
asm!("", out("g0") _);
|
||||||
|
//~^ ERROR invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm
|
||||||
|
// FIXME: see FIXME in compiler/rustc_target/src/asm/sparc.rs.
|
||||||
|
asm!("", out("g1") _);
|
||||||
|
//~^ ERROR invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm
|
||||||
|
asm!("", out("g2") _);
|
||||||
|
asm!("", out("g3") _);
|
||||||
|
asm!("", out("g4") _);
|
||||||
|
asm!("", out("g5") _);
|
||||||
|
//[sparc,sparcv8plus]~^ ERROR cannot use register `r5`: g5 is reserved for system on SPARC32
|
||||||
|
asm!("", out("g6") _);
|
||||||
|
//~^ ERROR invalid register `g6`: reserved for system and cannot be used as an operand for inline asm
|
||||||
|
asm!("", out("g7") _);
|
||||||
|
//~^ ERROR invalid register `g7`: reserved for system 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("fp") _);
|
||||||
|
//~^ ERROR invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
|
||||||
|
asm!("", out("i7") _);
|
||||||
|
//~^ ERROR invalid register `i7`: the return address register cannot be used as an operand for inline asm
|
||||||
|
|
||||||
|
// Clobber-only registers
|
||||||
|
// yreg
|
||||||
|
asm!("", out("y") _); // ok
|
||||||
|
asm!("", in("y") x);
|
||||||
|
//~^ ERROR can only be used as a clobber
|
||||||
|
//~| ERROR type `i32` cannot be used with this register class
|
||||||
|
asm!("", out("y") x);
|
||||||
|
//~^ ERROR can only be used as a clobber
|
||||||
|
//~| ERROR type `i32` cannot be used with this register class
|
||||||
|
asm!("/* {} */", in(yreg) x);
|
||||||
|
//~^ ERROR can only be used as a clobber
|
||||||
|
//~| ERROR type `i32` cannot be used with this register class
|
||||||
|
asm!("/* {} */", out(yreg) _);
|
||||||
|
//~^ ERROR can only be used as a clobber
|
||||||
|
}
|
||||||
|
}
|
98
tests/ui/asm/sparc/bad-reg.sparc.stderr
Normal file
98
tests/ui/asm/sparc/bad-reg.sparc.stderr
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
error: invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:30:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("g0") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:33:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("g1") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `g6`: reserved for system and cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:40:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("g6") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `g7`: reserved for system and cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:42:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("g7") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:44:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("sp") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:46:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("fp") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `i7`: the return address register cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:48:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("i7") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: register class `yreg` can only be used as a clobber, not as an input or output
|
||||||
|
--> $DIR/bad-reg.rs:54:18
|
||||||
|
|
|
||||||
|
LL | asm!("", in("y") x);
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
error: register class `yreg` can only be used as a clobber, not as an input or output
|
||||||
|
--> $DIR/bad-reg.rs:57:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("y") x);
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: register class `yreg` can only be used as a clobber, not as an input or output
|
||||||
|
--> $DIR/bad-reg.rs:60:26
|
||||||
|
|
|
||||||
|
LL | asm!("/* {} */", in(yreg) x);
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: register class `yreg` can only be used as a clobber, not as an input or output
|
||||||
|
--> $DIR/bad-reg.rs:63:26
|
||||||
|
|
|
||||||
|
LL | asm!("/* {} */", out(yreg) _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: cannot use register `r5`: g5 is reserved for system on SPARC32
|
||||||
|
--> $DIR/bad-reg.rs:38:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("g5") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: type `i32` cannot be used with this register class
|
||||||
|
--> $DIR/bad-reg.rs:54:26
|
||||||
|
|
|
||||||
|
LL | asm!("", in("y") x);
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: register class `yreg` supports these types:
|
||||||
|
|
||||||
|
error: type `i32` cannot be used with this register class
|
||||||
|
--> $DIR/bad-reg.rs:57:27
|
||||||
|
|
|
||||||
|
LL | asm!("", out("y") x);
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: register class `yreg` supports these types:
|
||||||
|
|
||||||
|
error: type `i32` cannot be used with this register class
|
||||||
|
--> $DIR/bad-reg.rs:60:35
|
||||||
|
|
|
||||||
|
LL | asm!("/* {} */", in(yreg) x);
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: register class `yreg` supports these types:
|
||||||
|
|
||||||
|
error: aborting due to 15 previous errors
|
||||||
|
|
92
tests/ui/asm/sparc/bad-reg.sparc64.stderr
Normal file
92
tests/ui/asm/sparc/bad-reg.sparc64.stderr
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
error: invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:30:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("g0") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:33:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("g1") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `g6`: reserved for system and cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:40:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("g6") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `g7`: reserved for system and cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:42:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("g7") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:44:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("sp") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:46:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("fp") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `i7`: the return address register cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:48:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("i7") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: register class `yreg` can only be used as a clobber, not as an input or output
|
||||||
|
--> $DIR/bad-reg.rs:54:18
|
||||||
|
|
|
||||||
|
LL | asm!("", in("y") x);
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
error: register class `yreg` can only be used as a clobber, not as an input or output
|
||||||
|
--> $DIR/bad-reg.rs:57:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("y") x);
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: register class `yreg` can only be used as a clobber, not as an input or output
|
||||||
|
--> $DIR/bad-reg.rs:60:26
|
||||||
|
|
|
||||||
|
LL | asm!("/* {} */", in(yreg) x);
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: register class `yreg` can only be used as a clobber, not as an input or output
|
||||||
|
--> $DIR/bad-reg.rs:63:26
|
||||||
|
|
|
||||||
|
LL | asm!("/* {} */", out(yreg) _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: type `i32` cannot be used with this register class
|
||||||
|
--> $DIR/bad-reg.rs:54:26
|
||||||
|
|
|
||||||
|
LL | asm!("", in("y") x);
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: register class `yreg` supports these types:
|
||||||
|
|
||||||
|
error: type `i32` cannot be used with this register class
|
||||||
|
--> $DIR/bad-reg.rs:57:27
|
||||||
|
|
|
||||||
|
LL | asm!("", out("y") x);
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: register class `yreg` supports these types:
|
||||||
|
|
||||||
|
error: type `i32` cannot be used with this register class
|
||||||
|
--> $DIR/bad-reg.rs:60:35
|
||||||
|
|
|
||||||
|
LL | asm!("/* {} */", in(yreg) x);
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: register class `yreg` supports these types:
|
||||||
|
|
||||||
|
error: aborting due to 14 previous errors
|
||||||
|
|
98
tests/ui/asm/sparc/bad-reg.sparcv8plus.stderr
Normal file
98
tests/ui/asm/sparc/bad-reg.sparcv8plus.stderr
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
error: invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:30:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("g0") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:33:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("g1") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `g6`: reserved for system and cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:40:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("g6") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `g7`: reserved for system and cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:42:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("g7") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:44:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("sp") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:46:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("fp") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: invalid register `i7`: the return address register cannot be used as an operand for inline asm
|
||||||
|
--> $DIR/bad-reg.rs:48:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("i7") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: register class `yreg` can only be used as a clobber, not as an input or output
|
||||||
|
--> $DIR/bad-reg.rs:54:18
|
||||||
|
|
|
||||||
|
LL | asm!("", in("y") x);
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
||||||
|
error: register class `yreg` can only be used as a clobber, not as an input or output
|
||||||
|
--> $DIR/bad-reg.rs:57:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("y") x);
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: register class `yreg` can only be used as a clobber, not as an input or output
|
||||||
|
--> $DIR/bad-reg.rs:60:26
|
||||||
|
|
|
||||||
|
LL | asm!("/* {} */", in(yreg) x);
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: register class `yreg` can only be used as a clobber, not as an input or output
|
||||||
|
--> $DIR/bad-reg.rs:63:26
|
||||||
|
|
|
||||||
|
LL | asm!("/* {} */", out(yreg) _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: cannot use register `r5`: g5 is reserved for system on SPARC32
|
||||||
|
--> $DIR/bad-reg.rs:38:18
|
||||||
|
|
|
||||||
|
LL | asm!("", out("g5") _);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: type `i32` cannot be used with this register class
|
||||||
|
--> $DIR/bad-reg.rs:54:26
|
||||||
|
|
|
||||||
|
LL | asm!("", in("y") x);
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: register class `yreg` supports these types:
|
||||||
|
|
||||||
|
error: type `i32` cannot be used with this register class
|
||||||
|
--> $DIR/bad-reg.rs:57:27
|
||||||
|
|
|
||||||
|
LL | asm!("", out("y") x);
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: register class `yreg` supports these types:
|
||||||
|
|
||||||
|
error: type `i32` cannot be used with this register class
|
||||||
|
--> $DIR/bad-reg.rs:60:35
|
||||||
|
|
|
||||||
|
LL | asm!("/* {} */", in(yreg) x);
|
||||||
|
| ^
|
||||||
|
|
|
||||||
|
= note: register class `yreg` supports these types:
|
||||||
|
|
||||||
|
error: aborting due to 15 previous errors
|
||||||
|
|
Loading…
Reference in New Issue
Block a user