mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
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:
parent
2c3984bb0f
commit
5d7b4b7ad0
3 changed files with 46 additions and 66 deletions
|
@ -3183,8 +3183,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
builder.position_at_end(entry);
|
builder.position_at_end(entry);
|
||||||
|
|
||||||
let elements = [Layout::Builtin(Builtin::Int64), return_layout];
|
let wrapped_layout = roc_result_layout(env.arena, return_layout);
|
||||||
let wrapped_layout = Layout::Struct(&elements);
|
|
||||||
call_roc_function(env, roc_function, &wrapped_layout, arguments_for_call)
|
call_roc_function(env, roc_function, &wrapped_layout, arguments_for_call)
|
||||||
} else {
|
} else {
|
||||||
call_roc_function(env, roc_function, &return_layout, arguments_for_call)
|
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>,
|
return_layout: Layout<'a>,
|
||||||
c_function_name: &str,
|
c_function_name: &str,
|
||||||
) -> FunctionValue<'ctx> {
|
) -> FunctionValue<'ctx> {
|
||||||
let context = env.context;
|
|
||||||
|
|
||||||
// a tagged union to indicate to the test loader that a panic occurred.
|
// 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
|
// especially when running 32-bit binaries on a 64-bit machine, there
|
||||||
// does not seem to be a smarter solution
|
// does not seem to be a smarter solution
|
||||||
let wrapper_return_type = context.struct_type(
|
let wrapper_return_type =
|
||||||
&[
|
roc_result_type(env, roc_function.get_type().get_return_type().unwrap());
|
||||||
context.i64_type().into(),
|
|
||||||
roc_function.get_type().get_return_type().unwrap(),
|
|
||||||
],
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut cc_argument_types = Vec::with_capacity_in(arguments.len(), env.arena);
|
let mut cc_argument_types = Vec::with_capacity_in(arguments.len(), env.arena);
|
||||||
for layout in arguments {
|
for layout in arguments {
|
||||||
|
@ -3346,8 +3338,6 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx, 'env>(
|
||||||
return_layout: Layout<'a>,
|
return_layout: Layout<'a>,
|
||||||
c_function_name: &str,
|
c_function_name: &str,
|
||||||
) -> FunctionValue<'ctx> {
|
) -> FunctionValue<'ctx> {
|
||||||
let context = env.context;
|
|
||||||
|
|
||||||
if env.is_gen_test {
|
if env.is_gen_test {
|
||||||
return expose_function_to_host_help_c_abi_gen_test(
|
return expose_function_to_host_help_c_abi_gen_test(
|
||||||
env,
|
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 {
|
let wrapper_return_type = if env.is_gen_test {
|
||||||
context
|
roc_result_type(env, roc_function.get_type().get_return_type().unwrap()).into()
|
||||||
.struct_type(
|
|
||||||
&[
|
|
||||||
context.i64_type().into(),
|
|
||||||
roc_function.get_type().get_return_type().unwrap(),
|
|
||||||
],
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
} else {
|
} else {
|
||||||
roc_function.get_type().get_return_type().unwrap()
|
roc_function.get_type().get_return_type().unwrap()
|
||||||
};
|
};
|
||||||
|
@ -3542,11 +3524,7 @@ where
|
||||||
let context = env.context;
|
let context = env.context;
|
||||||
let builder = env.builder;
|
let builder = env.builder;
|
||||||
|
|
||||||
let call_result_type = context.struct_type(
|
let call_result_type = roc_result_type(env, return_type.as_basic_type_enum());
|
||||||
&[context.i64_type().into(), return_type.as_basic_type_enum()],
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
let result_alloca = builder.build_alloca(call_result_type, "result");
|
let result_alloca = builder.build_alloca(call_result_type, "result");
|
||||||
|
|
||||||
let then_block = context.append_basic_block(parent, "then_block");
|
let then_block = context.append_basic_block(parent, "then_block");
|
||||||
|
@ -3648,12 +3626,8 @@ where
|
||||||
ptr_int
|
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 return_value = {
|
||||||
let v1 = return_type.const_zero();
|
let v1 = call_result_type.const_zero();
|
||||||
|
|
||||||
// flag is non-zero, indicating failure
|
// flag is non-zero, indicating failure
|
||||||
let flag = context.i64_type().const_int(1, false);
|
let flag = context.i64_type().const_int(1, false);
|
||||||
|
@ -3668,17 +3642,7 @@ where
|
||||||
v3
|
v3
|
||||||
};
|
};
|
||||||
|
|
||||||
// bitcast result alloca so we can store our concrete type { flag, error_msg } in there
|
builder.build_store(result_alloca, return_value);
|
||||||
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);
|
|
||||||
|
|
||||||
env.builder.build_unconditional_branch(cont_block);
|
env.builder.build_unconditional_branch(cont_block);
|
||||||
}
|
}
|
||||||
|
@ -3701,6 +3665,30 @@ fn make_exception_catcher<'a, 'ctx, 'env>(
|
||||||
function_value
|
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>(
|
fn make_good_roc_result<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
return_value: BasicValueEnum<'ctx>,
|
return_value: BasicValueEnum<'ctx>,
|
||||||
|
@ -3708,18 +3696,14 @@ fn make_good_roc_result<'a, 'ctx, 'env>(
|
||||||
let context = env.context;
|
let context = env.context;
|
||||||
let builder = env.builder;
|
let builder = env.builder;
|
||||||
|
|
||||||
let content_type = return_value.get_type();
|
let v1 = roc_result_type(env, return_value.get_type()).const_zero();
|
||||||
let wrapper_return_type =
|
|
||||||
context.struct_type(&[context.i64_type().into(), content_type], false);
|
|
||||||
|
|
||||||
let v1 = wrapper_return_type.const_zero();
|
|
||||||
|
|
||||||
let v2 = builder
|
let v2 = builder
|
||||||
.build_insert_value(v1, context.i64_type().const_zero(), 0, "set_no_error")
|
.build_insert_value(v1, context.i64_type().const_zero(), 0, "set_no_error")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let v3 = builder
|
let v3 = builder
|
||||||
.build_insert_value(v2, return_value, 1, "set_call_result")
|
.build_insert_value(v2, return_value, 2, "set_call_result")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
v3.into_struct_value().into()
|
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 roc_function_type = roc_function.get_type();
|
||||||
let argument_types = roc_function_type.get_param_types();
|
let argument_types = roc_function_type.get_param_types();
|
||||||
|
|
||||||
let wrapper_return_type = context.struct_type(
|
let wrapper_return_type =
|
||||||
&[
|
roc_result_type(env, roc_function.get_type().get_return_type().unwrap());
|
||||||
context.i64_type().into(),
|
|
||||||
roc_function.get_type().get_return_type().unwrap(),
|
|
||||||
],
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
// argument_types.push(wrapper_return_type.ptr_type(AddressSpace::Generic).into());
|
// argument_types.push(wrapper_return_type.ptr_type(AddressSpace::Generic).into());
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
use std::mem::MaybeUninit;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
use RocCallResult::*;
|
|
||||||
|
|
||||||
/// This must have the same size as the repr() of RocCallResult!
|
/// This must have the same size as the repr() of RocCallResult!
|
||||||
pub const ROC_CALL_RESULT_DISCRIMINANT_SIZE: usize = std::mem::size_of::<u64>();
|
pub const ROC_CALL_RESULT_DISCRIMINANT_SIZE: usize = std::mem::size_of::<u64>();
|
||||||
|
|
||||||
#[repr(u64)]
|
#[repr(C)]
|
||||||
pub enum RocCallResult<T> {
|
pub struct RocCallResult<T> {
|
||||||
Success(T),
|
tag: u64,
|
||||||
Failure(*mut c_char),
|
error_msg: *mut c_char,
|
||||||
|
value: MaybeUninit<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Sized> From<RocCallResult<T>> for Result<T, String> {
|
impl<T: Sized> From<RocCallResult<T>> for Result<T, String> {
|
||||||
fn from(call_result: RocCallResult<T>) -> Self {
|
fn from(call_result: RocCallResult<T>) -> Self {
|
||||||
match call_result {
|
match call_result.tag {
|
||||||
Success(value) => Ok(value),
|
0 => Ok(unsafe { call_result.value.assume_init() }),
|
||||||
Failure(failure) => Err({
|
_ => Err({
|
||||||
let raw = unsafe { CString::from_raw(failure) };
|
let raw = unsafe { CString::from_raw(call_result.error_msg) };
|
||||||
|
|
||||||
let result = format!("{:?}", raw);
|
let result = format!("{:?}", raw);
|
||||||
|
|
||||||
|
|
|
@ -2341,7 +2341,7 @@ fn list_any() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
#[ignore]
|
#[should_panic(expected = r#"Roc failed with message: "UnresolvedTypeVar"#)]
|
||||||
fn list_any_empty_with_unknown_element_type() {
|
fn list_any_empty_with_unknown_element_type() {
|
||||||
// Segfaults with invalid memory reference. Running this as a stand-alone
|
// Segfaults with invalid memory reference. Running this as a stand-alone
|
||||||
// Roc program, generates the following error message:
|
// Roc program, generates the following error message:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue