mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
wrap closure call result in RocCallResult
This commit is contained in:
parent
c3090cf9d7
commit
f07e69ad87
1 changed files with 12 additions and 141 deletions
|
@ -1937,14 +1937,10 @@ where
|
|||
false,
|
||||
);
|
||||
|
||||
// Add main's body
|
||||
let basic_block = context.append_basic_block(parent, "entry");
|
||||
let then_block = context.append_basic_block(parent, "then_block");
|
||||
let catch_block = context.append_basic_block(parent, "catch_block");
|
||||
let cont_block = context.append_basic_block(parent, "cont_block");
|
||||
|
||||
builder.position_at_end(basic_block);
|
||||
|
||||
let result_alloca = builder.build_alloca(call_result_type.clone(), "result");
|
||||
|
||||
// invoke instead of call, so that we can catch any exeptions thrown in Roc code
|
||||
|
@ -2080,8 +2076,6 @@ fn make_exception_catching_wrapper<'a, 'ctx, 'env>(
|
|||
let context = env.context;
|
||||
let builder = env.builder;
|
||||
|
||||
let u8_ptr = env.context.i8_type().ptr_type(AddressSpace::Generic);
|
||||
|
||||
let roc_function_type = roc_function.get_type();
|
||||
let argument_types = roc_function_type.get_param_types();
|
||||
|
||||
|
@ -2105,136 +2099,21 @@ fn make_exception_catching_wrapper<'a, 'ctx, 'env>(
|
|||
// our exposed main function adheres to the C calling convention
|
||||
wrapper_function.set_call_conventions(FAST_CALL_CONV);
|
||||
|
||||
// Add main's body
|
||||
let basic_block = context.append_basic_block(wrapper_function, "entry");
|
||||
let then_block = context.append_basic_block(wrapper_function, "then_block");
|
||||
let catch_block = context.append_basic_block(wrapper_function, "catch_block");
|
||||
let cont_block = context.append_basic_block(wrapper_function, "cont_block");
|
||||
|
||||
builder.position_at_end(basic_block);
|
||||
|
||||
let result_alloca = builder.build_alloca(wrapper_return_type, "result");
|
||||
|
||||
// invoke instead of call, so that we can catch any exeptions thrown in Roc code
|
||||
let arguments = wrapper_function.get_params();
|
||||
let call_result = {
|
||||
let call = builder.build_invoke(
|
||||
roc_function,
|
||||
&arguments,
|
||||
then_block,
|
||||
catch_block,
|
||||
"call_roc_function",
|
||||
);
|
||||
call.set_call_convention(FAST_CALL_CONV);
|
||||
call.try_as_basic_value().left().unwrap()
|
||||
};
|
||||
|
||||
// exception handling
|
||||
{
|
||||
builder.position_at_end(catch_block);
|
||||
let basic_block = context.append_basic_block(wrapper_function, "entry");
|
||||
builder.position_at_end(basic_block);
|
||||
|
||||
let landing_pad_type = {
|
||||
let exception_ptr = context.i8_type().ptr_type(AddressSpace::Generic).into();
|
||||
let selector_value = context.i32_type().into();
|
||||
let result = invoke_and_catch(
|
||||
env,
|
||||
wrapper_function,
|
||||
roc_function,
|
||||
&arguments,
|
||||
roc_function_type.get_return_type().unwrap(),
|
||||
);
|
||||
|
||||
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);
|
||||
|
||||
builder.build_unconditional_branch(cont_block);
|
||||
}
|
||||
|
||||
{
|
||||
builder.position_at_end(then_block);
|
||||
|
||||
let return_value = {
|
||||
let v1 = wrapper_return_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, call_result, 1, "set_call_result")
|
||||
.unwrap();
|
||||
|
||||
v3
|
||||
};
|
||||
|
||||
let ptr = builder.build_bitcast(
|
||||
result_alloca,
|
||||
wrapper_return_type.ptr_type(AddressSpace::Generic),
|
||||
"name",
|
||||
);
|
||||
builder.build_store(ptr.into_pointer_value(), return_value);
|
||||
|
||||
builder.build_unconditional_branch(cont_block);
|
||||
}
|
||||
|
||||
{
|
||||
builder.position_at_end(cont_block);
|
||||
|
||||
let result = builder.build_load(result_alloca, "result");
|
||||
|
||||
builder.build_return(Some(&result));
|
||||
}
|
||||
builder.build_return(Some(&result));
|
||||
|
||||
// MUST set the personality at the very end;
|
||||
// doing it earlier can cause the personality to be ignored
|
||||
|
@ -2388,18 +2267,10 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
|
|||
|
||||
let mut arguments = parameters;
|
||||
arguments.push(closure_data);
|
||||
let call = builder.build_call(function_ptr, &arguments, "call_closure");
|
||||
call.set_call_convention(FAST_CALL_CONV);
|
||||
|
||||
let result = call.try_as_basic_value().left().unwrap();
|
||||
let result = invoke_and_catch(env, function_value, function_ptr, &arguments, result_type);
|
||||
|
||||
// TODO here we just assume success (first i64 is 0)
|
||||
unsafe {
|
||||
// let tag_ptr = builder.build_struct_gep(output, 0, "gep");
|
||||
let result_ptr = builder.build_struct_gep(output, 1, "gep");
|
||||
|
||||
builder.build_store(result_ptr, result);
|
||||
}
|
||||
builder.build_store(output, result);
|
||||
|
||||
builder.build_return(None);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue