Skip to content

Commit dd56ca2

Browse files
Add missing register class conversion for inline asm
1 parent e84f9a1 commit dd56ca2

File tree

1 file changed

+70
-38
lines changed

1 file changed

+70
-38
lines changed

src/asm.rs

Lines changed: 70 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
155155
InlineAsmOperandRef::Out { reg, late, place } => {
156156
use ConstraintOrRegister::*;
157157

158-
let (constraint, ty) = match (reg_to_gcc(reg), place) {
158+
let constraint = reg_to_gcc(reg, place.map(|p| &p.layout));
159+
let (constraint, ty) = match (constraint, place) {
159160
(Constraint(constraint), Some(place)) => (constraint, place.layout.gcc_type(self.cx)),
160161
// When `reg` is a class and not an explicit register but the out place is not specified,
161162
// we need to create an unused output variable to assign the output to. This var
@@ -197,7 +198,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
197198
}
198199

199200
InlineAsmOperandRef::In { reg, value } => {
200-
if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) {
201+
if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg, None) {
201202
inputs.push(AsmInOperand {
202203
constraint: Cow::Borrowed(constraint),
203204
rust_idx,
@@ -211,7 +212,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
211212
}
212213

213214
InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => {
214-
let constraint = if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) {
215+
let layout = if let Some(ref out_place) = out_place {
216+
&out_place.layout
217+
} else {
218+
&in_value.layout
219+
};
220+
let constraint = if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg, Some(layout)) {
215221
constraint
216222
}
217223
else {
@@ -276,7 +282,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
276282
match *op {
277283
// `out("explicit register") var`
278284
InlineAsmOperandRef::Out { reg, late, place } => {
279-
if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) {
285+
if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg, place.map(|p| &p.layout)) {
280286
let out_place = if let Some(place) = place {
281287
place
282288
}
@@ -304,7 +310,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
304310

305311
// `in("explicit register") var`
306312
InlineAsmOperandRef::In { reg, value } => {
307-
if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) {
313+
if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg, None) {
308314
let ty = value.layout.gcc_type(self.cx);
309315
let reg_var = self.current_func().new_local(None, ty, "input_register");
310316
reg_var.set_register_name(reg_name);
@@ -322,7 +328,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
322328

323329
// `inout("explicit register") in_var => out_var`
324330
InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => {
325-
if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) {
331+
let layout = if let Some(ref out_place) = out_place {
332+
&out_place.layout
333+
} else {
334+
&in_value.layout
335+
};
336+
if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg, Some(&layout)) {
326337
// See explanation in the first pass.
327338
let ty = in_value.layout.gcc_type(self.cx);
328339
let tmp_var = self.current_func().new_local(None, ty, "output_register");
@@ -544,7 +555,7 @@ fn estimate_template_length(template: &[InlineAsmTemplatePiece], constants_len:
544555
}
545556

546557
/// Converts a register class to a GCC constraint code.
547-
fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
558+
fn reg_to_gcc(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> ConstraintOrRegister {
548559
let constraint = match reg {
549560
// For vector registers LLVM wants the register name to match the type size.
550561
InlineAsmRegOrRegClass::Reg(reg) => {
@@ -564,56 +575,77 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
564575
_ => unimplemented!(),
565576
}
566577
},
578+
// They can be retrieved from https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
567579
InlineAsmRegOrRegClass::RegClass(reg) => match reg {
568-
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => unimplemented!(),
569-
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => unimplemented!(),
570-
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => unimplemented!(),
571-
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => unimplemented!(),
572-
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => unimplemented!(),
580+
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => {
581+
match layout.map(|l| l.size.bytes()) {
582+
Some(64) => "L",
583+
_ => "K", // we default to `K` which is a 32 bits register.
584+
}
585+
}
586+
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w",
587+
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x",
588+
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
589+
unreachable!("clobber-only")
590+
}
591+
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r",
573592
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
574-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
575-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) => unimplemented!(),
576-
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16)
593+
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
594+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8)
595+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16)
577596
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8)
578-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => unimplemented!(),
579-
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
580-
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => unimplemented!(),
581-
InlineAsmRegClass::Avr(_) => unimplemented!(),
582-
InlineAsmRegClass::Bpf(_) => unimplemented!(),
583-
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => unimplemented!(),
584-
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => unimplemented!(),
585-
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => unimplemented!(),
586-
InlineAsmRegClass::Msp430(_) => unimplemented!(),
587-
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => unimplemented!(),
588-
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => unimplemented!(),
589-
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => unimplemented!(),
590-
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => unimplemented!(),
591-
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => unimplemented!(),
592-
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => unimplemented!(),
597+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4)
598+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
599+
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "t",
600+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r",
601+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d",
602+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r",
603+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w",
604+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e",
605+
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
606+
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
607+
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
608+
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r"
609+
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f",
610+
InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r",
611+
// For the NVPTX target, could only find the information from LLVM at
612+
// https://llvm.org/docs/LangRef.html#supported-constraint-code-list so they might be
613+
// incorrect.
614+
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h",
615+
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r",
616+
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l",
617+
618+
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
619+
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
620+
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
593621
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
594622
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
595623
unreachable!("clobber-only")
596624
},
597-
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => unimplemented!(),
598-
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => unimplemented!(),
599-
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => unimplemented!(),
625+
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
626+
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
627+
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
628+
unreachable!("clobber-only")
629+
}
600630
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
601631
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q",
602632
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q",
603633
InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg)
604634
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
605635
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
606636
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "Yk",
607-
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => unimplemented!(),
608-
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => unimplemented!(),
609637
InlineAsmRegClass::X86(
610-
X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg | X86InlineAsmRegClass::tmm_reg,
638+
X86InlineAsmRegClass::kreg0
639+
| X86InlineAsmRegClass::x87_reg
640+
| X86InlineAsmRegClass::mmx_reg
641+
| X86InlineAsmRegClass::tmm_reg,
611642
) => unreachable!("clobber-only"),
612643
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
613644
bug!("GCC backend does not support SPIR-V")
614645
}
615-
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => unimplemented!(),
616-
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => unimplemented!(),
646+
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
647+
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
648+
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
617649
InlineAsmRegClass::Err => unreachable!(),
618650
}
619651
};

0 commit comments

Comments
 (0)