mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
Use specialize_all
This commit is contained in:
parent
639c132ce0
commit
42e3d35564
4 changed files with 81 additions and 47 deletions
|
@ -5,7 +5,6 @@ use inkwell::passes::PassManager;
|
|||
use inkwell::types::BasicType;
|
||||
use inkwell::OptimizationLevel;
|
||||
use roc_collections::all::ImMap;
|
||||
use roc_collections::all::MutMap;
|
||||
use roc_gen::layout_id::LayoutIds;
|
||||
use roc_gen::llvm::build::{
|
||||
build_proc, build_proc_header, get_call_conventions, module_from_builtins, OptLevel,
|
||||
|
@ -14,7 +13,7 @@ use roc_gen::llvm::convert::basic_type_from_layout;
|
|||
use roc_load::file::LoadedModule;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::expr::{Env, Expr, PartialProc, Procs};
|
||||
use roc_mono::layout::Layout;
|
||||
use roc_mono::layout::{Layout, LayoutCache};
|
||||
|
||||
use inkwell::targets::{
|
||||
CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetTriple,
|
||||
|
@ -23,6 +22,7 @@ use std::path::{Path, PathBuf};
|
|||
use target_lexicon::{Architecture, OperatingSystem, Triple, Vendor};
|
||||
|
||||
// TODO this should probably use more helper functions
|
||||
// TODO make this polymorphic in the llvm functions so it can be reused for another backend.
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
pub fn build(
|
||||
arena: &Bump,
|
||||
|
@ -225,25 +225,28 @@ pub fn build(
|
|||
// Populate Procs further and get the low-level Expr from the canonical Expr
|
||||
let main_body = Expr::new(&mut mono_env, loc_expr.value, &mut procs);
|
||||
|
||||
// Put this module's ident_ids back in the interns, so we can use them in env.
|
||||
env.interns.all_ident_ids.insert(home, ident_ids);
|
||||
let mut headers = Vec::with_capacity(procs.pending_specializations.len());
|
||||
let mut layout_cache = LayoutCache::default();
|
||||
|
||||
let mut headers = Vec::with_capacity(procs.len());
|
||||
let (mut proc_map, runtime_errors) = procs.into_map();
|
||||
let (mut specializations, runtime_errors) =
|
||||
roc_mono::expr::specialize_all(&mut mono_env, procs, &mut layout_cache);
|
||||
|
||||
assert_eq!(runtime_errors, roc_collections::all::MutSet::default());
|
||||
|
||||
// Put this module's ident_ids back in the interns, so we can use them in env.
|
||||
// This must happen *after* building the headers, because otherwise there's
|
||||
// a conflicting mutable borrow on ident_ids.
|
||||
env.interns.all_ident_ids.insert(home, ident_ids);
|
||||
|
||||
// Add all the Proc headers to the module.
|
||||
// We have to do this in a separate pass first,
|
||||
// because their bodies may reference each other.
|
||||
for (symbol, mut procs_by_layout) in proc_map.drain() {
|
||||
for (layout, proc) in procs_by_layout.drain() {
|
||||
for (symbol, layout, proc) in specializations.drain(..) {
|
||||
let (fn_val, arg_basic_types) =
|
||||
build_proc_header(&env, &mut layout_ids, symbol, &layout, &proc);
|
||||
|
||||
headers.push((proc, fn_val, arg_basic_types));
|
||||
}
|
||||
}
|
||||
|
||||
// Build each proc using its header info.
|
||||
for (proc, fn_val, arg_basic_types) in headers {
|
||||
|
|
|
@ -75,24 +75,28 @@ macro_rules! assert_llvm_evals_to {
|
|||
};
|
||||
let main_body = Expr::new(&mut mono_env, loc_expr.value, &mut procs);
|
||||
|
||||
// Put this module's ident_ids back in the interns, so we can use them in Env.
|
||||
env.interns.all_ident_ids.insert(home, ident_ids);
|
||||
let mut headers = Vec::with_capacity(procs.pending_specializations.len());
|
||||
let mut layout_cache = roc_mono::layout::LayoutCache::default();
|
||||
|
||||
let mut headers = Vec::with_capacity(procs.len());
|
||||
let (mut proc_map, runtime_errors) = procs.into_map();
|
||||
let (mut specializations, runtime_errors) =
|
||||
roc_mono::expr::specialize_all(&mut mono_env, procs, &mut layout_cache);
|
||||
|
||||
assert_eq!(runtime_errors, roc_collections::all::MutSet::default());
|
||||
|
||||
// Put this module's ident_ids back in the interns, so we can use them in env.
|
||||
// This must happen *after* building the headers, because otherwise there's
|
||||
// a conflicting mutable borrow on ident_ids.
|
||||
env.interns.all_ident_ids.insert(home, ident_ids);
|
||||
|
||||
// Add all the Proc headers to the module.
|
||||
// We have to do this in a separate pass first,
|
||||
// because their bodies may reference each other.
|
||||
for (symbol, mut procs_by_layout) in proc_map.drain() {
|
||||
for (layout, proc) in procs_by_layout.drain() {
|
||||
let (fn_val, arg_basic_types) = build_proc_header(&env, &mut layout_ids, symbol, &layout, &proc);
|
||||
for (symbol, layout, proc) in specializations.drain(..) {
|
||||
let (fn_val, arg_basic_types) =
|
||||
build_proc_header(&env, &mut layout_ids, symbol, &layout, &proc);
|
||||
|
||||
headers.push((proc, fn_val, arg_basic_types));
|
||||
}
|
||||
}
|
||||
|
||||
// Build each proc using its header info.
|
||||
for (proc, fn_val, arg_basic_types) in headers {
|
||||
|
@ -106,7 +110,9 @@ macro_rules! assert_llvm_evals_to {
|
|||
fpm.run_on(&fn_val);
|
||||
} else {
|
||||
// NOTE: If this fails, uncomment the above println to debug.
|
||||
panic!("Non-main function failed LLVM verification. Uncomment the above println to debug!");
|
||||
panic!(
|
||||
"Non-main function failed LLVM verification. Uncomment the above println to debug!"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,24 +246,28 @@ macro_rules! assert_opt_evals_to {
|
|||
};
|
||||
let main_body = Expr::new(&mut mono_env, loc_expr.value, &mut procs);
|
||||
|
||||
// Put this module's ident_ids back in the interns, so we can use them in Env.
|
||||
env.interns.all_ident_ids.insert(home, ident_ids);
|
||||
let mut headers = Vec::with_capacity(procs.pending_specializations.len());
|
||||
let mut layout_cache = roc_mono::layout::LayoutCache::default();
|
||||
|
||||
let mut headers = Vec::with_capacity(procs.len());
|
||||
let (mut proc_map, runtime_errors) = procs.into_map();
|
||||
let (mut specializations, runtime_errors) =
|
||||
roc_mono::expr::specialize_all(&mut mono_env, procs, &mut layout_cache);
|
||||
|
||||
assert_eq!(runtime_errors, roc_collections::all::MutSet::default());
|
||||
|
||||
// Put this module's ident_ids back in the interns, so we can use them in env.
|
||||
// This must happen *after* building the headers, because otherwise there's
|
||||
// a conflicting mutable borrow on ident_ids.
|
||||
env.interns.all_ident_ids.insert(home, ident_ids);
|
||||
|
||||
// Add all the Proc headers to the module.
|
||||
// We have to do this in a separate pass first,
|
||||
// because their bodies may reference each other.
|
||||
for (symbol, mut procs_by_layout) in proc_map.drain() {
|
||||
for (layout, proc) in procs_by_layout.drain() {
|
||||
let (fn_val, arg_basic_types) = build_proc_header(&env, &mut layout_ids, symbol, &layout, &proc);
|
||||
for (symbol, layout, proc) in specializations.drain(..) {
|
||||
let (fn_val, arg_basic_types) =
|
||||
build_proc_header(&env, &mut layout_ids, symbol, &layout, &proc);
|
||||
|
||||
headers.push((proc, fn_val, arg_basic_types));
|
||||
}
|
||||
}
|
||||
|
||||
// Build each proc using its header info.
|
||||
for (proc, fn_val, arg_basic_types) in headers {
|
||||
|
@ -271,7 +281,9 @@ macro_rules! assert_opt_evals_to {
|
|||
fpm.run_on(&fn_val);
|
||||
} else {
|
||||
// NOTE: If this fails, uncomment the above println to debug.
|
||||
panic!("Non-main function failed LLVM verification. Uncomment the above println to debug!");
|
||||
panic!(
|
||||
"Non-main function failed LLVM verification. Uncomment the above println to debug!"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -398,21 +410,28 @@ macro_rules! emit_expr {
|
|||
};
|
||||
let main_body = Expr::new(&mut mono_env, loc_expr.value, &mut procs);
|
||||
|
||||
// Put this module's ident_ids back in the interns, so we can use them in Env.
|
||||
env.interns.all_ident_ids.insert(home, ident_ids);
|
||||
let mut headers = Vec::with_capacity(procs.pending_specializations.len());
|
||||
let mut layout_cache = roc_mono::layout::LayoutCache::default();
|
||||
|
||||
let mut headers = Vec::with_capacity(procs.len());
|
||||
let (mut specializations, runtime_errors) =
|
||||
roc_mono::expr::specialize_all(&mut mono_env, procs, &mut layout_cache);
|
||||
|
||||
assert_eq!(runtime_errors, roc_collections::all::MutSet::default());
|
||||
|
||||
// Put this module's ident_ids back in the interns, so we can use them in env.
|
||||
// This must happen *after* building the headers, because otherwise there's
|
||||
// a conflicting mutable borrow on ident_ids.
|
||||
env.interns.all_ident_ids.insert(home, ident_ids);
|
||||
|
||||
// Add all the Proc headers to the module.
|
||||
// We have to do this in a separate pass first,
|
||||
// because their bodies may reference each other.
|
||||
for (symbol, opt_proc) in procs.as_map().into_iter() {
|
||||
if let Some(proc) = opt_proc {
|
||||
let (fn_val, arg_basic_types) = build_proc_header(&env, symbol, &proc);
|
||||
for (symbol, layout, proc) in specializations.drain(..) {
|
||||
let (fn_val, arg_basic_types) =
|
||||
build_proc_header(&env, &mut layout_ids, symbol, &layout, &proc);
|
||||
|
||||
headers.push((proc, fn_val, arg_basic_types));
|
||||
}
|
||||
}
|
||||
|
||||
// Build each proc using its header info.
|
||||
for (proc, fn_val, arg_basic_types) in headers {
|
||||
|
@ -420,13 +439,15 @@ macro_rules! emit_expr {
|
|||
// (This approach means we don't have to defensively clone name here.)
|
||||
//
|
||||
// println!("\n\nBuilding and then verifying function {}\n\n", name);
|
||||
build_proc(&env, proc, &procs, fn_val, arg_basic_types);
|
||||
build_proc(&env, &mut layout_ids, proc, fn_val, arg_basic_types);
|
||||
|
||||
if fn_val.verify(true) {
|
||||
fpm.run_on(&fn_val);
|
||||
} else {
|
||||
// NOTE: If this fails, uncomment the above println to debug.
|
||||
panic!("Non-main function failed LLVM verification. Uncomment the above println to debug!");
|
||||
panic!(
|
||||
"Non-main function failed LLVM verification. Uncomment the above println to debug!"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ impl Symbol {
|
|||
.get_name(self.module_id())
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"module_string could not find IdentIds for {:?} in interns {:?}",
|
||||
"module_string could not find IdentIds for module {:?} in {:?}",
|
||||
self.module_id(),
|
||||
interns
|
||||
)
|
||||
|
@ -71,7 +71,7 @@ impl Symbol {
|
|||
.get(&self.module_id())
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"ident_string could not find IdentIds for {:?} in interns {:?}",
|
||||
"ident_string could not find IdentIds for module {:?} in {:?}",
|
||||
self.module_id(),
|
||||
interns
|
||||
)
|
||||
|
|
|
@ -1432,9 +1432,17 @@ pub fn specialize_all<'a>(
|
|||
env: &mut Env<'a, '_>,
|
||||
mut procs: Procs<'a>,
|
||||
layout_cache: &mut LayoutCache<'a>,
|
||||
) {
|
||||
) -> (Vec<'a, (Symbol, Layout<'a>, Proc<'a>)>, MutSet<Symbol>) {
|
||||
let mut answer = Vec::with_capacity_in(procs.pending_specializations.len(), env.arena);
|
||||
let mut runtime_errors = MutSet::default();
|
||||
let mut is_finished = procs.pending_specializations.is_empty();
|
||||
|
||||
// TODO replace this synchronous loop with a work-stealing queue which
|
||||
// processes each entry in pending_specializations in parallel, one
|
||||
// module at a time (because the &mut env will need exclusive access to
|
||||
// that module's IdentIds; the only reason Env is &mut in specialize is
|
||||
// that we need to generate unique symbols and register them in them module's
|
||||
// IdentIds).
|
||||
while !is_finished {
|
||||
let Procs {
|
||||
partial_procs,
|
||||
|
@ -1457,10 +1465,10 @@ pub fn specialize_all<'a>(
|
|||
|
||||
match specialize(env, &mut procs, name, layout_cache, pending, partial_proc) {
|
||||
Ok(proc) => {
|
||||
// TODO stuff
|
||||
answer.push((name, layout, proc));
|
||||
}
|
||||
Err(()) => {
|
||||
// TODO runtime error
|
||||
runtime_errors.insert(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1468,6 +1476,8 @@ pub fn specialize_all<'a>(
|
|||
|
||||
is_finished = procs.pending_specializations.is_empty();
|
||||
}
|
||||
|
||||
(answer, runtime_errors)
|
||||
}
|
||||
|
||||
fn specialize<'a>(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue