Fix compilation of addChecked for Dec

This commit is contained in:
Ayaz Hafiz 2023-06-06 17:34:35 -05:00
parent 0c632b1731
commit b3966a588a
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
2 changed files with 50 additions and 9 deletions

View file

@ -27,8 +27,9 @@ use crate::llvm::{
BitcodeReturns, BitcodeReturns,
}, },
build::{ build::{
complex_bitcast_check_size, create_entry_block_alloca, function_value_by_func_spec, cast_basic_basic, complex_bitcast_check_size, create_entry_block_alloca,
load_roc_value, roc_function_call, tag_pointer_clear_tag_id, BuilderExt, RocReturn, function_value_by_func_spec, load_roc_value, roc_function_call, tag_pointer_clear_tag_id,
BuilderExt, RocReturn,
}, },
build_list::{ build_list::{
list_append_unsafe, list_concat, list_drop_at, list_get_unsafe, list_len, list_map, list_append_unsafe, list_concat, list_drop_at, list_get_unsafe, list_len, list_map,
@ -1092,6 +1093,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
lhs_layout, lhs_layout,
rhs_arg, rhs_arg,
rhs_layout, rhs_layout,
layout,
op, op,
) )
} }
@ -1553,12 +1555,13 @@ fn build_int_binop<'ctx>(
pub fn build_num_binop<'a, 'ctx>( pub fn build_num_binop<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>, env: &Env<'a, 'ctx, '_>,
layout_interner: &STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
lhs_arg: BasicValueEnum<'ctx>, lhs_arg: BasicValueEnum<'ctx>,
lhs_layout: InLayout<'a>, lhs_layout: InLayout<'a>,
rhs_arg: BasicValueEnum<'ctx>, rhs_arg: BasicValueEnum<'ctx>,
rhs_layout: InLayout<'a>, rhs_layout: InLayout<'a>,
return_layout: InLayout<'a>,
op: LowLevel, op: LowLevel,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
match ( match (
@ -1588,9 +1591,15 @@ pub fn build_num_binop<'a, 'ctx>(
op, op,
), ),
Decimal => { Decimal => build_dec_binop(
build_dec_binop(env, parent, lhs_arg, lhs_layout, rhs_arg, rhs_layout, op) env,
} layout_interner,
parent,
lhs_arg,
rhs_arg,
return_layout,
op,
),
_ => { _ => {
unreachable!("Compiler bug: tried to run numeric operation {:?} on invalid builtin layout: ({:?})", op, lhs_layout); unreachable!("Compiler bug: tried to run numeric operation {:?} on invalid builtin layout: ({:?})", op, lhs_layout);
} }
@ -1927,19 +1936,35 @@ pub(crate) fn dec_binop_with_unchecked<'ctx>(
} }
} }
/// Zig returns a nominal `WithOverflow(Dec)` struct (see [zig_with_overflow_roc_dec]),
/// but the Roc side may flatten the overflow struct. LLVM does not admit comparisons
/// between the two representations, so always cast to the Roc representation.
fn cast_with_overflow_dec_to_roc_type<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
val: BasicValueEnum<'ctx>,
return_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
let return_type = convert::basic_type_from_layout(env, layout_interner, return_layout);
cast_basic_basic(env.builder, val.into(), return_type)
}
fn build_dec_binop<'a, 'ctx>( fn build_dec_binop<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
lhs: BasicValueEnum<'ctx>, lhs: BasicValueEnum<'ctx>,
_lhs_layout: InLayout<'a>,
rhs: BasicValueEnum<'ctx>, rhs: BasicValueEnum<'ctx>,
_rhs_layout: InLayout<'a>, return_layout: InLayout<'a>,
op: LowLevel, op: LowLevel,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
use roc_module::low_level::LowLevel::*; use roc_module::low_level::LowLevel::*;
match op { match op {
NumAddChecked => call_bitcode_fn(env, &[lhs, rhs], bitcode::DEC_ADD_WITH_OVERFLOW), NumAddChecked => {
let val = dec_binop_with_overflow(env, bitcode::DEC_ADD_WITH_OVERFLOW, lhs, rhs);
cast_with_overflow_dec_to_roc_type(env, layout_interner, val.into(), return_layout)
}
NumSubChecked => call_bitcode_fn(env, &[lhs, rhs], bitcode::DEC_SUB_WITH_OVERFLOW), NumSubChecked => call_bitcode_fn(env, &[lhs, rhs], bitcode::DEC_SUB_WITH_OVERFLOW),
NumMulChecked => call_bitcode_fn(env, &[lhs, rhs], bitcode::DEC_MUL_WITH_OVERFLOW), NumMulChecked => call_bitcode_fn(env, &[lhs, rhs], bitcode::DEC_MUL_WITH_OVERFLOW),
NumAdd => build_dec_binop_throw_on_overflow( NumAdd => build_dec_binop_throw_on_overflow(

View file

@ -3924,3 +3924,19 @@ fn bool_in_switch() {
bool bool
); );
} }
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
fn add_checked_frac_infer() {
assert_evals_to!(
indoc!(
r#"
app "test" provides [main] to "./platform"
main = Num.addChecked 2.0dec 4.0dec == Ok 6.0dec
"#
),
true,
bool
);
}