mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-11 16:51:53 +03:00
Record LLVM proc headers in a separate pass.
Turns out this was always necessary, and was only working before by chance - because the ordering in the one test we had for this happened to work out.
This commit is contained in:
parent
80511e6381
commit
1fa411f593
@ -401,12 +401,11 @@ pub fn create_entry_block_alloca<'a, 'ctx>(
|
||||
builder.build_alloca(basic_type, name)
|
||||
}
|
||||
|
||||
pub fn build_proc<'a, 'ctx, 'env>(
|
||||
pub fn build_proc_header<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
symbol: Symbol,
|
||||
proc: Proc<'a>,
|
||||
procs: &Procs<'a>,
|
||||
) -> FunctionValue<'ctx> {
|
||||
proc: &Proc<'a>,
|
||||
) -> (FunctionValue<'ctx>, Vec<'a, BasicTypeEnum<'ctx>>) {
|
||||
let args = proc.args;
|
||||
let arena = env.arena;
|
||||
let subs = &env.subs;
|
||||
@ -434,6 +433,19 @@ pub fn build_proc<'a, 'ctx, 'env>(
|
||||
Some(Linkage::Private),
|
||||
);
|
||||
|
||||
(fn_val, arg_basic_types)
|
||||
}
|
||||
|
||||
pub fn build_proc<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
proc: Proc<'a>,
|
||||
procs: &Procs<'a>,
|
||||
fn_val: FunctionValue<'ctx>,
|
||||
arg_basic_types: Vec<'a, BasicTypeEnum<'ctx>>,
|
||||
) {
|
||||
let args = proc.args;
|
||||
let context = &env.context;
|
||||
|
||||
// Add a basic block for the entry point
|
||||
let entry = context.append_basic_block(fn_val, "entry");
|
||||
let builder = env.builder;
|
||||
@ -459,8 +471,6 @@ pub fn build_proc<'a, 'ctx, 'env>(
|
||||
let body = build_expr(env, &scope, fn_val, &proc.body, procs);
|
||||
|
||||
builder.build_return(Some(&body));
|
||||
|
||||
fn_val
|
||||
}
|
||||
|
||||
pub fn verify_fn(fn_val: FunctionValue<'_>) {
|
||||
|
@ -189,12 +189,12 @@ fn from_can<'a>(
|
||||
Expr::Store(stored.into_bump_slice(), arena.alloc(ret))
|
||||
}
|
||||
|
||||
Closure(_, _symbol, _, loc_args, boxed_body) => {
|
||||
Closure(_, _, _, loc_args, boxed_body) => {
|
||||
let (loc_body, ret_var) = *boxed_body;
|
||||
let name =
|
||||
let symbol =
|
||||
name.unwrap_or_else(|| gen_closure_name(procs, &mut env.ident_ids, env.home));
|
||||
|
||||
add_closure(env, name, loc_body.value, ret_var, &loc_args, procs)
|
||||
add_closure(env, symbol, loc_body.value, ret_var, &loc_args, procs)
|
||||
}
|
||||
|
||||
Call(boxed, loc_args, _) => {
|
||||
@ -293,7 +293,7 @@ fn from_can<'a>(
|
||||
|
||||
fn add_closure<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
name: Symbol,
|
||||
symbol: Symbol,
|
||||
can_body: can::expr::Expr,
|
||||
ret_var: Variable,
|
||||
loc_args: &[(Variable, Located<Pattern>)],
|
||||
@ -310,9 +310,9 @@ fn add_closure<'a>(
|
||||
Ok(layout) => layout,
|
||||
Err(()) => {
|
||||
// Invalid closure!
|
||||
procs.insert(name.clone(), None);
|
||||
procs.insert(symbol, None);
|
||||
|
||||
return Expr::FunctionPointer(name);
|
||||
return Expr::FunctionPointer(symbol);
|
||||
}
|
||||
};
|
||||
|
||||
@ -333,9 +333,9 @@ fn add_closure<'a>(
|
||||
ret_var,
|
||||
};
|
||||
|
||||
procs.insert(name.clone(), Some(proc));
|
||||
procs.insert(symbol, Some(proc));
|
||||
|
||||
Expr::FunctionPointer(name)
|
||||
Expr::FunctionPointer(symbol)
|
||||
}
|
||||
|
||||
fn store_pattern<'a>(
|
||||
|
@ -29,7 +29,7 @@ mod test_gen {
|
||||
use roc::crane::build::{declare_proc, define_proc_body, ScopeEntry};
|
||||
use roc::crane::convert::type_from_layout;
|
||||
use roc::infer::infer_expr;
|
||||
use roc::llvm::build::build_proc;
|
||||
use roc::llvm::build::{build_proc, build_proc_header};
|
||||
use roc::llvm::convert::basic_type_from_layout;
|
||||
use roc::mono::expr::Expr;
|
||||
use roc::mono::layout::Layout;
|
||||
@ -230,14 +230,26 @@ mod test_gen {
|
||||
// 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);
|
||||
|
||||
// Add all the Procs to the module
|
||||
for (name, opt_proc) in procs.clone() {
|
||||
let mut headers = Vec::with_capacity(procs.len());
|
||||
|
||||
// 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.clone().into_iter() {
|
||||
if let Some(proc) = opt_proc {
|
||||
let (fn_val, arg_basic_types) = build_proc_header(&env, symbol, &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 {
|
||||
// NOTE: This is here to be uncommented in case verification fails.
|
||||
// (This approach means we don't have to defensively clone name here.)
|
||||
//
|
||||
// println!("\n\nBuilding and then verifying function {}\n\n", name);
|
||||
let fn_val = build_proc(&env, name, proc, &procs);
|
||||
build_proc(&env, proc, &procs, fn_val, arg_basic_types);
|
||||
|
||||
if fn_val.verify(true) {
|
||||
fpm.run_on(&fn_val);
|
||||
@ -246,7 +258,6 @@ mod test_gen {
|
||||
panic!("Non-main function failed LLVM verification. Uncomment the above println to debug!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add main to the module.
|
||||
let main_fn = env.module.add_function(main_fn_name, main_fn_type, None);
|
||||
|
Loading…
Reference in New Issue
Block a user