Merge remote-tracking branch 'origin/main' into upgrade-llvm-zig

This commit is contained in:
Brendan Hansknecht 2024-12-11 16:38:34 -08:00
commit 0a573ca557
No known key found for this signature in database
GPG key ID: 0EA784685083E75B
818 changed files with 15185 additions and 4951 deletions

View file

@ -12,8 +12,8 @@ use crate::llvm::refcounting::{
use inkwell::attributes::{Attribute, AttributeLoc};
use inkwell::types::{BasicType, BasicTypeEnum, StructType};
use inkwell::values::{
BasicValueEnum, CallSiteValue, FunctionValue, InstructionValue, IntValue, PointerValue,
StructValue,
BasicMetadataValueEnum, BasicValue, BasicValueEnum, CallSiteValue, FunctionValue,
InstructionValue, IntValue, PointerValue, StructValue,
};
use inkwell::AddressSpace;
use roc_error_macros::internal_error;
@ -47,6 +47,28 @@ pub fn call_bitcode_fn<'ctx>(
.build_bit_cast(ret, env.context.i128_type(), "return_i128")
.unwrap();
}
} else if env.target == roc_target::Target::MacArm64 {
// Essentially the same happens on macos arm64, but with array type [2xi64].
let i64_type = env.context.i64_type();
let arr_type = i64_type.array_type(2);
if ret.get_type() == arr_type.into() {
let alloca = env
.builder
.build_array_alloca(i64_type, i64_type.const_int(2, false), "dec_alloca")
.unwrap_or_else(|err| internal_error!("failed to build array alloca: {err}"));
let instruction = alloca.as_instruction_value().unwrap_or_else(|| {
internal_error!("failed to convert pointer to instruction value ({alloca:?})");
});
instruction.set_alignment(16).unwrap_or_else(|err| {
internal_error!(
"failed to set 16-byte alignment on instruction ({instruction:?}): {err}"
);
});
env.builder.new_build_store(alloca, ret);
return env
.builder
.new_build_load(env.context.i128_type(), alloca, "return_i128");
}
}
ret
@ -696,13 +718,18 @@ pub fn build_compare_wrapper<'a, 'ctx>(
"load_opaque",
);
let closure_data =
env.builder
.new_build_load(closure_type, closure_cast, "load_opaque");
let closure_data: BasicMetadataValueEnum =
if layout_interner.is_passed_by_reference(closure_data_repr) {
closure_cast.into()
} else {
env.builder
.new_build_load(closure_type, closure_cast, "load_opaque")
.into()
};
env.arena
.alloc([value1.into(), value2.into(), closure_data.into()])
as &[_]
.alloc([value1.into(), value2.into(), closure_data])
as &[BasicMetadataValueEnum]
}
};

View file

@ -685,7 +685,7 @@ macro_rules! debug_info_init {
pub enum LlvmBackendMode {
/// Assumes primitives (roc_alloc, roc_panic, etc) are provided by the host
Binary,
BinaryDev,
BinaryWithExpect,
/// Creates a test wrapper around the main roc function to catch and report panics.
/// Provides a testing implementation of primitives (roc_alloc, roc_panic, etc)
BinaryGlue,
@ -698,7 +698,7 @@ impl LlvmBackendMode {
pub(crate) fn has_host(self) -> bool {
match self {
LlvmBackendMode::Binary => true,
LlvmBackendMode::BinaryDev => true,
LlvmBackendMode::BinaryWithExpect => true,
LlvmBackendMode::BinaryGlue => false,
LlvmBackendMode::GenTest => false,
LlvmBackendMode::WasmGenTest => true,
@ -710,7 +710,7 @@ impl LlvmBackendMode {
fn returns_roc_result(self) -> bool {
match self {
LlvmBackendMode::Binary => false,
LlvmBackendMode::BinaryDev => false,
LlvmBackendMode::BinaryWithExpect => false,
LlvmBackendMode::BinaryGlue => true,
LlvmBackendMode::GenTest => true,
LlvmBackendMode::WasmGenTest => true,
@ -721,7 +721,7 @@ impl LlvmBackendMode {
pub(crate) fn runs_expects(self) -> bool {
match self {
LlvmBackendMode::Binary => false,
LlvmBackendMode::BinaryDev => true,
LlvmBackendMode::BinaryWithExpect => true,
LlvmBackendMode::BinaryGlue => false,
LlvmBackendMode::GenTest => false,
LlvmBackendMode::WasmGenTest => false,
@ -3470,12 +3470,10 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
variable: _,
remainder,
} => {
if env.mode.runs_expects() {
let location = build_string_literal(env, source_location);
let source = build_string_literal(env, source);
let message = scope.load_symbol(symbol);
env.call_dbg(env, location, source, message);
}
let location = build_string_literal(env, source_location);
let source = build_string_literal(env, source);
let message = scope.load_symbol(symbol);
env.call_dbg(env, location, source, message);
build_exp_stmt(
env,
@ -3531,7 +3529,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
variables,
);
if let LlvmBackendMode::BinaryDev = env.mode {
if let LlvmBackendMode::BinaryWithExpect = env.mode {
crate::llvm::expect::notify_parent_expect(env, &shared_memory);
}
@ -4809,7 +4807,9 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx>(
)
}
LlvmBackendMode::Binary | LlvmBackendMode::BinaryDev | LlvmBackendMode::BinaryGlue => {}
LlvmBackendMode::Binary
| LlvmBackendMode::BinaryWithExpect
| LlvmBackendMode::BinaryGlue => {}
}
// a generic version that writes the result into a passed *u8 pointer
@ -4862,13 +4862,13 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx>(
roc_call_result_type(env, roc_function.get_type().get_return_type().unwrap()).into()
}
LlvmBackendMode::Binary | LlvmBackendMode::BinaryDev | LlvmBackendMode::BinaryGlue => {
basic_type_from_layout(
env,
layout_interner,
layout_interner.get_repr(return_layout),
)
}
LlvmBackendMode::Binary
| LlvmBackendMode::BinaryWithExpect
| LlvmBackendMode::BinaryGlue => basic_type_from_layout(
env,
layout_interner,
layout_interner.get_repr(return_layout),
),
};
let size: BasicValueEnum = return_type.size_of().unwrap().into();
@ -5657,7 +5657,7 @@ fn build_procedures_help<'a>(
use LlvmBackendMode::*;
match env.mode {
GenTest | WasmGenTest | CliTest => { /* no host, or exposing types is not supported */ }
Binary | BinaryDev | BinaryGlue => {
Binary | BinaryWithExpect | BinaryGlue => {
for (proc_name, alias_name, hels) in host_exposed_lambda_sets.iter() {
let ident_string = proc_name.name().as_unsuffixed_str(&env.interns);
let fn_name: String = format!("{}_{}", ident_string, hels.id.0);

View file

@ -29,7 +29,7 @@ pub(crate) struct SharedMemoryPointer<'ctx>(PointerValue<'ctx>);
impl<'ctx> SharedMemoryPointer<'ctx> {
pub(crate) fn get<'a, 'env>(env: &Env<'a, 'ctx, 'env>) -> Self {
let start_function = if let LlvmBackendMode::BinaryDev = env.mode {
let start_function = if let LlvmBackendMode::BinaryWithExpect = env.mode {
bitcode::UTILS_EXPECT_FAILED_START_SHARED_FILE
} else {
bitcode::UTILS_EXPECT_FAILED_START_SHARED_BUFFER

View file

@ -1137,15 +1137,37 @@ pub(crate) fn run_low_level<'a, 'ctx>(
)
}
NumIntCast => {
arguments!(arg);
arguments_with_layouts!((arg, arg_layout));
let to = basic_type_from_layout(env, layout_interner, layout_interner.get_repr(layout))
.into_int_type();
let to_signed = intwidth_from_layout(layout).is_signed();
let from_signed = intwidth_from_layout(arg_layout).is_signed();
let extend = intwidth_from_layout(layout).stack_size()
> intwidth_from_layout(arg_layout).stack_size();
//Examples given with sizes of 32, 16, and 8
let result = match (from_signed, to_signed, extend) {
//I16 -> I32
(true, true, true) => {
env.builder
.build_int_s_extend(arg.into_int_value(), to, "inc_cast")
}
//U16 -> X32
(false, _, true) => {
env.builder
.build_int_z_extend(arg.into_int_value(), to, "inc_cast")
},
//I16 -> U32
(true,false,true)
//Any case where it is not an extension, also perhaps warn here?
| (_, _, false) => {
Ok(env.builder
.new_build_int_cast_sign_flag(arg.into_int_value(), to, to_signed, "inc_cast"))
}
};
env.builder
.new_build_int_cast_sign_flag(arg.into_int_value(), to, to_signed, "inc_cast")
.into()
let Ok(value) = result else { todo!() };
value.into()
}
NumToFloatCast => {
arguments_with_layouts!((arg, arg_layout));
@ -1748,7 +1770,7 @@ fn build_float_binop<'ctx>(
};
match op {
NumAdd => bd.new_build_float_add(lhs, rhs, "add_float").into(),
NumAdd | NumAddSaturated => bd.new_build_float_add(lhs, rhs, "add_float").into(),
NumAddChecked => {
let context = env.context;
@ -1775,7 +1797,7 @@ fn build_float_binop<'ctx>(
struct_value.into()
}
NumAddWrap => unreachable!("wrapping addition is not defined on floats"),
NumSub => bd.new_build_float_sub(lhs, rhs, "sub_float").into(),
NumSub | NumSubSaturated => bd.new_build_float_sub(lhs, rhs, "sub_float").into(),
NumSubChecked => {
let context = env.context;
@ -1802,8 +1824,7 @@ fn build_float_binop<'ctx>(
struct_value.into()
}
NumSubWrap => unreachable!("wrapping subtraction is not defined on floats"),
NumMul => bd.new_build_float_mul(lhs, rhs, "mul_float").into(),
NumMulSaturated => bd.new_build_float_mul(lhs, rhs, "mul_float").into(),
NumMul | NumMulSaturated => bd.new_build_float_mul(lhs, rhs, "mul_float").into(),
NumMulChecked => {
let context = env.context;
@ -1845,7 +1866,7 @@ fn build_float_binop<'ctx>(
&bitcode::NUM_POW[float_width],
),
_ => {
unreachable!("Unrecognized int binary operation: {:?}", op);
unreachable!("Unrecognized float binary operation: {:?}", op);
}
}
}
@ -2276,6 +2297,9 @@ fn build_dec_binop<'a, 'ctx>(
rhs,
"Decimal multiplication overflowed",
),
NumAddSaturated => dec_binary_op(env, bitcode::DEC_ADD_SATURATED, lhs, rhs),
NumSubSaturated => dec_binary_op(env, bitcode::DEC_SUB_SATURATED, lhs, rhs),
NumMulSaturated => dec_binary_op(env, bitcode::DEC_MUL_SATURATED, lhs, rhs),
NumDivFrac => dec_binop_with_unchecked(env, bitcode::DEC_DIV, lhs, rhs),
NumLt => call_bitcode_fn(env, &[lhs, rhs], &bitcode::NUM_LESS_THAN[IntWidth::I128]),