mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 08:11:12 +00:00
call to foreign function dropped continuation
This commit is contained in:
parent
e247b573a6
commit
1f0a16ec57
3 changed files with 127 additions and 22 deletions
|
@ -729,10 +729,9 @@ pub fn build_exp_call<'a, 'ctx, 'env>(
|
||||||
run_low_level(env, layout_ids, scope, parent, layout, *op, arguments)
|
run_low_level(env, layout_ids, scope, parent, layout, *op, arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
CallType::Foreign {
|
CallType::Foreign { .. } => {
|
||||||
foreign_symbol: foreign,
|
unreachable!("foreign symbols should always be invoked!")
|
||||||
ret_layout,
|
}
|
||||||
} => build_foreign_symbol(env, scope, foreign, arguments, ret_layout),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1846,8 +1845,6 @@ fn invoke_roc_function<'a, 'ctx, 'env>(
|
||||||
{
|
{
|
||||||
env.builder.position_at_end(pass_block);
|
env.builder.position_at_end(pass_block);
|
||||||
|
|
||||||
// env.builder.build_store(alloca, call_result);
|
|
||||||
// scope.insert(symbol, (layout, alloca));
|
|
||||||
scope.insert(symbol, (layout, call_result));
|
scope.insert(symbol, (layout, call_result));
|
||||||
|
|
||||||
build_exp_stmt(env, layout_ids, scope, parent, pass);
|
build_exp_stmt(env, layout_ids, scope, parent, pass);
|
||||||
|
@ -2010,7 +2007,18 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
CallType::Foreign {
|
CallType::Foreign {
|
||||||
ref foreign_symbol,
|
ref foreign_symbol,
|
||||||
ref ret_layout,
|
ref ret_layout,
|
||||||
} => build_foreign_symbol(env, scope, foreign_symbol, call.arguments, ret_layout),
|
} => build_foreign_symbol(
|
||||||
|
env,
|
||||||
|
layout_ids,
|
||||||
|
scope,
|
||||||
|
parent,
|
||||||
|
foreign_symbol,
|
||||||
|
call.arguments,
|
||||||
|
*symbol,
|
||||||
|
ret_layout,
|
||||||
|
pass,
|
||||||
|
fail,
|
||||||
|
),
|
||||||
|
|
||||||
CallType::LowLevel { .. } => {
|
CallType::LowLevel { .. } => {
|
||||||
unreachable!("lowlevel itself never throws exceptions")
|
unreachable!("lowlevel itself never throws exceptions")
|
||||||
|
@ -2114,12 +2122,6 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
context.i64_type().const_zero().into()
|
context.i64_type().const_zero().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Inc(symbol1, 1, Dec(symbol2, cont)) if symbol1 == symbol2 => {
|
|
||||||
dbg!(symbol1);
|
|
||||||
build_exp_stmt(env, layout_ids, scope, parent, cont)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
Refcounting(modify, cont) => {
|
Refcounting(modify, cont) => {
|
||||||
use ModifyRc::*;
|
use ModifyRc::*;
|
||||||
|
|
||||||
|
@ -3484,7 +3486,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let inplace = get_inplace_from_layout(layout);
|
let inplace = get_inplace_from_layout(layout);
|
||||||
|
|
||||||
str_concat(env, inplace, scope, args[0], args[1])
|
str_concat(env, layout_ids, inplace, scope, args[0], args[1])
|
||||||
}
|
}
|
||||||
StrJoinWith => {
|
StrJoinWith => {
|
||||||
// Str.joinWith : List Str, Str -> Str
|
// Str.joinWith : List Str, Str -> Str
|
||||||
|
@ -3981,17 +3983,26 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn build_foreign_symbol<'a, 'ctx, 'env>(
|
fn build_foreign_symbol<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
scope: &Scope<'a, 'ctx>,
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
|
scope: &mut Scope<'a, 'ctx>,
|
||||||
|
parent: FunctionValue<'ctx>,
|
||||||
foreign: &roc_module::ident::ForeignSymbol,
|
foreign: &roc_module::ident::ForeignSymbol,
|
||||||
arguments: &[Symbol],
|
arguments: &[Symbol],
|
||||||
|
symbol: Symbol,
|
||||||
ret_layout: &Layout<'a>,
|
ret_layout: &Layout<'a>,
|
||||||
|
pass: &'a roc_mono::ir::Stmt<'a>,
|
||||||
|
fail: &'a roc_mono::ir::Stmt<'a>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
let mut arg_vals: Vec<BasicValueEnum> = Vec::with_capacity_in(arguments.len(), env.arena);
|
let mut arg_vals: Vec<BasicValueEnum> = Vec::with_capacity_in(arguments.len(), env.arena);
|
||||||
|
|
||||||
let mut arg_types = Vec::with_capacity_in(arguments.len() + 1, env.arena);
|
let mut arg_types = Vec::with_capacity_in(arguments.len() + 1, env.arena);
|
||||||
|
|
||||||
|
let pass_block = env.context.append_basic_block(parent, "invoke_pass");
|
||||||
|
let fail_block = env.context.append_basic_block(parent, "invoke_fail");
|
||||||
|
|
||||||
// crude approximation of the C calling convention
|
// crude approximation of the C calling convention
|
||||||
let pass_result_by_pointer = ret_layout.stack_size(env.ptr_bytes) > 2 * env.ptr_bytes;
|
let pass_result_by_pointer = ret_layout.stack_size(env.ptr_bytes) > 2 * env.ptr_bytes;
|
||||||
|
|
||||||
|
@ -4017,14 +4028,51 @@ fn build_foreign_symbol<'a, 'ctx, 'env>(
|
||||||
let function_type = env.context.void_type().fn_type(&arg_types, false);
|
let function_type = env.context.void_type().fn_type(&arg_types, false);
|
||||||
let function = get_foreign_symbol(env, foreign.clone(), function_type);
|
let function = get_foreign_symbol(env, foreign.clone(), function_type);
|
||||||
|
|
||||||
let call = env.builder.build_call(function, arg_vals.as_slice(), "tmp");
|
let call =
|
||||||
|
env.builder
|
||||||
|
.build_invoke(function, arg_vals.as_slice(), pass_block, fail_block, "tmp");
|
||||||
|
|
||||||
// this is a foreign function, use c calling convention
|
// this is a foreign function, use c calling convention
|
||||||
call.set_call_convention(C_CALL_CONV);
|
call.set_call_convention(C_CALL_CONV);
|
||||||
|
|
||||||
call.try_as_basic_value();
|
call.try_as_basic_value();
|
||||||
|
|
||||||
env.builder.build_load(ret_ptr, "read_result")
|
let call_result = env.builder.build_load(ret_ptr, "read_result");
|
||||||
|
|
||||||
|
{
|
||||||
|
env.builder.position_at_end(pass_block);
|
||||||
|
|
||||||
|
scope.insert(symbol, (ret_layout.clone(), call_result));
|
||||||
|
|
||||||
|
build_exp_stmt(env, layout_ids, scope, parent, pass);
|
||||||
|
|
||||||
|
scope.remove(&symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
env.builder.position_at_end(fail_block);
|
||||||
|
|
||||||
|
let landing_pad_type = {
|
||||||
|
let exception_ptr = env.context.i8_type().ptr_type(AddressSpace::Generic).into();
|
||||||
|
let selector_value = env.context.i32_type().into();
|
||||||
|
|
||||||
|
env.context
|
||||||
|
.struct_type(&[exception_ptr, selector_value], false)
|
||||||
|
};
|
||||||
|
|
||||||
|
env.builder
|
||||||
|
.build_catch_all_landing_pad(
|
||||||
|
&landing_pad_type,
|
||||||
|
&BasicValueEnum::IntValue(env.context.i8_type().const_zero()),
|
||||||
|
env.context.i8_type().ptr_type(AddressSpace::Generic),
|
||||||
|
"invoke_landing_pad",
|
||||||
|
)
|
||||||
|
.into_struct_value();
|
||||||
|
|
||||||
|
build_exp_stmt(env, layout_ids, scope, parent, fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
call_result
|
||||||
} else {
|
} else {
|
||||||
for arg in arguments.iter() {
|
for arg in arguments.iter() {
|
||||||
let (value, layout) = load_symbol_and_layout(scope, arg);
|
let (value, layout) = load_symbol_and_layout(scope, arg);
|
||||||
|
@ -4037,14 +4085,52 @@ fn build_foreign_symbol<'a, 'ctx, 'env>(
|
||||||
let function_type = get_fn_type(&ret_type, &arg_types);
|
let function_type = get_fn_type(&ret_type, &arg_types);
|
||||||
let function = get_foreign_symbol(env, foreign.clone(), function_type);
|
let function = get_foreign_symbol(env, foreign.clone(), function_type);
|
||||||
|
|
||||||
let call = env.builder.build_call(function, arg_vals.as_slice(), "tmp");
|
let call =
|
||||||
|
env.builder
|
||||||
|
.build_invoke(function, arg_vals.as_slice(), pass_block, fail_block, "tmp");
|
||||||
|
|
||||||
// this is a foreign function, use c calling convention
|
// this is a foreign function, use c calling convention
|
||||||
call.set_call_convention(C_CALL_CONV);
|
call.set_call_convention(C_CALL_CONV);
|
||||||
|
|
||||||
call.try_as_basic_value()
|
let call_result = call
|
||||||
|
.try_as_basic_value()
|
||||||
.left()
|
.left()
|
||||||
.unwrap_or_else(|| panic!("LLVM error: Invalid call by pointer."))
|
.unwrap_or_else(|| panic!("LLVM error: Invalid call by pointer."));
|
||||||
|
|
||||||
|
{
|
||||||
|
env.builder.position_at_end(pass_block);
|
||||||
|
|
||||||
|
scope.insert(symbol, (ret_layout.clone(), call_result));
|
||||||
|
|
||||||
|
build_exp_stmt(env, layout_ids, scope, parent, pass);
|
||||||
|
|
||||||
|
scope.remove(&symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
env.builder.position_at_end(fail_block);
|
||||||
|
|
||||||
|
let landing_pad_type = {
|
||||||
|
let exception_ptr = env.context.i8_type().ptr_type(AddressSpace::Generic).into();
|
||||||
|
let selector_value = env.context.i32_type().into();
|
||||||
|
|
||||||
|
env.context
|
||||||
|
.struct_type(&[exception_ptr, selector_value], false)
|
||||||
|
};
|
||||||
|
|
||||||
|
env.builder
|
||||||
|
.build_catch_all_landing_pad(
|
||||||
|
&landing_pad_type,
|
||||||
|
&BasicValueEnum::IntValue(env.context.i8_type().const_zero()),
|
||||||
|
env.context.i8_type().ptr_type(AddressSpace::Generic),
|
||||||
|
"invoke_landing_pad",
|
||||||
|
)
|
||||||
|
.into_struct_value();
|
||||||
|
|
||||||
|
build_exp_stmt(env, layout_ids, scope, parent, fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
call_result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,13 @@ use crate::llvm::build::{
|
||||||
};
|
};
|
||||||
use crate::llvm::build_list::{allocate_list, store_list};
|
use crate::llvm::build_list::{allocate_list, store_list};
|
||||||
use crate::llvm::convert::collection;
|
use crate::llvm::convert::collection;
|
||||||
|
use crate::llvm::refcounting::decrement_refcount_layout;
|
||||||
use inkwell::types::BasicTypeEnum;
|
use inkwell::types::BasicTypeEnum;
|
||||||
use inkwell::values::{BasicValueEnum, IntValue, StructValue};
|
use inkwell::values::{BasicValueEnum, IntValue, StructValue};
|
||||||
use inkwell::AddressSpace;
|
use inkwell::AddressSpace;
|
||||||
use roc_builtins::bitcode;
|
use roc_builtins::bitcode;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_mono::layout::{Builtin, Layout};
|
use roc_mono::layout::{Builtin, Layout, LayoutIds};
|
||||||
|
|
||||||
use super::build::load_symbol;
|
use super::build::load_symbol;
|
||||||
|
|
||||||
|
@ -128,6 +129,7 @@ fn zig_str_to_struct<'a, 'ctx, 'env>(
|
||||||
/// Str.concat : Str, Str -> Str
|
/// Str.concat : Str, Str -> Str
|
||||||
pub fn str_concat<'a, 'ctx, 'env>(
|
pub fn str_concat<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
inplace: InPlace,
|
inplace: InPlace,
|
||||||
scope: &Scope<'a, 'ctx>,
|
scope: &Scope<'a, 'ctx>,
|
||||||
str1_symbol: Symbol,
|
str1_symbol: Symbol,
|
||||||
|
@ -151,6 +153,22 @@ pub fn str_concat<'a, 'ctx, 'env>(
|
||||||
)
|
)
|
||||||
.into_struct_value();
|
.into_struct_value();
|
||||||
|
|
||||||
|
let parent = env
|
||||||
|
.builder
|
||||||
|
.get_insert_block()
|
||||||
|
.unwrap()
|
||||||
|
.get_parent()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// fix refcounts; consume both arguments
|
||||||
|
let layout = Layout::Builtin(Builtin::Str);
|
||||||
|
|
||||||
|
let str1 = load_symbol(scope, &str1_symbol);
|
||||||
|
decrement_refcount_layout(env, parent, layout_ids, str1, &layout);
|
||||||
|
|
||||||
|
let str2 = load_symbol(scope, &str2_symbol);
|
||||||
|
decrement_refcount_layout(env, parent, layout_ids, str2, &layout);
|
||||||
|
|
||||||
zig_str_to_struct(env, zig_result).into()
|
zig_str_to_struct(env, zig_result).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -489,9 +489,10 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let field_ptr = env
|
let field_ptr = env
|
||||||
.builder
|
.builder
|
||||||
.build_extract_value(wrapper_struct, 1, "increment_closure_data")
|
.build_extract_value(wrapper_struct, 1, "moddify_rc_closure_data")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
// dbg!(&field_ptr, closure_layout.as_block_of_memory_layout());
|
||||||
modify_refcount_layout(
|
modify_refcount_layout(
|
||||||
env,
|
env,
|
||||||
parent,
|
parent,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue