update rust code to llvm-16 and fix build

also update:
 - llvm frame address
 - erased function type
 - dec passing to zig
 - gen dev storage size
This commit is contained in:
Brendan Hansknecht 2023-09-21 13:12:48 -07:00
parent 2e2e609547
commit 398bf2f96c
No known key found for this signature in database
GPG key ID: 0EA784685083E75B
20 changed files with 1830 additions and 1432 deletions

View file

@ -4,7 +4,7 @@ use inkwell::{
types::{BasicType, BasicTypeEnum, IntType},
values::{
BasicValue, BasicValueEnum, FloatValue, FunctionValue, InstructionOpcode, IntValue,
PointerValue, StructValue,
StructValue,
},
AddressSpace, IntPredicate,
};
@ -20,7 +20,7 @@ use roc_mono::{
},
list_element_layout,
};
use roc_target::PtrWidth;
use roc_target::{PtrWidth, TargetInfo};
use crate::llvm::{
bitcode::{
@ -270,7 +270,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
)
.ptr_type(AddressSpace::default());
let roc_return_alloca = env.builder.build_pointer_cast(
let roc_return_alloca = env.builder.new_build_pointer_cast(
zig_return_alloca,
roc_return_type,
"cast_to_roc",
@ -389,7 +389,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
let result_type = env.module.get_struct_type("str.FromUtf8Result").unwrap();
let result_ptr = env
.builder
.build_alloca(result_type, "alloca_utf8_validate_bytes_result");
.new_build_alloca(result_type, "alloca_utf8_validate_bytes_result");
match env.target_info.ptr_width() {
PtrWidth::Bytes4 => {
@ -482,11 +482,14 @@ pub(crate) fn run_low_level<'a, 'ctx>(
.into_int_value();
// cast to the appropriate usize of the current build
let byte_count =
env.builder
.build_int_cast_sign_flag(length, env.ptr_int(), false, "len_as_usize");
let byte_count = env.builder.new_build_int_cast_sign_flag(
length,
env.ptr_int(),
false,
"len_as_usize",
);
let is_zero = env.builder.build_int_compare(
let is_zero = env.builder.new_build_int_compare(
IntPredicate::EQ,
byte_count,
env.ptr_int().const_zero(),
@ -510,21 +513,16 @@ pub(crate) fn run_low_level<'a, 'ctx>(
// Str.getScalarUnsafe : Str, Nat -> { bytesParsed : Nat, scalar : U32 }
arguments!(string, index);
let roc_return_type =
basic_type_from_layout(env, layout_interner, layout_interner.get_repr(layout));
use roc_target::OperatingSystem::*;
match env.target_info.operating_system {
Windows => {
let zig_return_type = env
.module
.get_function(bitcode::STR_GET_SCALAR_UNSAFE)
.unwrap()
.get_type()
.get_param_types()[0]
.into_pointer_type()
.get_element_type();
let result = env
.builder
.build_alloca(BasicTypeEnum::try_from(zig_return_type).unwrap(), "result");
let result = env.builder.new_build_alloca(
BasicTypeEnum::try_from(roc_return_type).unwrap(),
"result",
);
call_void_bitcode_fn(
env,
@ -532,12 +530,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
bitcode::STR_GET_SCALAR_UNSAFE,
);
let roc_return_type = basic_type_from_layout(
env,
layout_interner,
layout_interner.get_repr(layout),
);
let cast_result = env.builder.build_pointer_cast(
let cast_result = env.builder.new_build_pointer_cast(
result,
roc_return_type.ptr_type(AddressSpace::default()),
"cast",
@ -555,18 +548,15 @@ pub(crate) fn run_low_level<'a, 'ctx>(
bitcode::STR_GET_SCALAR_UNSAFE,
);
// on 32-bit targets, zig bitpacks the struct
match env.target_info.ptr_width() {
PtrWidth::Bytes8 => result,
PtrWidth::Bytes4 => {
let to = basic_type_from_layout(
env,
layout_interner,
layout_interner.get_repr(layout),
);
complex_bitcast_check_size(env, result, to, "to_roc_record")
}
}
// zig will pad the struct to the alignment boundary, or bitpack it on 32-bit
// targets. So we have to cast it to the format that the roc code expects
let alloca = env
.builder
.new_build_alloca(result.get_type(), "to_roc_record");
env.builder.new_build_store(alloca, result);
env.builder
.new_build_load(roc_return_type, alloca, "to_roc_record")
}
Wasi => unimplemented!(),
}
@ -1057,7 +1047,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
match lhs_builtin {
Int(int_width) => {
let are_equal = env.builder.build_int_compare(
let are_equal = env.builder.new_build_int_compare(
IntPredicate::EQ,
lhs_arg.into_int_value(),
rhs_arg.into_int_value(),
@ -1070,18 +1060,21 @@ pub(crate) fn run_low_level<'a, 'ctx>(
IntPredicate::ULT
};
let is_less_than = env.builder.build_int_compare(
let is_less_than = env.builder.new_build_int_compare(
predicate,
lhs_arg.into_int_value(),
rhs_arg.into_int_value(),
"int_compare",
);
let step1 =
env.builder
.build_select(is_less_than, tag_lt, tag_gt, "lt_or_gt");
let step1 = env.builder.new_build_select(
is_less_than,
tag_lt,
tag_gt,
"lt_or_gt",
);
env.builder.build_select(
env.builder.new_build_select(
are_equal,
tag_eq,
step1.into_int_value(),
@ -1089,24 +1082,27 @@ pub(crate) fn run_low_level<'a, 'ctx>(
)
}
Float(_) => {
let are_equal = env.builder.build_float_compare(
let are_equal = env.builder.new_build_float_compare(
FloatPredicate::OEQ,
lhs_arg.into_float_value(),
rhs_arg.into_float_value(),
"float_eq",
);
let is_less_than = env.builder.build_float_compare(
let is_less_than = env.builder.new_build_float_compare(
FloatPredicate::OLT,
lhs_arg.into_float_value(),
rhs_arg.into_float_value(),
"float_compare",
);
let step1 =
env.builder
.build_select(is_less_than, tag_lt, tag_gt, "lt_or_gt");
let step1 = env.builder.new_build_select(
is_less_than,
tag_lt,
tag_gt,
"lt_or_gt",
);
env.builder.build_select(
env.builder.new_build_select(
are_equal,
tag_eq,
step1.into_int_value(),
@ -1177,7 +1173,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
// LLVM shift intrinsics expect the left and right sides to have the same type, so
// here we cast up `rhs` to the lhs type. Since the rhs was checked to be a U8,
// this cast isn't lossy.
let rhs_arg = env.builder.build_int_cast(
let rhs_arg = env.builder.new_build_int_cast(
rhs_arg.into_int_value(),
lhs_arg.get_type().into_int_type(),
"cast_for_shift",
@ -1205,7 +1201,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
let to_signed = intwidth_from_layout(layout).is_signed();
env.builder
.build_int_cast_sign_flag(arg.into_int_value(), to, to_signed, "inc_cast")
.new_build_int_cast_sign_flag(arg.into_int_value(), to, to_signed, "inc_cast")
.into()
}
NumToFloatCast => {
@ -1224,11 +1220,11 @@ pub(crate) fn run_low_level<'a, 'ctx>(
if width.is_signed() {
env.builder
.build_signed_int_to_float(int_val, dest, "signed_int_to_float")
.new_build_signed_int_to_float(int_val, dest, "signed_int_to_float")
.into()
} else {
env.builder
.build_unsigned_int_to_float(int_val, dest, "unsigned_int_to_float")
.new_build_unsigned_int_to_float(int_val, dest, "unsigned_int_to_float")
.into()
}
}
@ -1242,7 +1238,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
.into_float_type();
env.builder
.build_float_cast(arg.into_float_value(), dest, "cast_float_to_float")
.new_build_float_cast(arg.into_float_value(), dest, "cast_float_to_float")
.into()
}
LayoutRepr::Builtin(Builtin::Decimal) => {
@ -1292,7 +1288,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
// The (&&) operator
arguments!(lhs_arg, rhs_arg);
let bool_val = env.builder.build_and(
let bool_val = env.builder.new_build_and(
lhs_arg.into_int_value(),
rhs_arg.into_int_value(),
"bool_and",
@ -1304,7 +1300,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
// The (||) operator
arguments!(lhs_arg, rhs_arg);
let bool_val = env.builder.build_or(
let bool_val = env.builder.new_build_or(
lhs_arg.into_int_value(),
rhs_arg.into_int_value(),
"bool_or",
@ -1316,7 +1312,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
// The (!) operator
arguments!(arg);
let bool_val = env.builder.build_not(arg.into_int_value(), "bool_not");
let bool_val = env.builder.new_build_not(arg.into_int_value(), "bool_not");
BasicValueEnum::IntValue(bool_val)
}
Hash => {
@ -1341,14 +1337,14 @@ pub(crate) fn run_low_level<'a, 'ctx>(
debug_assert!(data_ptr.is_pointer_value());
env.builder
.build_pointer_cast(data_ptr.into_pointer_value(), target_type, "ptr_cast")
.new_build_pointer_cast(data_ptr.into_pointer_value(), target_type, "ptr_cast")
.into()
}
PtrStore => {
arguments!(ptr, value);
env.builder.build_store(ptr.into_pointer_value(), value);
env.builder.new_build_store(ptr.into_pointer_value(), value);
// ptr
env.context.struct_type(&[], false).const_zero().into()
@ -1377,7 +1373,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
RefCountIsUnique => {
arguments_with_layouts!((data_ptr, data_layout));
let ptr = env.builder.build_pointer_cast(
let ptr = env.builder.new_build_pointer_cast(
data_ptr.into_pointer_value(),
env.context.i8_type().ptr_type(AddressSpace::default()),
"cast_to_i8_ptr",
@ -1413,8 +1409,10 @@ pub(crate) fn run_low_level<'a, 'ctx>(
layout_interner,
layout_interner.get_repr(layout),
);
let ptr = env.builder.build_alloca(basic_type, "unreachable_alloca");
env.builder.build_store(ptr, basic_type.const_zero());
let ptr = env
.builder
.new_build_alloca(basic_type, "unreachable_alloca");
env.builder.new_build_store(ptr, basic_type.const_zero());
ptr.into()
}
@ -1459,7 +1457,7 @@ fn build_int_binop<'ctx>(
throw_on_overflow(env, parent, result, "integer addition overflowed!")
}
NumAddWrap => bd.build_int_add(lhs, rhs, "add_int_wrap").into(),
NumAddWrap => bd.new_build_int_add(lhs, rhs, "add_int_wrap").into(),
NumAddChecked => {
let with_overflow = env.call_intrinsic(
&LLVM_ADD_WITH_OVERFLOW[int_width],
@ -1490,7 +1488,7 @@ fn build_int_binop<'ctx>(
throw_on_overflow(env, parent, result, "integer subtraction overflowed!")
}
NumSubWrap => bd.build_int_sub(lhs, rhs, "sub_int").into(),
NumSubWrap => bd.new_build_int_sub(lhs, rhs, "sub_int").into(),
NumSubChecked => {
let with_overflow = env.call_intrinsic(
&LLVM_SUB_WITH_OVERFLOW[int_width],
@ -1521,7 +1519,7 @@ fn build_int_binop<'ctx>(
throw_on_overflow(env, parent, result, "integer multiplication overflowed!")
}
NumMulWrap => bd.build_int_mul(lhs, rhs, "mul_int").into(),
NumMulWrap => bd.new_build_int_mul(lhs, rhs, "mul_int").into(),
NumMulSaturated => call_bitcode_fn(
env,
&[lhs.into(), rhs.into()],
@ -1546,37 +1544,37 @@ fn build_int_binop<'ctx>(
}
NumGt => {
if int_width.is_signed() {
bd.build_int_compare(SGT, lhs, rhs, "gt_int").into()
bd.new_build_int_compare(SGT, lhs, rhs, "gt_int").into()
} else {
bd.build_int_compare(UGT, lhs, rhs, "gt_uint").into()
bd.new_build_int_compare(UGT, lhs, rhs, "gt_uint").into()
}
}
NumGte => {
if int_width.is_signed() {
bd.build_int_compare(SGE, lhs, rhs, "gte_int").into()
bd.new_build_int_compare(SGE, lhs, rhs, "gte_int").into()
} else {
bd.build_int_compare(UGE, lhs, rhs, "gte_uint").into()
bd.new_build_int_compare(UGE, lhs, rhs, "gte_uint").into()
}
}
NumLt => {
if int_width.is_signed() {
bd.build_int_compare(SLT, lhs, rhs, "lt_int").into()
bd.new_build_int_compare(SLT, lhs, rhs, "lt_int").into()
} else {
bd.build_int_compare(ULT, lhs, rhs, "lt_uint").into()
bd.new_build_int_compare(ULT, lhs, rhs, "lt_uint").into()
}
}
NumLte => {
if int_width.is_signed() {
bd.build_int_compare(SLE, lhs, rhs, "lte_int").into()
bd.new_build_int_compare(SLE, lhs, rhs, "lte_int").into()
} else {
bd.build_int_compare(ULE, lhs, rhs, "lte_uint").into()
bd.new_build_int_compare(ULE, lhs, rhs, "lte_uint").into()
}
}
NumRemUnchecked => {
if int_width.is_signed() {
bd.build_int_signed_rem(lhs, rhs, "rem_int").into()
bd.new_build_int_signed_rem(lhs, rhs, "rem_int").into()
} else {
bd.build_int_unsigned_rem(lhs, rhs, "rem_uint").into()
bd.new_build_int_unsigned_rem(lhs, rhs, "rem_uint").into()
}
}
NumIsMultipleOf => {
@ -1606,44 +1604,44 @@ fn build_int_binop<'ctx>(
let cont_block = env.context.append_basic_block(parent, "branchcont");
if is_signed {
bd.build_switch(
bd.new_build_switch(
rhs,
default_block,
&[(zero, special_block), (neg_1, special_block)],
)
} else {
bd.build_switch(rhs, default_block, &[(zero, special_block)])
bd.new_build_switch(rhs, default_block, &[(zero, special_block)])
};
let condition_rem = {
bd.position_at_end(default_block);
let rem = if is_signed {
bd.build_int_signed_rem(lhs, rhs, "int_rem")
bd.new_build_int_signed_rem(lhs, rhs, "int_rem")
} else {
bd.build_int_unsigned_rem(lhs, rhs, "uint_rem")
bd.new_build_int_unsigned_rem(lhs, rhs, "uint_rem")
};
let result = bd.build_int_compare(IntPredicate::EQ, rem, zero, "is_zero_rem");
let result = bd.new_build_int_compare(IntPredicate::EQ, rem, zero, "is_zero_rem");
bd.build_unconditional_branch(cont_block);
bd.new_build_unconditional_branch(cont_block);
result
};
let condition_special = {
bd.position_at_end(special_block);
let is_zero = bd.build_int_compare(IntPredicate::EQ, lhs, zero, "is_zero_lhs");
let is_zero = bd.new_build_int_compare(IntPredicate::EQ, lhs, zero, "is_zero_lhs");
let result = if is_signed {
let is_neg_one =
bd.build_int_compare(IntPredicate::EQ, rhs, neg_1, "is_neg_one_rhs");
bd.new_build_int_compare(IntPredicate::EQ, rhs, neg_1, "is_neg_one_rhs");
bd.build_or(is_neg_one, is_zero, "cond")
bd.new_build_or(is_neg_one, is_zero, "cond")
} else {
is_zero
};
bd.build_unconditional_branch(cont_block);
bd.new_build_unconditional_branch(cont_block);
result
};
@ -1651,7 +1649,7 @@ fn build_int_binop<'ctx>(
{
bd.position_at_end(cont_block);
let phi = bd.build_phi(env.context.bool_type(), "branch");
let phi = bd.new_build_phi(env.context.bool_type(), "branch");
phi.add_incoming(&[
(&condition_rem, default_block),
@ -1668,9 +1666,9 @@ fn build_int_binop<'ctx>(
),
NumDivTruncUnchecked => {
if int_width.is_signed() {
bd.build_int_signed_div(lhs, rhs, "div_int").into()
bd.new_build_int_signed_div(lhs, rhs, "div_int").into()
} else {
bd.build_int_unsigned_div(lhs, rhs, "div_uint").into()
bd.new_build_int_unsigned_div(lhs, rhs, "div_uint").into()
}
}
NumDivCeilUnchecked => call_bitcode_fn(
@ -1678,15 +1676,15 @@ fn build_int_binop<'ctx>(
&[lhs.into(), rhs.into()],
&bitcode::NUM_DIV_CEIL[int_width],
),
NumBitwiseAnd => bd.build_and(lhs, rhs, "int_bitwise_and").into(),
NumBitwiseXor => bd.build_xor(lhs, rhs, "int_bitwise_xor").into(),
NumBitwiseOr => bd.build_or(lhs, rhs, "int_bitwise_or").into(),
NumShiftLeftBy => bd.build_left_shift(lhs, rhs, "int_shift_left").into(),
NumBitwiseAnd => bd.new_build_and(lhs, rhs, "int_bitwise_and").into(),
NumBitwiseXor => bd.new_build_xor(lhs, rhs, "int_bitwise_xor").into(),
NumBitwiseOr => bd.new_build_or(lhs, rhs, "int_bitwise_or").into(),
NumShiftLeftBy => bd.new_build_left_shift(lhs, rhs, "int_shift_left").into(),
NumShiftRightBy => bd
.build_right_shift(lhs, rhs, true, "int_shift_right")
.new_build_right_shift(lhs, rhs, true, "int_shift_right")
.into(),
NumShiftRightZfBy => bd
.build_right_shift(lhs, rhs, false, "int_shift_right_zf")
.new_build_right_shift(lhs, rhs, false, "int_shift_right_zf")
.into(),
_ => {
@ -1767,16 +1765,16 @@ fn build_float_binop<'ctx>(
let bd = env.builder;
match op {
NumAdd => bd.build_float_add(lhs, rhs, "add_float").into(),
NumAdd => bd.new_build_float_add(lhs, rhs, "add_float").into(),
NumAddChecked => {
let context = env.context;
let result = bd.build_float_add(lhs, rhs, "add_float");
let result = bd.new_build_float_add(lhs, rhs, "add_float");
let is_finite =
call_bitcode_fn(env, &[result.into()], &bitcode::NUM_IS_FINITE[float_width])
.into_int_value();
let is_infinite = bd.build_not(is_finite, "negate");
let is_infinite = bd.new_build_not(is_finite, "negate");
let struct_type = context.struct_type(
&[context.f64_type().into(), context.bool_type().into()],
@ -1796,16 +1794,16 @@ fn build_float_binop<'ctx>(
struct_value.into()
}
NumAddWrap => unreachable!("wrapping addition is not defined on floats"),
NumSub => bd.build_float_sub(lhs, rhs, "sub_float").into(),
NumSub => bd.new_build_float_sub(lhs, rhs, "sub_float").into(),
NumSubChecked => {
let context = env.context;
let result = bd.build_float_sub(lhs, rhs, "sub_float");
let result = bd.new_build_float_sub(lhs, rhs, "sub_float");
let is_finite =
call_bitcode_fn(env, &[result.into()], &bitcode::NUM_IS_FINITE[float_width])
.into_int_value();
let is_infinite = bd.build_not(is_finite, "negate");
let is_infinite = bd.new_build_not(is_finite, "negate");
let struct_type = context.struct_type(
&[context.f64_type().into(), context.bool_type().into()],
@ -1825,17 +1823,17 @@ fn build_float_binop<'ctx>(
struct_value.into()
}
NumSubWrap => unreachable!("wrapping subtraction is not defined on floats"),
NumMul => bd.build_float_mul(lhs, rhs, "mul_float").into(),
NumMulSaturated => bd.build_float_mul(lhs, rhs, "mul_float").into(),
NumMul => bd.new_build_float_mul(lhs, rhs, "mul_float").into(),
NumMulSaturated => bd.new_build_float_mul(lhs, rhs, "mul_float").into(),
NumMulChecked => {
let context = env.context;
let result = bd.build_float_mul(lhs, rhs, "mul_float");
let result = bd.new_build_float_mul(lhs, rhs, "mul_float");
let is_finite =
call_bitcode_fn(env, &[result.into()], &bitcode::NUM_IS_FINITE[float_width])
.into_int_value();
let is_infinite = bd.build_not(is_finite, "negate");
let is_infinite = bd.new_build_not(is_finite, "negate");
let struct_type = context.struct_type(
&[context.f64_type().into(), context.bool_type().into()],
@ -1855,11 +1853,15 @@ fn build_float_binop<'ctx>(
struct_value.into()
}
NumMulWrap => unreachable!("wrapping multiplication is not defined on floats"),
NumGt => bd.build_float_compare(OGT, lhs, rhs, "float_gt").into(),
NumGte => bd.build_float_compare(OGE, lhs, rhs, "float_gte").into(),
NumLt => bd.build_float_compare(OLT, lhs, rhs, "float_lt").into(),
NumLte => bd.build_float_compare(OLE, lhs, rhs, "float_lte").into(),
NumDivFrac => bd.build_float_div(lhs, rhs, "div_float").into(),
NumGt => bd.new_build_float_compare(OGT, lhs, rhs, "float_gt").into(),
NumGte => bd
.new_build_float_compare(OGE, lhs, rhs, "float_gte")
.into(),
NumLt => bd.new_build_float_compare(OLT, lhs, rhs, "float_lt").into(),
NumLte => bd
.new_build_float_compare(OLE, lhs, rhs, "float_lte")
.into(),
NumDivFrac => bd.new_build_float_div(lhs, rhs, "div_float").into(),
NumPow => call_bitcode_fn(
env,
&[lhs.into(), rhs.into()],
@ -1882,7 +1884,7 @@ fn throw_on_overflow<'ctx>(
let has_overflowed = bd.build_extract_value(result, 1, "has_overflowed").unwrap();
let condition = bd.build_int_compare(
let condition = bd.new_build_int_compare(
IntPredicate::EQ,
has_overflowed.into_int_value(),
context.bool_type().const_zero(),
@ -1892,7 +1894,7 @@ fn throw_on_overflow<'ctx>(
let then_block = context.append_basic_block(parent, "then_block");
let throw_block = context.append_basic_block(parent, "throw_block");
bd.build_conditional_branch(condition, then_block, throw_block);
bd.new_build_conditional_branch(condition, then_block, throw_block);
bd.position_at_end(throw_block);
@ -1952,10 +1954,10 @@ fn throw_because_overflow(env: &Env<'_, '_, '_>, message: &str) {
env.builder.position_at_end(block);
env.builder.set_current_debug_location(di_location);
let call = env.builder.build_call(function, &[], "overflow");
let call = env.builder.new_build_call(function, &[], "overflow");
call.set_call_convention(FAST_CALL_CONV);
env.builder.build_unreachable();
env.builder.new_build_unreachable();
}
fn dec_split_into_words<'ctx>(
@ -1967,50 +1969,73 @@ fn dec_split_into_words<'ctx>(
let left_bits_i128 = env
.builder
.build_right_shift(value, int_64, false, "left_bits_i128");
.new_build_right_shift(value, int_64, false, "left_bits_i128");
(
env.builder.build_int_cast(value, int_64_type, ""),
env.builder.build_int_cast(left_bits_i128, int_64_type, ""),
env.builder.new_build_int_cast(value, int_64_type, ""),
env.builder
.new_build_int_cast(left_bits_i128, int_64_type, ""),
)
}
fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> PointerValue<'ctx> {
let dec_type = zig_dec_type(env);
fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> BasicValueEnum<'ctx> {
use roc_target::Architecture::*;
use roc_target::OperatingSystem::*;
match env.target_info.operating_system {
Windows => {
let dec_type = zig_dec_type(env);
let alloca = env.builder.build_alloca(dec_type, "dec_alloca");
let alloca = env.builder.new_build_alloca(dec_type, "dec_alloca");
let instruction = alloca.as_instruction_value().unwrap();
instruction.set_alignment(16).unwrap();
let instruction = alloca.as_instruction_value().unwrap();
instruction.set_alignment(16).unwrap();
let ptr = env.builder.build_pointer_cast(
alloca,
value.get_type().ptr_type(AddressSpace::default()),
"cast_to_i128_ptr",
);
let ptr = env.builder.new_build_pointer_cast(
alloca,
value.get_type().ptr_type(AddressSpace::default()),
"cast_to_i128_ptr",
);
env.builder.build_store(ptr, value);
env.builder.new_build_store(ptr, value);
alloca
alloca.into()
}
Unix => {
if matches!(env.target_info.architecture, X86_32 | X86_64) {
internal_error!("X86 unix does not pass with a dec alloc instead it splits into high and low halves");
}
let i64_type = env.context.i64_type();
let alloca = env
.builder
.build_array_alloca(i64_type, i64_type.const_int(2, false), "dec_alloca")
.unwrap();
let instruction = alloca.as_instruction_value().unwrap();
instruction.set_alignment(16).unwrap();
let ptr = env.builder.new_build_pointer_cast(
alloca,
value.get_type().ptr_type(AddressSpace::default()),
"cast_to_i128_ptr",
);
env.builder.new_build_store(ptr, value);
env.builder
.new_build_load(i64_type.array_type(2), alloca, "load as array")
.into()
}
Wasi => unimplemented!(),
}
}
fn dec_to_str<'ctx>(env: &Env<'_, 'ctx, '_>, dec: BasicValueEnum<'ctx>) -> BasicValueEnum<'ctx> {
use roc_target::Architecture::*;
use roc_target::OperatingSystem::*;
let dec = dec.into_int_value();
match env.target_info.operating_system {
Windows => {
//
call_str_bitcode_fn(
env,
&[],
&[dec_alloca(env, dec).into()],
BitcodeReturns::Str,
bitcode::DEC_TO_STR,
)
}
Unix => {
match env.target_info {
TargetInfo {
architecture: X86_64 | X86_32,
operating_system: Unix,
} => {
let (low, high) = dec_split_into_words(env, dec);
call_str_bitcode_fn(
@ -2021,7 +2046,13 @@ fn dec_to_str<'ctx>(env: &Env<'_, 'ctx, '_>, dec: BasicValueEnum<'ctx>) -> Basic
bitcode::DEC_TO_STR,
)
}
Wasi => unimplemented!(),
_ => call_str_bitcode_fn(
env,
&[],
&[dec_alloca(env, dec).into()],
BitcodeReturns::Str,
bitcode::DEC_TO_STR,
),
}
}
@ -2030,16 +2061,19 @@ fn dec_unary_op<'ctx>(
fn_name: &str,
dec: BasicValueEnum<'ctx>,
) -> BasicValueEnum<'ctx> {
use roc_target::Architecture::*;
use roc_target::OperatingSystem::*;
let dec = dec.into_int_value();
match env.target_info.operating_system {
Windows => call_bitcode_fn(env, &[dec_alloca(env, dec).into()], fn_name),
Unix => {
match env.target_info {
TargetInfo {
architecture: X86_64 | X86_32,
operating_system: Unix,
} => {
let (low, high) = dec_split_into_words(env, dec);
call_bitcode_fn(env, &[low.into(), high.into()], fn_name)
}
Wasi => unimplemented!(),
_ => call_bitcode_fn(env, &[dec_alloca(env, dec).into()], fn_name),
}
}
@ -2049,30 +2083,22 @@ fn dec_binop_with_overflow<'ctx>(
lhs: BasicValueEnum<'ctx>,
rhs: BasicValueEnum<'ctx>,
) -> StructValue<'ctx> {
use roc_target::Architecture::*;
use roc_target::OperatingSystem::*;
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 return_alloca = env.builder.new_build_alloca(return_type, "return_alloca");
match env.target_info.operating_system {
Windows => {
call_void_bitcode_fn(
env,
&[
return_alloca.into(),
dec_alloca(env, lhs).into(),
dec_alloca(env, rhs).into(),
],
fn_name,
);
}
Unix => {
match env.target_info {
TargetInfo {
architecture: X86_64 | X86_32,
operating_system: Unix,
} => {
let (lhs_low, lhs_high) = dec_split_into_words(env, lhs);
let (rhs_low, rhs_high) = dec_split_into_words(env, rhs);
call_void_bitcode_fn(
env,
&[
@ -2085,8 +2111,18 @@ fn dec_binop_with_overflow<'ctx>(
fn_name,
);
}
Wasi => unimplemented!(),
}
_ => {
call_void_bitcode_fn(
env,
&[
return_alloca.into(),
dec_alloca(env, lhs).into(),
dec_alloca(env, rhs).into(),
],
fn_name,
);
}
};
env.builder
.new_build_load(return_type, return_alloca, "load_dec")
@ -2099,24 +2135,19 @@ pub(crate) fn dec_binop_with_unchecked<'ctx>(
lhs: BasicValueEnum<'ctx>,
rhs: BasicValueEnum<'ctx>,
) -> BasicValueEnum<'ctx> {
use roc_target::Architecture::*;
use roc_target::OperatingSystem::*;
let lhs = lhs.into_int_value();
let rhs = rhs.into_int_value();
match env.target_info.operating_system {
Windows => {
// windows is much nicer for us here
call_bitcode_fn(
env,
&[dec_alloca(env, lhs).into(), dec_alloca(env, rhs).into()],
fn_name,
)
}
Unix => {
match env.target_info {
TargetInfo {
architecture: X86_64 | X86_32,
operating_system: Unix,
} => {
let (lhs_low, lhs_high) = dec_split_into_words(env, lhs);
let (rhs_low, rhs_high) = dec_split_into_words(env, rhs);
call_bitcode_fn(
env,
&[
@ -2128,7 +2159,11 @@ pub(crate) fn dec_binop_with_unchecked<'ctx>(
fn_name,
)
}
Wasi => unimplemented!(),
_ => call_bitcode_fn(
env,
&[dec_alloca(env, lhs).into(), dec_alloca(env, rhs).into()],
fn_name,
),
}
}
@ -2312,7 +2347,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
let target_float_type = convert::float_type_from_float_width(env, float_width);
bd.build_cast(
bd.new_build_cast(
InstructionOpcode::SIToFP,
arg,
target_float_type,
@ -2372,7 +2407,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
let target_int_type = convert::int_type_from_int_width(env, target_int_width);
let target_int_val: BasicValueEnum<'ctx> = env
.builder
.build_int_cast_sign_flag(
.new_build_int_cast_sign_flag(
arg,
target_int_type,
target_int_width.is_signed(),
@ -2441,7 +2476,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
)
.ptr_type(AddressSpace::default());
let roc_return_alloca = env.builder.build_pointer_cast(
let roc_return_alloca = env.builder.new_build_pointer_cast(
zig_return_alloca,
roc_return_type,
"cast_to_roc",
@ -2506,7 +2541,7 @@ fn int_neg_raise_on_overflow<'ctx>(
let builder = env.builder;
let min_val = int_type_signed_min(int_type);
let condition = builder.build_int_compare(IntPredicate::EQ, arg, min_val, "is_min_val");
let condition = builder.new_build_int_compare(IntPredicate::EQ, arg, min_val, "is_min_val");
let block = env.builder.get_insert_block().expect("to be in a function");
let parent = block.get_parent().expect("to be in a function");
@ -2514,7 +2549,7 @@ fn int_neg_raise_on_overflow<'ctx>(
let else_block = env.context.append_basic_block(parent, "else");
env.builder
.build_conditional_branch(condition, then_block, else_block);
.new_build_conditional_branch(condition, then_block, else_block);
builder.position_at_end(then_block);
@ -2526,7 +2561,7 @@ fn int_neg_raise_on_overflow<'ctx>(
builder.position_at_end(else_block);
builder.build_int_neg(arg, "negate_int").into()
builder.new_build_int_neg(arg, "negate_int").into()
}
fn int_abs_raise_on_overflow<'ctx>(
@ -2537,7 +2572,7 @@ fn int_abs_raise_on_overflow<'ctx>(
let builder = env.builder;
let min_val = int_type_signed_min(int_type);
let condition = builder.build_int_compare(IntPredicate::EQ, arg, min_val, "is_min_val");
let condition = builder.new_build_int_compare(IntPredicate::EQ, arg, min_val, "is_min_val");
let block = env.builder.get_insert_block().expect("to be in a function");
let parent = block.get_parent().expect("to be in a function");
@ -2545,7 +2580,7 @@ fn int_abs_raise_on_overflow<'ctx>(
let else_block = env.context.append_basic_block(parent, "else");
env.builder
.build_conditional_branch(condition, then_block, else_block);
.new_build_conditional_branch(condition, then_block, else_block);
builder.position_at_end(then_block);
@ -2577,16 +2612,16 @@ fn int_abs_with_overflow<'ctx>(
let shifted_alloca = {
let bits_to_shift = int_type.get_bit_width() as u64 - 1;
let shift_val = int_type.const_int(bits_to_shift, false);
let shifted = bd.build_right_shift(arg, shift_val, true, shifted_name);
let alloca = bd.build_alloca(int_type, "#int_abs_help");
let shifted = bd.new_build_right_shift(arg, shift_val, true, shifted_name);
let alloca = bd.new_build_alloca(int_type, "#int_abs_help");
// shifted = arg >>> 63
bd.build_store(alloca, shifted);
bd.new_build_store(alloca, shifted);
alloca
};
let xored_arg = bd.build_xor(
let xored_arg = bd.new_build_xor(
arg,
bd.new_build_load(int_type, shifted_alloca, shifted_name)
.into_int_value(),
@ -2594,7 +2629,7 @@ fn int_abs_with_overflow<'ctx>(
);
BasicValueEnum::IntValue(
bd.build_int_sub(
bd.new_build_int_sub(
xored_arg,
bd.new_build_load(int_type, shifted_alloca, shifted_name)
.into_int_value(),
@ -2617,7 +2652,7 @@ fn build_float_unary_op<'a, 'ctx>(
// TODO: Handle different sized floats
match op {
NumNeg => bd.build_float_neg(arg, "negate_float").into(),
NumNeg => bd.new_build_float_neg(arg, "negate_float").into(),
NumAbs => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_FABS[float_width]),
NumSqrtUnchecked => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_SQRT[float_width]),
NumLogUnchecked => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_LOG[float_width]),
@ -2628,13 +2663,13 @@ fn build_float_unary_op<'a, 'ctx>(
};
match (float_width, return_width) {
(FloatWidth::F32, FloatWidth::F32) => arg.into(),
(FloatWidth::F32, FloatWidth::F64) => bd.build_cast(
(FloatWidth::F32, FloatWidth::F64) => bd.new_build_cast(
InstructionOpcode::FPExt,
arg,
env.context.f64_type(),
"f32_to_f64",
),
(FloatWidth::F64, FloatWidth::F32) => bd.build_cast(
(FloatWidth::F64, FloatWidth::F32) => bd.new_build_cast(
InstructionOpcode::FPTrunc,
arg,
env.context.f32_type(),