change roc call result; adding an extra field for the error message pointer

When the returned value was smaller than a pointer, there was no space for the error message pointer.
This commit is contained in:
Folkert 2021-11-10 22:09:01 +01:00
parent 2c3984bb0f
commit 5d7b4b7ad0
3 changed files with 46 additions and 66 deletions

View file

@ -3183,8 +3183,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx, 'env>(
builder.position_at_end(entry);
let elements = [Layout::Builtin(Builtin::Int64), return_layout];
let wrapped_layout = Layout::Struct(&elements);
let wrapped_layout = roc_result_layout(env.arena, return_layout);
call_roc_function(env, roc_function, &wrapped_layout, arguments_for_call)
} else {
call_roc_function(env, roc_function, &return_layout, arguments_for_call)
@ -3212,18 +3211,11 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx, 'env>(
return_layout: Layout<'a>,
c_function_name: &str,
) -> FunctionValue<'ctx> {
let context = env.context;
// a tagged union to indicate to the test loader that a panic occurred.
// especially when running 32-bit binaries on a 64-bit machine, there
// does not seem to be a smarter solution
let wrapper_return_type = context.struct_type(
&[
context.i64_type().into(),
roc_function.get_type().get_return_type().unwrap(),
],
false,
);
let wrapper_return_type =
roc_result_type(env, roc_function.get_type().get_return_type().unwrap());
let mut cc_argument_types = Vec::with_capacity_in(arguments.len(), env.arena);
for layout in arguments {
@ -3346,8 +3338,6 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx, 'env>(
return_layout: Layout<'a>,
c_function_name: &str,
) -> FunctionValue<'ctx> {
let context = env.context;
if env.is_gen_test {
return expose_function_to_host_help_c_abi_gen_test(
env,
@ -3369,15 +3359,7 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx, 'env>(
);
let wrapper_return_type = if env.is_gen_test {
context
.struct_type(
&[
context.i64_type().into(),
roc_function.get_type().get_return_type().unwrap(),
],
false,
)
.into()
roc_result_type(env, roc_function.get_type().get_return_type().unwrap()).into()
} else {
roc_function.get_type().get_return_type().unwrap()
};
@ -3542,11 +3524,7 @@ where
let context = env.context;
let builder = env.builder;
let call_result_type = context.struct_type(
&[context.i64_type().into(), return_type.as_basic_type_enum()],
false,
);
let call_result_type = roc_result_type(env, return_type.as_basic_type_enum());
let result_alloca = builder.build_alloca(call_result_type, "result");
let then_block = context.append_basic_block(parent, "then_block");
@ -3648,12 +3626,8 @@ where
ptr_int
};
let u8_ptr = env.context.i8_type().ptr_type(AddressSpace::Generic);
let return_type = context.struct_type(&[context.i64_type().into(), u8_ptr.into()], false);
// let return_type = call_result_type;
let return_value = {
let v1 = return_type.const_zero();
let v1 = call_result_type.const_zero();
// flag is non-zero, indicating failure
let flag = context.i64_type().const_int(1, false);
@ -3668,17 +3642,7 @@ where
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);
builder.build_store(result_alloca, return_value);
env.builder.build_unconditional_branch(cont_block);
}
@ -3701,6 +3665,30 @@ fn make_exception_catcher<'a, 'ctx, 'env>(
function_value
}
fn roc_result_layout<'a>(arena: &'a Bump, return_layout: Layout<'a>) -> Layout<'a> {
let elements = [
Layout::Builtin(Builtin::Int64),
Layout::Builtin(Builtin::Usize),
return_layout,
];
Layout::Struct(arena.alloc(elements))
}
fn roc_result_type<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
return_type: BasicTypeEnum<'ctx>,
) -> StructType<'ctx> {
env.context.struct_type(
&[
env.context.i64_type().into(),
env.context.i8_type().ptr_type(AddressSpace::Generic).into(),
return_type,
],
false,
)
}
fn make_good_roc_result<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
return_value: BasicValueEnum<'ctx>,
@ -3708,18 +3696,14 @@ fn make_good_roc_result<'a, 'ctx, 'env>(
let context = env.context;
let builder = env.builder;
let content_type = return_value.get_type();
let wrapper_return_type =
context.struct_type(&[context.i64_type().into(), content_type], false);
let v1 = wrapper_return_type.const_zero();
let v1 = roc_result_type(env, return_value.get_type()).const_zero();
let v2 = builder
.build_insert_value(v1, context.i64_type().const_zero(), 0, "set_no_error")
.unwrap();
let v3 = builder
.build_insert_value(v2, return_value, 1, "set_call_result")
.build_insert_value(v2, return_value, 2, "set_call_result")
.unwrap();
v3.into_struct_value().into()
@ -3738,13 +3722,8 @@ fn make_exception_catching_wrapper<'a, 'ctx, 'env>(
let roc_function_type = roc_function.get_type();
let argument_types = roc_function_type.get_param_types();
let wrapper_return_type = context.struct_type(
&[
context.i64_type().into(),
roc_function.get_type().get_return_type().unwrap(),
],
false,
);
let wrapper_return_type =
roc_result_type(env, roc_function.get_type().get_return_type().unwrap());
// argument_types.push(wrapper_return_type.ptr_type(AddressSpace::Generic).into());