diff --git a/compiler/build/src/program.rs b/compiler/build/src/program.rs index bffd546449..09367a4b24 100644 --- a/compiler/build/src/program.rs +++ b/compiler/build/src/program.rs @@ -372,6 +372,7 @@ pub fn gen_from_mono_module( for ((symbol, layout), proc) in loaded.procedures { let fn_val = build_proc_header(&env, &mut layout_ids, symbol, &layout, &proc); + dbg!(&fn_val); headers.push((proc, fn_val)); } @@ -395,7 +396,7 @@ pub fn gen_from_mono_module( } // Uncomment this to see the module's optimized LLVM instruction output: - // env.module.print_to_stderr(); + env.module.print_to_stderr(); mpm.run_on(module); diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index 2d422b8f79..c339cf65b2 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -1899,17 +1899,18 @@ fn call_with_args<'a, 'ctx, 'env>( let fn_name = layout_ids .get(symbol, layout) .to_symbol_string(symbol, &env.interns); + let fn_name = fn_name.as_str(); - let fn_val = env - .module - .get_function(fn_name.as_str()) - .unwrap_or_else(|| { - if symbol.is_builtin() { - panic!("Unrecognized builtin function: {:?}", symbol) - } else { - panic!("Unrecognized non-builtin function: {:?}", symbol) - } - }); + let fn_val = env.module.get_function(fn_name).unwrap_or_else(|| { + if symbol.is_builtin() { + panic!("Unrecognized builtin function: {:?}", fn_name) + } else { + panic!( + "Unrecognized non-builtin function: {:?} {:?}", + fn_name, layout + ) + } + }); let call = env.builder.build_call(fn_val, args, "call"); diff --git a/compiler/mono/Cargo.toml b/compiler/mono/Cargo.toml index 5301d0bdc3..079e0f0da0 100644 --- a/compiler/mono/Cargo.toml +++ b/compiler/mono/Cargo.toml @@ -12,6 +12,8 @@ roc_module = { path = "../module" } roc_types = { path = "../types" } roc_can = { path = "../can" } roc_unify = { path = "../unify" } +roc_constrain = { path = "../constrain" } +roc_solve = { path = "../solve" } roc_problem = { path = "../problem" } ven_pretty = { path = "../../vendor/pretty" } bumpalo = { version = "3.2", features = ["collections"] } diff --git a/compiler/mono/src/ir.rs b/compiler/mono/src/ir.rs index 3ec87e91ab..1696f2c916 100644 --- a/compiler/mono/src/ir.rs +++ b/compiler/mono/src/ir.rs @@ -1208,30 +1208,44 @@ pub fn specialize_all<'a>( mut procs: Procs<'a>, layout_cache: &mut LayoutCache<'a>, ) -> Procs<'a> { - let mut pending_specializations = procs.pending_specializations.unwrap_or_default(); - // add the specializations that other modules require of us use roc_constrain::module::{to_type, FreeVars}; - use roc_solve::solve::insert_type_into_subs; - for (name, solved_type) in procs.externals_others_need.drain() { + use roc_solve::solve::{insert_type_into_subs, unsafe_copy_var_help}; + use roc_types::subs::VarStore; + + let it = procs.externals_others_need.clone(); + for (name, solved_type) in it.into_iter() { + let snapshot = env.subs.snapshot(); + let mut free_vars = FreeVars::default(); - let mut var_store = (); - let normal_type = to_type(solved_type, &mut free_vars, &mut var_store); + let mut var_store = VarStore::new_from_subs(env.subs); + + let normal_type = to_type(&solved_type, &mut free_vars, &mut var_store); + dbg!(name, &normal_type); + + let next = var_store.fresh().index(); + let variables_introduced = next as usize - (env.subs.len() - 1); + + env.subs.extend_by(variables_introduced); + let fn_var = insert_type_into_subs(env.subs, &normal_type); let layout = layout_cache .from_var(&env.arena, fn_var, env.subs) .unwrap_or_else(|err| panic!("TODO handle invalid function {:?}", err)); - let partial_proc = match procs.partial_procs.get(&name) { + let mut partial_proc = match procs.partial_procs.get(&name) { Some(v) => v.clone(), None => { unreachable!("now this is an error"); } }; + partial_proc.annotation = unsafe_copy_var_help(env.subs, partial_proc.annotation); + match specialize_external(env, &mut procs, name, layout_cache, fn_var, partial_proc) { Ok(proc) => { + dbg!(name, &layout); procs.specialized.insert((name, layout), Done(proc)); } Err(error) => { @@ -1243,8 +1257,12 @@ pub fn specialize_all<'a>( procs.runtime_errors.insert(name, error_msg); } } + + env.subs.rollback_to(snapshot); } + let mut pending_specializations = procs.pending_specializations.unwrap_or_default(); + // When calling from_can, pending_specializations should be unavailable. // This must be a single pass, and we must not add any more entries to it! procs.pending_specializations = None; diff --git a/compiler/solve/src/solve.rs b/compiler/solve/src/solve.rs index 084aa7fc1b..12a86a0618 100644 --- a/compiler/solve/src/solve.rs +++ b/compiler/solve/src/solve.rs @@ -1191,6 +1191,13 @@ fn introduce(subs: &mut Subs, rank: Rank, pools: &mut Pools, vars: &[Variable]) pool.extend(vars); } +pub fn unsafe_copy_var_help(subs: &mut Subs, var: Variable) -> Variable { + let rank = Rank::NONE; + let mut pools = Pools::default(); + + deep_copy_var(subs, rank, &mut pools, var) +} + fn deep_copy_var(subs: &mut Subs, rank: Rank, pools: &mut Pools, var: Variable) -> Variable { let copy = deep_copy_var_help(subs, rank, pools, var); diff --git a/compiler/types/src/subs.rs b/compiler/types/src/subs.rs index b47fa193ab..7322448633 100644 --- a/compiler/types/src/subs.rs +++ b/compiler/types/src/subs.rs @@ -72,6 +72,14 @@ impl VarStore { VarStore { next: next_var.0 } } + pub fn new_from_subs(subs: &Subs) -> Self { + // TODO why -2, are we not overwriting something here? + let next_var = (subs.utable.len() - 1) as u32; + debug_assert!(next_var >= Variable::FIRST_USER_SPACE_VAR.0); + + VarStore { next: next_var } + } + pub fn fresh(&mut self) -> Variable { // Increment the counter and return the value it had before it was incremented. let answer = self.next; @@ -163,6 +171,10 @@ impl Variable { pub unsafe fn unsafe_test_debug_variable(v: u32) -> Self { Variable(v) } + + pub fn index(&self) -> u32 { + self.0 + } } impl Into for Variable { @@ -255,6 +267,12 @@ impl Subs { subs } + pub fn extend_by(&mut self, entries: usize) { + for _ in self.len()..entries { + self.utable.new_key(flex_var_descriptor()); + } + } + pub fn fresh(&mut self, value: Descriptor) -> Variable { self.utable.new_key(value) }