From 4e508c5529143dc5c2bb90fb80d100fa9ab90be7 Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Mon, 27 Jun 2022 11:14:20 -0700 Subject: [PATCH] Cranelift/x64: fix register allocator metadata for 8-bit divides. `idiv` on x86-64 only reads `rdx`/`edx`/`dx`/`dl` for divides with width greater than 8 bits; for an 8-bit divide, it reads the whole 16-bit divisor from `ax`, as our CISC ancestors intended. This PR fixes the metadata to avoid a regalloc panic (due to undefined `rdx`) in this case. Does not affect Wasmtime or other Wasm-frontend embedders. --- cranelift/codegen/src/isa/x64/inst/emit.rs | 6 ++++-- cranelift/codegen/src/isa/x64/inst/mod.rs | 11 +++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/cranelift/codegen/src/isa/x64/inst/emit.rs b/cranelift/codegen/src/isa/x64/inst/emit.rs index 0192945c478a..83b343497b91 100644 --- a/cranelift/codegen/src/isa/x64/inst/emit.rs +++ b/cranelift/codegen/src/isa/x64/inst/emit.rs @@ -385,13 +385,15 @@ pub(crate) fn emit( dst_remainder, } => { let dividend_lo = allocs.next(dividend_lo.to_reg()); - let dividend_hi = allocs.next(dividend_hi.to_reg()); let dst_quotient = allocs.next(dst_quotient.to_reg().to_reg()); let dst_remainder = allocs.next(dst_remainder.to_reg().to_reg()); debug_assert_eq!(dividend_lo, regs::rax()); - debug_assert_eq!(dividend_hi, regs::rdx()); debug_assert_eq!(dst_quotient, regs::rax()); debug_assert_eq!(dst_remainder, regs::rdx()); + if size.to_bits() > 8 { + let dividend_hi = allocs.next(dividend_hi.to_reg()); + debug_assert_eq!(dividend_hi, regs::rdx()); + } let (opcode, prefix) = match size { OperandSize::Size8 => (0xF6, LegacyPrefixes::None), diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs index c022d16b2dea..502f378f7c7c 100644 --- a/cranelift/codegen/src/isa/x64/inst/mod.rs +++ b/cranelift/codegen/src/isa/x64/inst/mod.rs @@ -966,11 +966,15 @@ impl PrettyPrint for Inst { dst_remainder, } => { let dividend_lo = pretty_print_reg(dividend_lo.to_reg(), size.to_bytes(), allocs); - let dividend_hi = pretty_print_reg(dividend_hi.to_reg(), size.to_bytes(), allocs); let dst_quotient = pretty_print_reg(dst_quotient.to_reg().to_reg(), size.to_bytes(), allocs); let dst_remainder = pretty_print_reg(dst_remainder.to_reg().to_reg(), size.to_bytes(), allocs); + let dividend_hi = if size.to_bits() > 8 { + pretty_print_reg(dividend_hi.to_reg(), size.to_bytes(), allocs) + } else { + "(none)".to_string() + }; let divisor = divisor.pretty_print(size.to_bytes(), allocs); format!( "{} {}, {}, {}, {}, {}", @@ -1715,12 +1719,15 @@ fn x64_get_operands VReg>(inst: &Inst, collector: &mut OperandCol dividend_hi, dst_quotient, dst_remainder, + size, .. } => { collector.reg_fixed_use(dividend_lo.to_reg(), regs::rax()); - collector.reg_fixed_use(dividend_hi.to_reg(), regs::rdx()); collector.reg_fixed_def(dst_quotient.to_writable_reg(), regs::rax()); collector.reg_fixed_def(dst_remainder.to_writable_reg(), regs::rdx()); + if size.to_bits() > 8 { + collector.reg_fixed_use(dividend_hi.to_reg(), regs::rdx()); + } divisor.get_operands(collector); } Inst::MulHi {