diff --git a/compiler/build/src/program.rs b/compiler/build/src/program.rs index 938f8dfe4c..b75d7c397e 100644 --- a/compiler/build/src/program.rs +++ b/compiler/build/src/program.rs @@ -2,7 +2,7 @@ use crate::target; use bumpalo::Bump; use inkwell::context::Context; use inkwell::targets::{CodeModel, FileType, RelocMode}; -use inkwell::values::FunctionValue; +pub use roc_gen::llvm::build::FunctionIterator; use roc_gen::llvm::build::{ build_proc, build_proc_header_new, module_from_builtins, OptLevel, Scope, }; @@ -289,30 +289,3 @@ pub fn gen_from_mono_module( emit_o_file, } } - -pub struct FunctionIterator<'ctx> { - next: Option>, -} - -impl<'ctx> FunctionIterator<'ctx> { - pub fn from_module(module: &inkwell::module::Module<'ctx>) -> Self { - Self { - next: module.get_first_function(), - } - } -} - -impl<'ctx> Iterator for FunctionIterator<'ctx> { - type Item = FunctionValue<'ctx>; - - fn next(&mut self) -> Option { - match self.next { - Some(function) => { - self.next = function.get_next_function(); - - Some(function) - } - None => None, - } - } -} diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index 6e56de8c46..9ec366d8e7 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -100,6 +100,34 @@ impl From for OptimizationLevel { } } +/// Iterate over all functions in an llvm module +pub struct FunctionIterator<'ctx> { + next: Option>, +} + +impl<'ctx> FunctionIterator<'ctx> { + pub fn from_module(module: &inkwell::module::Module<'ctx>) -> Self { + Self { + next: module.get_first_function(), + } + } +} + +impl<'ctx> Iterator for FunctionIterator<'ctx> { + type Item = FunctionValue<'ctx>; + + fn next(&mut self) -> Option { + match self.next { + Some(function) => { + self.next = function.get_next_function(); + + Some(function) + } + None => None, + } + } +} + #[derive(Default, Debug, Clone, PartialEq)] pub struct Scope<'a, 'ctx> { symbols: ImMap, BasicValueEnum<'ctx>)>, @@ -3069,7 +3097,7 @@ pub fn build_proc_header_new<'a, 'ctx, 'env>( ) -> FunctionValue<'ctx> { let layout = env.arena.alloc(layout).full(); - dbg!(symbol, layout); + // eprintln!(" {:?}: {:?}\n", symbol, layout); build_proc_header(env, layout_ids, symbol, &layout, proc) } diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index b236e65cf4..7b5c02693e 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -1790,8 +1790,17 @@ fn specialize_all_help<'a>( partial_proc, ) { Ok((proc, layout)) => { - let top_level = TopLevelFunctionLayout::from_layout(env.arena, layout); - procs.specialized.insert((name, top_level), Done(proc)); + if procs.module_thunks.contains(&name) { + let top_level = TopLevelFunctionLayout::from_layout(env.arena, layout); + let layout = TopLevelFunctionLayout { + arguments: &[], + result: env.arena.alloc(top_level).full(), + }; + procs.specialized.insert((name, layout), Done(proc)); + } else { + let top_level = TopLevelFunctionLayout::from_layout(env.arena, layout); + procs.specialized.insert((name, top_level), Done(proc)); + } } Err(SpecializeFailure { problem: _, @@ -5822,16 +5831,15 @@ fn reuse_function_symbol<'a>( let function_ptr_layout = TopLevelFunctionLayout::from_layout(env.arena, res_layout.unwrap()); - procs.insert_passed_by_name( - env, - arg_var, - original, - function_ptr_layout, - layout_cache, - ); - if captures { // this is a closure by capture, meaning it itself captures local variables. + procs.insert_passed_by_name( + env, + arg_var, + original, + function_ptr_layout, + layout_cache, + ); let closure_data = symbol; @@ -6170,26 +6178,17 @@ fn call_by_name_help<'a>( } else if env.is_imported_symbol(proc_name) { add_needed_external(procs, env, original_fn_var, proc_name); - let call = if proc_name.module_id() == ModuleId::ATTR { - // the callable is one of the ATTR::ARG_n symbols - // we must call those by-pointer - self::Call { - call_type: CallType::ByPointer { - name: proc_name, - ret_layout: *ret_layout, - full_layout: function_layout, - arg_layouts: argument_layouts, - }, - arguments: field_symbols, - } + debug_assert_ne!(proc_name.module_id(), ModuleId::ATTR); + if field_symbols.is_empty() { + force_thunk(env, proc_name, function_layout, assigned, hole) } else { debug_assert_eq!( argument_layouts.len(), field_symbols.len(), - "scroll up a bit for background {:?}", - proc_name + "see call_by_name for background (scroll down a bit), function is {:?}", + proc_name, ); - self::Call { + let call = self::Call { call_type: CallType::ByName { name: proc_name, ret_layout: *ret_layout, @@ -6197,14 +6196,13 @@ fn call_by_name_help<'a>( arg_layouts: argument_layouts, }, arguments: field_symbols, - } - }; + }; - let result = build_call(env, call, assigned, *ret_layout, hole); + let result = build_call(env, call, assigned, *ret_layout, hole); - let iter = loc_args.into_iter().rev().zip(field_symbols.iter().rev()); - - assign_to_symbols(env, procs, layout_cache, iter, result) + let iter = loc_args.into_iter().rev().zip(field_symbols.iter().rev()); + assign_to_symbols(env, procs, layout_cache, iter, result) + } } else { let pending = PendingSpecialization::from_var(env.arena, env.subs, fn_var);