be more precise with zig return types

This commit is contained in:
Folkert 2022-12-20 15:43:11 +01:00
parent ec80161824
commit bb4ff34aaa
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
3 changed files with 68 additions and 14 deletions

View file

@ -9,7 +9,7 @@ use crate::llvm::refcounting::{
decrement_refcount_layout, increment_n_refcount_layout, increment_refcount_layout,
};
use inkwell::attributes::{Attribute, AttributeLoc};
use inkwell::types::{BasicType, BasicTypeEnum};
use inkwell::types::{BasicType, BasicTypeEnum, StructType};
use inkwell::values::{
BasicValue, BasicValueEnum, CallSiteValue, FunctionValue, InstructionValue, IntValue,
PointerValue, StructValue,
@ -97,6 +97,7 @@ fn call_bitcode_fn_help<'a, 'ctx, 'env>(
pub fn call_bitcode_fn_fixing_for_convention<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
bitcode_return_type: StructType<'ctx>,
args: &[BasicValueEnum<'ctx>],
return_layout: &Layout<'_>,
fn_name: &str,
@ -119,10 +120,7 @@ pub fn call_bitcode_fn_fixing_for_convention<'a, 'ctx, 'env>(
.get_type()
.get_param_types()[0]
.into_pointer_type();
let cc_return_type: BasicTypeEnum<'ctx> = cc_ptr_return_type
.get_element_type()
.try_into()
.expect("Zig bitcode return type is not a basic type!");
let cc_return_type: BasicTypeEnum<'ctx> = bitcode_return_type.into();
// when we write an i128 into this (happens in NumToInt), zig expects this pointer to
// be 16-byte aligned. Not doing so is UB and will immediately fail on CI

View file

@ -447,6 +447,30 @@ pub fn zig_has_tag_id_type<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> StructT
.struct_type(&[env.context.bool_type().into(), u8_ptr_t.into()], false)
}
pub fn zig_num_parse_result_type<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
type_name: &str,
) -> StructType<'ctx> {
let name = format!("num.NumParseResult({type_name})");
match env.module.get_struct_type(&name) {
Some(zig_type) => zig_type,
None => panic!("zig does not define the `{name}` type!"),
}
}
pub fn zig_to_int_checked_result_type<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
type_name: &str,
) -> StructType<'ctx> {
let name = format!("num.ToIntCheckedResult({type_name})");
match env.module.get_struct_type(&name) {
Some(zig_type) => zig_type,
None => panic!("zig does not define the `{name}` type!"),
}
}
pub fn zig_with_overflow_roc_dec<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> StructType<'ctx> {
env.module
.get_struct_type("utils.WithOverflow(dec.RocDec)")

View file

@ -33,7 +33,9 @@ use crate::llvm::{
pass_update_mode,
},
compare::{generic_eq, generic_neq},
convert::{self, basic_type_from_layout},
convert::{
self, basic_type_from_layout, zig_num_parse_result_type, zig_to_int_checked_result_type,
},
intrinsics::{
LLVM_ADD_SATURATED, LLVM_ADD_WITH_OVERFLOW, LLVM_CEILING, LLVM_COS, LLVM_FABS, LLVM_FLOOR,
LLVM_LOG, LLVM_MUL_WITH_OVERFLOW, LLVM_POW, LLVM_ROUND, LLVM_SIN, LLVM_SQRT,
@ -257,7 +259,31 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
}
}
PtrWidth::Bytes8 => {
call_bitcode_fn_fixing_for_convention(env, &[string], layout, intrinsic)
let cc_return_by_pointer = match number_layout {
Layout::Builtin(Builtin::Int(int_width)) => {
(int_width.stack_size() as usize > env.target_info.ptr_size())
.then_some(int_width.type_name())
}
Layout::Builtin(Builtin::Decimal) => {
// zig picks 128 for dec.RocDec
Some("i128")
}
_ => None,
};
if let Some(type_name) = cc_return_by_pointer {
let bitcode_return_type = zig_num_parse_result_type(env, type_name);
call_bitcode_fn_fixing_for_convention(
env,
bitcode_return_type,
&[string],
layout,
intrinsic,
)
} else {
call_bitcode_fn(env, &[string], intrinsic)
}
}
};
@ -1973,14 +1999,20 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
}
}
PtrWidth::Bytes8 => {
// call_bitcode_fn_fixing_for_convention(env, &[string], layout, intrinsic)
if target_int_width.stack_size() as usize > env.target_info.ptr_size() {
let bitcode_return_type =
zig_to_int_checked_result_type(env, target_int_width.type_name());
call_bitcode_fn_fixing_for_convention(
env,
&[arg.into()],
return_layout,
intrinsic,
)
call_bitcode_fn_fixing_for_convention(
env,
bitcode_return_type,
&[arg.into()],
return_layout,
intrinsic,
)
} else {
call_bitcode_fn(env, &[arg.into()], intrinsic)
}
}
};