mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-11 16:51:53 +03:00
Use intern tables over .emit()
This commit is contained in:
parent
3f35aa1f61
commit
1899f30912
@ -15,7 +15,7 @@ use cranelift_module::{Backend, FuncId, Linkage, Module};
|
||||
|
||||
use crate::collections::ImMap;
|
||||
use crate::crane::convert::{sig_from_layout, type_from_layout};
|
||||
use crate::module::symbol::Symbol;
|
||||
use crate::module::symbol::{Interns, Symbol};
|
||||
use crate::mono::expr::{Expr, Proc, Procs};
|
||||
use crate::mono::layout::{Builtin, Layout};
|
||||
use crate::subs::{Subs, Variable};
|
||||
@ -34,6 +34,7 @@ pub struct Env<'a> {
|
||||
pub arena: &'a Bump,
|
||||
pub cfg: TargetFrontendConfig,
|
||||
pub subs: Subs,
|
||||
pub interns: Interns,
|
||||
}
|
||||
|
||||
pub fn build_expr<'a, B: Backend>(
|
||||
@ -421,7 +422,7 @@ fn build_switch<'a, B: Backend>(
|
||||
pub fn declare_proc<'a, B: Backend>(
|
||||
env: &Env<'a>,
|
||||
module: &mut Module<B>,
|
||||
name: Symbol,
|
||||
symbol: Symbol,
|
||||
proc: &Proc<'a>,
|
||||
) -> (FuncId, Signature) {
|
||||
let args = proc.args;
|
||||
@ -448,8 +449,8 @@ pub fn declare_proc<'a, B: Backend>(
|
||||
|
||||
// Declare the function in the module
|
||||
let fn_id = module
|
||||
.declare_function(&name.emit(), Linkage::Local, &sig)
|
||||
.unwrap_or_else(|err| panic!("Error when building function {:?} - {:?}", name, err));
|
||||
.declare_function(symbol.ident_string(&env.interns), Linkage::Local, &sig)
|
||||
.unwrap_or_else(|err| panic!("Error when building function {:?} - {:?}", symbol, err));
|
||||
|
||||
(fn_id, sig)
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ use inkwell::{FloatPredicate, IntPredicate};
|
||||
|
||||
use crate::collections::ImMap;
|
||||
use crate::llvm::convert::{basic_type_from_layout, get_fn_type};
|
||||
use crate::module::symbol::Symbol;
|
||||
use crate::module::symbol::{Interns, Symbol};
|
||||
use crate::mono::expr::{Expr, Proc, Procs};
|
||||
use crate::mono::layout::Layout;
|
||||
use crate::subs::{Subs, Variable};
|
||||
@ -30,6 +30,7 @@ pub struct Env<'a, 'ctx, 'env> {
|
||||
pub context: &'ctx Context,
|
||||
pub builder: &'env Builder<'ctx>,
|
||||
pub module: &'ctx Module<'ctx>,
|
||||
pub interns: Interns,
|
||||
pub subs: Subs,
|
||||
}
|
||||
|
||||
@ -100,7 +101,12 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||
});
|
||||
let val = build_expr(env, &scope, parent, &expr, procs);
|
||||
let expr_bt = basic_type_from_layout(context, &layout);
|
||||
let alloca = create_entry_block_alloca(env, parent, expr_bt, &symbol.emit());
|
||||
let alloca = create_entry_block_alloca(
|
||||
env,
|
||||
parent,
|
||||
expr_bt,
|
||||
symbol.ident_string(&env.interns),
|
||||
);
|
||||
|
||||
env.builder.build_store(alloca, val);
|
||||
|
||||
@ -133,7 +139,7 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||
|
||||
let fn_val = env
|
||||
.module
|
||||
.get_function(&symbol.emit())
|
||||
.get_function(symbol.ident_string(&env.interns))
|
||||
.unwrap_or_else(|| panic!("Unrecognized function: {:?}", symbol));
|
||||
|
||||
let call = env.builder.build_call(fn_val, arg_vals.as_slice(), "tmp");
|
||||
@ -146,7 +152,7 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||
FunctionPointer(ref symbol) => {
|
||||
let ptr = env
|
||||
.module
|
||||
.get_function(&symbol.emit())
|
||||
.get_function(symbol.ident_string(&env.interns))
|
||||
.unwrap_or_else(|| panic!("Could not get pointer to unknown function {:?}", symbol))
|
||||
.as_global_value()
|
||||
.as_pointer_value();
|
||||
@ -177,9 +183,11 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||
.unwrap_or_else(|| panic!("LLVM error: Invalid call by pointer."))
|
||||
}
|
||||
|
||||
Load(name) => match scope.get(name) {
|
||||
Some((_, ptr)) => env.builder.build_load(*ptr, &name.emit()),
|
||||
None => panic!("Could not find a var for {:?} in scope {:?}", name, scope),
|
||||
Load(symbol) => match scope.get(symbol) {
|
||||
Some((_, ptr)) => env
|
||||
.builder
|
||||
.build_load(*ptr, symbol.ident_string(&env.interns)),
|
||||
None => panic!("Could not find a var for {:?} in scope {:?}", symbol, scope),
|
||||
},
|
||||
_ => {
|
||||
panic!("I don't yet know how to LLVM build {:?}", expr);
|
||||
@ -395,7 +403,7 @@ pub fn create_entry_block_alloca<'a, 'ctx>(
|
||||
|
||||
pub fn build_proc<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
name: Symbol,
|
||||
symbol: Symbol,
|
||||
proc: Proc<'a>,
|
||||
procs: &Procs<'a>,
|
||||
) -> FunctionValue<'ctx> {
|
||||
@ -409,20 +417,22 @@ pub fn build_proc<'a, 'ctx, 'env>(
|
||||
.unwrap_or_else(|_| panic!("TODO generate a runtime error in build_proc here!"));
|
||||
let ret_type = basic_type_from_layout(context, &ret_layout);
|
||||
let mut arg_basic_types = Vec::with_capacity_in(args.len(), arena);
|
||||
let mut arg_names = Vec::new_in(arena);
|
||||
let mut arg_symbols = Vec::new_in(arena);
|
||||
|
||||
for (layout, name, _var) in args.iter() {
|
||||
for (layout, arg_symbol, _var) in args.iter() {
|
||||
let arg_type = basic_type_from_layout(env.context, &layout);
|
||||
|
||||
arg_basic_types.push(arg_type);
|
||||
arg_names.push(name);
|
||||
arg_symbols.push(arg_symbol);
|
||||
}
|
||||
|
||||
let fn_type = get_fn_type(&ret_type, &arg_basic_types);
|
||||
|
||||
let fn_val = env
|
||||
.module
|
||||
.add_function(&name.emit(), fn_type, Some(Linkage::Private));
|
||||
let fn_val = env.module.add_function(
|
||||
symbol.ident_string(&env.interns),
|
||||
fn_type,
|
||||
Some(Linkage::Private),
|
||||
);
|
||||
|
||||
// Add a basic block for the entry point
|
||||
let entry = context.append_basic_block(fn_val, "entry");
|
||||
@ -433,16 +443,17 @@ pub fn build_proc<'a, 'ctx, 'env>(
|
||||
let mut scope = ImMap::default();
|
||||
|
||||
// Add args to scope
|
||||
for ((arg_val, arg_type), (_, arg_name, var)) in
|
||||
for ((arg_val, arg_type), (_, arg_symbol, var)) in
|
||||
fn_val.get_param_iter().zip(arg_basic_types).zip(args)
|
||||
{
|
||||
set_name(arg_val, &arg_name.emit());
|
||||
set_name(arg_val, arg_symbol.ident_string(&env.interns));
|
||||
|
||||
let alloca = create_entry_block_alloca(env, fn_val, arg_type, &arg_name.emit());
|
||||
let alloca =
|
||||
create_entry_block_alloca(env, fn_val, arg_type, arg_symbol.ident_string(&env.interns));
|
||||
|
||||
builder.build_store(alloca, arg_val);
|
||||
|
||||
scope.insert(arg_name.clone(), (*var, alloca));
|
||||
scope.insert(*arg_symbol, (*var, alloca));
|
||||
}
|
||||
|
||||
let body = build_expr(env, &scope, fn_val, &proc.body, procs);
|
||||
|
@ -89,13 +89,6 @@ impl Symbol {
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO This function should be deleted, and replaced by using intern table
|
||||
/// lookups instead. (Everywhere this function is used, an &str is expected anyway,
|
||||
/// so using this leads to a ton of unnecessary allocations.)
|
||||
pub fn emit(self) -> String {
|
||||
format!("${}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Rather than displaying as this:
|
||||
|
@ -21,11 +21,11 @@ pub struct Proc<'a> {
|
||||
pub ret_var: Variable,
|
||||
}
|
||||
|
||||
struct Env<'a> {
|
||||
struct Env<'a, 'i> {
|
||||
pub arena: &'a Bump,
|
||||
pub subs: &'a Subs,
|
||||
pub home: ModuleId,
|
||||
pub ident_ids: IdentIds,
|
||||
pub ident_ids: &'i mut IdentIds,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
@ -115,7 +115,7 @@ impl<'a> Expr<'a> {
|
||||
can_expr: can::expr::Expr,
|
||||
procs: &mut Procs<'a>,
|
||||
home: ModuleId,
|
||||
ident_ids: IdentIds,
|
||||
ident_ids: &mut IdentIds,
|
||||
) -> Self {
|
||||
let mut env = Env {
|
||||
arena,
|
||||
@ -129,7 +129,7 @@ impl<'a> Expr<'a> {
|
||||
}
|
||||
|
||||
fn from_can<'a>(
|
||||
env: &mut Env<'a>,
|
||||
env: &mut Env<'a, '_>,
|
||||
can_expr: can::expr::Expr,
|
||||
procs: &mut Procs<'a>,
|
||||
name: Option<Symbol>,
|
||||
@ -292,7 +292,7 @@ fn from_can<'a>(
|
||||
}
|
||||
|
||||
fn add_closure<'a>(
|
||||
env: &mut Env<'a>,
|
||||
env: &mut Env<'a, '_>,
|
||||
name: Symbol,
|
||||
can_body: can::expr::Expr,
|
||||
ret_var: Variable,
|
||||
@ -339,7 +339,7 @@ fn add_closure<'a>(
|
||||
}
|
||||
|
||||
fn store_pattern<'a>(
|
||||
env: &mut Env<'a>,
|
||||
env: &mut Env<'a, '_>,
|
||||
can_pat: Pattern,
|
||||
can_expr: can::expr::Expr,
|
||||
var: Variable,
|
||||
@ -384,7 +384,7 @@ fn gen_closure_name(procs: &Procs<'_>, ident_ids: &mut IdentIds, home: ModuleId)
|
||||
}
|
||||
|
||||
fn from_can_when<'a>(
|
||||
env: &mut Env<'a>,
|
||||
env: &mut Env<'a, '_>,
|
||||
cond_var: Variable,
|
||||
expr_var: Variable,
|
||||
loc_cond: Located<can::expr::Expr>,
|
||||
|
@ -45,7 +45,7 @@ mod test_gen {
|
||||
let mut ctx = module.make_context();
|
||||
let mut func_ctx = FunctionBuilderContext::new();
|
||||
|
||||
let CanExprOut { loc_expr, var_store, var, constraint, home, mut interns, .. } = can_expr($src);
|
||||
let CanExprOut { loc_expr, var_store, var, constraint, home, interns, .. } = can_expr($src);
|
||||
let subs = Subs::new(var_store.into());
|
||||
let mut unify_problems = Vec::new();
|
||||
let (content, solved) = infer_expr(subs, &mut unify_problems, &constraint, var);
|
||||
@ -75,16 +75,20 @@ mod test_gen {
|
||||
|
||||
// Compile and add all the Procs before adding main
|
||||
let mut procs = MutMap::default();
|
||||
let env = roc::crane::build::Env {
|
||||
let mut env = roc::crane::build::Env {
|
||||
arena: &arena,
|
||||
subs,
|
||||
interns,
|
||||
cfg,
|
||||
};
|
||||
|
||||
let ident_ids = interns.all_ident_ids.remove(&home).unwrap();
|
||||
let mut ident_ids = env.interns.all_ident_ids.remove(&home).unwrap();
|
||||
|
||||
// Populate Procs and Subs, and get the low-level Expr from the canonical Expr
|
||||
let mono_expr = Expr::new(&arena, &env.subs, loc_expr.value, &mut procs, home, ident_ids);
|
||||
let mono_expr = Expr::new(&arena, &env.subs, loc_expr.value, &mut procs, home, &mut ident_ids);
|
||||
|
||||
// Put this module's ident_ids back in the interns
|
||||
env.interns.all_ident_ids.insert(home, ident_ids);
|
||||
|
||||
let mut scope = ImMap::default();
|
||||
let mut declared = Vec::with_capacity(procs.len());
|
||||
|
||||
@ -174,7 +178,7 @@ mod test_gen {
|
||||
macro_rules! assert_llvm_evals_to {
|
||||
($src:expr, $expected:expr, $ty:ty) => {
|
||||
let arena = Bump::new();
|
||||
let CanExprOut { loc_expr, var_store, var, constraint, home, mut interns, .. } = can_expr($src);
|
||||
let CanExprOut { loc_expr, var_store, var, constraint, home, interns, .. } = can_expr($src);
|
||||
let subs = Subs::new(var_store.into());
|
||||
let mut unify_problems = Vec::new();
|
||||
let (content, solved) = infer_expr(subs, &mut unify_problems, &constraint, var);
|
||||
@ -209,19 +213,22 @@ mod test_gen {
|
||||
let main_fn_name = "$Test.main";
|
||||
|
||||
// Compile and add all the Procs before adding main
|
||||
let mut procs = MutMap::default();
|
||||
let env = roc::llvm::build::Env {
|
||||
let mut env = roc::llvm::build::Env {
|
||||
arena: &arena,
|
||||
subs,
|
||||
builder: &builder,
|
||||
context: &context,
|
||||
interns,
|
||||
module: arena.alloc(module),
|
||||
};
|
||||
|
||||
let ident_ids = interns.all_ident_ids.remove(&home).unwrap();
|
||||
let mut procs = MutMap::default();
|
||||
let mut ident_ids = env.interns.all_ident_ids.remove(&home).unwrap();
|
||||
|
||||
// Populate Procs and get the low-level Expr from the canonical Expr
|
||||
let main_body = Expr::new(&arena, &env.subs, loc_expr.value, &mut procs, home, ident_ids);
|
||||
let main_body = Expr::new(&arena, &env.subs, loc_expr.value, &mut procs, home, &mut ident_ids);
|
||||
|
||||
// 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() {
|
||||
|
Loading…
Reference in New Issue
Block a user