Merge remote-tracking branch 'origin/trunk' into name-functions-with-morphic

This commit is contained in:
Folkert 2021-06-13 13:15:18 +02:00
commit bb25746928
20 changed files with 484 additions and 181 deletions

View file

@ -8,6 +8,8 @@ pub const RocDec = struct {
num: i128,
pub const decimal_places: comptime u32 = 18;
pub const whole_number_places: comptime u32 = 21;
const max_digits: comptime u32 = decimal_places + whole_number_places;
pub const min: comptime RocDec = .{ .num = math.minInt(i128) };
pub const max: comptime RocDec = .{ .num = math.maxInt(i128) };
@ -19,7 +21,7 @@ pub const RocDec = struct {
return .{ .num = num * one_point_zero_i128 };
}
pub fn fromString(roc_str: RocStr) ?RocDec {
pub fn fromStr(roc_str: RocStr) ?RocDec {
if (roc_str.isEmpty()) {
return null;
}
@ -101,6 +103,7 @@ pub const RocDec = struct {
return dec;
}
// TODO: Replace this with https://github.com/rtfeldman/roc/pull/1365/files#r643580738
fn isDigit(c: u8) bool {
return switch (c) {
'0'...'9' => true,
@ -108,6 +111,92 @@ pub const RocDec = struct {
};
}
pub fn toStr(self: RocDec) ?RocStr {
// Check if this Dec is negative, and if so convert to positive
// We will handle adding the '-' later
const is_negative = self.num < 0;
const num = if (is_negative) std.math.negate(self.num) catch {
std.debug.panic("TODO runtime exception failing to negate", .{});
} else self.num;
// Format the backing i128 into an array of digits (u8s)
var digit_bytes: [max_digits + 1]u8 = undefined;
var num_digits_formatted = std.fmt.formatIntBuf(digit_bytes[0..], num, 10, false, .{});
// If self < 1, then pad digit_bytes with '0' to be at least 18 digits
if (num_digits_formatted < decimal_places) {
var diff = decimal_places - num_digits_formatted;
var padded_digit_bytes: [max_digits + 1]u8 = undefined;
var index: usize = 0;
while (index < decimal_places) {
if (index < diff) {
padded_digit_bytes[index] = '0';
} else {
padded_digit_bytes[index] = digit_bytes[index - diff];
}
index += 1;
}
num_digits_formatted = num_digits_formatted + diff;
digit_bytes = padded_digit_bytes;
}
// Get the slice of the part before the decimal
// If this is empty, then hardcode a '0'
var before_digits_num_raw: usize = undefined;
var before_digits_slice: []const u8 = undefined;
if (num_digits_formatted > decimal_places) {
before_digits_num_raw = num_digits_formatted - decimal_places;
before_digits_slice = digit_bytes[0..before_digits_num_raw];
} else {
before_digits_num_raw = 0;
before_digits_slice = "0";
}
// Figure out the index where the trailing zeros start
var index = decimal_places - 1;
var trim_index: ?usize = null;
var is_consecutive_zero = true;
while (index != 0) {
var digit = digit_bytes[before_digits_num_raw + index];
// 48 => '0', 170 => ''
if ((digit == 48 or digit == 170) and is_consecutive_zero) {
trim_index = index;
} else {
is_consecutive_zero = false;
}
index -= 1;
}
// Get the slice of the part afterthe decimal
var after_digits_slice: []const u8 = undefined;
after_digits_slice = digit_bytes[before_digits_num_raw..(before_digits_num_raw + if (trim_index) |i| i else decimal_places)];
// Make the RocStr
var sign_len: usize = if (is_negative) 1 else 0;
var dot_len: usize = 1;
var str_len: usize = sign_len + before_digits_slice.len + dot_len + after_digits_slice.len;
// TODO: Ideally we'd use [str_len]u8 here, but Zig gives an error if we do that.
// [max_digits + 2]u8 here to account for '.' and '-', aka the max possible length of the string
var str_bytes: [max_digits + 2]u8 = undefined;
// Join the whole number slice & the decimal slice together
// The format template arg in bufPrint is `comptime`, so we have to repeate the whole statement in each branch
if (is_negative) {
_ = std.fmt.bufPrint(str_bytes[0 .. str_len + 1], "-{s}.{s}", .{ before_digits_slice, after_digits_slice }) catch {
std.debug.panic("TODO runtime exception failing to print slices", .{});
};
} else {
_ = std.fmt.bufPrint(str_bytes[0 .. str_len + 1], "{s}.{s}", .{ before_digits_slice, after_digits_slice }) catch {
std.debug.panic("TODO runtime exception failing to print slices", .{});
};
}
return RocStr.init(&str_bytes, str_len);
}
pub fn negate(self: RocDec) ?RocDec {
var negated = math.negate(self.num) catch null;
return if (negated) |n| .{ .num = n } else null;
@ -319,6 +408,8 @@ fn mul_u128(a: u128, b: u128) U256 {
const testing = std.testing;
const expectEqual = testing.expectEqual;
const expectEqualSlices = testing.expectEqualSlices;
const expect = testing.expect;
test "fromU64" {
var dec = RocDec.fromU64(25);
@ -326,111 +417,229 @@ test "fromU64" {
try expectEqual(RocDec{ .num = 25000000000000000000 }, dec);
}
test "fromString: empty" {
test "fromStr: empty" {
var roc_str = RocStr.init("", 0);
var dec = RocDec.fromString(roc_str);
var dec = RocDec.fromStr(roc_str);
try expectEqual(dec, null);
}
test "fromString: 0" {
test "fromStr: 0" {
var roc_str = RocStr.init("0", 1);
var dec = RocDec.fromString(roc_str);
var dec = RocDec.fromStr(roc_str);
try expectEqual(RocDec{ .num = 0 }, dec.?);
}
test "fromString: 1" {
test "fromStr: 1" {
var roc_str = RocStr.init("1", 1);
var dec = RocDec.fromString(roc_str);
var dec = RocDec.fromStr(roc_str);
try expectEqual(RocDec.one_point_zero, dec.?);
}
test "fromString: 123.45" {
test "fromStr: 123.45" {
var roc_str = RocStr.init("123.45", 6);
var dec = RocDec.fromString(roc_str);
var dec = RocDec.fromStr(roc_str);
try expectEqual(RocDec{ .num = 123450000000000000000 }, dec.?);
}
test "fromString: .45" {
test "fromStr: .45" {
var roc_str = RocStr.init(".45", 3);
var dec = RocDec.fromString(roc_str);
var dec = RocDec.fromStr(roc_str);
try expectEqual(RocDec{ .num = 450000000000000000 }, dec.?);
}
test "fromString: 0.45" {
test "fromStr: 0.45" {
var roc_str = RocStr.init("0.45", 4);
var dec = RocDec.fromString(roc_str);
var dec = RocDec.fromStr(roc_str);
try expectEqual(RocDec{ .num = 450000000000000000 }, dec.?);
}
test "fromString: 123" {
test "fromStr: 123" {
var roc_str = RocStr.init("123", 3);
var dec = RocDec.fromString(roc_str);
var dec = RocDec.fromStr(roc_str);
try expectEqual(RocDec{ .num = 123000000000000000000 }, dec.?);
}
test "fromString: -.45" {
test "fromStr: -.45" {
var roc_str = RocStr.init("-.45", 4);
var dec = RocDec.fromString(roc_str);
var dec = RocDec.fromStr(roc_str);
try expectEqual(RocDec{ .num = -450000000000000000 }, dec.?);
}
test "fromString: -0.45" {
test "fromStr: -0.45" {
var roc_str = RocStr.init("-0.45", 5);
var dec = RocDec.fromString(roc_str);
var dec = RocDec.fromStr(roc_str);
try expectEqual(RocDec{ .num = -450000000000000000 }, dec.?);
}
test "fromString: -123" {
test "fromStr: -123" {
var roc_str = RocStr.init("-123", 4);
var dec = RocDec.fromString(roc_str);
var dec = RocDec.fromStr(roc_str);
try expectEqual(RocDec{ .num = -123000000000000000000 }, dec.?);
}
test "fromString: -123.45" {
test "fromStr: -123.45" {
var roc_str = RocStr.init("-123.45", 7);
var dec = RocDec.fromString(roc_str);
var dec = RocDec.fromStr(roc_str);
try expectEqual(RocDec{ .num = -123450000000000000000 }, dec.?);
}
test "fromString: abc" {
test "fromStr: abc" {
var roc_str = RocStr.init("abc", 3);
var dec = RocDec.fromString(roc_str);
var dec = RocDec.fromStr(roc_str);
try expectEqual(dec, null);
}
test "fromString: 123.abc" {
test "fromStr: 123.abc" {
var roc_str = RocStr.init("123.abc", 7);
var dec = RocDec.fromString(roc_str);
var dec = RocDec.fromStr(roc_str);
try expectEqual(dec, null);
}
test "fromString: abc.123" {
test "fromStr: abc.123" {
var roc_str = RocStr.init("abc.123", 7);
var dec = RocDec.fromString(roc_str);
var dec = RocDec.fromStr(roc_str);
try expectEqual(dec, null);
}
test "fromString: .123.1" {
test "fromStr: .123.1" {
var roc_str = RocStr.init(".123.1", 6);
var dec = RocDec.fromString(roc_str);
var dec = RocDec.fromStr(roc_str);
try expectEqual(dec, null);
}
test "toStr: 123.45" {
var dec: RocDec = .{ .num = 123450000000000000000 };
var res_roc_str = dec.toStr();
const res_slice: []const u8 = "123.45"[0..];
try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice());
}
test "toStr: -123.45" {
var dec: RocDec = .{ .num = -123450000000000000000 };
var res_roc_str = dec.toStr();
const res_slice: []const u8 = "-123.45"[0..];
try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice());
}
test "toStr: 123.0" {
var dec: RocDec = .{ .num = 123000000000000000000 };
var res_roc_str = dec.toStr();
const res_slice: []const u8 = "123.0"[0..];
try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice());
}
test "toStr: -123.0" {
var dec: RocDec = .{ .num = -123000000000000000000 };
var res_roc_str = dec.toStr();
const res_slice: []const u8 = "-123.0"[0..];
try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice());
}
test "toStr: 0.45" {
var dec: RocDec = .{ .num = 450000000000000000 };
var res_roc_str = dec.toStr();
const res_slice: []const u8 = "0.45"[0..];
try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice());
}
test "toStr: -0.45" {
var dec: RocDec = .{ .num = -450000000000000000 };
var res_roc_str = dec.toStr();
const res_slice: []const u8 = "-0.45"[0..];
try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice());
}
test "toStr: 0.00045" {
var dec: RocDec = .{ .num = 000450000000000000 };
var res_roc_str = dec.toStr();
const res_slice: []const u8 = "0.00045"[0..];
try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice());
}
test "toStr: -0.00045" {
var dec: RocDec = .{ .num = -000450000000000000 };
var res_roc_str = dec.toStr();
const res_slice: []const u8 = "-0.00045"[0..];
try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice());
}
test "toStr: -111.123456789" {
var dec: RocDec = .{ .num = -111123456789000000000 };
var res_roc_str = dec.toStr();
const res_slice: []const u8 = "-111.123456789"[0..];
try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice());
}
test "toStr: 123.1111111" {
var dec: RocDec = .{ .num = 123111111100000000000 };
var res_roc_str = dec.toStr();
const res_slice: []const u8 = "123.1111111"[0..];
try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice());
}
test "toStr: 123.1111111111111 (big str)" {
var dec: RocDec = .{ .num = 123111111111111000000 };
var res_roc_str = dec.toStr();
errdefer res_roc_str.?.deinit();
defer res_roc_str.?.deinit();
const res_slice: []const u8 = "123.111111111111"[0..];
try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice());
}
test "toStr: 123.111111111111444444 (max number of decimal places)" {
var dec: RocDec = .{ .num = 123111111111111444444 };
var res_roc_str = dec.toStr();
errdefer res_roc_str.?.deinit();
defer res_roc_str.?.deinit();
const res_slice: []const u8 = "123.111111111111444444"[0..];
try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice());
}
test "toStr: 12345678912345678912.111111111111111111 (max number of digits)" {
var dec: RocDec = .{ .num = 12345678912345678912111111111111111111 };
var res_roc_str = dec.toStr();
errdefer res_roc_str.?.deinit();
defer res_roc_str.?.deinit();
const res_slice: []const u8 = "12345678912345678912.111111111111111111"[0..];
try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice());
}
test "toStr: 0" {
var dec: RocDec = .{ .num = 0 };
var res_roc_str = dec.toStr();
const res_slice: []const u8 = "0.0"[0..];
try expectEqualSlices(u8, res_slice, res_roc_str.?.asSlice());
}
test "add: 0" {
var dec: RocDec = .{ .num = 0 };

View file

@ -21,7 +21,6 @@ im = "14" # im and im-rc should always have the same version!
im-rc = "14" # im and im-rc should always have the same version!
bumpalo = { version = "3.6.1", features = ["collections"] }
inlinable_string = "0.1"
either = "1.6.1"
inkwell = { path = "../../vendor/inkwell" }
target-lexicon = "0.10"

View file

@ -110,6 +110,9 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
&(bumpalo::vec![ in env.arena; BasicTypeEnum::PointerType(arg_type); argument_layouts.len() + 2 ]),
);
// called from zig, must use C calling convention
function_value.set_call_conventions(C_CALL_CONV);
let kind_id = Attribute::get_named_enum_kind_id("alwaysinline");
debug_assert!(kind_id > 0);
let attr = env.context.create_enum_attribute(kind_id, 1);
@ -303,6 +306,9 @@ fn build_rc_wrapper<'a, 'ctx, 'env>(
),
};
// called from zig, must use C calling convention
function_value.set_call_conventions(C_CALL_CONV);
let kind_id = Attribute::get_named_enum_kind_id("alwaysinline");
debug_assert!(kind_id > 0);
let attr = env.context.create_enum_attribute(kind_id, 1);
@ -381,6 +387,9 @@ pub fn build_eq_wrapper<'a, 'ctx, 'env>(
&[arg_type.into(), arg_type.into()],
);
// called from zig, must use C calling convention
function_value.set_call_conventions(C_CALL_CONV);
let kind_id = Attribute::get_named_enum_kind_id("alwaysinline");
debug_assert!(kind_id > 0);
let attr = env.context.create_enum_attribute(kind_id, 1);
@ -455,6 +464,9 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>(
&[arg_type.into(), arg_type.into(), arg_type.into()],
);
// called from zig, must use C calling convention
function_value.set_call_conventions(C_CALL_CONV);
// we expose this function to zig; must use c calling convention
function_value.set_call_conventions(C_CALL_CONV);

View file

@ -25,7 +25,6 @@ use crate::llvm::refcounting::{
};
use bumpalo::collections::Vec;
use bumpalo::Bump;
use either::Either;
use inkwell::basic_block::BasicBlock;
use inkwell::builder::Builder;
use inkwell::context::Context;
@ -38,8 +37,8 @@ use inkwell::passes::{PassManager, PassManagerBuilder};
use inkwell::types::{BasicType, BasicTypeEnum, FunctionType, IntType, StructType};
use inkwell::values::BasicValueEnum::{self, *};
use inkwell::values::{
BasicValue, CallSiteValue, FloatValue, FunctionValue, InstructionOpcode, InstructionValue,
IntValue, PointerValue, StructValue,
BasicValue, CallSiteValue, CallableValue, FloatValue, FunctionValue, InstructionOpcode,
InstructionValue, IntValue, PointerValue, StructValue,
};
use inkwell::OptimizationLevel;
use inkwell::{AddressSpace, IntPredicate};
@ -54,7 +53,7 @@ use roc_mono::ir::{
Wrapped,
};
use roc_mono::layout::{Builtin, InPlace, LambdaSet, Layout, LayoutIds, UnionLayout};
use target_lexicon::CallingConvention;
use std::convert::TryFrom;
/// This is for Inkwell's FunctionValue::verify - we want to know the verification
/// output in debug builds, but we don't want it to print to stdout in release builds!
@ -1841,7 +1840,7 @@ fn invoke_roc_function<'a, 'ctx, 'env>(
parent: FunctionValue<'ctx>,
symbol: Symbol,
layout: Layout<'a>,
function_value: Either<FunctionValue<'ctx>, PointerValue<'ctx>>,
function_value: FunctionValue<'ctx>,
arguments: &[Symbol],
closure_argument: Option<BasicValueEnum<'ctx>>,
pass: &'a roc_mono::ir::Stmt<'a>,
@ -1869,14 +1868,7 @@ fn invoke_roc_function<'a, 'ctx, 'env>(
"tmp",
);
match function_value {
Either::Left(function) => {
call.set_call_convention(function.get_call_conventions());
}
Either::Right(_) => {
call.set_call_convention(FAST_CALL_CONV);
}
}
call.set_call_convention(function_value.get_call_conventions());
call.try_as_basic_value()
.left()
@ -1903,10 +1895,13 @@ fn invoke_roc_function<'a, 'ctx, 'env>(
context.struct_type(&[exception_ptr, selector_value], false)
};
let exception_object = env.builder.build_cleanup_landing_pad(
&landing_pad_type,
&BasicValueEnum::IntValue(context.i8_type().const_zero()),
context.i8_type().ptr_type(AddressSpace::Generic),
let personality_function = get_gxx_personality_v0(env);
let exception_object = env.builder.build_landing_pad(
landing_pad_type,
personality_function,
&[],
true,
"invoke_landing_pad",
);
@ -2059,7 +2054,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
parent,
*symbol,
*layout,
function_value.into(),
function_value,
call.arguments,
None,
pass,
@ -2099,7 +2094,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
Resume(exception_id) => {
let exception_object = scope.get(&exception_id.into_inner()).unwrap().1;
env.builder.build_resume(&exception_object);
env.builder.build_resume(exception_object);
env.context.i64_type().const_zero().into()
}
@ -2854,18 +2849,17 @@ fn invoke_and_catch<'a, 'ctx, 'env, F, T>(
env: &Env<'a, 'ctx, 'env>,
parent: FunctionValue<'ctx>,
function: F,
calling_convention: u32,
arguments: &[BasicValueEnum<'ctx>],
return_type: T,
) -> BasicValueEnum<'ctx>
where
F: Into<either::Either<FunctionValue<'ctx>, PointerValue<'ctx>>>,
T: inkwell::types::BasicType<'ctx>,
F: Into<CallableValue<'ctx>>,
{
let context = env.context;
let builder = env.builder;
let u8_ptr = env.context.i8_type().ptr_type(AddressSpace::Generic);
let call_result_type = context.struct_type(
&[context.i64_type().into(), return_type.as_basic_type_enum()],
false,
@ -2886,7 +2880,7 @@ where
catch_block,
"call_roc_function",
);
call.set_call_convention(FAST_CALL_CONV);
call.set_call_convention(calling_convention);
call.try_as_basic_value().left().unwrap()
};
@ -2894,71 +2888,7 @@ where
{
builder.position_at_end(catch_block);
let landing_pad_type = {
let exception_ptr = context.i8_type().ptr_type(AddressSpace::Generic).into();
let selector_value = context.i32_type().into();
context.struct_type(&[exception_ptr, selector_value], false)
};
let info = builder
.build_catch_all_landing_pad(
&landing_pad_type,
&BasicValueEnum::IntValue(context.i8_type().const_zero()),
context.i8_type().ptr_type(AddressSpace::Generic),
"main_landing_pad",
)
.into_struct_value();
let exception_ptr = builder
.build_extract_value(info, 0, "exception_ptr")
.unwrap();
let thrown = cxa_begin_catch(env, exception_ptr);
let error_msg = {
let exception_type = u8_ptr;
let ptr = builder.build_bitcast(
thrown,
exception_type.ptr_type(AddressSpace::Generic),
"cast",
);
builder.build_load(ptr.into_pointer_value(), "error_msg")
};
let return_type = context.struct_type(&[context.i64_type().into(), u8_ptr.into()], false);
let return_value = {
let v1 = return_type.const_zero();
// flag is non-zero, indicating failure
let flag = context.i64_type().const_int(1, false);
let v2 = builder
.build_insert_value(v1, flag, 0, "set_error")
.unwrap();
let v3 = builder
.build_insert_value(v2, error_msg, 1, "set_exception")
.unwrap();
v3
};
// bitcast result alloca so we can store our concrete type { flag, error_msg } in there
let result_alloca_bitcast = builder
.build_bitcast(
result_alloca,
return_type.ptr_type(AddressSpace::Generic),
"result_alloca_bitcast",
)
.into_pointer_value();
// store our return value
builder.build_store(result_alloca_bitcast, return_value);
cxa_end_catch(env);
build_catch_all_landing_pad(env, result_alloca);
builder.build_unconditional_branch(cont_block);
}
@ -2991,14 +2921,89 @@ where
builder.position_at_end(cont_block);
let result = builder.build_load(result_alloca, "result");
builder.build_load(result_alloca, "result")
}
// MUST set the personality at the very end;
// doing it earlier can cause the personality to be ignored
let personality_func = get_gxx_personality_v0(env);
parent.set_personality_function(personality_func);
fn build_catch_all_landing_pad<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
result_alloca: PointerValue<'ctx>,
) {
let context = env.context;
let builder = env.builder;
result
let u8_ptr = env.context.i8_type().ptr_type(AddressSpace::Generic);
let landing_pad_type = {
let exception_ptr = context.i8_type().ptr_type(AddressSpace::Generic).into();
let selector_value = context.i32_type().into();
context.struct_type(&[exception_ptr, selector_value], false)
};
// null pointer functions as a catch-all catch clause
let null = u8_ptr.const_zero();
let personality_function = get_gxx_personality_v0(env);
let info = builder
.build_landing_pad(
landing_pad_type,
personality_function,
&[null.into()],
false,
"main_landing_pad",
)
.into_struct_value();
let exception_ptr = builder
.build_extract_value(info, 0, "exception_ptr")
.unwrap();
let thrown = cxa_begin_catch(env, exception_ptr);
let error_msg = {
let exception_type = u8_ptr;
let ptr = builder.build_bitcast(
thrown,
exception_type.ptr_type(AddressSpace::Generic),
"cast",
);
builder.build_load(ptr.into_pointer_value(), "error_msg")
};
let return_type = context.struct_type(&[context.i64_type().into(), u8_ptr.into()], false);
let return_value = {
let v1 = return_type.const_zero();
// flag is non-zero, indicating failure
let flag = context.i64_type().const_int(1, false);
let v2 = builder
.build_insert_value(v1, flag, 0, "set_error")
.unwrap();
let v3 = builder
.build_insert_value(v2, error_msg, 1, "set_exception")
.unwrap();
v3
};
// bitcast result alloca so we can store our concrete type { flag, error_msg } in there
let result_alloca_bitcast = builder
.build_bitcast(
result_alloca,
return_type.ptr_type(AddressSpace::Generic),
"result_alloca_bitcast",
)
.into_pointer_value();
// store our return value
builder.build_store(result_alloca_bitcast, return_value);
cxa_end_catch(env);
}
fn make_exception_catcher<'a, 'ctx, 'env>(
@ -3064,17 +3069,13 @@ fn make_exception_catching_wrapper<'a, 'ctx, 'env>(
env,
wrapper_function,
roc_function,
roc_function.get_call_conventions(),
&arguments,
roc_function_type.get_return_type().unwrap(),
);
builder.build_return(Some(&result));
// MUST set the personality at the very end;
// doing it earlier can cause the personality to be ignored
let personality_func = get_gxx_personality_v0(env);
wrapper_function.set_personality_function(personality_func);
wrapper_function
}
@ -3361,8 +3362,14 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
*param = builder.build_load(param.into_pointer_value(), "load_param");
}
let call_result =
invoke_and_catch(env, function_value, evaluator, &[closure_data], result_type);
let call_result = invoke_and_catch(
env,
function_value,
evaluator,
evaluator.get_call_conventions(),
&[closure_data],
result_type,
);
builder.build_store(output, call_result);
@ -3476,7 +3483,14 @@ fn build_function_caller<'a, 'ctx, 'env>(
*param = builder.build_load(param.into_pointer_value(), "load_param");
}
let call_result = invoke_and_catch(env, function_value, function_ptr, &parameters, result_type);
let call_result = invoke_and_catch(
env,
function_value,
CallableValue::try_from(function_ptr).unwrap(),
C_CALL_CONV,
&parameters,
result_type,
);
builder.build_store(output, call_result);
@ -3733,8 +3747,8 @@ fn roc_call_with_args<'a, 'ctx, 'env>(
/// Translates a target_lexicon::Triple to a LLVM calling convention u32
/// as described in https://llvm.org/doxygen/namespacellvm_1_1CallingConv.html
pub fn get_call_conventions(cc: CallingConvention) -> u32 {
use CallingConvention::*;
pub fn get_call_conventions(cc: target_lexicon::CallingConvention) -> u32 {
use target_lexicon::CallingConvention::*;
// For now, we're returning 0 for the C calling convention on all of these.
// Not sure if we should be picking something more specific!
@ -3746,9 +3760,9 @@ pub fn get_call_conventions(cc: CallingConvention) -> u32 {
}
/// Source: https://llvm.org/doxygen/namespacellvm_1_1CallingConv.html
pub static C_CALL_CONV: u32 = 0;
pub static FAST_CALL_CONV: u32 = 8;
pub static COLD_CALL_CONV: u32 = 9;
pub const C_CALL_CONV: u32 = 0;
pub const FAST_CALL_CONV: u32 = 8;
pub const COLD_CALL_CONV: u32 = 9;
pub struct RocFunctionCall<'ctx> {
pub caller: PointerValue<'ctx>,
@ -5102,10 +5116,13 @@ fn build_foreign_symbol<'a, 'ctx, 'env>(
.struct_type(&[exception_ptr, selector_value], false)
};
let exception_object = env.builder.build_cleanup_landing_pad(
&landing_pad_type,
&BasicValueEnum::IntValue(env.context.i8_type().const_zero()),
env.context.i8_type().ptr_type(AddressSpace::Generic),
let personality_function = get_gxx_personality_v0(env);
let exception_object = env.builder.build_landing_pad(
landing_pad_type,
personality_function,
&[],
true,
"invoke_landing_pad",
);