Skip to content

Commit 57fd394

Browse files
committed
refactor and support reg_byte registers
1 parent 1f98329 commit 57fd394

File tree

2 files changed

+136
-101
lines changed

2 files changed

+136
-101
lines changed

src/asm.rs

+113-101
Original file line numberDiff line numberDiff line change
@@ -611,114 +611,126 @@ fn estimate_template_length(
611611
}
612612

613613
/// Converts a register class to a GCC constraint code.
614-
fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
615-
let constraint = match reg {
616-
// For vector registers LLVM wants the register name to match the type size.
614+
fn reg_to_gcc(reg_or_reg_class: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
615+
match reg_or_reg_class {
617616
InlineAsmRegOrRegClass::Reg(reg) => {
618-
match reg {
619-
InlineAsmReg::X86(_) => {
620-
// TODO(antoyo): add support for vector register.
621-
//
622-
// // For explicit registers, we have to create a register variable: https://stackoverflow.com/a/31774784/389119
623-
return ConstraintOrRegister::Register(match reg.name() {
624-
// Some of registers' names does not map 1-1 from rust to gcc
625-
"st(0)" => "st",
617+
ConstraintOrRegister::Register(explicit_reg_to_gcc(reg))
618+
}
619+
InlineAsmRegOrRegClass::RegClass(reg_class) => {
620+
ConstraintOrRegister::Constraint(reg_class_to_gcc(reg_class))
621+
}
622+
}
623+
}
626624

627-
name => name,
628-
});
625+
fn explicit_reg_to_gcc(reg: InlineAsmReg) -> &'static str {
626+
// For explicit registers, we have to create a register variable: https://stackoverflow.com/a/31774784/389119
627+
match reg {
628+
InlineAsmReg::X86(reg) => {
629+
// TODO(antoyo): add support for vector register.
630+
match reg.reg_class() {
631+
X86InlineAsmRegClass::reg_byte => {
632+
// see https://github.com/rust-lang/rustc_codegen_gcc/issues/485
633+
reg.name().trim_end_matches('b')
629634
}
635+
_ => match reg.name() {
636+
// Some of registers' names does not map 1-1 from rust to gcc
637+
"st(0)" => "st",
630638

631-
_ => unimplemented!(),
639+
name => name,
640+
},
632641
}
633642
}
634-
// They can be retrieved from https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
635-
InlineAsmRegOrRegClass::RegClass(reg) => match reg {
636-
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r",
637-
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w",
638-
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x",
639-
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
640-
unreachable!("clobber-only")
641-
}
642-
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r",
643-
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
644-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
645-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8)
646-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16)
647-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8)
648-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4)
649-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
650-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "t",
651-
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r",
652-
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d",
653-
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r",
654-
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w",
655-
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e",
656-
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
657-
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
658-
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
659-
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => {
660-
unreachable!("clobber-only")
661-
}
662-
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r",
663-
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f",
664-
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r",
665-
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a",
666-
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d",
667-
InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r",
668-
InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f",
669-
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r"
670-
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f",
671-
InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r",
672-
// https://github.com/gcc-mirror/gcc/blob/master/gcc/config/nvptx/nvptx.md -> look for
673-
// "define_constraint".
674-
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h",
675-
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r",
676-
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l",
677-
678-
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
679-
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
680-
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
681-
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => "v",
682-
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
683-
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
684-
unreachable!("clobber-only")
685-
}
686-
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
687-
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
688-
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
689-
unreachable!("clobber-only")
690-
}
691-
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
692-
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q",
693-
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q",
694-
InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg)
695-
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
696-
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
697-
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "Yk",
698-
InlineAsmRegClass::X86(
699-
X86InlineAsmRegClass::kreg0
700-
| X86InlineAsmRegClass::x87_reg
701-
| X86InlineAsmRegClass::mmx_reg
702-
| X86InlineAsmRegClass::tmm_reg,
703-
) => unreachable!("clobber-only"),
704-
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
705-
bug!("GCC backend does not support SPIR-V")
706-
}
707-
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
708-
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
709-
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a",
710-
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
711-
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => "v",
712-
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => {
713-
unreachable!("clobber-only")
714-
}
715-
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r",
716-
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
717-
InlineAsmRegClass::Err => unreachable!(),
718-
},
719-
};
720643

721-
ConstraintOrRegister::Constraint(constraint)
644+
_ => unimplemented!(),
645+
}
646+
}
647+
648+
/// They can be retrieved from https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
649+
fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str {
650+
match reg_class {
651+
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r",
652+
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w",
653+
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x",
654+
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
655+
unreachable!("clobber-only")
656+
}
657+
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r",
658+
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
659+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
660+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8)
661+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16)
662+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8)
663+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4)
664+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
665+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "t",
666+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r",
667+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d",
668+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r",
669+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w",
670+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e",
671+
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
672+
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
673+
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
674+
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => {
675+
unreachable!("clobber-only")
676+
}
677+
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r",
678+
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f",
679+
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r",
680+
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a",
681+
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d",
682+
InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r",
683+
InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f",
684+
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r"
685+
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f",
686+
InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r",
687+
// https://github.com/gcc-mirror/gcc/blob/master/gcc/config/nvptx/nvptx.md -> look for
688+
// "define_constraint".
689+
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h",
690+
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r",
691+
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l",
692+
693+
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
694+
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
695+
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
696+
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => "v",
697+
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
698+
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
699+
unreachable!("clobber-only")
700+
}
701+
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
702+
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
703+
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
704+
unreachable!("clobber-only")
705+
}
706+
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
707+
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q",
708+
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q",
709+
InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg)
710+
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
711+
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
712+
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "Yk",
713+
InlineAsmRegClass::X86(
714+
X86InlineAsmRegClass::kreg0
715+
| X86InlineAsmRegClass::x87_reg
716+
| X86InlineAsmRegClass::mmx_reg
717+
| X86InlineAsmRegClass::tmm_reg,
718+
) => unreachable!("clobber-only"),
719+
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
720+
bug!("GCC backend does not support SPIR-V")
721+
}
722+
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
723+
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
724+
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a",
725+
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
726+
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::vreg) => "v",
727+
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::areg) => {
728+
unreachable!("clobber-only")
729+
}
730+
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r",
731+
InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"),
732+
InlineAsmRegClass::Err => unreachable!(),
733+
}
722734
}
723735

724736
/// Type to use for outputs that are discarded. It doesn't really matter what

tests/run/asm.rs

+23
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,29 @@ fn asm() {
205205
}
206206
assert_eq!((x, y), (16, 16));
207207
}
208+
209+
// the `b` suffix for registers in the `reg_byte` register class is not supported in GCC
210+
// and needs to be stripped in order to use these registers.
211+
unsafe {
212+
core::arch::asm!(
213+
"",
214+
out("al") _,
215+
out("bl") _,
216+
out("cl") _,
217+
out("dl") _,
218+
out("sil") _,
219+
out("dil") _,
220+
// out("bpl") _, // frame pointer
221+
out("r8b") _,
222+
out("r9b") _,
223+
out("r10b") _,
224+
out("r11b") _,
225+
out("r12b") _,
226+
out("r13b") _,
227+
out("r14b") _,
228+
out("r15b") _,
229+
);
230+
}
208231
}
209232

210233
#[cfg(not(target_arch = "x86_64"))]

0 commit comments

Comments
 (0)