From f07e69ad8743ad57ae4ef192c3bc8cde4246e268 Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 5 Nov 2020 00:43:13 +0100 Subject: [PATCH] wrap closure call result in RocCallResult --- compiler/gen/src/llvm/build.rs | 153 +++------------------------------ 1 file changed, 12 insertions(+), 141 deletions(-) diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index 8e583fa330..da7812491a 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -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);