Add clobber-only register classes for asm!
These are needed to properly express a function call ABI using a clobber list, even though we don't support passing actual values into/out of these registers.
This commit is contained in:
parent
1e13a9bb33
commit
e1c3f5e017
11 changed files with 241 additions and 30 deletions
|
@ -128,6 +128,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
let mut clobbers = vec![];
|
||||
let mut output_types = vec![];
|
||||
let mut op_idx = FxHashMap::default();
|
||||
let mut clobbered_x87 = false;
|
||||
for (idx, op) in operands.iter().enumerate() {
|
||||
match *op {
|
||||
InlineAsmOperandRef::Out { reg, late, place } => {
|
||||
|
@ -150,7 +151,27 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
let ty = if let Some(ref place) = place {
|
||||
layout = Some(&place.layout);
|
||||
llvm_fixup_output_type(self.cx, reg.reg_class(), &place.layout)
|
||||
} else if !is_target_supported(reg.reg_class()) {
|
||||
} else if matches!(
|
||||
reg.reg_class(),
|
||||
InlineAsmRegClass::X86(
|
||||
X86InlineAsmRegClass::mmx_reg | X86InlineAsmRegClass::x87_reg
|
||||
)
|
||||
) {
|
||||
// Special handling for x87/mmx registers: we always
|
||||
// clobber the whole set if one register is marked as
|
||||
// clobbered. This is due to the way LLVM handles the
|
||||
// FP stack in inline assembly.
|
||||
if !clobbered_x87 {
|
||||
clobbered_x87 = true;
|
||||
clobbers.push("~{st}".to_string());
|
||||
for i in 1..=7 {
|
||||
clobbers.push(format!("~{{st({})}}", i));
|
||||
}
|
||||
}
|
||||
continue;
|
||||
} else if !is_target_supported(reg.reg_class())
|
||||
|| reg.reg_class().is_clobber_only(asm_arch)
|
||||
{
|
||||
// We turn discarded outputs into clobber constraints
|
||||
// if the target feature needed by the register class is
|
||||
// disabled. This is necessary otherwise LLVM will try
|
||||
|
@ -564,6 +585,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
|
|||
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r",
|
||||
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w",
|
||||
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x",
|
||||
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
|
||||
unreachable!("clobber-only")
|
||||
}
|
||||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r",
|
||||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => "l",
|
||||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
|
||||
|
@ -585,6 +609,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
|
|||
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
|
||||
unreachable!("clobber-only")
|
||||
}
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q",
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q",
|
||||
|
@ -592,6 +619,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
|
|||
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk",
|
||||
InlineAsmRegClass::X86(
|
||||
X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg,
|
||||
) => unreachable!("clobber-only"),
|
||||
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
|
||||
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
|
||||
bug!("LLVM backend does not support SPIR-V")
|
||||
|
@ -614,6 +644,9 @@ fn modifier_to_llvm(
|
|||
| InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
|
||||
if modifier == Some('v') { None } else { modifier }
|
||||
}
|
||||
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
|
||||
unreachable!("clobber-only")
|
||||
}
|
||||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg)
|
||||
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => None,
|
||||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
|
||||
|
@ -636,6 +669,9 @@ fn modifier_to_llvm(
|
|||
InlineAsmRegClass::PowerPC(_) => None,
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg)
|
||||
| InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => None,
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
|
||||
unreachable!("clobber-only")
|
||||
}
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
|
||||
| InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => match modifier {
|
||||
None if arch == InlineAsmArch::X86_64 => Some('q'),
|
||||
|
@ -660,6 +696,9 @@ fn modifier_to_llvm(
|
|||
_ => unreachable!(),
|
||||
},
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => {
|
||||
unreachable!("clobber-only")
|
||||
}
|
||||
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None,
|
||||
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
|
||||
bug!("LLVM backend does not support SPIR-V")
|
||||
|
@ -677,6 +716,9 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
|
|||
| InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
|
||||
cx.type_vector(cx.type_i64(), 2)
|
||||
}
|
||||
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
|
||||
unreachable!("clobber-only")
|
||||
}
|
||||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg)
|
||||
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg_thumb) => cx.type_i32(),
|
||||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
|
||||
|
@ -700,6 +742,9 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
|
|||
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(),
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
|
||||
unreachable!("clobber-only")
|
||||
}
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
|
||||
| InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => cx.type_i32(),
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => cx.type_i8(),
|
||||
|
@ -707,6 +752,9 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
|
|||
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg)
|
||||
| InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
|
||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg) => {
|
||||
unreachable!("clobber-only")
|
||||
}
|
||||
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
|
||||
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
|
||||
bug!("LLVM backend does not support SPIR-V")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue