mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 06:55:15 +00:00
Merge pull request #3877 from roc-lang/dev-backend-add-checked
dev backend add checked
This commit is contained in:
commit
1db7c3664d
6 changed files with 120 additions and 67 deletions
|
@ -826,6 +826,10 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
|
|||
todo!("registers greater than or equal for AArch64");
|
||||
}
|
||||
|
||||
fn set_if_overflow(_buf: &mut Vec<'_, u8>, _dst: AArch64GeneralReg) {
|
||||
todo!("set if overflow for AArch64");
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn ret(buf: &mut Vec<'_, u8>) {
|
||||
ret_reg64(buf, AArch64GeneralReg::LR)
|
||||
|
|
|
@ -320,6 +320,8 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
|||
src2: GeneralReg,
|
||||
);
|
||||
|
||||
fn set_if_overflow(buf: &mut Vec<'_, u8>, dst: GeneralReg);
|
||||
|
||||
fn ret(buf: &mut Vec<'_, u8>);
|
||||
}
|
||||
|
||||
|
@ -340,6 +342,7 @@ pub struct Backend64Bit<
|
|||
// They are likely to be small enough that it is faster to use a vec and linearly scan it or keep it sorted and binary search.
|
||||
phantom_asm: PhantomData<ASM>,
|
||||
phantom_cc: PhantomData<CC>,
|
||||
target_info: TargetInfo,
|
||||
env: &'a Env<'a>,
|
||||
interns: &'a mut Interns,
|
||||
helper_proc_gen: CodeGenHelp<'a>,
|
||||
|
@ -374,6 +377,7 @@ pub fn new_backend_64bit<
|
|||
Backend64Bit {
|
||||
phantom_asm: PhantomData,
|
||||
phantom_cc: PhantomData,
|
||||
target_info,
|
||||
env,
|
||||
interns,
|
||||
helper_proc_gen: CodeGenHelp::new(env.arena, target_info, env.module_id),
|
||||
|
@ -790,11 +794,62 @@ impl<
|
|||
}
|
||||
}
|
||||
|
||||
fn build_num_add_checked(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
src1: &Symbol,
|
||||
src2: &Symbol,
|
||||
num_layout: &Layout<'a>,
|
||||
return_layout: &Layout<'a>,
|
||||
) {
|
||||
use Builtin::Int;
|
||||
|
||||
let buf = &mut self.buf;
|
||||
|
||||
let struct_size = return_layout.stack_size(self.target_info);
|
||||
|
||||
let base_offset = self.storage_manager.claim_stack_area(dst, struct_size);
|
||||
|
||||
match num_layout {
|
||||
Layout::Builtin(Int(IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8)) => {
|
||||
let dst_reg = self
|
||||
.storage_manager
|
||||
.claim_general_reg(buf, &Symbol::DEV_TMP);
|
||||
|
||||
let overflow_reg = self
|
||||
.storage_manager
|
||||
.claim_general_reg(buf, &Symbol::DEV_TMP2);
|
||||
|
||||
let src1_reg = self.storage_manager.load_to_general_reg(buf, src1);
|
||||
let src2_reg = self.storage_manager.load_to_general_reg(buf, src2);
|
||||
|
||||
ASM::add_reg64_reg64_reg64(buf, dst_reg, src1_reg, src2_reg);
|
||||
ASM::set_if_overflow(buf, overflow_reg);
|
||||
|
||||
ASM::mov_base32_reg64(buf, base_offset, dst_reg);
|
||||
ASM::mov_base32_reg64(buf, base_offset + 8, overflow_reg);
|
||||
|
||||
self.free_symbol(&Symbol::DEV_TMP);
|
||||
self.free_symbol(&Symbol::DEV_TMP2);
|
||||
}
|
||||
Layout::Builtin(Int(IntWidth::U64 | IntWidth::U32 | IntWidth::U16 | IntWidth::U8)) => {
|
||||
todo!("addChecked for unsigned integers")
|
||||
}
|
||||
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
|
||||
todo!("addChecked for f64")
|
||||
}
|
||||
Layout::Builtin(Builtin::Float(FloatWidth::F32)) => {
|
||||
todo!("addChecked for f32")
|
||||
}
|
||||
x => todo!("NumAdd: layout, {:?}", x),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_num_mul(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &Layout<'a>) {
|
||||
use Builtin::Int;
|
||||
|
||||
match layout {
|
||||
Layout::Builtin(Builtin::Int(
|
||||
IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8,
|
||||
)) => {
|
||||
Layout::Builtin(Int(IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8)) => {
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src1_reg = self
|
||||
.storage_manager
|
||||
|
@ -804,9 +859,7 @@ impl<
|
|||
.load_to_general_reg(&mut self.buf, src2);
|
||||
ASM::imul_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||
}
|
||||
Layout::Builtin(Builtin::Int(
|
||||
IntWidth::U64 | IntWidth::U32 | IntWidth::U16 | IntWidth::U8,
|
||||
)) => {
|
||||
Layout::Builtin(Int(IntWidth::U64 | IntWidth::U32 | IntWidth::U16 | IntWidth::U8)) => {
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src1_reg = self
|
||||
.storage_manager
|
||||
|
|
|
@ -1390,6 +1390,10 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
|||
fn ret(buf: &mut Vec<'_, u8>) {
|
||||
ret(buf);
|
||||
}
|
||||
|
||||
fn set_if_overflow(buf: &mut Vec<'_, u8>, dst: X86_64GeneralReg) {
|
||||
seto_reg64(buf, dst);
|
||||
}
|
||||
}
|
||||
|
||||
impl X86_64Assembler {
|
||||
|
@ -2118,6 +2122,12 @@ fn setge_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
|
|||
set_reg64_help(0x9d, buf, reg);
|
||||
}
|
||||
|
||||
/// `SETO r/m64` -> Set byte if oveflow flag is set.
|
||||
#[inline(always)]
|
||||
fn seto_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
|
||||
set_reg64_help(0x90, buf, reg);
|
||||
}
|
||||
|
||||
/// `RET` -> Near return to calling procedure.
|
||||
#[inline(always)]
|
||||
fn ret(buf: &mut Vec<'_, u8>) {
|
||||
|
|
|
@ -405,6 +405,9 @@ trait Backend<'a> {
|
|||
);
|
||||
self.build_num_add(sym, &args[0], &args[1], ret_layout)
|
||||
}
|
||||
LowLevel::NumAddChecked => {
|
||||
self.build_num_add_checked(sym, &args[0], &args[1], &arg_layouts[0], ret_layout)
|
||||
}
|
||||
LowLevel::NumAcos => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::NUM_ACOS[FloatWidth::F64].to_string(),
|
||||
|
@ -694,6 +697,13 @@ trait Backend<'a> {
|
|||
self.load_literal_symbols(args);
|
||||
self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout)
|
||||
}
|
||||
Symbol::NUM_ADD_CHECKED => {
|
||||
let layout_id = LayoutIds::default().get(func_sym, ret_layout);
|
||||
let fn_name = self.symbol_to_string(func_sym, layout_id);
|
||||
// Now that the arguments are needed, load them if they are literals.
|
||||
self.load_literal_symbols(args);
|
||||
self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout)
|
||||
}
|
||||
_ => todo!("the function, {:?}", func_sym),
|
||||
}
|
||||
}
|
||||
|
@ -715,6 +725,16 @@ trait Backend<'a> {
|
|||
/// build_num_add stores the sum of src1 and src2 into dst.
|
||||
fn build_num_add(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &Layout<'a>);
|
||||
|
||||
/// build_num_add_checked stores the sum of src1 and src2 into dst.
|
||||
fn build_num_add_checked(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
src1: &Symbol,
|
||||
src2: &Symbol,
|
||||
num_layout: &Layout<'a>,
|
||||
return_layout: &Layout<'a>,
|
||||
);
|
||||
|
||||
/// build_num_mul stores `src1 * src2` into dst.
|
||||
fn build_num_mul(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &Layout<'a>);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue