implement panic on overflow for mul in the dev backend

This commit is contained in:
Folkert 2024-01-02 15:56:28 +01:00
parent 865eff1956
commit cfdfbe18a4
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
5 changed files with 71 additions and 9 deletions

View file

@ -1424,9 +1424,38 @@ impl<
}
fn build_num_mul(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
// for the time being, `num_mul` is implemented as wrapping multiplication. In roc, the normal
// `mul` should panic on overflow, but we just don't do that yet
self.build_num_mul_wrap(dst, src1, src2, layout)
match self.layout_interner.get_repr(*layout) {
LayoutRepr::Builtin(Builtin::Int(int_width)) => self.build_fn_call(
dst,
bitcode::NUM_MUL_OR_PANIC_INT[int_width].to_string(),
&[*src1, *src2],
&[*layout, *layout],
layout,
),
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
ASM::mul_freg64_freg64_freg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
}
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
ASM::mul_freg32_freg32_freg32(&mut self.buf, dst_reg, src1_reg, src2_reg);
}
LayoutRepr::DEC => self.build_fn_call(
dst,
bitcode::DEC_MUL_OR_PANIC.to_string(),
&[*src1, *src2],
&[Layout::DEC, Layout::DEC],
&Layout::DEC,
),
other => unreachable!("NumMul for layout {other:?}"),
}
}
fn build_num_mul_wrap(

View file

@ -523,12 +523,12 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
use X86_64GeneralReg::*;
type ASM = X86_64Assembler;
// move the first argument to roc_panic (a *RocStr) into r8
ASM::add_reg64_reg64_imm32(buf, R8, RSP, 8);
// move the first argument to roc_panic (a *const RocStr) into r8
ASM::mov_reg64_reg64(buf, R8, RDI);
// move the crash tag into the second return register. We add 1 to it because the 0 value
// is already used for "no crash occurred"
ASM::add_reg64_reg64_imm32(buf, RDX, RDI, 1);
ASM::add_reg64_reg64_imm32(buf, RDX, RSI, 1);
// the setlongjmp_buffer
ASM::data_pointer(buf, relocs, String::from("setlongjmp_buffer"), RDI);