Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b91a3a0

Browse files
committedNov 7, 2024
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 #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 https://github.com/gcc-mirror/gcc/blob/63b6967b06b5387821c4e5f2c113da6aaeeae2b7/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
2 parents 57a8a7e + 241f82a commit b91a3a0

File tree

14 files changed

+770
-43
lines changed

14 files changed

+770
-43
lines changed
 

‎compiler/rustc_codegen_gcc/src/asm.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
688688
) => {
689689
unreachable!("clobber-only")
690690
}
691+
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r",
692+
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
691693
InlineAsmRegClass::Err => unreachable!(),
692694
},
693695
};
@@ -767,6 +769,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
767769
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => {
768770
unreachable!("clobber-only")
769771
}
772+
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(),
773+
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
770774
InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(),
771775
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(),
772776
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(),
@@ -946,6 +950,7 @@ fn modifier_to_gcc(
946950
},
947951
InlineAsmRegClass::Avr(_) => None,
948952
InlineAsmRegClass::S390x(_) => None,
953+
InlineAsmRegClass::Sparc(_) => None,
949954
InlineAsmRegClass::Msp430(_) => None,
950955
InlineAsmRegClass::M68k(_) => None,
951956
InlineAsmRegClass::CSKY(_) => None,

‎compiler/rustc_codegen_llvm/src/asm.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,15 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
268268
InlineAsmArch::S390x => {
269269
constraints.push("~{cc}".to_string());
270270
}
271+
InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => {
272+
// In LLVM, ~{icc} represents icc and xcc in 64-bit code.
273+
// https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.td#L64
274+
constraints.push("~{icc}".to_string());
275+
constraints.push("~{fcc0}".to_string());
276+
constraints.push("~{fcc1}".to_string());
277+
constraints.push("~{fcc2}".to_string());
278+
constraints.push("~{fcc3}".to_string());
279+
}
271280
InlineAsmArch::SpirV => {}
272281
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {}
273282
InlineAsmArch::Bpf => {}
@@ -672,6 +681,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
672681
S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => {
673682
unreachable!("clobber-only")
674683
}
684+
Sparc(SparcInlineAsmRegClass::reg) => "r",
685+
Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
675686
Msp430(Msp430InlineAsmRegClass::reg) => "r",
676687
M68k(M68kInlineAsmRegClass::reg) => "r",
677688
M68k(M68kInlineAsmRegClass::reg_addr) => "a",
@@ -765,6 +776,7 @@ fn modifier_to_llvm(
765776
},
766777
Avr(_) => None,
767778
S390x(_) => None,
779+
Sparc(_) => None,
768780
Msp430(_) => None,
769781
SpirV(SpirVInlineAsmRegClass::reg) => bug!("LLVM backend does not support SPIR-V"),
770782
M68k(_) => None,
@@ -835,6 +847,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
835847
S390x(S390xInlineAsmRegClass::vreg | S390xInlineAsmRegClass::areg) => {
836848
unreachable!("clobber-only")
837849
}
850+
Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(),
851+
Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
838852
Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(),
839853
M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(),
840854
M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(),

‎compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2175,6 +2175,7 @@ symbols! {
21752175
yes,
21762176
yield_expr,
21772177
ymm_reg,
2178+
yreg,
21782179
zfh,
21792180
zfhmin,
21802181
zmm_reg,

‎compiler/rustc_target/src/asm/mod.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ mod nvptx;
191191
mod powerpc;
192192
mod riscv;
193193
mod s390x;
194+
mod sparc;
194195
mod spirv;
195196
mod wasm;
196197
mod x86;
@@ -209,6 +210,7 @@ pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
209210
pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass};
210211
pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
211212
pub use s390x::{S390xInlineAsmReg, S390xInlineAsmRegClass};
213+
pub use sparc::{SparcInlineAsmReg, SparcInlineAsmRegClass};
212214
pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass};
213215
pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass};
214216
pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass};
@@ -230,6 +232,8 @@ pub enum InlineAsmArch {
230232
PowerPC,
231233
PowerPC64,
232234
S390x,
235+
Sparc,
236+
Sparc64,
233237
SpirV,
234238
Wasm32,
235239
Wasm64,
@@ -260,6 +264,8 @@ impl FromStr for InlineAsmArch {
260264
"mips" | "mips32r6" => Ok(Self::Mips),
261265
"mips64" | "mips64r6" => Ok(Self::Mips64),
262266
"s390x" => Ok(Self::S390x),
267+
"sparc" => Ok(Self::Sparc),
268+
"sparc64" => Ok(Self::Sparc64),
263269
"spirv" => Ok(Self::SpirV),
264270
"wasm32" => Ok(Self::Wasm32),
265271
"wasm64" => Ok(Self::Wasm64),
@@ -286,6 +292,7 @@ pub enum InlineAsmReg {
286292
LoongArch(LoongArchInlineAsmReg),
287293
Mips(MipsInlineAsmReg),
288294
S390x(S390xInlineAsmReg),
295+
Sparc(SparcInlineAsmReg),
289296
SpirV(SpirVInlineAsmReg),
290297
Wasm(WasmInlineAsmReg),
291298
Bpf(BpfInlineAsmReg),
@@ -309,6 +316,7 @@ impl InlineAsmReg {
309316
Self::LoongArch(r) => r.name(),
310317
Self::Mips(r) => r.name(),
311318
Self::S390x(r) => r.name(),
319+
Self::Sparc(r) => r.name(),
312320
Self::Bpf(r) => r.name(),
313321
Self::Avr(r) => r.name(),
314322
Self::Msp430(r) => r.name(),
@@ -329,6 +337,7 @@ impl InlineAsmReg {
329337
Self::LoongArch(r) => InlineAsmRegClass::LoongArch(r.reg_class()),
330338
Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
331339
Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()),
340+
Self::Sparc(r) => InlineAsmRegClass::Sparc(r.reg_class()),
332341
Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()),
333342
Self::Avr(r) => InlineAsmRegClass::Avr(r.reg_class()),
334343
Self::Msp430(r) => InlineAsmRegClass::Msp430(r.reg_class()),
@@ -361,6 +370,9 @@ impl InlineAsmReg {
361370
Self::Mips(MipsInlineAsmReg::parse(name)?)
362371
}
363372
InlineAsmArch::S390x => Self::S390x(S390xInlineAsmReg::parse(name)?),
373+
InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => {
374+
Self::Sparc(SparcInlineAsmReg::parse(name)?)
375+
}
364376
InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmReg::parse(name)?),
365377
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
366378
Self::Wasm(WasmInlineAsmReg::parse(name)?)
@@ -393,6 +405,7 @@ impl InlineAsmReg {
393405
}
394406
Self::Mips(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
395407
Self::S390x(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
408+
Self::Sparc(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
396409
Self::Bpf(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
397410
Self::Avr(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
398411
Self::Msp430(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
@@ -420,6 +433,7 @@ impl InlineAsmReg {
420433
Self::LoongArch(r) => r.emit(out, arch, modifier),
421434
Self::Mips(r) => r.emit(out, arch, modifier),
422435
Self::S390x(r) => r.emit(out, arch, modifier),
436+
Self::Sparc(r) => r.emit(out, arch, modifier),
423437
Self::Bpf(r) => r.emit(out, arch, modifier),
424438
Self::Avr(r) => r.emit(out, arch, modifier),
425439
Self::Msp430(r) => r.emit(out, arch, modifier),
@@ -440,6 +454,7 @@ impl InlineAsmReg {
440454
Self::LoongArch(_) => cb(self),
441455
Self::Mips(_) => cb(self),
442456
Self::S390x(r) => r.overlapping_regs(|r| cb(Self::S390x(r))),
457+
Self::Sparc(_) => cb(self),
443458
Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),
444459
Self::Avr(r) => r.overlapping_regs(|r| cb(Self::Avr(r))),
445460
Self::Msp430(_) => cb(self),
@@ -463,6 +478,7 @@ pub enum InlineAsmRegClass {
463478
LoongArch(LoongArchInlineAsmRegClass),
464479
Mips(MipsInlineAsmRegClass),
465480
S390x(S390xInlineAsmRegClass),
481+
Sparc(SparcInlineAsmRegClass),
466482
SpirV(SpirVInlineAsmRegClass),
467483
Wasm(WasmInlineAsmRegClass),
468484
Bpf(BpfInlineAsmRegClass),
@@ -487,6 +503,7 @@ impl InlineAsmRegClass {
487503
Self::LoongArch(r) => r.name(),
488504
Self::Mips(r) => r.name(),
489505
Self::S390x(r) => r.name(),
506+
Self::Sparc(r) => r.name(),
490507
Self::SpirV(r) => r.name(),
491508
Self::Wasm(r) => r.name(),
492509
Self::Bpf(r) => r.name(),
@@ -513,6 +530,7 @@ impl InlineAsmRegClass {
513530
Self::LoongArch(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::LoongArch),
514531
Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
515532
Self::S390x(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::S390x),
533+
Self::Sparc(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Sparc),
516534
Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
517535
Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
518536
Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf),
@@ -542,6 +560,7 @@ impl InlineAsmRegClass {
542560
Self::LoongArch(r) => r.suggest_modifier(arch, ty),
543561
Self::Mips(r) => r.suggest_modifier(arch, ty),
544562
Self::S390x(r) => r.suggest_modifier(arch, ty),
563+
Self::Sparc(r) => r.suggest_modifier(arch, ty),
545564
Self::SpirV(r) => r.suggest_modifier(arch, ty),
546565
Self::Wasm(r) => r.suggest_modifier(arch, ty),
547566
Self::Bpf(r) => r.suggest_modifier(arch, ty),
@@ -571,6 +590,7 @@ impl InlineAsmRegClass {
571590
Self::LoongArch(r) => r.default_modifier(arch),
572591
Self::Mips(r) => r.default_modifier(arch),
573592
Self::S390x(r) => r.default_modifier(arch),
593+
Self::Sparc(r) => r.default_modifier(arch),
574594
Self::SpirV(r) => r.default_modifier(arch),
575595
Self::Wasm(r) => r.default_modifier(arch),
576596
Self::Bpf(r) => r.default_modifier(arch),
@@ -599,6 +619,7 @@ impl InlineAsmRegClass {
599619
Self::LoongArch(r) => r.supported_types(arch),
600620
Self::Mips(r) => r.supported_types(arch),
601621
Self::S390x(r) => r.supported_types(arch),
622+
Self::Sparc(r) => r.supported_types(arch),
602623
Self::SpirV(r) => r.supported_types(arch),
603624
Self::Wasm(r) => r.supported_types(arch),
604625
Self::Bpf(r) => r.supported_types(arch),
@@ -632,6 +653,9 @@ impl InlineAsmRegClass {
632653
Self::Mips(MipsInlineAsmRegClass::parse(name)?)
633654
}
634655
InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(name)?),
656+
InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => {
657+
Self::Sparc(SparcInlineAsmRegClass::parse(name)?)
658+
}
635659
InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(name)?),
636660
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
637661
Self::Wasm(WasmInlineAsmRegClass::parse(name)?)
@@ -658,6 +682,7 @@ impl InlineAsmRegClass {
658682
Self::LoongArch(r) => r.valid_modifiers(arch),
659683
Self::Mips(r) => r.valid_modifiers(arch),
660684
Self::S390x(r) => r.valid_modifiers(arch),
685+
Self::Sparc(r) => r.valid_modifiers(arch),
661686
Self::SpirV(r) => r.valid_modifiers(arch),
662687
Self::Wasm(r) => r.valid_modifiers(arch),
663688
Self::Bpf(r) => r.valid_modifiers(arch),
@@ -843,6 +868,11 @@ pub fn allocatable_registers(
843868
s390x::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
844869
map
845870
}
871+
InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => {
872+
let mut map = sparc::regclass_map();
873+
sparc::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
874+
map
875+
}
846876
InlineAsmArch::SpirV => {
847877
let mut map = spirv::regclass_map();
848878
spirv::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
use std::fmt;
2+
3+
use rustc_data_structures::fx::FxIndexSet;
4+
use rustc_span::Symbol;
5+
6+
use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
7+
use crate::spec::{RelocModel, Target};
8+
9+
def_reg_class! {
10+
Sparc SparcInlineAsmRegClass {
11+
reg,
12+
yreg,
13+
}
14+
}
15+
16+
impl SparcInlineAsmRegClass {
17+
pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] {
18+
&[]
19+
}
20+
21+
pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
22+
None
23+
}
24+
25+
pub fn suggest_modifier(
26+
self,
27+
_arch: InlineAsmArch,
28+
_ty: InlineAsmType,
29+
) -> Option<ModifierInfo> {
30+
None
31+
}
32+
33+
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
34+
None
35+
}
36+
37+
pub fn supported_types(
38+
self,
39+
arch: InlineAsmArch,
40+
) -> &'static [(InlineAsmType, Option<Symbol>)] {
41+
match self {
42+
Self::reg => {
43+
if arch == InlineAsmArch::Sparc {
44+
types! {
45+
_: I8, I16, I32;
46+
// FIXME: i64 is ok for g*/o* registers on SPARC-V8+ ("h" constraint in GCC),
47+
// but not yet supported in LLVM.
48+
// v8plus: I64;
49+
}
50+
} else {
51+
types! { _: I8, I16, I32, I64; }
52+
}
53+
}
54+
Self::yreg => &[],
55+
}
56+
}
57+
}
58+
59+
fn reserved_g5(
60+
arch: InlineAsmArch,
61+
_reloc_model: RelocModel,
62+
_target_features: &FxIndexSet<Symbol>,
63+
_target: &Target,
64+
_is_clobber: bool,
65+
) -> Result<(), &'static str> {
66+
if arch == InlineAsmArch::Sparc {
67+
// FIXME: Section 2.1.5 "Function Registers with Unassigned Roles" of the V8+ Technical
68+
// Specification says "%g5; no longer reserved for system software" [1], but LLVM always
69+
// reserves it on SPARC32 [2].
70+
// [1]: https://temlib.org/pub/SparcStation/Standards/V8plus.pdf
71+
// [2]: https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp#L64-L66
72+
Err("g5 is reserved for system on SPARC32")
73+
} else {
74+
Ok(())
75+
}
76+
}
77+
78+
def_regs! {
79+
Sparc SparcInlineAsmReg SparcInlineAsmRegClass {
80+
// FIXME:
81+
// - LLVM has reserve-{g,o,l,i}N feature to reserve each general-purpose registers.
82+
// - g2-g4 are reserved for application (optional in both LLVM and GCC, and GCC has -mno-app-regs option to reserve them).
83+
// There are currently no builtin targets that use them, but in the future they may need to
84+
// be supported via options similar to AArch64's -Z fixed-x18.
85+
r2: reg = ["r2", "g2"], // % reserved_g2
86+
r3: reg = ["r3", "g3"], // % reserved_g3
87+
r4: reg = ["r4", "g4"], // % reserved_g4
88+
r5: reg = ["r5", "g5"] % reserved_g5,
89+
r8: reg = ["r8", "o0"], // % reserved_o0
90+
r9: reg = ["r9", "o1"], // % reserved_o1
91+
r10: reg = ["r10", "o2"], // % reserved_o2
92+
r11: reg = ["r11", "o3"], // % reserved_o3
93+
r12: reg = ["r12", "o4"], // % reserved_o4
94+
r13: reg = ["r13", "o5"], // % reserved_o5
95+
r15: reg = ["r15", "o7"], // % reserved_o7
96+
r16: reg = ["r16", "l0"], // % reserved_l0
97+
r17: reg = ["r17", "l1"], // % reserved_l1
98+
r18: reg = ["r18", "l2"], // % reserved_l2
99+
r19: reg = ["r19", "l3"], // % reserved_l3
100+
r20: reg = ["r20", "l4"], // % reserved_l4
101+
r21: reg = ["r21", "l5"], // % reserved_l5
102+
r22: reg = ["r22", "l6"], // % reserved_l6
103+
r23: reg = ["r23", "l7"], // % reserved_l7
104+
r24: reg = ["r24", "i0"], // % reserved_i0
105+
r25: reg = ["r25", "i1"], // % reserved_i1
106+
r26: reg = ["r26", "i2"], // % reserved_i2
107+
r27: reg = ["r27", "i3"], // % reserved_i3
108+
r28: reg = ["r28", "i4"], // % reserved_i4
109+
r29: reg = ["r29", "i5"], // % reserved_i5
110+
y: yreg = ["y"],
111+
#error = ["r0", "g0"] =>
112+
"g0 is always zero and cannot be used as an operand for inline asm",
113+
// FIXME: %g1 is volatile in ABI, but used internally by LLVM.
114+
// https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp#L55-L56
115+
// > FIXME: G1 reserved for now for large imm generation by frame code.
116+
#error = ["r1", "g1"] =>
117+
"reserved by LLVM and cannot be used as an operand for inline asm",
118+
#error = ["r6", "g6", "r7", "g7"] =>
119+
"reserved for system and cannot be used as an operand for inline asm",
120+
#error = ["sp", "r14", "o6"] =>
121+
"the stack pointer cannot be used as an operand for inline asm",
122+
#error = ["fp", "r30", "i6"] =>
123+
"the frame pointer cannot be used as an operand for inline asm",
124+
#error = ["r31", "i7"] =>
125+
"the return address register cannot be used as an operand for inline asm",
126+
}
127+
}
128+
129+
impl SparcInlineAsmReg {
130+
pub fn emit(
131+
self,
132+
out: &mut dyn fmt::Write,
133+
_arch: InlineAsmArch,
134+
_modifier: Option<char>,
135+
) -> fmt::Result {
136+
write!(out, "%{}", self.name())
137+
}
138+
}

‎src/doc/unstable-book/src/language-features/asm-experimental-arch.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
2020
- CSKY
2121
- s390x
2222
- Arm64EC
23+
- SPARC
2324

2425
## Register classes
2526

@@ -56,6 +57,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
5657
| s390x | `freg` | `f[0-15]` | `f` |
5758
| s390x | `vreg` | `v[0-31]` | Only clobbers |
5859
| s390x | `areg` | `a[2-15]` | Only clobbers |
60+
| SPARC | `reg` | `r[2-29]` | `r` |
61+
| SPARC | `yreg` | `y` | Only clobbers |
5962
| Arm64EC | `reg` | `x[0-12]`, `x[15-22]`, `x[25-27]`, `x30` | `r` |
6063
| Arm64EC | `vreg` | `v[0-15]` | `w` |
6164
| Arm64EC | `vreg_low16` | `v[0-15]` | `x` |
@@ -97,6 +100,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
97100
| s390x | `freg` | None | `f32`, `f64` |
98101
| s390x | `vreg` | N/A | Only clobbers |
99102
| s390x | `areg` | N/A | Only clobbers |
103+
| SPARC | `reg` | None | `i8`, `i16`, `i32`, `i64` (SPARC64 only) |
104+
| SPARC | `yreg` | N/A | Only clobbers |
100105
| Arm64EC | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
101106
| Arm64EC | `vreg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`, <br> `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
102107

@@ -135,6 +140,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
135140
| CSKY | `r29` | `rtb` |
136141
| CSKY | `r30` | `svbr` |
137142
| CSKY | `r31` | `tls` |
143+
| SPARC | `r[0-7]` | `g[0-7]` |
144+
| SPARC | `r[8-15]` | `o[0-7]` |
145+
| SPARC | `r[16-23]` | `l[0-7]` |
146+
| SPARC | `r[24-31]` | `i[0-7]` |
138147
| Arm64EC | `x[0-30]` | `w[0-30]` |
139148
| Arm64EC | `x29` | `fp` |
140149
| Arm64EC | `x30` | `lr` |
@@ -150,8 +159,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
150159

151160
| Architecture | Unsupported register | Reason |
152161
| ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
153-
| All | `sp`, `r15` (s390x) | The stack pointer must be restored to its original value at the end of an asm code block. |
154-
| 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. |
162+
| 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. |
163+
| 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. |
155164
| All | `r19` (Hexagon), `r29` (PowerPC), `r30` (PowerPC), `x19` (Arm64EC) | These are used internally by LLVM as "base pointer" for functions with complex stack frames. |
156165
| MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. |
157166
| MIPS | `$1` or `$at` | Reserved for assembler. |
@@ -174,6 +183,11 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
174183
| CSKY | `r31` | This is the TLS register. |
175184
| s390x | `c[0-15]` | Reserved by the kernel. |
176185
| s390x | `a[0-1]` | Reserved for system use. |
186+
| SPARC | `r0`/`g0` | This is always zero and cannot be used as inputs or outputs. |
187+
| SPARC | `r1`/`g1` | Used internally by LLVM. |
188+
| SPARC | `r5`/`g5` | Reserved for system. (SPARC32 only) |
189+
| SPARC | `r6`/`g6`, `r7`/`g7` | Reserved for system. |
190+
| SPARC | `r31`/`i7` | Return address cannot be used as inputs or outputs. |
177191
| Arm64EC | `xzr` | This is a constant zero register which can't be modified. |
178192
| Arm64EC | `x18` | This is an OS-reserved register. |
179193
| 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
195209
| s390x | `reg` | None | `%r0` | None |
196210
| s390x | `reg_addr` | None | `%r1` | None |
197211
| s390x | `freg` | None | `%f0` | None |
212+
| SPARC | `reg` | None | `%o0` | None |
198213
| CSKY | `reg` | None | `r0` | None |
199214
| CSKY | `freg` | None | `f0` | None |
200215
| Arm64EC | `reg` | None | `x0` | `x` |
@@ -219,6 +234,9 @@ These flags registers must be restored upon exiting the asm block if the `preser
219234
- The condition code register `ccr`.
220235
- s390x
221236
- The condition code register `cc`.
237+
- SPARC
238+
- Integer condition codes (`icc` and `xcc`)
239+
- Floating-point condition codes (`fcc[0-3]`)
222240
- Arm64EC
223241
- Condition flags (`NZCV` register).
224242
- Floating-point status (`FPSR` register).

‎tests/assembly/asm/sparc-types.rs

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
//@ revisions: sparc sparcv8plus sparc64
2+
//@ assembly-output: emit-asm
3+
//@[sparc] compile-flags: --target sparc-unknown-none-elf
4+
//@[sparc] needs-llvm-components: sparc
5+
//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu
6+
//@[sparcv8plus] needs-llvm-components: sparc
7+
//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu
8+
//@[sparc64] needs-llvm-components: sparc
9+
//@ compile-flags: -Zmerge-functions=disabled
10+
11+
#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
12+
#![crate_type = "rlib"]
13+
#![no_core]
14+
#![allow(asm_sub_register, non_camel_case_types)]
15+
16+
#[rustc_builtin_macro]
17+
macro_rules! asm {
18+
() => {};
19+
}
20+
#[rustc_builtin_macro]
21+
macro_rules! concat {
22+
() => {};
23+
}
24+
#[rustc_builtin_macro]
25+
macro_rules! stringify {
26+
() => {};
27+
}
28+
29+
#[lang = "sized"]
30+
trait Sized {}
31+
#[lang = "copy"]
32+
trait Copy {}
33+
34+
type ptr = *const i32;
35+
36+
impl Copy for i8 {}
37+
impl Copy for u8 {}
38+
impl Copy for i16 {}
39+
impl Copy for i32 {}
40+
impl Copy for i64 {}
41+
impl Copy for f32 {}
42+
impl Copy for f64 {}
43+
impl Copy for ptr {}
44+
45+
extern "C" {
46+
fn extern_func();
47+
static extern_static: u8;
48+
}
49+
50+
macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => {
51+
#[no_mangle]
52+
pub unsafe fn $func(x: $ty) -> $ty {
53+
let y;
54+
asm!(concat!($mov," {}, {}"), in($class) x, out($class) y);
55+
y
56+
}
57+
};}
58+
59+
macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
60+
#[no_mangle]
61+
pub unsafe fn $func(x: $ty) -> $ty {
62+
let y;
63+
asm!(concat!($mov, " %", $reg, ", %", $reg), in($reg) x, lateout($reg) y);
64+
y
65+
}
66+
};}
67+
68+
// CHECK-LABEL: sym_fn_32:
69+
// CHECK: !APP
70+
// CHECK-NEXT: call extern_func
71+
// CHECK-NEXT: !NO_APP
72+
#[no_mangle]
73+
pub unsafe fn sym_fn_32() {
74+
asm!("call {}", sym extern_func);
75+
}
76+
77+
// CHECK-LABEL: sym_static:
78+
// CHECK: !APP
79+
// CHECK-NEXT: call extern_static
80+
// CHECK-NEXT: !NO_APP
81+
#[no_mangle]
82+
pub unsafe fn sym_static() {
83+
asm!("call {}", sym extern_static);
84+
}
85+
86+
// CHECK-LABEL: reg_i8:
87+
// CHECK: !APP
88+
// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
89+
// CHECK-NEXT: !NO_APP
90+
check!(reg_i8, i8, reg, "mov");
91+
92+
// CHECK-LABEL: reg_i16:
93+
// CHECK: !APP
94+
// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
95+
// CHECK-NEXT: !NO_APP
96+
check!(reg_i16, i16, reg, "mov");
97+
98+
// CHECK-LABEL: reg_i32:
99+
// CHECK: !APP
100+
// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
101+
// CHECK-NEXT: !NO_APP
102+
check!(reg_i32, i32, reg, "mov");
103+
104+
// FIXME: should be allowed for sparcv8plus but not yet supported in LLVM
105+
// sparc64-LABEL: reg_i64:
106+
// sparc64: !APP
107+
// sparc64-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
108+
// sparc64-NEXT: !NO_APP
109+
#[cfg(sparc64)]
110+
check!(reg_i64, i64, reg, "mov");
111+
112+
// CHECK-LABEL: reg_ptr:
113+
// CHECK: !APP
114+
// CHECK-NEXT: mov %{{[goli]}}{{[0-9]+}}, %{{[goli]}}{{[0-9]+}}
115+
// CHECK-NEXT: !NO_APP
116+
check!(reg_ptr, ptr, reg, "mov");
117+
118+
// CHECK-LABEL: o0_i8:
119+
// CHECK: !APP
120+
// CHECK-NEXT: mov %o0, %o0
121+
// CHECK-NEXT: !NO_APP
122+
check_reg!(o0_i8, i8, "o0", "mov");
123+
124+
// CHECK-LABEL: o0_i16:
125+
// CHECK: !APP
126+
// CHECK-NEXT: mov %o0, %o0
127+
// CHECK-NEXT: !NO_APP
128+
check_reg!(o0_i16, i16, "o0", "mov");
129+
130+
// CHECK-LABEL: o0_i32:
131+
// CHECK: !APP
132+
// CHECK-NEXT: mov %o0, %o0
133+
// CHECK-NEXT: !NO_APP
134+
check_reg!(o0_i32, i32, "o0", "mov");
135+
136+
// FIXME: should be allowed for sparcv8plus but not yet supported in LLVM
137+
// sparc64-LABEL: o0_i64:
138+
// sparc64: !APP
139+
// sparc64-NEXT: mov %o0, %o0
140+
// sparc64-NEXT: !NO_APP
141+
#[cfg(sparc64)]
142+
check_reg!(o0_i64, i64, "o0", "mov");
143+
144+
// CHECK-LABEL: r9_i8:
145+
// CHECK: !APP
146+
// CHECK-NEXT: mov %o1, %o1
147+
// CHECK-NEXT: !NO_APP
148+
check_reg!(r9_i8, i8, "r9", "mov");
149+
150+
// CHECK-LABEL: r9_i16:
151+
// CHECK: !APP
152+
// CHECK-NEXT: mov %o1, %o1
153+
// CHECK-NEXT: !NO_APP
154+
check_reg!(r9_i16, i16, "r9", "mov");
155+
156+
// CHECK-LABEL: r9_i32:
157+
// CHECK: !APP
158+
// CHECK-NEXT: mov %o1, %o1
159+
// CHECK-NEXT: !NO_APP
160+
check_reg!(r9_i32, i32, "r9", "mov");
161+
162+
// FIXME: should be allowed for sparcv8plus but not yet supported in LLVM
163+
// sparc64-LABEL: r9_i64:
164+
// sparc64: !APP
165+
// sparc64-NEXT: mov %o1, %o1
166+
// sparc64-NEXT: !NO_APP
167+
#[cfg(sparc64)]
168+
check_reg!(r9_i64, i64, "r9", "mov");

‎tests/codegen/asm/sparc-clobbers.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//@ revisions: sparc sparcv8plus sparc64
2+
//@[sparc] compile-flags: --target sparc-unknown-none-elf
3+
//@[sparc] needs-llvm-components: sparc
4+
//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu
5+
//@[sparcv8plus] needs-llvm-components: sparc
6+
//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu
7+
//@[sparc64] needs-llvm-components: sparc
8+
9+
#![crate_type = "rlib"]
10+
#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
11+
#![no_core]
12+
13+
#[lang = "sized"]
14+
trait Sized {}
15+
16+
#[rustc_builtin_macro]
17+
macro_rules! asm {
18+
() => {};
19+
}
20+
21+
// CHECK-LABEL: @cc_clobber
22+
// CHECK: call void asm sideeffect "", "~{icc},~{fcc0},~{fcc1},~{fcc2},~{fcc3}"()
23+
#[no_mangle]
24+
pub unsafe fn cc_clobber() {
25+
asm!("", options(nostack, nomem));
26+
}
27+
28+
// CHECK-LABEL: @no_clobber
29+
// CHECK: call void asm sideeffect "", ""()
30+
#[no_mangle]
31+
pub unsafe fn no_clobber() {
32+
asm!("", options(nostack, nomem, preserves_flags));
33+
}
34+
35+
// CHECK-LABEL: @y_clobber
36+
// CHECK: call void asm sideeffect "", "~{y}"()
37+
#[no_mangle]
38+
pub unsafe fn y_clobber() {
39+
asm!("", out("y") _, options(nostack, nomem, preserves_flags));
40+
}

‎tests/ui/asm/bad-arch.rs

Lines changed: 0 additions & 26 deletions
This file was deleted.

‎tests/ui/asm/bad-arch.stderr

Lines changed: 0 additions & 15 deletions
This file was deleted.

‎tests/ui/asm/sparc/bad-reg.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//@ revisions: sparc sparcv8plus sparc64
2+
//@[sparc] compile-flags: --target sparc-unknown-none-elf
3+
//@[sparc] needs-llvm-components: sparc
4+
//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu
5+
//@[sparcv8plus] needs-llvm-components: sparc
6+
//@[sparc64] compile-flags: --target sparc64-unknown-linux-gnu
7+
//@[sparc64] needs-llvm-components: sparc
8+
//@ needs-asm-support
9+
10+
#![crate_type = "rlib"]
11+
#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
12+
#![no_core]
13+
14+
#[lang = "sized"]
15+
trait Sized {}
16+
#[lang = "copy"]
17+
trait Copy {}
18+
19+
impl Copy for i32 {}
20+
21+
#[rustc_builtin_macro]
22+
macro_rules! asm {
23+
() => {};
24+
}
25+
26+
fn f() {
27+
let mut x = 0;
28+
unsafe {
29+
// Unsupported registers
30+
asm!("", out("g0") _);
31+
//~^ ERROR invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm
32+
// FIXME: see FIXME in compiler/rustc_target/src/asm/sparc.rs.
33+
asm!("", out("g1") _);
34+
//~^ ERROR invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm
35+
asm!("", out("g2") _);
36+
asm!("", out("g3") _);
37+
asm!("", out("g4") _);
38+
asm!("", out("g5") _);
39+
//[sparc,sparcv8plus]~^ ERROR cannot use register `r5`: g5 is reserved for system on SPARC32
40+
asm!("", out("g6") _);
41+
//~^ ERROR invalid register `g6`: reserved for system and cannot be used as an operand for inline asm
42+
asm!("", out("g7") _);
43+
//~^ ERROR invalid register `g7`: reserved for system and cannot be used as an operand for inline asm
44+
asm!("", out("sp") _);
45+
//~^ ERROR invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
46+
asm!("", out("fp") _);
47+
//~^ ERROR invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
48+
asm!("", out("i7") _);
49+
//~^ ERROR invalid register `i7`: the return address register cannot be used as an operand for inline asm
50+
51+
// Clobber-only registers
52+
// yreg
53+
asm!("", out("y") _); // ok
54+
asm!("", in("y") x);
55+
//~^ ERROR can only be used as a clobber
56+
//~| ERROR type `i32` cannot be used with this register class
57+
asm!("", out("y") x);
58+
//~^ ERROR can only be used as a clobber
59+
//~| ERROR type `i32` cannot be used with this register class
60+
asm!("/* {} */", in(yreg) x);
61+
//~^ ERROR can only be used as a clobber
62+
//~| ERROR type `i32` cannot be used with this register class
63+
asm!("/* {} */", out(yreg) _);
64+
//~^ ERROR can only be used as a clobber
65+
}
66+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
error: invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm
2+
--> $DIR/bad-reg.rs:30:18
3+
|
4+
LL | asm!("", out("g0") _);
5+
| ^^^^^^^^^^^
6+
7+
error: invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm
8+
--> $DIR/bad-reg.rs:33:18
9+
|
10+
LL | asm!("", out("g1") _);
11+
| ^^^^^^^^^^^
12+
13+
error: invalid register `g6`: reserved for system and cannot be used as an operand for inline asm
14+
--> $DIR/bad-reg.rs:40:18
15+
|
16+
LL | asm!("", out("g6") _);
17+
| ^^^^^^^^^^^
18+
19+
error: invalid register `g7`: reserved for system and cannot be used as an operand for inline asm
20+
--> $DIR/bad-reg.rs:42:18
21+
|
22+
LL | asm!("", out("g7") _);
23+
| ^^^^^^^^^^^
24+
25+
error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
26+
--> $DIR/bad-reg.rs:44:18
27+
|
28+
LL | asm!("", out("sp") _);
29+
| ^^^^^^^^^^^
30+
31+
error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
32+
--> $DIR/bad-reg.rs:46:18
33+
|
34+
LL | asm!("", out("fp") _);
35+
| ^^^^^^^^^^^
36+
37+
error: invalid register `i7`: the return address register cannot be used as an operand for inline asm
38+
--> $DIR/bad-reg.rs:48:18
39+
|
40+
LL | asm!("", out("i7") _);
41+
| ^^^^^^^^^^^
42+
43+
error: register class `yreg` can only be used as a clobber, not as an input or output
44+
--> $DIR/bad-reg.rs:54:18
45+
|
46+
LL | asm!("", in("y") x);
47+
| ^^^^^^^^^
48+
49+
error: register class `yreg` can only be used as a clobber, not as an input or output
50+
--> $DIR/bad-reg.rs:57:18
51+
|
52+
LL | asm!("", out("y") x);
53+
| ^^^^^^^^^^
54+
55+
error: register class `yreg` can only be used as a clobber, not as an input or output
56+
--> $DIR/bad-reg.rs:60:26
57+
|
58+
LL | asm!("/* {} */", in(yreg) x);
59+
| ^^^^^^^^^^
60+
61+
error: register class `yreg` can only be used as a clobber, not as an input or output
62+
--> $DIR/bad-reg.rs:63:26
63+
|
64+
LL | asm!("/* {} */", out(yreg) _);
65+
| ^^^^^^^^^^^
66+
67+
error: cannot use register `r5`: g5 is reserved for system on SPARC32
68+
--> $DIR/bad-reg.rs:38:18
69+
|
70+
LL | asm!("", out("g5") _);
71+
| ^^^^^^^^^^^
72+
73+
error: type `i32` cannot be used with this register class
74+
--> $DIR/bad-reg.rs:54:26
75+
|
76+
LL | asm!("", in("y") x);
77+
| ^
78+
|
79+
= note: register class `yreg` supports these types:
80+
81+
error: type `i32` cannot be used with this register class
82+
--> $DIR/bad-reg.rs:57:27
83+
|
84+
LL | asm!("", out("y") x);
85+
| ^
86+
|
87+
= note: register class `yreg` supports these types:
88+
89+
error: type `i32` cannot be used with this register class
90+
--> $DIR/bad-reg.rs:60:35
91+
|
92+
LL | asm!("/* {} */", in(yreg) x);
93+
| ^
94+
|
95+
= note: register class `yreg` supports these types:
96+
97+
error: aborting due to 15 previous errors
98+
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
error: invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm
2+
--> $DIR/bad-reg.rs:30:18
3+
|
4+
LL | asm!("", out("g0") _);
5+
| ^^^^^^^^^^^
6+
7+
error: invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm
8+
--> $DIR/bad-reg.rs:33:18
9+
|
10+
LL | asm!("", out("g1") _);
11+
| ^^^^^^^^^^^
12+
13+
error: invalid register `g6`: reserved for system and cannot be used as an operand for inline asm
14+
--> $DIR/bad-reg.rs:40:18
15+
|
16+
LL | asm!("", out("g6") _);
17+
| ^^^^^^^^^^^
18+
19+
error: invalid register `g7`: reserved for system and cannot be used as an operand for inline asm
20+
--> $DIR/bad-reg.rs:42:18
21+
|
22+
LL | asm!("", out("g7") _);
23+
| ^^^^^^^^^^^
24+
25+
error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
26+
--> $DIR/bad-reg.rs:44:18
27+
|
28+
LL | asm!("", out("sp") _);
29+
| ^^^^^^^^^^^
30+
31+
error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
32+
--> $DIR/bad-reg.rs:46:18
33+
|
34+
LL | asm!("", out("fp") _);
35+
| ^^^^^^^^^^^
36+
37+
error: invalid register `i7`: the return address register cannot be used as an operand for inline asm
38+
--> $DIR/bad-reg.rs:48:18
39+
|
40+
LL | asm!("", out("i7") _);
41+
| ^^^^^^^^^^^
42+
43+
error: register class `yreg` can only be used as a clobber, not as an input or output
44+
--> $DIR/bad-reg.rs:54:18
45+
|
46+
LL | asm!("", in("y") x);
47+
| ^^^^^^^^^
48+
49+
error: register class `yreg` can only be used as a clobber, not as an input or output
50+
--> $DIR/bad-reg.rs:57:18
51+
|
52+
LL | asm!("", out("y") x);
53+
| ^^^^^^^^^^
54+
55+
error: register class `yreg` can only be used as a clobber, not as an input or output
56+
--> $DIR/bad-reg.rs:60:26
57+
|
58+
LL | asm!("/* {} */", in(yreg) x);
59+
| ^^^^^^^^^^
60+
61+
error: register class `yreg` can only be used as a clobber, not as an input or output
62+
--> $DIR/bad-reg.rs:63:26
63+
|
64+
LL | asm!("/* {} */", out(yreg) _);
65+
| ^^^^^^^^^^^
66+
67+
error: type `i32` cannot be used with this register class
68+
--> $DIR/bad-reg.rs:54:26
69+
|
70+
LL | asm!("", in("y") x);
71+
| ^
72+
|
73+
= note: register class `yreg` supports these types:
74+
75+
error: type `i32` cannot be used with this register class
76+
--> $DIR/bad-reg.rs:57:27
77+
|
78+
LL | asm!("", out("y") x);
79+
| ^
80+
|
81+
= note: register class `yreg` supports these types:
82+
83+
error: type `i32` cannot be used with this register class
84+
--> $DIR/bad-reg.rs:60:35
85+
|
86+
LL | asm!("/* {} */", in(yreg) x);
87+
| ^
88+
|
89+
= note: register class `yreg` supports these types:
90+
91+
error: aborting due to 14 previous errors
92+
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
error: invalid register `g0`: g0 is always zero and cannot be used as an operand for inline asm
2+
--> $DIR/bad-reg.rs:30:18
3+
|
4+
LL | asm!("", out("g0") _);
5+
| ^^^^^^^^^^^
6+
7+
error: invalid register `g1`: reserved by LLVM and cannot be used as an operand for inline asm
8+
--> $DIR/bad-reg.rs:33:18
9+
|
10+
LL | asm!("", out("g1") _);
11+
| ^^^^^^^^^^^
12+
13+
error: invalid register `g6`: reserved for system and cannot be used as an operand for inline asm
14+
--> $DIR/bad-reg.rs:40:18
15+
|
16+
LL | asm!("", out("g6") _);
17+
| ^^^^^^^^^^^
18+
19+
error: invalid register `g7`: reserved for system and cannot be used as an operand for inline asm
20+
--> $DIR/bad-reg.rs:42:18
21+
|
22+
LL | asm!("", out("g7") _);
23+
| ^^^^^^^^^^^
24+
25+
error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
26+
--> $DIR/bad-reg.rs:44:18
27+
|
28+
LL | asm!("", out("sp") _);
29+
| ^^^^^^^^^^^
30+
31+
error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
32+
--> $DIR/bad-reg.rs:46:18
33+
|
34+
LL | asm!("", out("fp") _);
35+
| ^^^^^^^^^^^
36+
37+
error: invalid register `i7`: the return address register cannot be used as an operand for inline asm
38+
--> $DIR/bad-reg.rs:48:18
39+
|
40+
LL | asm!("", out("i7") _);
41+
| ^^^^^^^^^^^
42+
43+
error: register class `yreg` can only be used as a clobber, not as an input or output
44+
--> $DIR/bad-reg.rs:54:18
45+
|
46+
LL | asm!("", in("y") x);
47+
| ^^^^^^^^^
48+
49+
error: register class `yreg` can only be used as a clobber, not as an input or output
50+
--> $DIR/bad-reg.rs:57:18
51+
|
52+
LL | asm!("", out("y") x);
53+
| ^^^^^^^^^^
54+
55+
error: register class `yreg` can only be used as a clobber, not as an input or output
56+
--> $DIR/bad-reg.rs:60:26
57+
|
58+
LL | asm!("/* {} */", in(yreg) x);
59+
| ^^^^^^^^^^
60+
61+
error: register class `yreg` can only be used as a clobber, not as an input or output
62+
--> $DIR/bad-reg.rs:63:26
63+
|
64+
LL | asm!("/* {} */", out(yreg) _);
65+
| ^^^^^^^^^^^
66+
67+
error: cannot use register `r5`: g5 is reserved for system on SPARC32
68+
--> $DIR/bad-reg.rs:38:18
69+
|
70+
LL | asm!("", out("g5") _);
71+
| ^^^^^^^^^^^
72+
73+
error: type `i32` cannot be used with this register class
74+
--> $DIR/bad-reg.rs:54:26
75+
|
76+
LL | asm!("", in("y") x);
77+
| ^
78+
|
79+
= note: register class `yreg` supports these types:
80+
81+
error: type `i32` cannot be used with this register class
82+
--> $DIR/bad-reg.rs:57:27
83+
|
84+
LL | asm!("", out("y") x);
85+
| ^
86+
|
87+
= note: register class `yreg` supports these types:
88+
89+
error: type `i32` cannot be used with this register class
90+
--> $DIR/bad-reg.rs:60:35
91+
|
92+
LL | asm!("/* {} */", in(yreg) x);
93+
| ^
94+
|
95+
= note: register class `yreg` supports these types:
96+
97+
error: aborting due to 15 previous errors
98+

0 commit comments

Comments
 (0)
Please sign in to comment.