mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
commit
449ec19b0f
12 changed files with 209 additions and 192 deletions
|
@ -6,6 +6,7 @@ use roc_gen_llvm::{run_jit_function, run_jit_function_dynamic_type};
|
||||||
use roc_module::ident::{Lowercase, TagName};
|
use roc_module::ident::{Lowercase, TagName};
|
||||||
use roc_module::operator::CalledVia;
|
use roc_module::operator::CalledVia;
|
||||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||||
|
use roc_mono::ir::TopLevelFunctionLayout;
|
||||||
use roc_mono::layout::{union_sorted_tags_help, Builtin, Layout, UnionLayout, UnionVariant};
|
use roc_mono::layout::{union_sorted_tags_help, Builtin, Layout, UnionLayout, UnionVariant};
|
||||||
use roc_parse::ast::{AssignedField, Expr, StrLiteral};
|
use roc_parse::ast::{AssignedField, Expr, StrLiteral};
|
||||||
use roc_region::all::{Located, Region};
|
use roc_region::all::{Located, Region};
|
||||||
|
@ -37,7 +38,7 @@ pub unsafe fn jit_to_ast<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
lib: Library,
|
lib: Library,
|
||||||
main_fn_name: &str,
|
main_fn_name: &str,
|
||||||
layout: &Layout<'a>,
|
layout: TopLevelFunctionLayout<'a>,
|
||||||
content: &Content,
|
content: &Content,
|
||||||
interns: &Interns,
|
interns: &Interns,
|
||||||
home: ModuleId,
|
home: ModuleId,
|
||||||
|
@ -53,11 +54,14 @@ pub unsafe fn jit_to_ast<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
match layout {
|
match layout {
|
||||||
Layout::FunctionPointer(&[], result) => {
|
TopLevelFunctionLayout {
|
||||||
|
arguments: [],
|
||||||
|
result,
|
||||||
|
} => {
|
||||||
// this is a thunk
|
// this is a thunk
|
||||||
jit_to_ast_help(&env, lib, main_fn_name, result, content)
|
jit_to_ast_help(&env, lib, main_fn_name, &result, content)
|
||||||
}
|
}
|
||||||
_ => jit_to_ast_help(&env, lib, main_fn_name, layout, content),
|
_ => Err(ToAstProblem::FunctionLayout),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -226,7 +226,7 @@ pub fn gen_and_eval<'a>(
|
||||||
&arena,
|
&arena,
|
||||||
lib,
|
lib,
|
||||||
main_fn_name,
|
main_fn_name,
|
||||||
&arena.alloc(main_fn_layout).full(),
|
main_fn_layout,
|
||||||
&content,
|
&content,
|
||||||
&env.interns,
|
&env.interns,
|
||||||
home,
|
home,
|
||||||
|
|
|
@ -9,8 +9,7 @@ use object::{
|
||||||
};
|
};
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
use roc_module::symbol;
|
use roc_module::symbol;
|
||||||
use roc_mono::ir::Proc;
|
use roc_mono::ir::{Proc, TopLevelFunctionLayout};
|
||||||
use roc_mono::layout::Layout;
|
|
||||||
use target_lexicon::{Architecture as TargetArch, BinaryFormat as TargetBF, Triple};
|
use target_lexicon::{Architecture as TargetArch, BinaryFormat as TargetBF, Triple};
|
||||||
|
|
||||||
// This is used by some code below which is currently commented out.
|
// This is used by some code below which is currently commented out.
|
||||||
|
@ -22,7 +21,7 @@ use target_lexicon::{Architecture as TargetArch, BinaryFormat as TargetBF, Tripl
|
||||||
pub fn build_module<'a>(
|
pub fn build_module<'a>(
|
||||||
env: &'a Env,
|
env: &'a Env,
|
||||||
target: &Triple,
|
target: &Triple,
|
||||||
procedures: MutMap<(symbol::Symbol, Layout<'a>), Proc<'a>>,
|
procedures: MutMap<(symbol::Symbol, TopLevelFunctionLayout<'a>), Proc<'a>>,
|
||||||
) -> Result<Object, String> {
|
) -> Result<Object, String> {
|
||||||
match target {
|
match target {
|
||||||
Triple {
|
Triple {
|
||||||
|
@ -145,7 +144,7 @@ fn generate_wrapper<'a, B: Backend<'a>>(
|
||||||
|
|
||||||
fn build_object<'a, B: Backend<'a>>(
|
fn build_object<'a, B: Backend<'a>>(
|
||||||
env: &'a Env,
|
env: &'a Env,
|
||||||
procedures: MutMap<(symbol::Symbol, Layout<'a>), Proc<'a>>,
|
procedures: MutMap<(symbol::Symbol, TopLevelFunctionLayout<'a>), Proc<'a>>,
|
||||||
mut backend: B,
|
mut backend: B,
|
||||||
mut output: Object,
|
mut output: Object,
|
||||||
) -> Result<Object, String> {
|
) -> Result<Object, String> {
|
||||||
|
@ -187,7 +186,7 @@ fn build_object<'a, B: Backend<'a>>(
|
||||||
let mut procs = Vec::with_capacity_in(procedures.len(), env.arena);
|
let mut procs = Vec::with_capacity_in(procedures.len(), env.arena);
|
||||||
for ((sym, layout), proc) in procedures {
|
for ((sym, layout), proc) in procedures {
|
||||||
let fn_name = layout_ids
|
let fn_name = layout_ids
|
||||||
.get(sym, &layout)
|
.get_toplevel(sym, &layout)
|
||||||
.to_symbol_string(sym, &env.interns);
|
.to_symbol_string(sym, &env.interns);
|
||||||
|
|
||||||
let section_id = output.add_section(
|
let section_id = output.add_section(
|
||||||
|
|
|
@ -69,8 +69,8 @@ pub fn helper<'a>(
|
||||||
|
|
||||||
let mut procedures = MutMap::default();
|
let mut procedures = MutMap::default();
|
||||||
|
|
||||||
for ((symbol, top_level), proc) in top_procedures {
|
for (key, proc) in top_procedures {
|
||||||
procedures.insert((symbol, arena.alloc(top_level).full()), proc);
|
procedures.insert(key, proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -87,17 +87,12 @@ pub fn helper<'a>(
|
||||||
println!("=================================\n");
|
println!("=================================\n");
|
||||||
*/
|
*/
|
||||||
debug_assert_eq!(exposed_to_host.len(), 1);
|
debug_assert_eq!(exposed_to_host.len(), 1);
|
||||||
let main_fn_symbol = exposed_to_host.keys().copied().next().unwrap();
|
let main_fn_symbol = loaded.entry_point.symbol;
|
||||||
|
let main_fn_layout = loaded.entry_point.layout;
|
||||||
let main_fn_layout = procedures
|
|
||||||
.keys()
|
|
||||||
.find(|(s, _)| *s == main_fn_symbol)
|
|
||||||
.map(|t| t.1)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut layout_ids = roc_mono::layout::LayoutIds::default();
|
let mut layout_ids = roc_mono::layout::LayoutIds::default();
|
||||||
let main_fn_name = layout_ids
|
let main_fn_name = layout_ids
|
||||||
.get(main_fn_symbol, &main_fn_layout)
|
.get_toplevel(main_fn_symbol, &main_fn_layout)
|
||||||
.to_symbol_string(main_fn_symbol, &interns);
|
.to_symbol_string(main_fn_symbol, &interns);
|
||||||
|
|
||||||
let mut lines = Vec::new();
|
let mut lines = Vec::new();
|
||||||
|
|
|
@ -17,8 +17,8 @@ use crate::llvm::build_str::{
|
||||||
};
|
};
|
||||||
use crate::llvm::compare::{generic_eq, generic_neq};
|
use crate::llvm::compare::{generic_eq, generic_neq};
|
||||||
use crate::llvm::convert::{
|
use crate::llvm::convert::{
|
||||||
basic_type_from_builtin, basic_type_from_layout, block_of_memory, block_of_memory_slices,
|
basic_type_from_builtin, basic_type_from_function_layout, basic_type_from_layout,
|
||||||
ptr_int,
|
block_of_memory, block_of_memory_slices, ptr_int,
|
||||||
};
|
};
|
||||||
use crate::llvm::refcounting::{
|
use crate::llvm::refcounting::{
|
||||||
decrement_refcount_layout, increment_refcount_layout, PointerToRefcount,
|
decrement_refcount_layout, increment_refcount_layout, PointerToRefcount,
|
||||||
|
@ -118,7 +118,7 @@ impl<'ctx> Iterator for FunctionIterator<'ctx> {
|
||||||
#[derive(Default, Debug, Clone, PartialEq)]
|
#[derive(Default, Debug, Clone, PartialEq)]
|
||||||
pub struct Scope<'a, 'ctx> {
|
pub struct Scope<'a, 'ctx> {
|
||||||
symbols: ImMap<Symbol, (Layout<'a>, BasicValueEnum<'ctx>)>,
|
symbols: ImMap<Symbol, (Layout<'a>, BasicValueEnum<'ctx>)>,
|
||||||
pub top_level_thunks: ImMap<Symbol, (Layout<'a>, FunctionValue<'ctx>)>,
|
pub top_level_thunks: ImMap<Symbol, (TopLevelFunctionLayout<'a>, FunctionValue<'ctx>)>,
|
||||||
join_points: ImMap<JoinPointId, (BasicBlock<'ctx>, &'a [PointerValue<'ctx>])>,
|
join_points: ImMap<JoinPointId, (BasicBlock<'ctx>, &'a [PointerValue<'ctx>])>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ impl<'a, 'ctx> Scope<'a, 'ctx> {
|
||||||
function_value: FunctionValue<'ctx>,
|
function_value: FunctionValue<'ctx>,
|
||||||
) {
|
) {
|
||||||
self.top_level_thunks
|
self.top_level_thunks
|
||||||
.insert(symbol, (layout.full(), function_value));
|
.insert(symbol, (*layout, function_value));
|
||||||
}
|
}
|
||||||
fn remove(&mut self, symbol: &Symbol) {
|
fn remove(&mut self, symbol: &Symbol) {
|
||||||
self.symbols.remove(symbol);
|
self.symbols.remove(symbol);
|
||||||
|
@ -602,7 +602,9 @@ fn promote_to_main_function<'a, 'ctx, 'env>(
|
||||||
"we expect only one specialization of this symbol"
|
"we expect only one specialization of this symbol"
|
||||||
);
|
);
|
||||||
|
|
||||||
let roc_main_fn = function_value_by_func_spec(env, *func_spec, symbol, Layout::Struct(&[]));
|
// NOTE fake layout; it is only used for debug prints
|
||||||
|
let roc_main_fn =
|
||||||
|
function_value_by_func_spec(env, *func_spec, symbol, &[], &Layout::Struct(&[]));
|
||||||
|
|
||||||
let main_fn_name = "$Test.main";
|
let main_fn_name = "$Test.main";
|
||||||
|
|
||||||
|
@ -800,8 +802,9 @@ pub fn build_exp_call<'a, 'ctx, 'env>(
|
||||||
match call_type {
|
match call_type {
|
||||||
CallType::ByName {
|
CallType::ByName {
|
||||||
name,
|
name,
|
||||||
full_layout,
|
|
||||||
specialization_id,
|
specialization_id,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let mut arg_tuples: Vec<BasicValueEnum> =
|
let mut arg_tuples: Vec<BasicValueEnum> =
|
||||||
|
@ -817,7 +820,8 @@ pub fn build_exp_call<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
roc_call_with_args(
|
roc_call_with_args(
|
||||||
env,
|
env,
|
||||||
&full_layout,
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
*name,
|
*name,
|
||||||
func_spec,
|
func_spec,
|
||||||
arg_tuples.into_bump_slice(),
|
arg_tuples.into_bump_slice(),
|
||||||
|
@ -839,7 +843,6 @@ pub fn build_exp_call<'a, 'ctx, 'env>(
|
||||||
let bytes = specialization_id.to_bytes();
|
let bytes = specialization_id.to_bytes();
|
||||||
let callee_var = CalleeSpecVar(&bytes);
|
let callee_var = CalleeSpecVar(&bytes);
|
||||||
let func_spec = func_spec_solutions.callee_spec(callee_var).unwrap();
|
let func_spec = func_spec_solutions.callee_spec(callee_var).unwrap();
|
||||||
// let fn_val = function_value_by_func_spec(env, func_spec, symbol, *layout);
|
|
||||||
|
|
||||||
run_higher_order_low_level(
|
run_higher_order_low_level(
|
||||||
env,
|
env,
|
||||||
|
@ -2051,7 +2054,8 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
} => match call.call_type {
|
} => match call.call_type {
|
||||||
CallType::ByName {
|
CallType::ByName {
|
||||||
name,
|
name,
|
||||||
ref full_layout,
|
arg_layouts,
|
||||||
|
ref ret_layout,
|
||||||
specialization_id,
|
specialization_id,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
|
@ -2060,7 +2064,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
let func_spec = func_spec_solutions.callee_spec(callee_var).unwrap();
|
let func_spec = func_spec_solutions.callee_spec(callee_var).unwrap();
|
||||||
|
|
||||||
let function_value =
|
let function_value =
|
||||||
function_value_by_func_spec(env, func_spec, name, *full_layout);
|
function_value_by_func_spec(env, func_spec, name, arg_layouts, ret_layout);
|
||||||
|
|
||||||
invoke_roc_function(
|
invoke_roc_function(
|
||||||
env,
|
env,
|
||||||
|
@ -3392,8 +3396,8 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
|
||||||
);
|
);
|
||||||
|
|
||||||
// STEP 4: build a {} -> u64 function that gives the size of the closure
|
// STEP 4: build a {} -> u64 function that gives the size of the closure
|
||||||
let layout = Layout::Closure(arguments, lambda_set, result);
|
let layout = lambda_set.runtime_representation();
|
||||||
build_host_exposed_alias_size(env, def_name, alias_symbol, &layout);
|
build_host_exposed_alias_size(env, def_name, alias_symbol, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_function_caller<'a, 'ctx, 'env>(
|
fn build_function_caller<'a, 'ctx, 'env>(
|
||||||
|
@ -3431,10 +3435,8 @@ fn build_function_caller<'a, 'ctx, 'env>(
|
||||||
// pretend the closure layout is empty
|
// pretend the closure layout is empty
|
||||||
args.push(Layout::Struct(&[]));
|
args.push(Layout::Struct(&[]));
|
||||||
|
|
||||||
let function_layout = Layout::FunctionPointer(&args, result);
|
|
||||||
|
|
||||||
// this is already a (function) pointer type
|
// this is already a (function) pointer type
|
||||||
basic_type_from_layout(env, &function_layout)
|
basic_type_from_function_layout(env, &args, result)
|
||||||
};
|
};
|
||||||
argument_types.push(function_pointer_type);
|
argument_types.push(function_pointer_type);
|
||||||
|
|
||||||
|
@ -3474,10 +3476,7 @@ fn build_function_caller<'a, 'ctx, 'env>(
|
||||||
let _closure_data_ptr = parameters.pop().unwrap().into_pointer_value();
|
let _closure_data_ptr = parameters.pop().unwrap().into_pointer_value();
|
||||||
let function_ptr = parameters.pop().unwrap().into_pointer_value();
|
let function_ptr = parameters.pop().unwrap().into_pointer_value();
|
||||||
|
|
||||||
// let closure_data = context.struct_type(&[], false).const_zero().into();
|
let actual_function_type = basic_type_from_function_layout(env, arguments, result);
|
||||||
|
|
||||||
let actual_function_type =
|
|
||||||
basic_type_from_layout(env, &Layout::FunctionPointer(arguments, result));
|
|
||||||
|
|
||||||
let function_ptr = builder
|
let function_ptr = builder
|
||||||
.build_bitcast(function_ptr, actual_function_type, "cast")
|
.build_bitcast(function_ptr, actual_function_type, "cast")
|
||||||
|
@ -3513,22 +3512,22 @@ fn build_function_caller<'a, 'ctx, 'env>(
|
||||||
);
|
);
|
||||||
|
|
||||||
// STEP 4: build a {} -> u64 function that gives the size of the function
|
// STEP 4: build a {} -> u64 function that gives the size of the function
|
||||||
let layout = Layout::FunctionPointer(arguments, result);
|
let layout = Layout::Struct(&[]);
|
||||||
build_host_exposed_alias_size(env, def_name, alias_symbol, &layout);
|
build_host_exposed_alias_size(env, def_name, alias_symbol, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_host_exposed_alias_size<'a, 'ctx, 'env>(
|
fn build_host_exposed_alias_size<'a, 'ctx, 'env>(
|
||||||
env: &'a Env<'a, 'ctx, 'env>,
|
env: &'a Env<'a, 'ctx, 'env>,
|
||||||
def_name: &str,
|
def_name: &str,
|
||||||
alias_symbol: Symbol,
|
alias_symbol: Symbol,
|
||||||
layout: &Layout<'a>,
|
layout: Layout<'a>,
|
||||||
) {
|
) {
|
||||||
build_host_exposed_alias_size_help(
|
build_host_exposed_alias_size_help(
|
||||||
env,
|
env,
|
||||||
def_name,
|
def_name,
|
||||||
alias_symbol,
|
alias_symbol,
|
||||||
None,
|
None,
|
||||||
basic_type_from_layout(env, layout),
|
basic_type_from_layout(env, &layout),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3597,8 +3596,6 @@ pub fn build_proc<'a, 'ctx, 'env>(
|
||||||
// * roc__mainForHost_1_Update_size() -> i64
|
// * roc__mainForHost_1_Update_size() -> i64
|
||||||
// * roc__mainForHost_1_Update_result_size() -> i64
|
// * roc__mainForHost_1_Update_result_size() -> i64
|
||||||
|
|
||||||
let evaluator_layout = env.arena.alloc(top_level).full();
|
|
||||||
|
|
||||||
let it = top_level.arguments.iter().copied();
|
let it = top_level.arguments.iter().copied();
|
||||||
let bytes = roc_mono::alias_analysis::func_name_bytes_help(
|
let bytes = roc_mono::alias_analysis::func_name_bytes_help(
|
||||||
symbol,
|
symbol,
|
||||||
|
@ -3615,8 +3612,13 @@ pub fn build_proc<'a, 'ctx, 'env>(
|
||||||
"we expect only one specialization of this symbol"
|
"we expect only one specialization of this symbol"
|
||||||
);
|
);
|
||||||
|
|
||||||
let evaluator =
|
let evaluator = function_value_by_func_spec(
|
||||||
function_value_by_func_spec(env, *func_spec, symbol, evaluator_layout);
|
env,
|
||||||
|
*func_spec,
|
||||||
|
symbol,
|
||||||
|
top_level.arguments,
|
||||||
|
&top_level.result,
|
||||||
|
);
|
||||||
|
|
||||||
let ident_string = proc.name.ident_string(&env.interns);
|
let ident_string = proc.name.ident_string(&env.interns);
|
||||||
let fn_name: String = format!("{}_1", ident_string);
|
let fn_name: String = format!("{}_1", ident_string);
|
||||||
|
@ -3690,17 +3692,19 @@ fn function_value_by_func_spec<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
func_spec: FuncSpec,
|
func_spec: FuncSpec,
|
||||||
symbol: Symbol,
|
symbol: Symbol,
|
||||||
layout: Layout<'a>,
|
arguments: &[Layout<'a>],
|
||||||
|
result: &Layout<'a>,
|
||||||
) -> FunctionValue<'ctx> {
|
) -> FunctionValue<'ctx> {
|
||||||
let fn_name = func_spec_name(env.arena, &env.interns, symbol, func_spec);
|
let fn_name = func_spec_name(env.arena, &env.interns, symbol, func_spec);
|
||||||
let fn_name = fn_name.as_str();
|
let fn_name = fn_name.as_str();
|
||||||
|
|
||||||
function_value_by_name_help(env, layout, symbol, fn_name)
|
function_value_by_name_help(env, arguments, result, symbol, fn_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn function_value_by_name_help<'a, 'ctx, 'env>(
|
fn function_value_by_name_help<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
layout: Layout<'a>,
|
arguments: &[Layout<'a>],
|
||||||
|
result: &Layout<'a>,
|
||||||
symbol: Symbol,
|
symbol: Symbol,
|
||||||
fn_name: &str,
|
fn_name: &str,
|
||||||
) -> FunctionValue<'ctx> {
|
) -> FunctionValue<'ctx> {
|
||||||
|
@ -3708,7 +3712,8 @@ fn function_value_by_name_help<'a, 'ctx, 'env>(
|
||||||
if symbol.is_builtin() {
|
if symbol.is_builtin() {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"Unrecognized builtin function: {:?}\nLayout: {:?}\n",
|
"Unrecognized builtin function: {:?}\nLayout: {:?}\n",
|
||||||
fn_name, layout
|
fn_name,
|
||||||
|
(arguments, result)
|
||||||
);
|
);
|
||||||
eprintln!("Is the function defined? If so, maybe there is a problem with the layout");
|
eprintln!("Is the function defined? If so, maybe there is a problem with the layout");
|
||||||
|
|
||||||
|
@ -3720,7 +3725,9 @@ fn function_value_by_name_help<'a, 'ctx, 'env>(
|
||||||
// Unrecognized non-builtin function:
|
// Unrecognized non-builtin function:
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"Unrecognized non-builtin function: {:?}\n\nSymbol: {:?}\nLayout: {:?}\n",
|
"Unrecognized non-builtin function: {:?}\n\nSymbol: {:?}\nLayout: {:?}\n",
|
||||||
fn_name, symbol, layout
|
fn_name,
|
||||||
|
symbol,
|
||||||
|
(arguments, result)
|
||||||
);
|
);
|
||||||
eprintln!("Is the function defined? If so, maybe there is a problem with the layout");
|
eprintln!("Is the function defined? If so, maybe there is a problem with the layout");
|
||||||
|
|
||||||
|
@ -3736,12 +3743,14 @@ fn function_value_by_name_help<'a, 'ctx, 'env>(
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn roc_call_with_args<'a, 'ctx, 'env>(
|
fn roc_call_with_args<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
layout: &Layout<'a>,
|
argument_layouts: &[Layout<'a>],
|
||||||
|
result_layout: &Layout<'a>,
|
||||||
symbol: Symbol,
|
symbol: Symbol,
|
||||||
func_spec: FuncSpec,
|
func_spec: FuncSpec,
|
||||||
args: &[BasicValueEnum<'ctx>],
|
args: &[BasicValueEnum<'ctx>],
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
let fn_val = function_value_by_func_spec(env, func_spec, symbol, *layout);
|
let fn_val =
|
||||||
|
function_value_by_func_spec(env, func_spec, symbol, argument_layouts, result_layout);
|
||||||
|
|
||||||
let call = env.builder.build_call(fn_val, args, "call");
|
let call = env.builder.build_call(fn_val, args, "call");
|
||||||
|
|
||||||
|
@ -3837,9 +3846,14 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
||||||
macro_rules! passed_function_at_index {
|
macro_rules! passed_function_at_index {
|
||||||
($index:expr) => {{
|
($index:expr) => {{
|
||||||
let function_symbol = args[$index];
|
let function_symbol = args[$index];
|
||||||
let function_layout = Layout::FunctionPointer(argument_layouts, return_layout);
|
|
||||||
|
|
||||||
function_value_by_func_spec(env, func_spec, function_symbol, function_layout)
|
function_value_by_func_spec(
|
||||||
|
env,
|
||||||
|
func_spec,
|
||||||
|
function_symbol,
|
||||||
|
argument_layouts,
|
||||||
|
return_layout,
|
||||||
|
)
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,9 @@ use inkwell::types::{BasicType, BasicTypeEnum, IntType, StructType};
|
||||||
use inkwell::AddressSpace;
|
use inkwell::AddressSpace;
|
||||||
use roc_mono::layout::{Builtin, Layout, UnionLayout};
|
use roc_mono::layout::{Builtin, Layout, UnionLayout};
|
||||||
|
|
||||||
fn basic_type_from_function_layout<'a, 'ctx, 'env>(
|
pub fn basic_type_from_function_layout<'a, 'ctx, 'env>(
|
||||||
env: &crate::llvm::build::Env<'a, 'ctx, 'env>,
|
env: &crate::llvm::build::Env<'a, 'ctx, 'env>,
|
||||||
args: &[Layout<'_>],
|
args: &[Layout<'_>],
|
||||||
closure_type: Option<BasicTypeEnum<'ctx>>,
|
|
||||||
ret_layout: &Layout<'_>,
|
ret_layout: &Layout<'_>,
|
||||||
) -> BasicTypeEnum<'ctx> {
|
) -> BasicTypeEnum<'ctx> {
|
||||||
let ret_type = basic_type_from_layout(env, &ret_layout);
|
let ret_type = basic_type_from_layout(env, &ret_layout);
|
||||||
|
@ -17,10 +16,6 @@ fn basic_type_from_function_layout<'a, 'ctx, 'env>(
|
||||||
arg_basic_types.push(basic_type_from_layout(env, arg_layout));
|
arg_basic_types.push(basic_type_from_layout(env, arg_layout));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(closure) = closure_type {
|
|
||||||
arg_basic_types.push(closure);
|
|
||||||
}
|
|
||||||
|
|
||||||
let fn_type = ret_type.fn_type(arg_basic_types.into_bump_slice(), false);
|
let fn_type = ret_type.fn_type(arg_basic_types.into_bump_slice(), false);
|
||||||
let ptr_type = fn_type.ptr_type(AddressSpace::Generic);
|
let ptr_type = fn_type.ptr_type(AddressSpace::Generic);
|
||||||
|
|
||||||
|
@ -49,9 +44,7 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
|
||||||
use Layout::*;
|
use Layout::*;
|
||||||
|
|
||||||
match layout {
|
match layout {
|
||||||
FunctionPointer(args, ret_layout) => {
|
FunctionPointer(args, ret_layout) => basic_type_from_function_layout(env, args, ret_layout),
|
||||||
basic_type_from_function_layout(env, args, None, ret_layout)
|
|
||||||
}
|
|
||||||
Closure(_args, closure_layout, _ret_layout) => {
|
Closure(_args, closure_layout, _ret_layout) => {
|
||||||
let closure_data_layout = closure_layout.runtime_representation();
|
let closure_data_layout = closure_layout.runtime_representation();
|
||||||
basic_type_from_layout(env, &closure_data_layout)
|
basic_type_from_layout(env, &closure_data_layout)
|
||||||
|
|
|
@ -445,7 +445,6 @@ fn call_spec(
|
||||||
match &call.call_type {
|
match &call.call_type {
|
||||||
ByName {
|
ByName {
|
||||||
name: symbol,
|
name: symbol,
|
||||||
full_layout: _,
|
|
||||||
ret_layout,
|
ret_layout,
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
specialization_id,
|
specialization_id,
|
||||||
|
|
|
@ -24,9 +24,8 @@ pub fn infer_borrow<'a>(
|
||||||
items: MutMap::default(),
|
items: MutMap::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
for ((s, top_level), proc) in procs {
|
for (key, proc) in procs {
|
||||||
let key = (*s, arena.alloc(*top_level).full());
|
param_map.visit_proc(arena, proc, *key);
|
||||||
param_map.visit_proc(arena, proc, key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut env = BorrowInfState {
|
let mut env = BorrowInfState {
|
||||||
|
@ -51,8 +50,7 @@ pub fn infer_borrow<'a>(
|
||||||
// mutually recursive functions (or just make all their arguments owned)
|
// mutually recursive functions (or just make all their arguments owned)
|
||||||
|
|
||||||
for (key, proc) in procs {
|
for (key, proc) in procs {
|
||||||
let layout = arena.alloc(key.1).full();
|
env.collect_proc(proc, key.1);
|
||||||
env.collect_proc(proc, layout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !env.modified {
|
if !env.modified {
|
||||||
|
@ -69,7 +67,7 @@ pub fn infer_borrow<'a>(
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
||||||
pub enum Key<'a> {
|
pub enum Key<'a> {
|
||||||
Declaration(Symbol, Layout<'a>),
|
Declaration(Symbol, TopLevelFunctionLayout<'a>),
|
||||||
JoinPoint(JoinPointId),
|
JoinPoint(JoinPointId),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +96,11 @@ impl<'a> IntoIterator for &'a ParamMap<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ParamMap<'a> {
|
impl<'a> ParamMap<'a> {
|
||||||
pub fn get_symbol(&self, symbol: Symbol, layout: Layout<'a>) -> Option<&'a [Param<'a>]> {
|
pub fn get_symbol(
|
||||||
|
&self,
|
||||||
|
symbol: Symbol,
|
||||||
|
layout: TopLevelFunctionLayout<'a>,
|
||||||
|
) -> Option<&'a [Param<'a>]> {
|
||||||
let key = Key::Declaration(symbol, layout);
|
let key = Key::Declaration(symbol, layout);
|
||||||
|
|
||||||
self.items.get(&key).copied()
|
self.items.get(&key).copied()
|
||||||
|
@ -153,7 +155,12 @@ impl<'a> ParamMap<'a> {
|
||||||
.into_bump_slice()
|
.into_bump_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_proc(&mut self, arena: &'a Bump, proc: &Proc<'a>, key: (Symbol, Layout<'a>)) {
|
fn visit_proc(
|
||||||
|
&mut self,
|
||||||
|
arena: &'a Bump,
|
||||||
|
proc: &Proc<'a>,
|
||||||
|
key: (Symbol, TopLevelFunctionLayout<'a>),
|
||||||
|
) {
|
||||||
if proc.must_own_arguments {
|
if proc.must_own_arguments {
|
||||||
self.visit_proc_always_owned(arena, proc, key);
|
self.visit_proc_always_owned(arena, proc, key);
|
||||||
return;
|
return;
|
||||||
|
@ -171,7 +178,7 @@ impl<'a> ParamMap<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
proc: &Proc<'a>,
|
proc: &Proc<'a>,
|
||||||
key: (Symbol, Layout<'a>),
|
key: (Symbol, TopLevelFunctionLayout<'a>),
|
||||||
) {
|
) {
|
||||||
let already_in_there = self.items.insert(
|
let already_in_there = self.items.insert(
|
||||||
Key::Declaration(proc.name, key.1),
|
Key::Declaration(proc.name, key.1),
|
||||||
|
@ -359,12 +366,17 @@ impl<'a> BorrowInfState<'a> {
|
||||||
|
|
||||||
match call_type {
|
match call_type {
|
||||||
ByName {
|
ByName {
|
||||||
name, full_layout, ..
|
name,
|
||||||
|
ret_layout,
|
||||||
|
arg_layouts,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let top_level = TopLevelFunctionLayout::new(self.arena, arg_layouts, *ret_layout);
|
||||||
|
|
||||||
// get the borrow signature of the applied function
|
// get the borrow signature of the applied function
|
||||||
let ps = self
|
let ps = self
|
||||||
.param_map
|
.param_map
|
||||||
.get_symbol(*name, *full_layout)
|
.get_symbol(*name, top_level)
|
||||||
.expect("function is defined");
|
.expect("function is defined");
|
||||||
|
|
||||||
// the return value will be owned
|
// the return value will be owned
|
||||||
|
@ -402,7 +414,10 @@ impl<'a> BorrowInfState<'a> {
|
||||||
|
|
||||||
debug_assert!(op.is_higher_order());
|
debug_assert!(op.is_higher_order());
|
||||||
|
|
||||||
let closure_layout = Layout::FunctionPointer(arg_layouts, ret_layout);
|
let closure_layout = TopLevelFunctionLayout {
|
||||||
|
arguments: arg_layouts,
|
||||||
|
result: *ret_layout,
|
||||||
|
};
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
ListMap | ListKeepIf | ListKeepOks | ListKeepErrs => {
|
ListMap | ListKeepIf | ListKeepOks | ListKeepErrs => {
|
||||||
|
@ -584,7 +599,8 @@ impl<'a> BorrowInfState<'a> {
|
||||||
call_type:
|
call_type:
|
||||||
crate::ir::CallType::ByName {
|
crate::ir::CallType::ByName {
|
||||||
name: g,
|
name: g,
|
||||||
full_layout,
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
arguments: ys,
|
arguments: ys,
|
||||||
|
@ -593,10 +609,12 @@ impl<'a> BorrowInfState<'a> {
|
||||||
Stmt::Ret(z),
|
Stmt::Ret(z),
|
||||||
) = (v, b)
|
) = (v, b)
|
||||||
{
|
{
|
||||||
|
let top_level = TopLevelFunctionLayout::new(self.arena, arg_layouts, *ret_layout);
|
||||||
|
|
||||||
if self.current_proc == *g && x == *z {
|
if self.current_proc == *g && x == *z {
|
||||||
// anonymous functions (for which the ps may not be known)
|
// anonymous functions (for which the ps may not be known)
|
||||||
// can never be tail-recursive, so this is fine
|
// can never be tail-recursive, so this is fine
|
||||||
if let Some(ps) = self.param_map.get_symbol(*g, *full_layout) {
|
if let Some(ps) = self.param_map.get_symbol(*g, top_level) {
|
||||||
self.own_params_using_args(ys, ps)
|
self.own_params_using_args(ys, ps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -684,7 +702,7 @@ impl<'a> BorrowInfState<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_proc(&mut self, proc: &Proc<'a>, layout: Layout<'a>) {
|
fn collect_proc(&mut self, proc: &Proc<'a>, layout: TopLevelFunctionLayout<'a>) {
|
||||||
let old = self.param_set.clone();
|
let old = self.param_set.clone();
|
||||||
|
|
||||||
let ys = Vec::from_iter_in(proc.args.iter().map(|t| t.1), self.arena).into_bump_slice();
|
let ys = Vec::from_iter_in(proc.args.iter().map(|t| t.1), self.arena).into_bump_slice();
|
||||||
|
|
|
@ -245,9 +245,6 @@ fn layout_for_constructor<'a>(
|
||||||
HasFields(fields)
|
HasFields(fields)
|
||||||
}
|
}
|
||||||
Closure(_arguments, _lambda_set, _result) => {
|
Closure(_arguments, _lambda_set, _result) => {
|
||||||
// TODO can this be improved again?
|
|
||||||
// let fpointer = Layout::FunctionPointer(arguments, result);
|
|
||||||
// let fields = arena.alloc([fpointer, *lambda_set.layout]);
|
|
||||||
// HasFields(fields)
|
// HasFields(fields)
|
||||||
ConstructorLayout::Unknown
|
ConstructorLayout::Unknown
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::borrow::{ParamMap, BORROWED, OWNED};
|
use crate::borrow::{ParamMap, BORROWED, OWNED};
|
||||||
use crate::ir::{Expr, JoinPointId, ModifyRc, Param, Proc, Stmt};
|
use crate::ir::{Expr, JoinPointId, ModifyRc, Param, Proc, Stmt, TopLevelFunctionLayout};
|
||||||
use crate::layout::Layout;
|
use crate::layout::Layout;
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
@ -497,7 +497,10 @@ impl<'a> Context<'a> {
|
||||||
const FUNCTION: bool = BORROWED;
|
const FUNCTION: bool = BORROWED;
|
||||||
const CLOSURE_DATA: bool = BORROWED;
|
const CLOSURE_DATA: bool = BORROWED;
|
||||||
|
|
||||||
let function_layout = Layout::FunctionPointer(arg_layouts, ret_layout);
|
let function_layout = TopLevelFunctionLayout {
|
||||||
|
arguments: arg_layouts,
|
||||||
|
result: *ret_layout,
|
||||||
|
};
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
roc_module::low_level::LowLevel::ListMap
|
roc_module::low_level::LowLevel::ListMap
|
||||||
|
@ -679,12 +682,17 @@ impl<'a> Context<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ByName {
|
ByName {
|
||||||
name, full_layout, ..
|
name,
|
||||||
|
ret_layout,
|
||||||
|
arg_layouts,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let top_level = TopLevelFunctionLayout::new(self.arena, arg_layouts, *ret_layout);
|
||||||
|
|
||||||
// get the borrow signature
|
// get the borrow signature
|
||||||
let ps = self
|
let ps = self
|
||||||
.param_map
|
.param_map
|
||||||
.get_symbol(*name, *full_layout)
|
.get_symbol(*name, top_level)
|
||||||
.expect("function is defined");
|
.expect("function is defined");
|
||||||
|
|
||||||
let v = Expr::Call(crate::ir::Call {
|
let v = Expr::Call(crate::ir::Call {
|
||||||
|
@ -963,12 +971,18 @@ impl<'a> Context<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
CallType::ByName {
|
CallType::ByName {
|
||||||
name, full_layout, ..
|
name,
|
||||||
|
ret_layout,
|
||||||
|
arg_layouts,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let top_level =
|
||||||
|
TopLevelFunctionLayout::new(self.arena, arg_layouts, *ret_layout);
|
||||||
|
|
||||||
// get the borrow signature
|
// get the borrow signature
|
||||||
let ps = self
|
let ps = self
|
||||||
.param_map
|
.param_map
|
||||||
.get_symbol(*name, *full_layout)
|
.get_symbol(*name, top_level)
|
||||||
.expect("function is defined");
|
.expect("function is defined");
|
||||||
self.add_dec_after_application(call.arguments, ps, cont, &invoke_live_vars)
|
self.add_dec_after_application(call.arguments, ps, cont, &invoke_live_vars)
|
||||||
}
|
}
|
||||||
|
@ -1222,7 +1236,7 @@ pub fn visit_proc<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
param_map: &'a ParamMap<'a>,
|
param_map: &'a ParamMap<'a>,
|
||||||
proc: &mut Proc<'a>,
|
proc: &mut Proc<'a>,
|
||||||
layout: Layout<'a>,
|
layout: TopLevelFunctionLayout<'a>,
|
||||||
) {
|
) {
|
||||||
let ctx = Context::new(arena, param_map);
|
let ctx = Context::new(arena, param_map);
|
||||||
|
|
||||||
|
|
|
@ -215,7 +215,7 @@ impl<'a> Proc<'a> {
|
||||||
let borrow_params = arena.alloc(crate::borrow::infer_borrow(arena, procs));
|
let borrow_params = arena.alloc(crate::borrow::infer_borrow(arena, procs));
|
||||||
|
|
||||||
for (key, proc) in procs.iter_mut() {
|
for (key, proc) in procs.iter_mut() {
|
||||||
crate::inc_dec::visit_proc(arena, borrow_params, proc, arena.alloc(key.1).full());
|
crate::inc_dec::visit_proc(arena, borrow_params, proc, key.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,8 +410,7 @@ impl<'a> Procs<'a> {
|
||||||
let borrow_params = arena.alloc(crate::borrow::infer_borrow(arena, &result));
|
let borrow_params = arena.alloc(crate::borrow::infer_borrow(arena, &result));
|
||||||
|
|
||||||
for (key, proc) in result.iter_mut() {
|
for (key, proc) in result.iter_mut() {
|
||||||
let layout = arena.alloc(key.1).full();
|
crate::inc_dec::visit_proc(arena, borrow_params, proc, key.1);
|
||||||
crate::inc_dec::visit_proc(arena, borrow_params, proc, layout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
|
@ -454,8 +453,7 @@ impl<'a> Procs<'a> {
|
||||||
let borrow_params = arena.alloc(crate::borrow::infer_borrow(arena, &result));
|
let borrow_params = arena.alloc(crate::borrow::infer_borrow(arena, &result));
|
||||||
|
|
||||||
for (key, proc) in result.iter_mut() {
|
for (key, proc) in result.iter_mut() {
|
||||||
let layout = arena.alloc(key.1).full();
|
crate::inc_dec::visit_proc(arena, borrow_params, proc, key.1);
|
||||||
crate::inc_dec::visit_proc(arena, borrow_params, proc, layout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(result, borrow_params)
|
(result, borrow_params)
|
||||||
|
@ -1138,7 +1136,6 @@ impl UpdateModeId {
|
||||||
pub enum CallType<'a> {
|
pub enum CallType<'a> {
|
||||||
ByName {
|
ByName {
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
full_layout: Layout<'a>,
|
|
||||||
ret_layout: Layout<'a>,
|
ret_layout: Layout<'a>,
|
||||||
arg_layouts: &'a [Layout<'a>],
|
arg_layouts: &'a [Layout<'a>],
|
||||||
specialization_id: CallSpecId,
|
specialization_id: CallSpecId,
|
||||||
|
@ -2627,10 +2624,6 @@ impl<'a> TopLevelFunctionLayout<'a> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn full(&'a self) -> Layout<'a> {
|
|
||||||
Layout::FunctionPointer(self.arguments, &self.result)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn specialize_naked_symbol<'a>(
|
fn specialize_naked_symbol<'a>(
|
||||||
|
@ -3701,7 +3694,7 @@ pub fn with_hole<'a>(
|
||||||
} => {
|
} => {
|
||||||
let loc_body = *boxed_body;
|
let loc_body = *boxed_body;
|
||||||
|
|
||||||
match layout_cache.from_var(env.arena, function_type, env.subs) {
|
match layout_cache.raw_from_var(env.arena, function_type, env.subs) {
|
||||||
Err(e) => panic!("invalid layout {:?}", e),
|
Err(e) => panic!("invalid layout {:?}", e),
|
||||||
Ok(Layout::Closure(_argument_layouts, lambda_set, _ret_layout)) => {
|
Ok(Layout::Closure(_argument_layouts, lambda_set, _ret_layout)) => {
|
||||||
let mut captured_symbols = Vec::from_iter_in(captured_symbols, env.arena);
|
let mut captured_symbols = Vec::from_iter_in(captured_symbols, env.arena);
|
||||||
|
@ -3738,43 +3731,6 @@ pub fn with_hole<'a>(
|
||||||
|
|
||||||
construct_closure_data(env, lambda_set, name, symbols, assigned, hole)
|
construct_closure_data(env, lambda_set, name, symbols, assigned, hole)
|
||||||
}
|
}
|
||||||
Ok(Layout::FunctionPointer(_, _)) => {
|
|
||||||
// CLEANUP
|
|
||||||
unreachable!("closures should never have a function pointer layout");
|
|
||||||
|
|
||||||
// match procs.insert_anonymous(
|
|
||||||
// env,
|
|
||||||
// name,
|
|
||||||
// function_type,
|
|
||||||
// arguments,
|
|
||||||
// loc_body,
|
|
||||||
// CapturedSymbols::None,
|
|
||||||
// return_type,
|
|
||||||
// layout_cache,
|
|
||||||
// ) {
|
|
||||||
// Ok(layout) => {
|
|
||||||
// bg!(name);
|
|
||||||
// // TODO should the let have layout Pointer?
|
|
||||||
// // Stmt::Let(assigned, Expr::Struct(&[]), Layout::Struct(&[]), hole)
|
|
||||||
// if false {
|
|
||||||
// let mut hole = hole.clone();
|
|
||||||
// substitute_in_exprs(env.arena, &mut hole, assigned, name);
|
|
||||||
// hole
|
|
||||||
// } else {
|
|
||||||
// Stmt::Let(
|
|
||||||
// assigned,
|
|
||||||
// call_by_pointer(env, procs, name, layout),
|
|
||||||
// layout,
|
|
||||||
// hole,
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Err(_error) => Stmt::RuntimeError(
|
|
||||||
// "TODO convert anonymous function error to a RuntimeError string",
|
|
||||||
// ),
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
Ok(_) => unreachable!(),
|
Ok(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3833,11 +3789,10 @@ pub fn with_hole<'a>(
|
||||||
|
|
||||||
let full_layout = return_on_layout_error!(
|
let full_layout = return_on_layout_error!(
|
||||||
env,
|
env,
|
||||||
layout_cache.from_var(env.arena, fn_var, env.subs)
|
layout_cache.raw_from_var(env.arena, fn_var, env.subs)
|
||||||
);
|
);
|
||||||
|
|
||||||
let arg_layouts = match full_layout {
|
let arg_layouts = match full_layout {
|
||||||
Layout::FunctionPointer(args, _) => args,
|
|
||||||
Layout::Closure(args, _, _) => args,
|
Layout::Closure(args, _, _) => args,
|
||||||
_ => unreachable!("function has layout that is not function pointer"),
|
_ => unreachable!("function has layout that is not function pointer"),
|
||||||
};
|
};
|
||||||
|
@ -3905,38 +3860,6 @@ pub fn with_hole<'a>(
|
||||||
env.arena.alloc(result),
|
env.arena.alloc(result),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Layout::FunctionPointer(_, _) => {
|
|
||||||
// CLEANUP
|
|
||||||
unreachable!("should not be a function pointer");
|
|
||||||
|
|
||||||
// let function_symbol = env.unique_symbol();
|
|
||||||
// let closure_data_symbol = function_symbol;
|
|
||||||
//
|
|
||||||
// // layout of the closure record
|
|
||||||
// let closure_data_layout = Layout::Struct(&[]);
|
|
||||||
//
|
|
||||||
// result = lambda_set_to_switch_make_branch_help(
|
|
||||||
// env,
|
|
||||||
// function_symbol,
|
|
||||||
// closure_data_symbol,
|
|
||||||
// closure_data_layout,
|
|
||||||
// arg_symbols,
|
|
||||||
// arg_layouts,
|
|
||||||
// ret_layout,
|
|
||||||
// assigned,
|
|
||||||
// hole,
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// result = with_hole(
|
|
||||||
// env,
|
|
||||||
// loc_expr.value,
|
|
||||||
// fn_var,
|
|
||||||
// procs,
|
|
||||||
// layout_cache,
|
|
||||||
// closure_data_symbol,
|
|
||||||
// env.arena.alloc(result),
|
|
||||||
// );
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
todo!("{:?}", full_layout)
|
todo!("{:?}", full_layout)
|
||||||
}
|
}
|
||||||
|
@ -5461,13 +5384,11 @@ fn substitute_in_call<'a>(
|
||||||
name,
|
name,
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
ret_layout,
|
ret_layout,
|
||||||
full_layout,
|
|
||||||
specialization_id,
|
specialization_id,
|
||||||
} => substitute(subs, *name).map(|new| CallType::ByName {
|
} => substitute(subs, *name).map(|new| CallType::ByName {
|
||||||
name: new,
|
name: new,
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
ret_layout: *ret_layout,
|
ret_layout: *ret_layout,
|
||||||
full_layout: *full_layout,
|
|
||||||
specialization_id: *specialization_id,
|
specialization_id: *specialization_id,
|
||||||
}),
|
}),
|
||||||
CallType::Foreign { .. } => None,
|
CallType::Foreign { .. } => None,
|
||||||
|
@ -5930,13 +5851,10 @@ fn force_thunk<'a>(
|
||||||
assigned: Symbol,
|
assigned: Symbol,
|
||||||
hole: &'a Stmt<'a>,
|
hole: &'a Stmt<'a>,
|
||||||
) -> Stmt<'a> {
|
) -> Stmt<'a> {
|
||||||
let full_layout = Layout::FunctionPointer(&[], env.arena.alloc(layout));
|
|
||||||
|
|
||||||
let call = self::Call {
|
let call = self::Call {
|
||||||
call_type: CallType::ByName {
|
call_type: CallType::ByName {
|
||||||
name: thunk_name,
|
name: thunk_name,
|
||||||
ret_layout: layout,
|
ret_layout: layout,
|
||||||
full_layout,
|
|
||||||
arg_layouts: &[],
|
arg_layouts: &[],
|
||||||
specialization_id: env.next_call_specialization_id(),
|
specialization_id: env.next_call_specialization_id(),
|
||||||
},
|
},
|
||||||
|
@ -6396,7 +6314,6 @@ fn call_by_name_help<'a>(
|
||||||
// debug_assert!(!procs.module_thunks.contains(&proc_name), "{:?}", proc_name);
|
// debug_assert!(!procs.module_thunks.contains(&proc_name), "{:?}", proc_name);
|
||||||
|
|
||||||
let top_level_layout = TopLevelFunctionLayout::new(env.arena, argument_layouts, *ret_layout);
|
let top_level_layout = TopLevelFunctionLayout::new(env.arena, argument_layouts, *ret_layout);
|
||||||
let function_layout = env.arena.alloc(top_level_layout).full();
|
|
||||||
|
|
||||||
// the arguments given to the function, stored in symbols
|
// the arguments given to the function, stored in symbols
|
||||||
let field_symbols = Vec::from_iter_in(
|
let field_symbols = Vec::from_iter_in(
|
||||||
|
@ -6438,7 +6355,6 @@ fn call_by_name_help<'a>(
|
||||||
call_type: CallType::ByName {
|
call_type: CallType::ByName {
|
||||||
name: proc_name,
|
name: proc_name,
|
||||||
ret_layout: *ret_layout,
|
ret_layout: *ret_layout,
|
||||||
full_layout: function_layout,
|
|
||||||
arg_layouts: argument_layouts,
|
arg_layouts: argument_layouts,
|
||||||
specialization_id: env.next_call_specialization_id(),
|
specialization_id: env.next_call_specialization_id(),
|
||||||
},
|
},
|
||||||
|
@ -6471,7 +6387,6 @@ fn call_by_name_help<'a>(
|
||||||
call_type: CallType::ByName {
|
call_type: CallType::ByName {
|
||||||
name: proc_name,
|
name: proc_name,
|
||||||
ret_layout: *ret_layout,
|
ret_layout: *ret_layout,
|
||||||
full_layout: function_layout,
|
|
||||||
arg_layouts: argument_layouts,
|
arg_layouts: argument_layouts,
|
||||||
specialization_id: env.next_call_specialization_id(),
|
specialization_id: env.next_call_specialization_id(),
|
||||||
},
|
},
|
||||||
|
@ -6524,7 +6439,6 @@ fn call_by_name_help<'a>(
|
||||||
call_type: CallType::ByName {
|
call_type: CallType::ByName {
|
||||||
name: proc_name,
|
name: proc_name,
|
||||||
ret_layout: *ret_layout,
|
ret_layout: *ret_layout,
|
||||||
full_layout: function_layout,
|
|
||||||
arg_layouts: argument_layouts,
|
arg_layouts: argument_layouts,
|
||||||
specialization_id: env.next_call_specialization_id(),
|
specialization_id: env.next_call_specialization_id(),
|
||||||
},
|
},
|
||||||
|
@ -6775,7 +6689,6 @@ fn call_specialized_proc<'a>(
|
||||||
call_type: CallType::ByName {
|
call_type: CallType::ByName {
|
||||||
name: proc_name,
|
name: proc_name,
|
||||||
ret_layout: function_layout.result,
|
ret_layout: function_layout.result,
|
||||||
full_layout: function_layout.full(),
|
|
||||||
arg_layouts: function_layout.arguments,
|
arg_layouts: function_layout.arguments,
|
||||||
specialization_id: env.next_call_specialization_id(),
|
specialization_id: env.next_call_specialization_id(),
|
||||||
},
|
},
|
||||||
|
@ -6795,14 +6708,13 @@ fn call_specialized_proc<'a>(
|
||||||
call_type: CallType::ByName {
|
call_type: CallType::ByName {
|
||||||
name: proc_name,
|
name: proc_name,
|
||||||
ret_layout: function_layout.result,
|
ret_layout: function_layout.result,
|
||||||
full_layout: function_layout.full(),
|
|
||||||
arg_layouts: function_layout.arguments,
|
arg_layouts: function_layout.arguments,
|
||||||
specialization_id: env.next_call_specialization_id(),
|
specialization_id: env.next_call_specialization_id(),
|
||||||
},
|
},
|
||||||
arguments: field_symbols,
|
arguments: field_symbols,
|
||||||
};
|
};
|
||||||
|
|
||||||
build_call(env, call, assigned, function_layout.full(), hole)
|
build_call(env, call, assigned, function_layout.result, hole)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -6819,7 +6731,6 @@ fn call_specialized_proc<'a>(
|
||||||
call_type: CallType::ByName {
|
call_type: CallType::ByName {
|
||||||
name: proc_name,
|
name: proc_name,
|
||||||
ret_layout: function_layout.result,
|
ret_layout: function_layout.result,
|
||||||
full_layout: function_layout.full(),
|
|
||||||
arg_layouts: function_layout.arguments,
|
arg_layouts: function_layout.arguments,
|
||||||
specialization_id: env.next_call_specialization_id(),
|
specialization_id: env.next_call_specialization_id(),
|
||||||
},
|
},
|
||||||
|
@ -8091,13 +8002,10 @@ fn union_lambda_set_branch_help<'a>(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let full_layout = Layout::FunctionPointer(argument_layouts, env.arena.alloc(return_layout));
|
|
||||||
|
|
||||||
// build the call
|
// build the call
|
||||||
let call = self::Call {
|
let call = self::Call {
|
||||||
call_type: CallType::ByName {
|
call_type: CallType::ByName {
|
||||||
name: function_symbol,
|
name: function_symbol,
|
||||||
full_layout,
|
|
||||||
ret_layout: return_layout,
|
ret_layout: return_layout,
|
||||||
arg_layouts: argument_layouts,
|
arg_layouts: argument_layouts,
|
||||||
specialization_id: env.next_call_specialization_id(),
|
specialization_id: env.next_call_specialization_id(),
|
||||||
|
@ -8212,12 +8120,9 @@ fn enum_lambda_set_branch<'a>(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let full_layout = Layout::FunctionPointer(argument_layouts, env.arena.alloc(return_layout));
|
|
||||||
|
|
||||||
let call = self::Call {
|
let call = self::Call {
|
||||||
call_type: CallType::ByName {
|
call_type: CallType::ByName {
|
||||||
name: function_symbol,
|
name: function_symbol,
|
||||||
full_layout,
|
|
||||||
ret_layout: return_layout,
|
ret_layout: return_layout,
|
||||||
arg_layouts: argument_layouts,
|
arg_layouts: argument_layouts,
|
||||||
specialization_id: env.next_call_specialization_id(),
|
specialization_id: env.next_call_specialization_id(),
|
||||||
|
|
|
@ -791,6 +791,50 @@ impl<'a> LayoutCache<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn raw_from_var(
|
||||||
|
&mut self,
|
||||||
|
arena: &'a Bump,
|
||||||
|
var: Variable,
|
||||||
|
subs: &Subs,
|
||||||
|
) -> Result<Layout<'a>, LayoutProblem> {
|
||||||
|
// Store things according to the root Variable, to avoid duplicate work.
|
||||||
|
let var = subs.get_root_key_without_compacting(var);
|
||||||
|
|
||||||
|
let cached_var = CachedVariable::new(var);
|
||||||
|
|
||||||
|
self.expand_to_fit(cached_var);
|
||||||
|
|
||||||
|
use CachedLayout::*;
|
||||||
|
match self.layouts.probe_value(cached_var) {
|
||||||
|
Cached(result) => Ok(result),
|
||||||
|
Problem(problem) => Err(problem),
|
||||||
|
NotCached => {
|
||||||
|
let mut env = Env {
|
||||||
|
arena,
|
||||||
|
subs,
|
||||||
|
seen: MutSet::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = Layout::from_var(&mut env, var);
|
||||||
|
|
||||||
|
// Don't actually cache. The layout cache is very hard to get right in the presence
|
||||||
|
// of specialization, it's turned of for now so an invalid cache is never the cause
|
||||||
|
// of a problem
|
||||||
|
if false {
|
||||||
|
let cached_layout = match &result {
|
||||||
|
Ok(layout) => Cached(*layout),
|
||||||
|
Err(problem) => Problem(problem.clone()),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.layouts
|
||||||
|
.update_value(cached_var, |existing| existing.value = cached_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn expand_to_fit(&mut self, var: CachedVariable<'a>) {
|
fn expand_to_fit(&mut self, var: CachedVariable<'a>) {
|
||||||
use ven_ena::unify::UnifyKey;
|
use ven_ena::unify::UnifyKey;
|
||||||
|
|
||||||
|
@ -1909,6 +1953,7 @@ impl LayoutId {
|
||||||
|
|
||||||
struct IdsByLayout<'a> {
|
struct IdsByLayout<'a> {
|
||||||
by_id: MutMap<Layout<'a>, u32>,
|
by_id: MutMap<Layout<'a>, u32>,
|
||||||
|
toplevels_by_id: MutMap<crate::ir::TopLevelFunctionLayout<'a>, u32>,
|
||||||
next_id: u32,
|
next_id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1925,6 +1970,7 @@ impl<'a> LayoutIds<'a> {
|
||||||
// There's probably a nicer way to write it that still works.
|
// There's probably a nicer way to write it that still works.
|
||||||
let ids = self.by_symbol.entry(symbol).or_insert_with(|| IdsByLayout {
|
let ids = self.by_symbol.entry(symbol).or_insert_with(|| IdsByLayout {
|
||||||
by_id: HashMap::with_capacity_and_hasher(1, default_hasher()),
|
by_id: HashMap::with_capacity_and_hasher(1, default_hasher()),
|
||||||
|
toplevels_by_id: Default::default(),
|
||||||
next_id: 1,
|
next_id: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1941,6 +1987,39 @@ impl<'a> LayoutIds<'a> {
|
||||||
|
|
||||||
LayoutId(answer)
|
LayoutId(answer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a LayoutId which is unique for the given symbol and layout.
|
||||||
|
/// If given the same symbol and same layout, returns the same LayoutId.
|
||||||
|
pub fn get_toplevel<'b>(
|
||||||
|
&mut self,
|
||||||
|
symbol: Symbol,
|
||||||
|
layout: &'b crate::ir::TopLevelFunctionLayout<'a>,
|
||||||
|
) -> LayoutId {
|
||||||
|
// Note: this function does some weird stuff to satisfy the borrow checker.
|
||||||
|
// There's probably a nicer way to write it that still works.
|
||||||
|
let ids = self.by_symbol.entry(symbol).or_insert_with(|| IdsByLayout {
|
||||||
|
by_id: Default::default(),
|
||||||
|
toplevels_by_id: HashMap::with_capacity_and_hasher(1, default_hasher()),
|
||||||
|
next_id: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get the id associated with this layout, or default to next_id.
|
||||||
|
let answer = ids
|
||||||
|
.toplevels_by_id
|
||||||
|
.get(&layout)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or(ids.next_id);
|
||||||
|
|
||||||
|
// If we had to default to next_id, it must not have been found;
|
||||||
|
// store the ID we're going to return and increment next_id.
|
||||||
|
if answer == ids.next_id {
|
||||||
|
ids.toplevels_by_id.insert(*layout, ids.next_id);
|
||||||
|
|
||||||
|
ids.next_id += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LayoutId(answer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue