mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
Merge pull request #1422 from rtfeldman/raw-function-layout
remove FunctionPointer layout variant
This commit is contained in:
commit
f08c764cad
19 changed files with 467 additions and 799 deletions
|
@ -6,7 +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::ir::ProcLayout;
|
||||||
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};
|
||||||
|
@ -38,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: TopLevelFunctionLayout<'a>,
|
layout: ProcLayout<'a>,
|
||||||
content: &Content,
|
content: &Content,
|
||||||
interns: &Interns,
|
interns: &Interns,
|
||||||
home: ModuleId,
|
home: ModuleId,
|
||||||
|
@ -54,7 +54,7 @@ pub unsafe fn jit_to_ast<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
match layout {
|
match layout {
|
||||||
TopLevelFunctionLayout {
|
ProcLayout {
|
||||||
arguments: [],
|
arguments: [],
|
||||||
result,
|
result,
|
||||||
} => {
|
} => {
|
||||||
|
@ -153,20 +153,30 @@ fn jit_to_ast_help<'a>(
|
||||||
Layout::Struct(field_layouts) => {
|
Layout::Struct(field_layouts) => {
|
||||||
let ptr_to_ast = |ptr: *const u8| match content {
|
let ptr_to_ast = |ptr: *const u8| match content {
|
||||||
Content::Structure(FlatType::Record(fields, _)) => {
|
Content::Structure(FlatType::Record(fields, _)) => {
|
||||||
struct_to_ast(env, ptr, field_layouts, fields)
|
Ok(struct_to_ast(env, ptr, field_layouts, fields))
|
||||||
}
|
}
|
||||||
Content::Structure(FlatType::EmptyRecord) => {
|
Content::Structure(FlatType::EmptyRecord) => {
|
||||||
struct_to_ast(env, ptr, field_layouts, &MutMap::default())
|
Ok(struct_to_ast(env, ptr, field_layouts, &MutMap::default()))
|
||||||
}
|
}
|
||||||
Content::Structure(FlatType::TagUnion(tags, _)) => {
|
Content::Structure(FlatType::TagUnion(tags, _)) => {
|
||||||
debug_assert_eq!(tags.len(), 1);
|
debug_assert_eq!(tags.len(), 1);
|
||||||
|
|
||||||
let (tag_name, payload_vars) = tags.iter().next().unwrap();
|
let (tag_name, payload_vars) = tags.iter().next().unwrap();
|
||||||
|
|
||||||
single_tag_union_to_ast(env, ptr, field_layouts, tag_name.clone(), payload_vars)
|
Ok(single_tag_union_to_ast(
|
||||||
|
env,
|
||||||
|
ptr,
|
||||||
|
field_layouts,
|
||||||
|
tag_name.clone(),
|
||||||
|
payload_vars,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
Content::Structure(FlatType::FunctionOrTagUnion(tag_name, _, _)) => {
|
Content::Structure(FlatType::FunctionOrTagUnion(tag_name, _, _)) => Ok(
|
||||||
single_tag_union_to_ast(env, ptr, field_layouts, tag_name.clone(), &[])
|
single_tag_union_to_ast(env, ptr, field_layouts, tag_name.clone(), &[]),
|
||||||
|
),
|
||||||
|
Content::Structure(FlatType::Func(_, _, _)) => {
|
||||||
|
// a function with a struct as the closure environment
|
||||||
|
Err(ToAstProblem::FunctionLayout)
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
unreachable!(
|
unreachable!(
|
||||||
|
@ -181,12 +191,12 @@ fn jit_to_ast_help<'a>(
|
||||||
|
|
||||||
let result_stack_size = layout.stack_size(env.ptr_bytes);
|
let result_stack_size = layout.stack_size(env.ptr_bytes);
|
||||||
|
|
||||||
Ok(run_jit_function_dynamic_type!(
|
run_jit_function_dynamic_type!(
|
||||||
lib,
|
lib,
|
||||||
main_fn_name,
|
main_fn_name,
|
||||||
result_stack_size as usize,
|
result_stack_size as usize,
|
||||||
|bytes: *const u8| { ptr_to_ast(bytes as *const u8) }
|
|bytes: *const u8| { ptr_to_ast(bytes as *const u8) }
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
Layout::Union(UnionLayout::NonRecursive(union_layouts)) => match content {
|
Layout::Union(UnionLayout::NonRecursive(union_layouts)) => match content {
|
||||||
Content::Structure(FlatType::TagUnion(tags, _)) => {
|
Content::Structure(FlatType::TagUnion(tags, _)) => {
|
||||||
|
@ -265,7 +275,6 @@ fn jit_to_ast_help<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout::Closure(_, _, _) => Err(ToAstProblem::FunctionLayout),
|
Layout::Closure(_, _, _) => Err(ToAstProblem::FunctionLayout),
|
||||||
Layout::FunctionPointer(_, _) => Err(ToAstProblem::FunctionLayout),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -910,13 +910,14 @@ test "endsWith: hello world ends with world" {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Str.concat
|
// Str.concat
|
||||||
pub fn strConcatC(result_in_place: InPlace, arg1: RocStr, arg2: RocStr) callconv(.C) RocStr {
|
pub fn strConcatC(arg1: RocStr, arg2: RocStr) callconv(.C) RocStr {
|
||||||
return @call(.{ .modifier = always_inline }, strConcat, .{ result_in_place, arg1, arg2 });
|
return @call(.{ .modifier = always_inline }, strConcat, .{ arg1, arg2 });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn strConcat(result_in_place: InPlace, arg1: RocStr, arg2: RocStr) RocStr {
|
fn strConcat(arg1: RocStr, arg2: RocStr) RocStr {
|
||||||
if (arg1.isEmpty()) {
|
if (arg1.isEmpty()) {
|
||||||
// the second argument is borrowed, so we must increment its refcount before returning
|
// the second argument is borrowed, so we must increment its refcount before returning
|
||||||
|
const result_in_place = InPlace.Clone;
|
||||||
return RocStr.clone(result_in_place, arg2);
|
return RocStr.clone(result_in_place, arg2);
|
||||||
} else if (arg2.isEmpty()) {
|
} else if (arg2.isEmpty()) {
|
||||||
// the first argument is owned, so we can return it without cloning
|
// the first argument is owned, so we can return it without cloning
|
||||||
|
@ -974,7 +975,7 @@ test "RocStr.concat: small concat small" {
|
||||||
roc_str3.deinit();
|
roc_str3.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = strConcat(InPlace.Clone, roc_str1, roc_str2);
|
const result = strConcat(roc_str1, roc_str2);
|
||||||
|
|
||||||
defer result.deinit();
|
defer result.deinit();
|
||||||
|
|
||||||
|
|
|
@ -9,7 +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, TopLevelFunctionLayout};
|
use roc_mono::ir::{Proc, ProcLayout};
|
||||||
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.
|
||||||
|
@ -21,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, TopLevelFunctionLayout<'a>), Proc<'a>>,
|
procedures: MutMap<(symbol::Symbol, ProcLayout<'a>), Proc<'a>>,
|
||||||
) -> Result<Object, String> {
|
) -> Result<Object, String> {
|
||||||
match target {
|
match target {
|
||||||
Triple {
|
Triple {
|
||||||
|
@ -144,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, TopLevelFunctionLayout<'a>), Proc<'a>>,
|
procedures: MutMap<(symbol::Symbol, ProcLayout<'a>), Proc<'a>>,
|
||||||
mut backend: B,
|
mut backend: B,
|
||||||
mut output: Object,
|
mut output: Object,
|
||||||
) -> Result<Object, String> {
|
) -> Result<Object, String> {
|
||||||
|
|
|
@ -151,9 +151,6 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
|
|
||||||
match closure_data_layout {
|
match closure_data_layout {
|
||||||
Layout::FunctionPointer(_, _) => {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
Layout::Closure(_, lambda_set, _) => {
|
Layout::Closure(_, lambda_set, _) => {
|
||||||
if let Layout::Struct(&[]) = lambda_set.runtime_representation() {
|
if let Layout::Struct(&[]) = lambda_set.runtime_representation() {
|
||||||
// do nothing
|
// do nothing
|
||||||
|
@ -508,7 +505,6 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>(
|
||||||
let default = [value1, value2];
|
let default = [value1, value2];
|
||||||
|
|
||||||
let arguments_cast = match closure_data_layout {
|
let arguments_cast = match closure_data_layout {
|
||||||
Layout::FunctionPointer(_, _) => &default,
|
|
||||||
Layout::Closure(_, lambda_set, _) => {
|
Layout::Closure(_, lambda_set, _) => {
|
||||||
if let Layout::Struct(&[]) = lambda_set.runtime_representation() {
|
if let Layout::Struct(&[]) = lambda_set.runtime_representation() {
|
||||||
&default
|
&default
|
||||||
|
|
|
@ -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_function_layout, basic_type_from_layout,
|
basic_type_from_builtin, basic_type_from_layout, block_of_memory, block_of_memory_slices,
|
||||||
block_of_memory, block_of_memory_slices, ptr_int,
|
ptr_int,
|
||||||
};
|
};
|
||||||
use crate::llvm::refcounting::{
|
use crate::llvm::refcounting::{
|
||||||
decrement_refcount_layout, increment_refcount_layout, PointerToRefcount,
|
decrement_refcount_layout, increment_refcount_layout, PointerToRefcount,
|
||||||
|
@ -49,11 +49,10 @@ use roc_module::ident::TagName;
|
||||||
use roc_module::low_level::LowLevel;
|
use roc_module::low_level::LowLevel;
|
||||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||||
use roc_mono::ir::{
|
use roc_mono::ir::{
|
||||||
BranchInfo, CallType, EntryPoint, ExceptionId, JoinPointId, ModifyRc, OptLevel,
|
BranchInfo, CallType, EntryPoint, ExceptionId, JoinPointId, ModifyRc, OptLevel, ProcLayout,
|
||||||
TopLevelFunctionLayout, Wrapped,
|
Wrapped,
|
||||||
};
|
};
|
||||||
use roc_mono::layout::{Builtin, InPlace, LambdaSet, Layout, LayoutIds, UnionLayout};
|
use roc_mono::layout::{Builtin, LambdaSet, Layout, LayoutIds, UnionLayout};
|
||||||
use std::convert::TryFrom;
|
|
||||||
|
|
||||||
/// This is for Inkwell's FunctionValue::verify - we want to know the verification
|
/// This is for Inkwell's FunctionValue::verify - we want to know the verification
|
||||||
/// output in debug builds, but we don't want it to print to stdout in release builds!
|
/// output in debug builds, but we don't want it to print to stdout in release builds!
|
||||||
|
@ -118,7 +117,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, (TopLevelFunctionLayout<'a>, FunctionValue<'ctx>)>,
|
pub top_level_thunks: ImMap<Symbol, (ProcLayout<'a>, FunctionValue<'ctx>)>,
|
||||||
join_points: ImMap<JoinPointId, (BasicBlock<'ctx>, &'a [PointerValue<'ctx>])>,
|
join_points: ImMap<JoinPointId, (BasicBlock<'ctx>, &'a [PointerValue<'ctx>])>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +131,7 @@ impl<'a, 'ctx> Scope<'a, 'ctx> {
|
||||||
pub fn insert_top_level_thunk(
|
pub fn insert_top_level_thunk(
|
||||||
&mut self,
|
&mut self,
|
||||||
symbol: Symbol,
|
symbol: Symbol,
|
||||||
layout: &'a TopLevelFunctionLayout<'a>,
|
layout: &'a ProcLayout<'a>,
|
||||||
function_value: FunctionValue<'ctx>,
|
function_value: FunctionValue<'ctx>,
|
||||||
) {
|
) {
|
||||||
self.top_level_thunks
|
self.top_level_thunks
|
||||||
|
@ -588,7 +587,7 @@ fn promote_to_main_function<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
mod_solutions: &'a ModSolutions,
|
mod_solutions: &'a ModSolutions,
|
||||||
symbol: Symbol,
|
symbol: Symbol,
|
||||||
top_level: TopLevelFunctionLayout<'a>,
|
top_level: ProcLayout<'a>,
|
||||||
) -> (&'static str, FunctionValue<'ctx>) {
|
) -> (&'static str, FunctionValue<'ctx>) {
|
||||||
let it = top_level.arguments.iter().copied();
|
let it = top_level.arguments.iter().copied();
|
||||||
let bytes = roc_mono::alias_analysis::func_name_bytes_help(symbol, it, top_level.result);
|
let bytes = roc_mono::alias_analysis::func_name_bytes_help(symbol, it, top_level.result);
|
||||||
|
@ -1638,9 +1637,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EmptyArray => empty_polymorphic_list(env),
|
EmptyArray => empty_polymorphic_list(env),
|
||||||
Array { elem_layout, elems } => {
|
Array { elem_layout, elems } => list_literal(env, scope, elem_layout, elems),
|
||||||
list_literal(env, layout.in_place(), scope, elem_layout, elems)
|
|
||||||
}
|
|
||||||
RuntimeErrorFunction(_) => todo!(),
|
RuntimeErrorFunction(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1794,7 +1791,6 @@ pub fn allocate_with_refcount_help<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
fn list_literal<'a, 'ctx, 'env>(
|
fn list_literal<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
inplace: InPlace,
|
|
||||||
scope: &Scope<'a, 'ctx>,
|
scope: &Scope<'a, 'ctx>,
|
||||||
elem_layout: &Layout<'a>,
|
elem_layout: &Layout<'a>,
|
||||||
elems: &&[Symbol],
|
elems: &&[Symbol],
|
||||||
|
@ -1808,7 +1804,7 @@ fn list_literal<'a, 'ctx, 'env>(
|
||||||
let len_type = env.ptr_int();
|
let len_type = env.ptr_int();
|
||||||
let len = len_type.const_int(len_u64, false);
|
let len = len_type.const_int(len_u64, false);
|
||||||
|
|
||||||
allocate_list(env, inplace, elem_layout, len)
|
allocate_list(env, elem_layout, len)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Copy the elements from the list literal into the array
|
// Copy the elements from the list literal into the array
|
||||||
|
@ -3102,7 +3098,7 @@ fn make_exception_catching_wrapper<'a, 'ctx, 'env>(
|
||||||
pub fn build_proc_headers<'a, 'ctx, 'env>(
|
pub fn build_proc_headers<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
mod_solutions: &'a ModSolutions,
|
mod_solutions: &'a ModSolutions,
|
||||||
procedures: MutMap<(Symbol, TopLevelFunctionLayout<'a>), roc_mono::ir::Proc<'a>>,
|
procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>,
|
||||||
scope: &mut Scope<'a, 'ctx>,
|
scope: &mut Scope<'a, 'ctx>,
|
||||||
// alias_analysis_solutions: AliasAnalysisSolutions,
|
// alias_analysis_solutions: AliasAnalysisSolutions,
|
||||||
) -> Vec<
|
) -> Vec<
|
||||||
|
@ -3144,7 +3140,7 @@ pub fn build_proc_headers<'a, 'ctx, 'env>(
|
||||||
pub fn build_procedures<'a, 'ctx, 'env>(
|
pub fn build_procedures<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
opt_level: OptLevel,
|
opt_level: OptLevel,
|
||||||
procedures: MutMap<(Symbol, TopLevelFunctionLayout<'a>), roc_mono::ir::Proc<'a>>,
|
procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>,
|
||||||
entry_point: EntryPoint<'a>,
|
entry_point: EntryPoint<'a>,
|
||||||
) {
|
) {
|
||||||
build_procedures_help(env, opt_level, procedures, entry_point);
|
build_procedures_help(env, opt_level, procedures, entry_point);
|
||||||
|
@ -3153,7 +3149,7 @@ pub fn build_procedures<'a, 'ctx, 'env>(
|
||||||
pub fn build_procedures_return_main<'a, 'ctx, 'env>(
|
pub fn build_procedures_return_main<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
opt_level: OptLevel,
|
opt_level: OptLevel,
|
||||||
procedures: MutMap<(Symbol, TopLevelFunctionLayout<'a>), roc_mono::ir::Proc<'a>>,
|
procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>,
|
||||||
entry_point: EntryPoint<'a>,
|
entry_point: EntryPoint<'a>,
|
||||||
) -> (&'static str, FunctionValue<'ctx>) {
|
) -> (&'static str, FunctionValue<'ctx>) {
|
||||||
let mod_solutions = build_procedures_help(env, opt_level, procedures, entry_point);
|
let mod_solutions = build_procedures_help(env, opt_level, procedures, entry_point);
|
||||||
|
@ -3164,7 +3160,7 @@ pub fn build_procedures_return_main<'a, 'ctx, 'env>(
|
||||||
fn build_procedures_help<'a, 'ctx, 'env>(
|
fn build_procedures_help<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
opt_level: OptLevel,
|
opt_level: OptLevel,
|
||||||
procedures: MutMap<(Symbol, TopLevelFunctionLayout<'a>), roc_mono::ir::Proc<'a>>,
|
procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>,
|
||||||
entry_point: EntryPoint<'a>,
|
entry_point: EntryPoint<'a>,
|
||||||
) -> &'a ModSolutions {
|
) -> &'a ModSolutions {
|
||||||
let mut layout_ids = roc_mono::layout::LayoutIds::default();
|
let mut layout_ids = roc_mono::layout::LayoutIds::default();
|
||||||
|
@ -3400,122 +3396,6 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
|
||||||
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>(
|
|
||||||
env: &'a Env<'a, 'ctx, 'env>,
|
|
||||||
def_name: &str,
|
|
||||||
alias_symbol: Symbol,
|
|
||||||
arguments: &[Layout<'a>],
|
|
||||||
result: &Layout<'a>,
|
|
||||||
) {
|
|
||||||
let context = &env.context;
|
|
||||||
let builder = env.builder;
|
|
||||||
|
|
||||||
// STEP 1: build function header
|
|
||||||
|
|
||||||
// e.g. `roc__main_1_Fx_caller`
|
|
||||||
let function_name = format!(
|
|
||||||
"roc_{}_{}_caller",
|
|
||||||
def_name,
|
|
||||||
alias_symbol.ident_string(&env.interns)
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut argument_types = Vec::with_capacity_in(arguments.len() + 3, env.arena);
|
|
||||||
|
|
||||||
for layout in arguments {
|
|
||||||
let arg_type = basic_type_from_layout(env, layout);
|
|
||||||
let arg_ptr_type = arg_type.ptr_type(AddressSpace::Generic);
|
|
||||||
|
|
||||||
argument_types.push(arg_ptr_type.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let function_pointer_type = {
|
|
||||||
let mut args = Vec::new_in(env.arena);
|
|
||||||
args.extend(arguments.iter().cloned());
|
|
||||||
|
|
||||||
// pretend the closure layout is empty
|
|
||||||
args.push(Layout::Struct(&[]));
|
|
||||||
|
|
||||||
// this is already a (function) pointer type
|
|
||||||
basic_type_from_function_layout(env, &args, result)
|
|
||||||
};
|
|
||||||
argument_types.push(function_pointer_type);
|
|
||||||
|
|
||||||
let closure_argument_type = {
|
|
||||||
let basic_type = basic_type_from_layout(env, &Layout::Struct(&[]));
|
|
||||||
|
|
||||||
basic_type.ptr_type(AddressSpace::Generic)
|
|
||||||
};
|
|
||||||
argument_types.push(closure_argument_type.into());
|
|
||||||
|
|
||||||
let result_type = basic_type_from_layout(env, result);
|
|
||||||
|
|
||||||
let roc_call_result_type =
|
|
||||||
context.struct_type(&[context.i64_type().into(), result_type], false);
|
|
||||||
|
|
||||||
let output_type = { roc_call_result_type.ptr_type(AddressSpace::Generic) };
|
|
||||||
argument_types.push(output_type.into());
|
|
||||||
|
|
||||||
let function_type = context.void_type().fn_type(&argument_types, false);
|
|
||||||
|
|
||||||
let function_value = add_func(
|
|
||||||
env.module,
|
|
||||||
function_name.as_str(),
|
|
||||||
function_type,
|
|
||||||
Linkage::External,
|
|
||||||
C_CALL_CONV,
|
|
||||||
);
|
|
||||||
|
|
||||||
// STEP 2: build function body
|
|
||||||
|
|
||||||
let entry = context.append_basic_block(function_value, "entry");
|
|
||||||
|
|
||||||
builder.position_at_end(entry);
|
|
||||||
|
|
||||||
let mut parameters = function_value.get_params();
|
|
||||||
let output = 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 actual_function_type = basic_type_from_function_layout(env, arguments, result);
|
|
||||||
|
|
||||||
let function_ptr = builder
|
|
||||||
.build_bitcast(function_ptr, actual_function_type, "cast")
|
|
||||||
.into_pointer_value();
|
|
||||||
|
|
||||||
let mut parameters = parameters;
|
|
||||||
|
|
||||||
for param in parameters.iter_mut() {
|
|
||||||
debug_assert!(param.is_pointer_value());
|
|
||||||
*param = builder.build_load(param.into_pointer_value(), "load_param");
|
|
||||||
}
|
|
||||||
|
|
||||||
let call_result = invoke_and_catch(
|
|
||||||
env,
|
|
||||||
function_value,
|
|
||||||
CallableValue::try_from(function_ptr).unwrap(),
|
|
||||||
C_CALL_CONV,
|
|
||||||
¶meters,
|
|
||||||
result_type,
|
|
||||||
);
|
|
||||||
|
|
||||||
builder.build_store(output, call_result);
|
|
||||||
|
|
||||||
builder.build_return(None);
|
|
||||||
|
|
||||||
// STEP 3: build a {} -> u64 function that gives the size of the return type
|
|
||||||
build_host_exposed_alias_size_help(
|
|
||||||
env,
|
|
||||||
def_name,
|
|
||||||
alias_symbol,
|
|
||||||
Some("result"),
|
|
||||||
roc_call_result_type.into(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// STEP 4: build a {} -> u64 function that gives the size of the function
|
|
||||||
let layout = Layout::Struct(&[]);
|
|
||||||
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,
|
||||||
|
@ -3583,14 +3463,14 @@ pub fn build_proc<'a, 'ctx, 'env>(
|
||||||
fn_val: FunctionValue<'ctx>,
|
fn_val: FunctionValue<'ctx>,
|
||||||
) {
|
) {
|
||||||
use roc_mono::ir::HostExposedLayouts;
|
use roc_mono::ir::HostExposedLayouts;
|
||||||
|
use roc_mono::layout::RawFunctionLayout;
|
||||||
let copy = proc.host_exposed_layouts.clone();
|
let copy = proc.host_exposed_layouts.clone();
|
||||||
let fn_name = fn_val.get_name().to_string_lossy();
|
|
||||||
match copy {
|
match copy {
|
||||||
HostExposedLayouts::NotHostExposed => {}
|
HostExposedLayouts::NotHostExposed => {}
|
||||||
HostExposedLayouts::HostExposed { rigids: _, aliases } => {
|
HostExposedLayouts::HostExposed { rigids: _, aliases } => {
|
||||||
for (name, (symbol, top_level, layout)) in aliases {
|
for (name, (symbol, top_level, layout)) in aliases {
|
||||||
match layout {
|
match layout {
|
||||||
Layout::Closure(arguments, closure, result) => {
|
RawFunctionLayout::Function(arguments, closure, result) => {
|
||||||
// define closure size and return value size, e.g.
|
// define closure size and return value size, e.g.
|
||||||
//
|
//
|
||||||
// * roc__mainForHost_1_Update_size() -> i64
|
// * roc__mainForHost_1_Update_size() -> i64
|
||||||
|
@ -3627,18 +3507,10 @@ pub fn build_proc<'a, 'ctx, 'env>(
|
||||||
env, &fn_name, evaluator, name, arguments, closure, result,
|
env, &fn_name, evaluator, name, arguments, closure, result,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Layout::FunctionPointer(arguments, result) => {
|
|
||||||
// define function size (equal to pointer size) and return value size, e.g.
|
|
||||||
//
|
|
||||||
// * roc__mainForHost_1_Update_size() -> i64
|
|
||||||
// * roc__mainForHost_1_Update_result_size() -> i64
|
|
||||||
build_function_caller(env, &fn_name, name, arguments, result)
|
|
||||||
}
|
|
||||||
|
|
||||||
Layout::Builtin(_) => {}
|
RawFunctionLayout::ZeroArgumentThunk(_) => {
|
||||||
Layout::Struct(_) => {}
|
// do nothing
|
||||||
Layout::Union(_) => {}
|
}
|
||||||
Layout::RecursivePointer => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4289,13 +4161,13 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
// Str.concat : Str, Str -> Str
|
// Str.concat : Str, Str -> Str
|
||||||
debug_assert_eq!(args.len(), 2);
|
debug_assert_eq!(args.len(), 2);
|
||||||
|
|
||||||
str_concat(env, layout.in_place(), scope, args[0], args[1])
|
str_concat(env, scope, args[0], args[1])
|
||||||
}
|
}
|
||||||
StrJoinWith => {
|
StrJoinWith => {
|
||||||
// Str.joinWith : List Str, Str -> Str
|
// Str.joinWith : List Str, Str -> Str
|
||||||
debug_assert_eq!(args.len(), 2);
|
debug_assert_eq!(args.len(), 2);
|
||||||
|
|
||||||
str_join_with(env, layout.in_place(), scope, args[0], args[1])
|
str_join_with(env, scope, args[0], args[1])
|
||||||
}
|
}
|
||||||
StrStartsWith => {
|
StrStartsWith => {
|
||||||
// Str.startsWith : Str, Str -> Bool
|
// Str.startsWith : Str, Str -> Bool
|
||||||
|
@ -4349,7 +4221,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
// Str.split : Str, Str -> List Str
|
// Str.split : Str, Str -> List Str
|
||||||
debug_assert_eq!(args.len(), 2);
|
debug_assert_eq!(args.len(), 2);
|
||||||
|
|
||||||
str_split(env, scope, layout.in_place(), args[0], args[1])
|
str_split(env, scope, args[0], args[1])
|
||||||
}
|
}
|
||||||
StrIsEmpty => {
|
StrIsEmpty => {
|
||||||
// Str.isEmpty : Str -> Str
|
// Str.isEmpty : Str -> Str
|
||||||
|
@ -4384,7 +4256,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let (arg, arg_layout) = load_symbol_and_layout(scope, &args[0]);
|
let (arg, arg_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||||
|
|
||||||
list_single(env, layout.in_place(), arg, arg_layout)
|
list_single(env, arg, arg_layout)
|
||||||
}
|
}
|
||||||
ListRepeat => {
|
ListRepeat => {
|
||||||
// List.repeat : Int, elem -> List elem
|
// List.repeat : Int, elem -> List elem
|
||||||
|
@ -4401,7 +4273,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||||
|
|
||||||
list_reverse(env, layout.in_place(), list, list_layout)
|
list_reverse(env, list, list_layout)
|
||||||
}
|
}
|
||||||
ListConcat => {
|
ListConcat => {
|
||||||
debug_assert_eq!(args.len(), 2);
|
debug_assert_eq!(args.len(), 2);
|
||||||
|
@ -4410,14 +4282,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let second_list = load_symbol(scope, &args[1]);
|
let second_list = load_symbol(scope, &args[1]);
|
||||||
|
|
||||||
list_concat(
|
list_concat(env, parent, first_list, second_list, list_layout)
|
||||||
env,
|
|
||||||
layout.in_place(),
|
|
||||||
parent,
|
|
||||||
first_list,
|
|
||||||
second_list,
|
|
||||||
list_layout,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
ListContains => {
|
ListContains => {
|
||||||
// List.contains : List elem, elem -> Bool
|
// List.contains : List elem, elem -> Bool
|
||||||
|
@ -4450,7 +4315,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
let original_wrapper = load_symbol(scope, &args[0]).into_struct_value();
|
let original_wrapper = load_symbol(scope, &args[0]).into_struct_value();
|
||||||
let (elem, elem_layout) = load_symbol_and_layout(scope, &args[1]);
|
let (elem, elem_layout) = load_symbol_and_layout(scope, &args[1]);
|
||||||
|
|
||||||
list_append(env, layout.in_place(), original_wrapper, elem, elem_layout)
|
list_append(env, original_wrapper, elem, elem_layout)
|
||||||
}
|
}
|
||||||
ListSwap => {
|
ListSwap => {
|
||||||
// List.swap : List elem, Nat, Nat -> List elem
|
// List.swap : List elem, Nat, Nat -> List elem
|
||||||
|
@ -4502,7 +4367,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
let original_wrapper = load_symbol(scope, &args[0]).into_struct_value();
|
let original_wrapper = load_symbol(scope, &args[0]).into_struct_value();
|
||||||
let (elem, elem_layout) = load_symbol_and_layout(scope, &args[1]);
|
let (elem, elem_layout) = load_symbol_and_layout(scope, &args[1]);
|
||||||
|
|
||||||
list_prepend(env, layout.in_place(), original_wrapper, elem, elem_layout)
|
list_prepend(env, original_wrapper, elem, elem_layout)
|
||||||
}
|
}
|
||||||
ListJoin => {
|
ListJoin => {
|
||||||
// List.join : List (List elem) -> List elem
|
// List.join : List (List elem) -> List elem
|
||||||
|
@ -4510,7 +4375,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let (list, outer_list_layout) = load_symbol_and_layout(scope, &args[0]);
|
let (list, outer_list_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||||
|
|
||||||
list_join(env, layout.in_place(), parent, list, outer_list_layout)
|
list_join(env, parent, list, outer_list_layout)
|
||||||
}
|
}
|
||||||
NumAbs | NumNeg | NumRound | NumSqrtUnchecked | NumLogUnchecked | NumSin | NumCos
|
NumAbs | NumNeg | NumRound | NumSqrtUnchecked | NumLogUnchecked | NumSin | NumCos
|
||||||
| NumCeiling | NumFloor | NumToFloat | NumIsFinite | NumAtan | NumAcos | NumAsin => {
|
| NumCeiling | NumFloor | NumToFloat | NumIsFinite | NumAtan | NumAcos | NumAsin => {
|
||||||
|
|
|
@ -88,7 +88,7 @@ fn build_hash_layout<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
Layout::FunctionPointer(_, _) | Layout::Closure(_, _, _) => {
|
Layout::Closure(_, _, _) => {
|
||||||
unreachable!("the type system will guarantee these are never hashed")
|
unreachable!("the type system will guarantee these are never hashed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![allow(clippy::too_many_arguments)]
|
#![allow(clippy::too_many_arguments)]
|
||||||
use crate::llvm::bitcode::{
|
use crate::llvm::bitcode::{
|
||||||
build_dec_wrapper, build_eq_wrapper, build_inc_n_wrapper, build_inc_wrapper,
|
build_dec_wrapper, build_eq_wrapper, build_inc_n_wrapper, build_inc_wrapper, call_bitcode_fn,
|
||||||
build_transform_caller, call_bitcode_fn, call_void_bitcode_fn,
|
call_void_bitcode_fn,
|
||||||
};
|
};
|
||||||
use crate::llvm::build::{
|
use crate::llvm::build::{
|
||||||
allocate_with_refcount_help, cast_basic_basic, complex_bitcast, Env, RocFunctionCall,
|
allocate_with_refcount_help, cast_basic_basic, complex_bitcast, Env, RocFunctionCall,
|
||||||
|
@ -14,7 +14,7 @@ use inkwell::types::{BasicType, BasicTypeEnum, PointerType};
|
||||||
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue};
|
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue};
|
||||||
use inkwell::{AddressSpace, IntPredicate};
|
use inkwell::{AddressSpace, IntPredicate};
|
||||||
use roc_builtins::bitcode;
|
use roc_builtins::bitcode;
|
||||||
use roc_mono::layout::{Builtin, InPlace, Layout, LayoutIds};
|
use roc_mono::layout::{Builtin, Layout, LayoutIds};
|
||||||
|
|
||||||
fn list_returned_from_zig<'a, 'ctx, 'env>(
|
fn list_returned_from_zig<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
|
@ -83,7 +83,6 @@ pub fn pass_as_opaque<'a, 'ctx, 'env>(
|
||||||
/// List.single : a -> List a
|
/// List.single : a -> List a
|
||||||
pub fn list_single<'a, 'ctx, 'env>(
|
pub fn list_single<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
_inplace: InPlace,
|
|
||||||
element: BasicValueEnum<'ctx>,
|
element: BasicValueEnum<'ctx>,
|
||||||
element_layout: &Layout<'a>,
|
element_layout: &Layout<'a>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
@ -124,7 +123,6 @@ pub fn list_repeat<'a, 'ctx, 'env>(
|
||||||
/// List.prepend : List elem, elem -> List elem
|
/// List.prepend : List elem, elem -> List elem
|
||||||
pub fn list_prepend<'a, 'ctx, 'env>(
|
pub fn list_prepend<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
inplace: InPlace,
|
|
||||||
original_wrapper: StructValue<'ctx>,
|
original_wrapper: StructValue<'ctx>,
|
||||||
elem: BasicValueEnum<'ctx>,
|
elem: BasicValueEnum<'ctx>,
|
||||||
elem_layout: &Layout<'a>,
|
elem_layout: &Layout<'a>,
|
||||||
|
@ -146,7 +144,7 @@ pub fn list_prepend<'a, 'ctx, 'env>(
|
||||||
);
|
);
|
||||||
|
|
||||||
// Allocate space for the new array that we'll copy into.
|
// Allocate space for the new array that we'll copy into.
|
||||||
let clone_ptr = allocate_list(env, inplace, elem_layout, new_list_len);
|
let clone_ptr = allocate_list(env, elem_layout, new_list_len);
|
||||||
|
|
||||||
builder.build_store(clone_ptr, elem);
|
builder.build_store(clone_ptr, elem);
|
||||||
|
|
||||||
|
@ -189,7 +187,6 @@ pub fn list_prepend<'a, 'ctx, 'env>(
|
||||||
/// List.join : List (List elem) -> List elem
|
/// List.join : List (List elem) -> List elem
|
||||||
pub fn list_join<'a, 'ctx, 'env>(
|
pub fn list_join<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
_inplace: InPlace,
|
|
||||||
_parent: FunctionValue<'ctx>,
|
_parent: FunctionValue<'ctx>,
|
||||||
outer_list: BasicValueEnum<'ctx>,
|
outer_list: BasicValueEnum<'ctx>,
|
||||||
outer_list_layout: &Layout<'a>,
|
outer_list_layout: &Layout<'a>,
|
||||||
|
@ -221,17 +218,16 @@ pub fn list_join<'a, 'ctx, 'env>(
|
||||||
/// List.reverse : List elem -> List elem
|
/// List.reverse : List elem -> List elem
|
||||||
pub fn list_reverse<'a, 'ctx, 'env>(
|
pub fn list_reverse<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
_output_inplace: InPlace,
|
|
||||||
list: BasicValueEnum<'ctx>,
|
list: BasicValueEnum<'ctx>,
|
||||||
list_layout: &Layout<'a>,
|
list_layout: &Layout<'a>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
let (_, element_layout) = match *list_layout {
|
let element_layout = match *list_layout {
|
||||||
Layout::Builtin(Builtin::EmptyList) => (
|
Layout::Builtin(Builtin::EmptyList) => {
|
||||||
InPlace::InPlace,
|
|
||||||
// this pointer will never actually be dereferenced
|
// this pointer will never actually be dereferenced
|
||||||
Layout::Builtin(Builtin::Int64),
|
Layout::Builtin(Builtin::Int64)
|
||||||
),
|
}
|
||||||
Layout::Builtin(Builtin::List(elem_layout)) => (InPlace::Clone, *elem_layout),
|
|
||||||
|
Layout::Builtin(Builtin::List(elem_layout)) => *elem_layout,
|
||||||
|
|
||||||
_ => unreachable!("Invalid layout {:?} in List.reverse", list_layout),
|
_ => unreachable!("Invalid layout {:?} in List.reverse", list_layout),
|
||||||
};
|
};
|
||||||
|
@ -287,7 +283,6 @@ pub fn list_get_unsafe<'a, 'ctx, 'env>(
|
||||||
/// List.append : List elem, elem -> List elem
|
/// List.append : List elem, elem -> List elem
|
||||||
pub fn list_append<'a, 'ctx, 'env>(
|
pub fn list_append<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
_inplace: InPlace,
|
|
||||||
original_wrapper: StructValue<'ctx>,
|
original_wrapper: StructValue<'ctx>,
|
||||||
element: BasicValueEnum<'ctx>,
|
element: BasicValueEnum<'ctx>,
|
||||||
element_layout: &Layout<'a>,
|
element_layout: &Layout<'a>,
|
||||||
|
@ -658,54 +653,6 @@ pub fn list_keep_errs<'a, 'ctx, 'env>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_keep_result<'a, 'ctx, 'env>(
|
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
|
||||||
layout_ids: &mut LayoutIds<'a>,
|
|
||||||
transform: FunctionValue<'ctx>,
|
|
||||||
transform_layout: Layout<'a>,
|
|
||||||
closure_data: BasicValueEnum<'ctx>,
|
|
||||||
closure_data_layout: Layout<'a>,
|
|
||||||
list: BasicValueEnum<'ctx>,
|
|
||||||
before_layout: &Layout<'a>,
|
|
||||||
after_layout: &Layout<'a>,
|
|
||||||
op: &str,
|
|
||||||
) -> BasicValueEnum<'ctx> {
|
|
||||||
let builder = env.builder;
|
|
||||||
|
|
||||||
let result_layout = match transform_layout {
|
|
||||||
Layout::FunctionPointer(_, ret) => ret,
|
|
||||||
Layout::Closure(_, _, ret) => ret,
|
|
||||||
_ => unreachable!("not a callable layout"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let closure_data_ptr = builder.build_alloca(closure_data.get_type(), "closure_data_ptr");
|
|
||||||
env.builder.build_store(closure_data_ptr, closure_data);
|
|
||||||
|
|
||||||
let stepper_caller =
|
|
||||||
build_transform_caller(env, transform, closure_data_layout, &[*before_layout])
|
|
||||||
.as_global_value()
|
|
||||||
.as_pointer_value();
|
|
||||||
|
|
||||||
let inc_closure = build_inc_wrapper(env, layout_ids, &transform_layout);
|
|
||||||
let dec_result_fn = build_dec_wrapper(env, layout_ids, result_layout);
|
|
||||||
|
|
||||||
call_bitcode_fn(
|
|
||||||
env,
|
|
||||||
&[
|
|
||||||
pass_list_as_i128(env, list),
|
|
||||||
pass_as_opaque(env, closure_data_ptr),
|
|
||||||
stepper_caller.into(),
|
|
||||||
env.alignment_intvalue(&before_layout),
|
|
||||||
layout_width(env, before_layout),
|
|
||||||
layout_width(env, after_layout),
|
|
||||||
layout_width(env, result_layout),
|
|
||||||
inc_closure.as_global_value().as_pointer_value().into(),
|
|
||||||
dec_result_fn.as_global_value().as_pointer_value().into(),
|
|
||||||
],
|
|
||||||
op,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// List.sortWith : List a, (a, a -> Ordering) -> List a
|
/// List.sortWith : List a, (a, a -> Ordering) -> List a
|
||||||
pub fn list_sort_with<'a, 'ctx, 'env>(
|
pub fn list_sort_with<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
|
@ -852,7 +799,6 @@ pub fn list_map3<'a, 'ctx, 'env>(
|
||||||
/// List.concat : List elem, List elem -> List elem
|
/// List.concat : List elem, List elem -> List elem
|
||||||
pub fn list_concat<'a, 'ctx, 'env>(
|
pub fn list_concat<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
_inplace: InPlace,
|
|
||||||
_parent: FunctionValue<'ctx>,
|
_parent: FunctionValue<'ctx>,
|
||||||
first_list: BasicValueEnum<'ctx>,
|
first_list: BasicValueEnum<'ctx>,
|
||||||
second_list: BasicValueEnum<'ctx>,
|
second_list: BasicValueEnum<'ctx>,
|
||||||
|
@ -1118,7 +1064,6 @@ pub fn load_list_ptr<'ctx>(
|
||||||
|
|
||||||
pub fn allocate_list<'a, 'ctx, 'env>(
|
pub fn allocate_list<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
inplace: InPlace,
|
|
||||||
elem_layout: &Layout<'a>,
|
elem_layout: &Layout<'a>,
|
||||||
number_of_elements: IntValue<'ctx>,
|
number_of_elements: IntValue<'ctx>,
|
||||||
) -> PointerValue<'ctx> {
|
) -> PointerValue<'ctx> {
|
||||||
|
@ -1131,14 +1076,9 @@ pub fn allocate_list<'a, 'ctx, 'env>(
|
||||||
let number_of_data_bytes =
|
let number_of_data_bytes =
|
||||||
builder.build_int_mul(bytes_per_element, number_of_elements, "data_length");
|
builder.build_int_mul(bytes_per_element, number_of_elements, "data_length");
|
||||||
|
|
||||||
let rc1 = match inplace {
|
|
||||||
InPlace::InPlace => number_of_elements,
|
|
||||||
InPlace::Clone => {
|
|
||||||
// the refcount of a new list is initially 1
|
// the refcount of a new list is initially 1
|
||||||
// we assume that the list is indeed used (dead variables are eliminated)
|
// we assume that the list is indeed used (dead variables are eliminated)
|
||||||
crate::llvm::refcounting::refcount_1(ctx, env.ptr_bytes)
|
let rc1 = crate::llvm::refcounting::refcount_1(ctx, env.ptr_bytes);
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
allocate_with_refcount_help(env, elem_layout, number_of_data_bytes, rc1)
|
allocate_with_refcount_help(env, elem_layout, number_of_data_bytes, rc1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, Str
|
||||||
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, InPlace, Layout};
|
use roc_mono::layout::{Builtin, Layout};
|
||||||
|
|
||||||
use super::build::load_symbol;
|
use super::build::load_symbol;
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ pub static CHAR_LAYOUT: Layout = Layout::Builtin(Builtin::Int8);
|
||||||
pub fn str_split<'a, 'ctx, 'env>(
|
pub fn str_split<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
scope: &Scope<'a, 'ctx>,
|
scope: &Scope<'a, 'ctx>,
|
||||||
inplace: InPlace,
|
|
||||||
str_symbol: Symbol,
|
str_symbol: Symbol,
|
||||||
delimiter_symbol: Symbol,
|
delimiter_symbol: Symbol,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
@ -33,7 +32,7 @@ pub fn str_split<'a, 'ctx, 'env>(
|
||||||
.into_int_value();
|
.into_int_value();
|
||||||
|
|
||||||
// a pointer to the elements
|
// a pointer to the elements
|
||||||
let ret_list_ptr = allocate_list(env, inplace, &Layout::Builtin(Builtin::Str), segment_count);
|
let ret_list_ptr = allocate_list(env, &Layout::Builtin(Builtin::Str), segment_count);
|
||||||
|
|
||||||
// get the RocStr type defined by zig
|
// get the RocStr type defined by zig
|
||||||
let roc_str_type = env.module.get_struct_type("str.RocStr").unwrap();
|
let roc_str_type = env.module.get_struct_type("str.RocStr").unwrap();
|
||||||
|
@ -109,7 +108,6 @@ pub fn destructure<'ctx>(
|
||||||
/// 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>,
|
||||||
inplace: InPlace,
|
|
||||||
scope: &Scope<'a, 'ctx>,
|
scope: &Scope<'a, 'ctx>,
|
||||||
str1_symbol: Symbol,
|
str1_symbol: Symbol,
|
||||||
str2_symbol: Symbol,
|
str2_symbol: Symbol,
|
||||||
|
@ -120,14 +118,7 @@ pub fn str_concat<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
call_bitcode_fn(
|
call_bitcode_fn(
|
||||||
env,
|
env,
|
||||||
&[
|
&[str1_i128.into(), str2_i128.into()],
|
||||||
env.context
|
|
||||||
.i8_type()
|
|
||||||
.const_int(inplace as u64, false)
|
|
||||||
.into(),
|
|
||||||
str1_i128.into(),
|
|
||||||
str2_i128.into(),
|
|
||||||
],
|
|
||||||
&bitcode::STR_CONCAT,
|
&bitcode::STR_CONCAT,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -135,7 +126,6 @@ pub fn str_concat<'a, 'ctx, 'env>(
|
||||||
/// Str.join : List Str, Str -> Str
|
/// Str.join : List Str, Str -> Str
|
||||||
pub fn str_join_with<'a, 'ctx, 'env>(
|
pub fn str_join_with<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
_inplace: InPlace,
|
|
||||||
scope: &Scope<'a, 'ctx>,
|
scope: &Scope<'a, 'ctx>,
|
||||||
list_symbol: Symbol,
|
list_symbol: Symbol,
|
||||||
str_symbol: Symbol,
|
str_symbol: Symbol,
|
||||||
|
|
|
@ -195,7 +195,7 @@ fn build_eq<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
Layout::FunctionPointer(_, _) | Layout::Closure(_, _, _) => {
|
Layout::Closure(_, _, _) => {
|
||||||
unreachable!("the type system will guarantee these are never compared")
|
unreachable!("the type system will guarantee these are never compared")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,7 +336,7 @@ fn build_neq<'a, 'ctx, 'env>(
|
||||||
unreachable!("recursion pointers should never be compared directly")
|
unreachable!("recursion pointers should never be compared directly")
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout::FunctionPointer(_, _) | Layout::Closure(_, _, _) => {
|
Layout::Closure(_, _, _) => {
|
||||||
unreachable!("the type system will guarantee these are never compared")
|
unreachable!("the type system will guarantee these are never compared")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,24 +4,6 @@ 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};
|
||||||
|
|
||||||
pub fn basic_type_from_function_layout<'a, 'ctx, 'env>(
|
|
||||||
env: &crate::llvm::build::Env<'a, 'ctx, 'env>,
|
|
||||||
args: &[Layout<'_>],
|
|
||||||
ret_layout: &Layout<'_>,
|
|
||||||
) -> BasicTypeEnum<'ctx> {
|
|
||||||
let ret_type = basic_type_from_layout(env, &ret_layout);
|
|
||||||
let mut arg_basic_types = Vec::with_capacity_in(args.len(), env.arena);
|
|
||||||
|
|
||||||
for arg_layout in args.iter() {
|
|
||||||
arg_basic_types.push(basic_type_from_layout(env, arg_layout));
|
|
||||||
}
|
|
||||||
|
|
||||||
let fn_type = ret_type.fn_type(arg_basic_types.into_bump_slice(), false);
|
|
||||||
let ptr_type = fn_type.ptr_type(AddressSpace::Generic);
|
|
||||||
|
|
||||||
ptr_type.as_basic_type_enum()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn basic_type_from_record<'a, 'ctx, 'env>(
|
fn basic_type_from_record<'a, 'ctx, 'env>(
|
||||||
env: &crate::llvm::build::Env<'a, 'ctx, 'env>,
|
env: &crate::llvm::build::Env<'a, 'ctx, 'env>,
|
||||||
fields: &[Layout<'_>],
|
fields: &[Layout<'_>],
|
||||||
|
@ -44,7 +26,6 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
|
||||||
use Layout::*;
|
use Layout::*;
|
||||||
|
|
||||||
match layout {
|
match layout {
|
||||||
FunctionPointer(args, ret_layout) => basic_type_from_function_layout(env, args, 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)
|
||||||
|
|
|
@ -750,8 +750,6 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
||||||
Some(function)
|
Some(function)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
FunctionPointer(_, _) => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ use roc_module::symbol::{
|
||||||
};
|
};
|
||||||
use roc_mono::ir::{
|
use roc_mono::ir::{
|
||||||
CapturedSymbols, EntryPoint, ExternalSpecializations, PartialProc, PendingSpecialization, Proc,
|
CapturedSymbols, EntryPoint, ExternalSpecializations, PartialProc, PendingSpecialization, Proc,
|
||||||
Procs, TopLevelFunctionLayout,
|
ProcLayout, Procs,
|
||||||
};
|
};
|
||||||
use roc_mono::layout::{Layout, LayoutCache, LayoutProblem};
|
use roc_mono::layout::{Layout, LayoutCache, LayoutProblem};
|
||||||
use roc_parse::ast::{self, StrLiteral, TypeAnnotation};
|
use roc_parse::ast::{self, StrLiteral, TypeAnnotation};
|
||||||
|
@ -708,7 +708,7 @@ pub struct MonomorphizedModule<'a> {
|
||||||
pub can_problems: MutMap<ModuleId, Vec<roc_problem::can::Problem>>,
|
pub can_problems: MutMap<ModuleId, Vec<roc_problem::can::Problem>>,
|
||||||
pub type_problems: MutMap<ModuleId, Vec<solve::TypeError>>,
|
pub type_problems: MutMap<ModuleId, Vec<solve::TypeError>>,
|
||||||
pub mono_problems: MutMap<ModuleId, Vec<roc_mono::ir::MonoProblem>>,
|
pub mono_problems: MutMap<ModuleId, Vec<roc_mono::ir::MonoProblem>>,
|
||||||
pub procedures: MutMap<(Symbol, TopLevelFunctionLayout<'a>), Proc<'a>>,
|
pub procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
|
||||||
pub entry_point: EntryPoint<'a>,
|
pub entry_point: EntryPoint<'a>,
|
||||||
pub exposed_to_host: MutMap<Symbol, Variable>,
|
pub exposed_to_host: MutMap<Symbol, Variable>,
|
||||||
pub header_sources: MutMap<ModuleId, (PathBuf, Box<str>)>,
|
pub header_sources: MutMap<ModuleId, (PathBuf, Box<str>)>,
|
||||||
|
@ -781,7 +781,7 @@ enum Msg<'a> {
|
||||||
ident_ids: IdentIds,
|
ident_ids: IdentIds,
|
||||||
layout_cache: LayoutCache<'a>,
|
layout_cache: LayoutCache<'a>,
|
||||||
external_specializations_requested: BumpMap<ModuleId, ExternalSpecializations<'a>>,
|
external_specializations_requested: BumpMap<ModuleId, ExternalSpecializations<'a>>,
|
||||||
procedures: MutMap<(Symbol, TopLevelFunctionLayout<'a>), Proc<'a>>,
|
procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
|
||||||
problems: Vec<roc_mono::ir::MonoProblem>,
|
problems: Vec<roc_mono::ir::MonoProblem>,
|
||||||
module_timing: ModuleTiming,
|
module_timing: ModuleTiming,
|
||||||
subs: Subs,
|
subs: Subs,
|
||||||
|
@ -829,7 +829,7 @@ struct State<'a> {
|
||||||
|
|
||||||
pub module_cache: ModuleCache<'a>,
|
pub module_cache: ModuleCache<'a>,
|
||||||
pub dependencies: Dependencies<'a>,
|
pub dependencies: Dependencies<'a>,
|
||||||
pub procedures: MutMap<(Symbol, TopLevelFunctionLayout<'a>), Proc<'a>>,
|
pub procedures: MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
|
||||||
pub exposed_to_host: MutMap<Symbol, Variable>,
|
pub exposed_to_host: MutMap<Symbol, Variable>,
|
||||||
|
|
||||||
/// This is the "final" list of IdentIds, after canonicalization and constraint gen
|
/// This is the "final" list of IdentIds, after canonicalization and constraint gen
|
||||||
|
@ -860,7 +860,7 @@ struct State<'a> {
|
||||||
pub needs_specialization: MutSet<ModuleId>,
|
pub needs_specialization: MutSet<ModuleId>,
|
||||||
|
|
||||||
pub all_pending_specializations:
|
pub all_pending_specializations:
|
||||||
MutMap<Symbol, MutMap<TopLevelFunctionLayout<'a>, PendingSpecialization<'a>>>,
|
MutMap<Symbol, MutMap<ProcLayout<'a>, PendingSpecialization<'a>>>,
|
||||||
|
|
||||||
pub specializations_in_flight: u32,
|
pub specializations_in_flight: u32,
|
||||||
|
|
||||||
|
@ -2065,8 +2065,6 @@ fn update<'a>(
|
||||||
&& state.dependencies.solved_all()
|
&& state.dependencies.solved_all()
|
||||||
&& state.goal_phase == Phase::MakeSpecializations
|
&& state.goal_phase == Phase::MakeSpecializations
|
||||||
{
|
{
|
||||||
Proc::insert_refcount_operations(arena, &mut state.procedures);
|
|
||||||
|
|
||||||
// display the mono IR of the module, for debug purposes
|
// display the mono IR of the module, for debug purposes
|
||||||
if roc_mono::ir::PRETTY_PRINT_IR_SYMBOLS {
|
if roc_mono::ir::PRETTY_PRINT_IR_SYMBOLS {
|
||||||
let procs_string = state
|
let procs_string = state
|
||||||
|
@ -2080,6 +2078,8 @@ fn update<'a>(
|
||||||
println!("{}", result);
|
println!("{}", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Proc::insert_refcount_operations(arena, &mut state.procedures);
|
||||||
|
|
||||||
// This is not safe with the new non-recursive RC updates that we do for tag unions
|
// This is not safe with the new non-recursive RC updates that we do for tag unions
|
||||||
//
|
//
|
||||||
// Proc::optimize_refcount_operations(
|
// Proc::optimize_refcount_operations(
|
||||||
|
@ -2237,7 +2237,7 @@ fn finish_specialization(
|
||||||
// the entry point is not specialized. This can happen if the repl output
|
// the entry point is not specialized. This can happen if the repl output
|
||||||
// is a function value
|
// is a function value
|
||||||
EntryPoint {
|
EntryPoint {
|
||||||
layout: roc_mono::ir::TopLevelFunctionLayout {
|
layout: roc_mono::ir::ProcLayout {
|
||||||
arguments: &[],
|
arguments: &[],
|
||||||
result: Layout::Struct(&[]),
|
result: Layout::Struct(&[]),
|
||||||
},
|
},
|
||||||
|
@ -4056,7 +4056,7 @@ fn add_def_to_module<'a>(
|
||||||
|
|
||||||
procs.insert_exposed(
|
procs.insert_exposed(
|
||||||
symbol,
|
symbol,
|
||||||
TopLevelFunctionLayout::from_layout(mono_env.arena, layout),
|
ProcLayout::from_layout(mono_env.arena, layout),
|
||||||
mono_env.arena,
|
mono_env.arena,
|
||||||
mono_env.subs,
|
mono_env.subs,
|
||||||
def.annotation,
|
def.annotation,
|
||||||
|
@ -4087,14 +4087,14 @@ fn add_def_to_module<'a>(
|
||||||
if is_exposed {
|
if is_exposed {
|
||||||
let annotation = def.expr_var;
|
let annotation = def.expr_var;
|
||||||
|
|
||||||
let layout = match layout_cache.from_var(
|
let top_level = match layout_cache.from_var(
|
||||||
mono_env.arena,
|
mono_env.arena,
|
||||||
annotation,
|
annotation,
|
||||||
mono_env.subs,
|
mono_env.subs,
|
||||||
) {
|
) {
|
||||||
Ok(l) => {
|
Ok(l) => {
|
||||||
// remember, this is a 0-argument thunk
|
// remember, this is a 0-argument thunk
|
||||||
Layout::FunctionPointer(&[], mono_env.arena.alloc(l))
|
ProcLayout::new(mono_env.arena, &[], l)
|
||||||
}
|
}
|
||||||
Err(LayoutProblem::Erroneous) => {
|
Err(LayoutProblem::Erroneous) => {
|
||||||
let message = "top level function has erroneous type";
|
let message = "top level function has erroneous type";
|
||||||
|
@ -4115,7 +4115,7 @@ fn add_def_to_module<'a>(
|
||||||
|
|
||||||
procs.insert_exposed(
|
procs.insert_exposed(
|
||||||
symbol,
|
symbol,
|
||||||
TopLevelFunctionLayout::from_layout(mono_env.arena, layout),
|
top_level,
|
||||||
mono_env.arena,
|
mono_env.arena,
|
||||||
mono_env.subs,
|
mono_env.subs,
|
||||||
def.annotation,
|
def.annotation,
|
||||||
|
|
|
@ -396,17 +396,15 @@ impl<'a> PackageModuleIds<'a> {
|
||||||
fn insert_debug_name(module_id: ModuleId, module_name: &PQModuleName) {
|
fn insert_debug_name(module_id: ModuleId, module_name: &PQModuleName) {
|
||||||
let mut names = DEBUG_MODULE_ID_NAMES.lock().expect("Failed to acquire lock for Debug interning into DEBUG_MODULE_ID_NAMES, presumably because a thread panicked.");
|
let mut names = DEBUG_MODULE_ID_NAMES.lock().expect("Failed to acquire lock for Debug interning into DEBUG_MODULE_ID_NAMES, presumably because a thread panicked.");
|
||||||
|
|
||||||
if !names.contains_key(&module_id.0) {
|
names
|
||||||
match module_name {
|
.entry(module_id.0)
|
||||||
PQModuleName::Unqualified(module) => {
|
.or_insert_with(|| match module_name {
|
||||||
names.insert(module_id.0, module.to_string().into());
|
PQModuleName::Unqualified(module) => module.to_string().into(),
|
||||||
}
|
|
||||||
PQModuleName::Qualified(package, module) => {
|
PQModuleName::Qualified(package, module) => {
|
||||||
let name = format!("{}.{}", package, module).into();
|
let name = format!("{}.{}", package, module).into();
|
||||||
names.insert(module_id.0, name);
|
name
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
|
@ -464,9 +462,9 @@ impl ModuleIds {
|
||||||
let mut names = DEBUG_MODULE_ID_NAMES.lock().expect("Failed to acquire lock for Debug interning into DEBUG_MODULE_ID_NAMES, presumably because a thread panicked.");
|
let mut names = DEBUG_MODULE_ID_NAMES.lock().expect("Failed to acquire lock for Debug interning into DEBUG_MODULE_ID_NAMES, presumably because a thread panicked.");
|
||||||
|
|
||||||
// TODO make sure modules are never added more than once!
|
// TODO make sure modules are never added more than once!
|
||||||
if !names.contains_key(&module_id.0) {
|
names
|
||||||
names.insert(module_id.0, module_name.to_string().into());
|
.entry(module_id.0)
|
||||||
}
|
.or_insert_with(|| module_name.to_string().into());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
|
|
|
@ -144,7 +144,7 @@ where
|
||||||
"{:?}: {:?} with {:?} args",
|
"{:?}: {:?} with {:?} args",
|
||||||
proc.name,
|
proc.name,
|
||||||
bytes_as_ascii(&bytes),
|
bytes_as_ascii(&bytes),
|
||||||
proc.args.len()
|
(proc.args, proc.ret_layout),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,10 +173,7 @@ where
|
||||||
morphic_lib::solve(program)
|
morphic_lib::solve(program)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_entry_point(
|
fn build_entry_point(layout: crate::ir::ProcLayout, func_name: FuncName) -> Result<FuncDef> {
|
||||||
layout: crate::ir::TopLevelFunctionLayout,
|
|
||||||
func_name: FuncName,
|
|
||||||
) -> Result<FuncDef> {
|
|
||||||
let mut builder = FuncDefBuilder::new();
|
let mut builder = FuncDefBuilder::new();
|
||||||
let block = builder.add_block();
|
let block = builder.add_block();
|
||||||
|
|
||||||
|
@ -976,7 +973,6 @@ fn layout_spec(builder: &mut FuncDefBuilder, layout: &Layout) -> Result<TypeId>
|
||||||
} => worst_case_type(builder),
|
} => worst_case_type(builder),
|
||||||
},
|
},
|
||||||
RecursivePointer => worst_case_type(builder),
|
RecursivePointer => worst_case_type(builder),
|
||||||
FunctionPointer(_, _) => todo!(),
|
|
||||||
Closure(_, lambda_set, _) => layout_spec(builder, &lambda_set.runtime_representation()),
|
Closure(_, lambda_set, _) => layout_spec(builder, &lambda_set.runtime_representation()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::ir::{Expr, JoinPointId, Param, Proc, Stmt, TopLevelFunctionLayout};
|
use crate::ir::{Expr, JoinPointId, Param, Proc, ProcLayout, Stmt};
|
||||||
use crate::layout::Layout;
|
use crate::layout::Layout;
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
@ -18,7 +18,7 @@ fn should_borrow_layout(layout: &Layout) -> bool {
|
||||||
|
|
||||||
pub fn infer_borrow<'a>(
|
pub fn infer_borrow<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
procs: &MutMap<(Symbol, TopLevelFunctionLayout<'a>), Proc<'a>>,
|
procs: &MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
|
||||||
) -> ParamMap<'a> {
|
) -> ParamMap<'a> {
|
||||||
let mut param_map = ParamMap {
|
let mut param_map = ParamMap {
|
||||||
items: MutMap::default(),
|
items: MutMap::default(),
|
||||||
|
@ -67,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, TopLevelFunctionLayout<'a>),
|
Declaration(Symbol, ProcLayout<'a>),
|
||||||
JoinPoint(JoinPointId),
|
JoinPoint(JoinPointId),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,11 +96,7 @@ impl<'a> IntoIterator for &'a ParamMap<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ParamMap<'a> {
|
impl<'a> ParamMap<'a> {
|
||||||
pub fn get_symbol(
|
pub fn get_symbol(&self, symbol: Symbol, layout: ProcLayout<'a>) -> Option<&'a [Param<'a>]> {
|
||||||
&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()
|
||||||
|
@ -155,12 +151,7 @@ impl<'a> ParamMap<'a> {
|
||||||
.into_bump_slice()
|
.into_bump_slice()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_proc(
|
fn visit_proc(&mut self, arena: &'a Bump, proc: &Proc<'a>, key: (Symbol, ProcLayout<'a>)) {
|
||||||
&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;
|
||||||
|
@ -178,7 +169,7 @@ impl<'a> ParamMap<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
proc: &Proc<'a>,
|
proc: &Proc<'a>,
|
||||||
key: (Symbol, TopLevelFunctionLayout<'a>),
|
key: (Symbol, ProcLayout<'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),
|
||||||
|
@ -371,7 +362,7 @@ impl<'a> BorrowInfState<'a> {
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let top_level = TopLevelFunctionLayout::new(self.arena, arg_layouts, *ret_layout);
|
let top_level = ProcLayout::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
|
||||||
|
@ -414,7 +405,7 @@ impl<'a> BorrowInfState<'a> {
|
||||||
|
|
||||||
debug_assert!(op.is_higher_order());
|
debug_assert!(op.is_higher_order());
|
||||||
|
|
||||||
let closure_layout = TopLevelFunctionLayout {
|
let closure_layout = ProcLayout {
|
||||||
arguments: arg_layouts,
|
arguments: arg_layouts,
|
||||||
result: *ret_layout,
|
result: *ret_layout,
|
||||||
};
|
};
|
||||||
|
@ -609,7 +600,7 @@ 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);
|
let top_level = ProcLayout::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)
|
||||||
|
@ -702,7 +693,7 @@ impl<'a> BorrowInfState<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_proc(&mut self, proc: &Proc<'a>, layout: TopLevelFunctionLayout<'a>) {
|
fn collect_proc(&mut self, proc: &Proc<'a>, layout: ProcLayout<'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();
|
||||||
|
|
|
@ -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, TopLevelFunctionLayout};
|
use crate::ir::{Expr, JoinPointId, ModifyRc, Param, Proc, ProcLayout, Stmt};
|
||||||
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,7 @@ 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 = TopLevelFunctionLayout {
|
let function_layout = ProcLayout {
|
||||||
arguments: arg_layouts,
|
arguments: arg_layouts,
|
||||||
result: *ret_layout,
|
result: *ret_layout,
|
||||||
};
|
};
|
||||||
|
@ -687,7 +687,7 @@ impl<'a> Context<'a> {
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let top_level = TopLevelFunctionLayout::new(self.arena, arg_layouts, *ret_layout);
|
let top_level = ProcLayout::new(self.arena, arg_layouts, *ret_layout);
|
||||||
|
|
||||||
// get the borrow signature
|
// get the borrow signature
|
||||||
let ps = self
|
let ps = self
|
||||||
|
@ -976,8 +976,7 @@ impl<'a> Context<'a> {
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let top_level =
|
let top_level = ProcLayout::new(self.arena, arg_layouts, *ret_layout);
|
||||||
TopLevelFunctionLayout::new(self.arena, arg_layouts, *ret_layout);
|
|
||||||
|
|
||||||
// get the borrow signature
|
// get the borrow signature
|
||||||
let ps = self
|
let ps = self
|
||||||
|
@ -1236,7 +1235,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: TopLevelFunctionLayout<'a>,
|
layout: ProcLayout<'a>,
|
||||||
) {
|
) {
|
||||||
let ctx = Context::new(arena, param_map);
|
let ctx = Context::new(arena, param_map);
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -20,19 +20,24 @@ impl Layout<'_> {
|
||||||
pub const TAG_SIZE: Layout<'static> = Layout::Builtin(Builtin::Int64);
|
pub const TAG_SIZE: Layout<'static> = Layout::Builtin(Builtin::Int64);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum InPlace {
|
|
||||||
InPlace,
|
|
||||||
Clone,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum LayoutProblem {
|
pub enum LayoutProblem {
|
||||||
UnresolvedTypeVar(Variable),
|
UnresolvedTypeVar(Variable),
|
||||||
Erroneous,
|
Erroneous,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum RawFunctionLayout<'a> {
|
||||||
|
Function(&'a [Layout<'a>], LambdaSet<'a>, &'a Layout<'a>),
|
||||||
|
ZeroArgumentThunk(Layout<'a>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawFunctionLayout<'_> {
|
||||||
|
pub fn is_zero_argument_thunk(&self) -> bool {
|
||||||
|
matches!(self, RawFunctionLayout::ZeroArgumentThunk(_))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Types for code gen must be monomorphic. No type variables allowed!
|
/// Types for code gen must be monomorphic. No type variables allowed!
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum Layout<'a> {
|
pub enum Layout<'a> {
|
||||||
|
@ -45,23 +50,9 @@ pub enum Layout<'a> {
|
||||||
RecursivePointer,
|
RecursivePointer,
|
||||||
|
|
||||||
/// A function. The types of its arguments, then the type of its return value.
|
/// A function. The types of its arguments, then the type of its return value.
|
||||||
FunctionPointer(&'a [Layout<'a>], &'a Layout<'a>),
|
|
||||||
Closure(&'a [Layout<'a>], LambdaSet<'a>, &'a Layout<'a>),
|
Closure(&'a [Layout<'a>], LambdaSet<'a>, &'a Layout<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Layout<'a> {
|
|
||||||
pub fn in_place(&self) -> InPlace {
|
|
||||||
match self {
|
|
||||||
Layout::Builtin(Builtin::EmptyList) => InPlace::InPlace,
|
|
||||||
Layout::Builtin(Builtin::List(_)) => InPlace::Clone,
|
|
||||||
Layout::Builtin(Builtin::EmptyStr) => InPlace::InPlace,
|
|
||||||
Layout::Builtin(Builtin::Str) => InPlace::Clone,
|
|
||||||
Layout::Builtin(Builtin::Int1) => InPlace::Clone,
|
|
||||||
_ => unreachable!("Layout {:?} does not have an inplace", self),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum UnionLayout<'a> {
|
pub enum UnionLayout<'a> {
|
||||||
/// A non-recursive tag union
|
/// A non-recursive tag union
|
||||||
|
@ -89,9 +80,9 @@ pub enum UnionLayout<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> UnionLayout<'a> {
|
impl<'a> UnionLayout<'a> {
|
||||||
pub fn to_doc<'b, D, A>(&'b self, alloc: &'b D, _parens: Parens) -> DocBuilder<'b, D, A>
|
pub fn to_doc<D, A>(self, alloc: &'a D, _parens: Parens) -> DocBuilder<'a, D, A>
|
||||||
where
|
where
|
||||||
D: DocAllocator<'b, A>,
|
D: DocAllocator<'a, A>,
|
||||||
D::Doc: Clone,
|
D::Doc: Clone,
|
||||||
A: Clone,
|
A: Clone,
|
||||||
{
|
{
|
||||||
|
@ -192,32 +183,31 @@ impl<'a> LambdaSet<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extend_function_layout(
|
pub fn extend_argument_list(
|
||||||
&self,
|
&self,
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
argument_layouts: &'a [Layout<'a>],
|
argument_layouts: &'a [Layout<'a>],
|
||||||
ret_layout: &'a Layout<'a>,
|
) -> &'a [Layout<'a>] {
|
||||||
) -> Layout<'a> {
|
|
||||||
if let [] = self.set {
|
if let [] = self.set {
|
||||||
// TERRIBLE HACK for builting functions
|
// TERRIBLE HACK for builting functions
|
||||||
Layout::FunctionPointer(argument_layouts, ret_layout)
|
argument_layouts
|
||||||
} else {
|
} else {
|
||||||
match self.representation {
|
match self.representation {
|
||||||
Layout::Struct(&[]) => {
|
Layout::Struct(&[]) => {
|
||||||
// this function does not have anything in its closure, and the lambda set is a
|
// this function does not have anything in its closure, and the lambda set is a
|
||||||
// singleton, so we pass no extra argument
|
// singleton, so we pass no extra argument
|
||||||
Layout::FunctionPointer(argument_layouts, ret_layout)
|
argument_layouts
|
||||||
}
|
}
|
||||||
Layout::Builtin(Builtin::Int1) | Layout::Builtin(Builtin::Int8) => {
|
Layout::Builtin(Builtin::Int1) | Layout::Builtin(Builtin::Int8) => {
|
||||||
// we don't pass this along either
|
// we don't pass this along either
|
||||||
Layout::FunctionPointer(argument_layouts, ret_layout)
|
argument_layouts
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut arguments = Vec::with_capacity_in(argument_layouts.len() + 1, arena);
|
let mut arguments = Vec::with_capacity_in(argument_layouts.len() + 1, arena);
|
||||||
arguments.extend(argument_layouts);
|
arguments.extend(argument_layouts);
|
||||||
arguments.push(self.runtime_representation());
|
arguments.push(self.runtime_representation());
|
||||||
|
|
||||||
Layout::FunctionPointer(arguments.into_bump_slice(), ret_layout)
|
arguments.into_bump_slice()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -503,10 +493,6 @@ impl<'a> Layout<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FunctionPointer(_, _) => {
|
|
||||||
// Function pointers are immutable and can always be safely copied
|
|
||||||
true
|
|
||||||
}
|
|
||||||
Closure(_, closure_layout, _) => closure_layout.safe_to_memcpy(),
|
Closure(_, closure_layout, _) => closure_layout.safe_to_memcpy(),
|
||||||
RecursivePointer => {
|
RecursivePointer => {
|
||||||
// We cannot memcpy pointers, because then we would have the same pointer in multiple places!
|
// We cannot memcpy pointers, because then we would have the same pointer in multiple places!
|
||||||
|
@ -558,7 +544,6 @@ impl<'a> Layout<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Closure(_, lambda_set, _) => lambda_set.stack_size(pointer_size),
|
Closure(_, lambda_set, _) => lambda_set.stack_size(pointer_size),
|
||||||
FunctionPointer(_, _) => pointer_size,
|
|
||||||
RecursivePointer => pointer_size,
|
RecursivePointer => pointer_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -590,7 +575,6 @@ impl<'a> Layout<'a> {
|
||||||
}
|
}
|
||||||
Layout::Builtin(builtin) => builtin.alignment_bytes(pointer_size),
|
Layout::Builtin(builtin) => builtin.alignment_bytes(pointer_size),
|
||||||
Layout::RecursivePointer => pointer_size,
|
Layout::RecursivePointer => pointer_size,
|
||||||
Layout::FunctionPointer(_, _) => pointer_size,
|
|
||||||
Layout::Closure(_, captured, _) => {
|
Layout::Closure(_, captured, _) => {
|
||||||
pointer_size.max(captured.alignment_bytes(pointer_size))
|
pointer_size.max(captured.alignment_bytes(pointer_size))
|
||||||
}
|
}
|
||||||
|
@ -645,13 +629,12 @@ impl<'a> Layout<'a> {
|
||||||
}
|
}
|
||||||
RecursivePointer => true,
|
RecursivePointer => true,
|
||||||
Closure(_, closure_layout, _) => closure_layout.contains_refcounted(),
|
Closure(_, closure_layout, _) => closure_layout.contains_refcounted(),
|
||||||
FunctionPointer(_, _) => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_doc<'b, D, A>(&'b self, alloc: &'b D, parens: Parens) -> DocBuilder<'b, D, A>
|
pub fn to_doc<D, A>(self, alloc: &'a D, parens: Parens) -> DocBuilder<'a, D, A>
|
||||||
where
|
where
|
||||||
D: DocAllocator<'b, A>,
|
D: DocAllocator<'a, A>,
|
||||||
D::Doc: Clone,
|
D::Doc: Clone,
|
||||||
A: Clone,
|
A: Clone,
|
||||||
{
|
{
|
||||||
|
@ -669,14 +652,6 @@ impl<'a> Layout<'a> {
|
||||||
}
|
}
|
||||||
Union(union_layout) => union_layout.to_doc(alloc, parens),
|
Union(union_layout) => union_layout.to_doc(alloc, parens),
|
||||||
RecursivePointer => alloc.text("*self"),
|
RecursivePointer => alloc.text("*self"),
|
||||||
FunctionPointer(args, result) => {
|
|
||||||
let args_doc = args.iter().map(|x| x.to_doc(alloc, Parens::InFunction));
|
|
||||||
|
|
||||||
alloc
|
|
||||||
.intersperse(args_doc, ", ")
|
|
||||||
.append(alloc.text(" -> "))
|
|
||||||
.append(result.to_doc(alloc, Parens::InFunction))
|
|
||||||
}
|
|
||||||
Closure(args, closure_layout, result) => {
|
Closure(args, closure_layout, result) => {
|
||||||
let args_doc = args.iter().map(|x| x.to_doc(alloc, Parens::InFunction));
|
let args_doc = args.iter().map(|x| x.to_doc(alloc, Parens::InFunction));
|
||||||
|
|
||||||
|
@ -725,8 +700,6 @@ impl<'a> CachedVariable<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// use ven_ena::unify::{InPlace, Snapshot, UnificationTable, UnifyKey};
|
|
||||||
|
|
||||||
impl<'a> ven_ena::unify::UnifyKey for CachedVariable<'a> {
|
impl<'a> ven_ena::unify::UnifyKey for CachedVariable<'a> {
|
||||||
type Value = CachedLayout<'a>;
|
type Value = CachedLayout<'a>;
|
||||||
|
|
||||||
|
@ -796,7 +769,7 @@ impl<'a> LayoutCache<'a> {
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
var: Variable,
|
var: Variable,
|
||||||
subs: &Subs,
|
subs: &Subs,
|
||||||
) -> Result<Layout<'a>, LayoutProblem> {
|
) -> Result<RawFunctionLayout<'a>, LayoutProblem> {
|
||||||
// Store things according to the root Variable, to avoid duplicate work.
|
// Store things according to the root Variable, to avoid duplicate work.
|
||||||
let var = subs.get_root_key_without_compacting(var);
|
let var = subs.get_root_key_without_compacting(var);
|
||||||
|
|
||||||
|
@ -806,31 +779,18 @@ impl<'a> LayoutCache<'a> {
|
||||||
|
|
||||||
use CachedLayout::*;
|
use CachedLayout::*;
|
||||||
match self.layouts.probe_value(cached_var) {
|
match self.layouts.probe_value(cached_var) {
|
||||||
Cached(result) => Ok(result),
|
|
||||||
Problem(problem) => Err(problem),
|
Problem(problem) => Err(problem),
|
||||||
NotCached => {
|
Cached(_) | NotCached => {
|
||||||
let mut env = Env {
|
let mut env = Env {
|
||||||
arena,
|
arena,
|
||||||
subs,
|
subs,
|
||||||
seen: MutSet::default(),
|
seen: MutSet::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = Layout::from_var(&mut env, var);
|
Layout::from_var(&mut env, var).map(|l| match l {
|
||||||
|
Layout::Closure(a, b, c) => RawFunctionLayout::Function(a, b, c),
|
||||||
// Don't actually cache. The layout cache is very hard to get right in the presence
|
other => RawFunctionLayout::ZeroArgumentThunk(other),
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -959,9 +919,9 @@ impl<'a> Builtin<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_doc<'b, D, A>(&'b self, alloc: &'b D, _parens: Parens) -> DocBuilder<'b, D, A>
|
pub fn to_doc<D, A>(self, alloc: &'a D, _parens: Parens) -> DocBuilder<'a, D, A>
|
||||||
where
|
where
|
||||||
D: DocAllocator<'b, A>,
|
D: DocAllocator<'a, A>,
|
||||||
D::Doc: Clone,
|
D::Doc: Clone,
|
||||||
A: Clone,
|
A: Clone,
|
||||||
{
|
{
|
||||||
|
@ -1953,7 +1913,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>,
|
toplevels_by_id: MutMap<crate::ir::ProcLayout<'a>, u32>,
|
||||||
next_id: u32,
|
next_id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1993,7 +1953,7 @@ impl<'a> LayoutIds<'a> {
|
||||||
pub fn get_toplevel<'b>(
|
pub fn get_toplevel<'b>(
|
||||||
&mut self,
|
&mut self,
|
||||||
symbol: Symbol,
|
symbol: Symbol,
|
||||||
layout: &'b crate::ir::TopLevelFunctionLayout<'a>,
|
layout: &'b crate::ir::ProcLayout<'a>,
|
||||||
) -> LayoutId {
|
) -> LayoutId {
|
||||||
// Note: this function does some weird stuff to satisfy the borrow checker.
|
// Note: this function does some weird stuff to satisfy the borrow checker.
|
||||||
// There's probably a nicer way to write it that still works.
|
// There's probably a nicer way to write it that still works.
|
||||||
|
|
|
@ -23,7 +23,7 @@ use roc_collections::all::MutMap;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_mono::ir::Proc;
|
use roc_mono::ir::Proc;
|
||||||
|
|
||||||
use roc_mono::ir::TopLevelFunctionLayout;
|
use roc_mono::ir::ProcLayout;
|
||||||
|
|
||||||
/// Without this, some tests pass in `cargo test --release` but fail without
|
/// Without this, some tests pass in `cargo test --release` but fail without
|
||||||
/// the --release flag because they run out of stack space. This increases
|
/// the --release flag because they run out of stack space. This increases
|
||||||
|
@ -146,7 +146,7 @@ fn compiles_to_ir(test_name: &str, src: &str) {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
fn verify_procedures(
|
fn verify_procedures(
|
||||||
test_name: &str,
|
test_name: &str,
|
||||||
procedures: MutMap<(Symbol, TopLevelFunctionLayout<'_>), Proc<'_>>,
|
procedures: MutMap<(Symbol, ProcLayout<'_>), Proc<'_>>,
|
||||||
main_fn_symbol: Symbol,
|
main_fn_symbol: Symbol,
|
||||||
) {
|
) {
|
||||||
let index = procedures
|
let index = procedures
|
||||||
|
@ -205,7 +205,7 @@ fn verify_procedures(
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
fn verify_procedures(
|
fn verify_procedures(
|
||||||
_expected: &str,
|
_expected: &str,
|
||||||
_procedures: MutMap<(Symbol, TopLevelFunctionLayout<'_>), Proc<'_>>,
|
_procedures: MutMap<(Symbol, ProcLayout<'_>), Proc<'_>>,
|
||||||
_main_fn_symbol: Symbol,
|
_main_fn_symbol: Symbol,
|
||||||
) {
|
) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue