mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 07:41:12 +00:00
Merge branch 'trunk' into mfonism/rename-num-float-type-to-frac
This commit is contained in:
commit
df7df4ccf8
96 changed files with 4357 additions and 1433 deletions
|
@ -68,6 +68,8 @@ use roc_mono::layout::{Builtin, LambdaSet, Layout, LayoutIds, TagIdIntType, Unio
|
|||
use roc_target::{PtrWidth, TargetInfo};
|
||||
use target_lexicon::{Architecture, OperatingSystem, Triple};
|
||||
|
||||
use super::convert::zig_with_overflow_roc_dec;
|
||||
|
||||
#[inline(always)]
|
||||
fn print_fn_verification_output() -> bool {
|
||||
dbg_do!(ROC_PRINT_LLVM_FN_VERIFICATION, {
|
||||
|
@ -5246,6 +5248,7 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
argument_layouts,
|
||||
Layout::Builtin(Builtin::Bool),
|
||||
);
|
||||
|
||||
list_find_unsafe(env, layout_ids, roc_function_call, list, element_layout)
|
||||
}
|
||||
_ => unreachable!("invalid list layout"),
|
||||
|
@ -5368,7 +5371,17 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
let string = load_symbol(scope, &args[0]);
|
||||
|
||||
call_bitcode_fn(env, &[string], intrinsic)
|
||||
let result = call_bitcode_fn(env, &[string], intrinsic);
|
||||
|
||||
// zig passes the result as a packed integer sometimes, instead of a struct. So we cast
|
||||
let expected_type = basic_type_from_layout(env, layout);
|
||||
let actual_type = result.get_type();
|
||||
|
||||
if expected_type != actual_type {
|
||||
complex_bitcast_check_size(env, result, expected_type, "str_to_num_cast")
|
||||
} else {
|
||||
result
|
||||
}
|
||||
}
|
||||
StrFromInt => {
|
||||
// Str.fromInt : Int -> Str
|
||||
|
@ -7054,6 +7067,76 @@ fn build_float_binop<'a, 'ctx, 'env>(
|
|||
}
|
||||
}
|
||||
|
||||
fn dec_binop_with_overflow<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
fn_name: &str,
|
||||
lhs: BasicValueEnum<'ctx>,
|
||||
rhs: BasicValueEnum<'ctx>,
|
||||
) -> StructValue<'ctx> {
|
||||
let lhs = lhs.into_int_value();
|
||||
let rhs = rhs.into_int_value();
|
||||
|
||||
let return_type = zig_with_overflow_roc_dec(env);
|
||||
let return_alloca = env.builder.build_alloca(return_type, "return_alloca");
|
||||
|
||||
let int_64 = env.context.i128_type().const_int(64, false);
|
||||
let int_64_type = env.context.i64_type();
|
||||
|
||||
let lhs1 = env
|
||||
.builder
|
||||
.build_right_shift(lhs, int_64, false, "lhs_left_bits");
|
||||
let rhs1 = env
|
||||
.builder
|
||||
.build_right_shift(rhs, int_64, false, "rhs_left_bits");
|
||||
|
||||
call_void_bitcode_fn(
|
||||
env,
|
||||
&[
|
||||
return_alloca.into(),
|
||||
env.builder.build_int_cast(lhs, int_64_type, "").into(),
|
||||
env.builder.build_int_cast(lhs1, int_64_type, "").into(),
|
||||
env.builder.build_int_cast(rhs, int_64_type, "").into(),
|
||||
env.builder.build_int_cast(rhs1, int_64_type, "").into(),
|
||||
],
|
||||
fn_name,
|
||||
);
|
||||
|
||||
env.builder
|
||||
.build_load(return_alloca, "load_dec")
|
||||
.into_struct_value()
|
||||
}
|
||||
|
||||
pub fn dec_binop_with_unchecked<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
fn_name: &str,
|
||||
lhs: BasicValueEnum<'ctx>,
|
||||
rhs: BasicValueEnum<'ctx>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let lhs = lhs.into_int_value();
|
||||
let rhs = rhs.into_int_value();
|
||||
|
||||
let int_64 = env.context.i128_type().const_int(64, false);
|
||||
let int_64_type = env.context.i64_type();
|
||||
|
||||
let lhs1 = env
|
||||
.builder
|
||||
.build_right_shift(lhs, int_64, false, "lhs_left_bits");
|
||||
let rhs1 = env
|
||||
.builder
|
||||
.build_right_shift(rhs, int_64, false, "rhs_left_bits");
|
||||
|
||||
call_bitcode_fn(
|
||||
env,
|
||||
&[
|
||||
env.builder.build_int_cast(lhs, int_64_type, "").into(),
|
||||
env.builder.build_int_cast(lhs1, int_64_type, "").into(),
|
||||
env.builder.build_int_cast(rhs, int_64_type, "").into(),
|
||||
env.builder.build_int_cast(rhs1, int_64_type, "").into(),
|
||||
],
|
||||
fn_name,
|
||||
)
|
||||
}
|
||||
|
||||
fn build_dec_binop<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
|
@ -7093,7 +7176,7 @@ fn build_dec_binop<'a, 'ctx, 'env>(
|
|||
rhs,
|
||||
"decimal multiplication overflowed",
|
||||
),
|
||||
NumDivUnchecked => call_bitcode_fn(env, &[lhs, rhs], bitcode::DEC_DIV),
|
||||
NumDivUnchecked => dec_binop_with_unchecked(env, bitcode::DEC_DIV, lhs, rhs),
|
||||
_ => {
|
||||
unreachable!("Unrecognized int binary operation: {:?}", op);
|
||||
}
|
||||
|
@ -7108,15 +7191,7 @@ fn build_dec_binop_throw_on_overflow<'a, 'ctx, 'env>(
|
|||
rhs: BasicValueEnum<'ctx>,
|
||||
message: &str,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let overflow_type = crate::llvm::convert::zig_with_overflow_roc_dec(env);
|
||||
|
||||
let result_ptr = env.builder.build_alloca(overflow_type, "result_ptr");
|
||||
call_void_bitcode_fn(env, &[result_ptr.into(), lhs, rhs], operation);
|
||||
|
||||
let result = env
|
||||
.builder
|
||||
.build_load(result_ptr, "load_overflow")
|
||||
.into_struct_value();
|
||||
let result = dec_binop_with_overflow(env, operation, lhs, rhs);
|
||||
|
||||
let value = throw_on_overflow(env, parent, result, message).into_struct_value();
|
||||
|
||||
|
@ -7211,6 +7286,9 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
|| // Or if the two types are the same, they trivially fit.
|
||||
arg_width == target_int_width;
|
||||
|
||||
let return_type =
|
||||
convert::basic_type_from_layout(env, return_layout).into_struct_type();
|
||||
|
||||
if arg_always_fits_in_target {
|
||||
// This is guaranteed to succeed so we can just make it an int cast and let LLVM
|
||||
// optimize it away.
|
||||
|
@ -7225,8 +7303,6 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
)
|
||||
.into();
|
||||
|
||||
let return_type =
|
||||
convert::basic_type_from_layout(env, return_layout).into_struct_type();
|
||||
let r = return_type.const_zero();
|
||||
let r = bd
|
||||
.build_insert_value(r, target_int_val, 0, "converted_int")
|
||||
|
@ -7249,7 +7325,14 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
&bitcode::NUM_INT_TO_INT_CHECKING_MAX_AND_MIN[target_int_width][arg_width]
|
||||
};
|
||||
|
||||
call_bitcode_fn_fixing_for_convention(env, &[arg.into()], return_layout, bitcode_fn)
|
||||
let result = call_bitcode_fn_fixing_for_convention(
|
||||
env,
|
||||
&[arg.into()],
|
||||
return_layout,
|
||||
bitcode_fn,
|
||||
);
|
||||
|
||||
complex_bitcast_check_size(env, result, return_type.into(), "cast_bitpacked")
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
|
|
@ -283,6 +283,8 @@ pub fn dict_get<'a, 'ctx, 'env>(
|
|||
.ptr_int()
|
||||
.const_int(value_layout.stack_size(env.target_info) as u64, false);
|
||||
|
||||
let value_bt = basic_type_from_layout(env, value_layout);
|
||||
|
||||
let alignment = Alignment::from_key_value_layout(key_layout, value_layout, env.target_info);
|
||||
let alignment_iv = alignment.as_int_value(env.context);
|
||||
|
||||
|
@ -308,17 +310,26 @@ pub fn dict_get<'a, 'ctx, 'env>(
|
|||
)
|
||||
.into_struct_value();
|
||||
|
||||
let flag = env
|
||||
let flag_u8 = env
|
||||
.builder
|
||||
.build_extract_value(result, 1, "get_flag")
|
||||
.unwrap()
|
||||
.into_int_value();
|
||||
|
||||
let flag = env
|
||||
.builder
|
||||
.build_int_cast(flag_u8, env.context.bool_type(), "to_bool");
|
||||
|
||||
let value_u8_ptr_int = env
|
||||
.builder
|
||||
.build_extract_value(result, 0, "get_value_ptr_int")
|
||||
.unwrap()
|
||||
.into_int_value();
|
||||
|
||||
let ptr_type = value_bt.ptr_type(AddressSpace::Generic);
|
||||
let value_u8_ptr = env
|
||||
.builder
|
||||
.build_extract_value(result, 0, "get_value_ptr")
|
||||
.unwrap()
|
||||
.into_pointer_value();
|
||||
.build_int_to_ptr(value_u8_ptr_int, ptr_type, "opaque_value_ptr");
|
||||
|
||||
let start_block = env.builder.get_insert_block().unwrap();
|
||||
let parent = start_block.get_parent().unwrap();
|
||||
|
@ -326,7 +337,6 @@ pub fn dict_get<'a, 'ctx, 'env>(
|
|||
let if_not_null = env.context.append_basic_block(parent, "if_not_null");
|
||||
let done_block = env.context.append_basic_block(parent, "done");
|
||||
|
||||
let value_bt = basic_type_from_layout(env, value_layout);
|
||||
let default = value_bt.const_zero();
|
||||
|
||||
env.builder
|
||||
|
|
|
@ -494,7 +494,7 @@ pub fn list_walk_generic<'a, 'ctx, 'env>(
|
|||
layout_width(env, element_layout),
|
||||
layout_width(env, function_call_return_layout),
|
||||
layout_width(env, default_layout),
|
||||
has_tag_id.as_global_value().as_pointer_value().into(),
|
||||
has_tag_id_helper(env, has_tag_id).into(),
|
||||
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||
pass_as_opaque(env, result_ptr),
|
||||
],
|
||||
|
@ -603,6 +603,30 @@ fn empty_list<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> BasicValueEnum<'ctx>
|
|||
BasicValueEnum::StructValue(struct_type.const_zero())
|
||||
}
|
||||
|
||||
fn has_tag_id_helper<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
has_tag_id: FunctionValue<'ctx>,
|
||||
) -> PointerValue<'ctx> {
|
||||
let u8_t = env.context.i8_type();
|
||||
let u16_t = env.context.i16_type();
|
||||
|
||||
let u8_ptr_t = u8_t.ptr_type(AddressSpace::Generic);
|
||||
|
||||
let struct_t = env
|
||||
.context
|
||||
.struct_type(&[u8_t.into(), env.ptr_int().into()], false);
|
||||
|
||||
let has_tag_id_type = struct_t
|
||||
.fn_type(&[u16_t.into(), u8_ptr_t.into()], false)
|
||||
.ptr_type(AddressSpace::Generic);
|
||||
|
||||
env.builder.build_pointer_cast(
|
||||
has_tag_id.as_global_value().as_pointer_value(),
|
||||
has_tag_id_type,
|
||||
"has_tag_id_cast",
|
||||
)
|
||||
}
|
||||
|
||||
/// List.keepOks : List before, (before -> Result after *) -> List after
|
||||
pub fn list_keep_oks<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
|
@ -626,7 +650,7 @@ pub fn list_keep_oks<'a, 'ctx, 'env>(
|
|||
let has_tag_id = match result_layout {
|
||||
Layout::Union(union_layout) => build_has_tag_id(env, function, *union_layout),
|
||||
Layout::Builtin(Builtin::Bool) => {
|
||||
// a `Result [] whatever`, so there is nothing to keep
|
||||
// a `Result whatever []`, so there is nothing to keep
|
||||
return empty_list(env);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
|
@ -644,7 +668,7 @@ pub fn list_keep_oks<'a, 'ctx, 'env>(
|
|||
layout_width(env, before_layout),
|
||||
layout_width(env, result_layout),
|
||||
layout_width(env, after_layout),
|
||||
has_tag_id.as_global_value().as_pointer_value().into(),
|
||||
has_tag_id_helper(env, has_tag_id).into(),
|
||||
dec_result_fn.as_global_value().as_pointer_value().into(),
|
||||
],
|
||||
bitcode::LIST_KEEP_OKS,
|
||||
|
@ -692,7 +716,7 @@ pub fn list_keep_errs<'a, 'ctx, 'env>(
|
|||
layout_width(env, before_layout),
|
||||
layout_width(env, result_layout),
|
||||
layout_width(env, after_layout),
|
||||
has_tag_id.as_global_value().as_pointer_value().into(),
|
||||
has_tag_id_helper(env, has_tag_id).into(),
|
||||
dec_result_fn.as_global_value().as_pointer_value().into(),
|
||||
],
|
||||
bitcode::LIST_KEEP_ERRS,
|
||||
|
@ -968,7 +992,6 @@ pub fn list_find_unsafe<'a, 'ctx, 'env>(
|
|||
pass_as_opaque(env, roc_function_call.data),
|
||||
roc_function_call.inc_n_data.into(),
|
||||
roc_function_call.data_is_owned.into(),
|
||||
env.alignment_intvalue(element_layout),
|
||||
layout_width(env, element_layout),
|
||||
inc_element_fn.as_global_value().as_pointer_value().into(),
|
||||
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||
|
@ -982,18 +1005,22 @@ pub fn list_find_unsafe<'a, 'ctx, 'env>(
|
|||
// in the Zig definition called above, because we don't know the size of the
|
||||
// element until user compile time, which is later than the compile time of bitcode defs.
|
||||
|
||||
let value_u8_ptr = env
|
||||
let value_u8_ptr_int = env
|
||||
.builder
|
||||
.build_extract_value(result, 0, "get_value_ptr")
|
||||
.build_extract_value(result, 0, "get_value_ptr_int")
|
||||
.unwrap()
|
||||
.into_pointer_value();
|
||||
.into_int_value();
|
||||
|
||||
let found = env
|
||||
let found_u8 = env
|
||||
.builder
|
||||
.build_extract_value(result, 1, "get_found")
|
||||
.unwrap()
|
||||
.into_int_value();
|
||||
|
||||
let found = env
|
||||
.builder
|
||||
.build_int_cast(found_u8, env.context.bool_type(), "found_as_bool");
|
||||
|
||||
let start_block = env.builder.get_insert_block().unwrap();
|
||||
let parent = start_block.get_parent().unwrap();
|
||||
|
||||
|
@ -1007,14 +1034,13 @@ pub fn list_find_unsafe<'a, 'ctx, 'env>(
|
|||
.build_conditional_branch(found, if_not_null, done_block);
|
||||
|
||||
env.builder.position_at_end(if_not_null);
|
||||
let value_ptr = env
|
||||
.builder
|
||||
.build_bitcast(
|
||||
value_u8_ptr,
|
||||
value_bt.ptr_type(AddressSpace::Generic),
|
||||
"from_opaque",
|
||||
)
|
||||
.into_pointer_value();
|
||||
|
||||
let value_ptr = env.builder.build_int_to_ptr(
|
||||
value_u8_ptr_int,
|
||||
value_bt.ptr_type(AddressSpace::Generic),
|
||||
"get_value_ptr",
|
||||
);
|
||||
|
||||
let loaded = env.builder.build_load(value_ptr, "load_value");
|
||||
env.builder.build_unconditional_branch(done_block);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::llvm::bitcode::{call_bitcode_fn, call_str_bitcode_fn, call_void_bitcode_fn};
|
||||
use crate::llvm::build::{complex_bitcast, Env, Scope};
|
||||
use crate::llvm::build::{Env, Scope};
|
||||
use crate::llvm::build_list::{allocate_list, pass_update_mode, store_list};
|
||||
use inkwell::builder::Builder;
|
||||
use inkwell::values::{BasicValueEnum, IntValue, PointerValue, StructValue};
|
||||
|
@ -155,16 +155,22 @@ pub fn str_from_utf8_range<'a, 'ctx, 'env>(
|
|||
let result_type = env.module.get_struct_type("str.FromUtf8Result").unwrap();
|
||||
let result_ptr = builder.build_alloca(result_type, "alloca_utf8_validate_bytes_result");
|
||||
|
||||
let count = env
|
||||
.builder
|
||||
.build_extract_value(count_and_start, 0, "get_count")
|
||||
.unwrap();
|
||||
|
||||
let start = env
|
||||
.builder
|
||||
.build_extract_value(count_and_start, 1, "get_start")
|
||||
.unwrap();
|
||||
|
||||
call_void_bitcode_fn(
|
||||
env,
|
||||
&[
|
||||
list_symbol_to_c_abi(env, scope, list).into(),
|
||||
complex_bitcast(
|
||||
env.builder,
|
||||
count_and_start.into(),
|
||||
env.twice_ptr_int().into(),
|
||||
"to_i128",
|
||||
),
|
||||
count,
|
||||
start,
|
||||
result_ptr.into(),
|
||||
],
|
||||
bitcode::STR_FROM_UTF8_RANGE,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use crate::llvm::bitcode::call_bitcode_fn;
|
||||
use crate::llvm::build::{get_tag_id, tag_pointer_clear_tag_id, Env, FAST_CALL_CONV};
|
||||
use crate::llvm::build_list::{list_len, load_list_ptr};
|
||||
use crate::llvm::build_str::str_equal;
|
||||
|
@ -14,7 +13,7 @@ use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
|||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds, UnionLayout};
|
||||
|
||||
use super::build::{load_roc_value, use_roc_value};
|
||||
use super::build::{dec_binop_with_unchecked, load_roc_value, use_roc_value};
|
||||
use super::convert::argument_type_from_union_layout;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -124,7 +123,7 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
|
|||
}
|
||||
|
||||
Builtin::Bool => int_cmp(IntPredicate::EQ, "eq_i1"),
|
||||
Builtin::Decimal => call_bitcode_fn(env, &[lhs_val, rhs_val], bitcode::DEC_EQ),
|
||||
Builtin::Decimal => dec_binop_with_unchecked(env, bitcode::DEC_EQ, lhs_val, rhs_val),
|
||||
|
||||
Builtin::Str => str_equal(env, lhs_val, rhs_val),
|
||||
Builtin::List(elem) => build_list_eq(
|
||||
|
@ -289,7 +288,7 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
|
|||
}
|
||||
|
||||
Builtin::Bool => int_cmp(IntPredicate::NE, "neq_i1"),
|
||||
Builtin::Decimal => call_bitcode_fn(env, &[lhs_val, rhs_val], bitcode::DEC_NEQ),
|
||||
Builtin::Decimal => dec_binop_with_unchecked(env, bitcode::DEC_NEQ, lhs_val, rhs_val),
|
||||
|
||||
Builtin::Str => {
|
||||
let is_equal = str_equal(env, lhs_val, rhs_val).into_int_value();
|
||||
|
|
|
@ -273,7 +273,10 @@ pub fn zig_str_type<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> StructType<'ct
|
|||
}
|
||||
|
||||
pub fn zig_has_tag_id_type<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> StructType<'ctx> {
|
||||
env.module.get_struct_type("list.HasTagId").unwrap()
|
||||
let u8_ptr_t = env.context.i8_type().ptr_type(AddressSpace::Generic);
|
||||
|
||||
env.context
|
||||
.struct_type(&[env.context.bool_type().into(), u8_ptr_t.into()], false)
|
||||
}
|
||||
|
||||
pub fn zig_with_overflow_roc_dec<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> StructType<'ctx> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue