Add Num.abs as inlined function

This commit is contained in:
Brendan Hansknecht 2020-11-20 23:04:35 -08:00
parent 9e6eb85166
commit 13781a6f8f
5 changed files with 248 additions and 65 deletions

View file

@ -15,9 +15,10 @@ use bumpalo::Bump;
use object::write::Object;
use roc_collections::all::{MutMap, MutSet};
use roc_module::ident::TagName;
use roc_module::low_level::LowLevel;
use roc_module::symbol::{Interns, Symbol};
use roc_mono::ir::{CallType, Expr, JoinPointId, Literal, Proc, Stmt};
use roc_mono::layout::Layout;
use roc_mono::layout::{Builtin, Layout};
use target_lexicon::{BinaryFormat, Triple};
pub mod elf;
@ -68,9 +69,13 @@ where
/// last_seen_map gets the map from symbol to when it is last seen in the function.
fn last_seen_map(&mut self) -> &mut MutMap<Symbol, *const Stmt<'a>>;
/// set_symbol_to_lit sets a symbol to be equal to a literal.
/// When the symbol is used, the literal should be loaded.
fn set_symbol_to_lit(&mut self, sym: &Symbol, lit: &Literal<'a>);
/// load_literal sets a symbol to be equal to a literal.
fn load_literal(
&mut self,
sym: &Symbol,
lit: &Literal<'a>,
layout: &Layout<'a>,
) -> Result<(), String>;
/// free_symbol frees any registers or stack space used to hold a symbol.
fn free_symbol(&mut self, sym: &Symbol);
@ -85,8 +90,6 @@ where
fn finalize(&mut self) -> Result<(&'a [u8], &[Relocation]), String>;
/// build_proc creates a procedure and outputs it to the wrapped object writer.
/// This will need to return the list of relocations because they have to be added differently based on file format.
/// Also, assembly will of course be generated by individual calls on backend like may setup_stack.
fn build_proc(&mut self, proc: Proc<'a>) -> Result<(&'a [u8], &[Relocation]), String> {
self.reset();
// TODO: let the backend know of all the arguments.
@ -119,22 +122,70 @@ where
/// build_expr builds the expressions for the specified symbol.
/// The builder must keep track of the symbol because it may be refered to later.
/// In many cases values can be lazy loaded, like literals.
fn build_expr(
&mut self,
sym: &Symbol,
expr: &Expr<'a>,
_layout: &Layout<'a>,
layout: &Layout<'a>,
) -> Result<(), String> {
match expr {
Expr::Literal(lit) => {
self.set_symbol_to_lit(sym, lit);
self.load_literal(sym, lit, layout);
Ok(())
}
Expr::FunctionCall {
call_type: CallType::ByName(func_sym),
args,
..
} => {
match *func_sym {
Symbol::NUM_ABS => {
// Instead of calling the function, just inline it.
self.build_expr(sym, &Expr::RunLowLevel(LowLevel::NumAbs, args), layout)
}
x => Err(format!("the function, {:?}, is not yet implemented", x)),
}
}
Expr::RunLowLevel(lowlevel, args) => {
self.build_run_low_level(sym, lowlevel, args, layout)
}
x => Err(format!("the expression, {:?}, is not yet implemented", x)),
}
}
/// build_run_low_level builds the low level opertation and outputs to the specified symbol.
/// The builder must keep track of the symbol because it may be refered to later.
fn build_run_low_level(
&mut self,
sym: &Symbol,
lowlevel: &LowLevel,
args: &'a [Symbol],
layout: &Layout<'a>,
) -> Result<(), String> {
match lowlevel {
LowLevel::NumAbs => self.build_num_abs(sym, &args[0], layout),
x => Err(format!("low level, {:?}. is not yet implemented", x)),
}
}
/// build_num_abs stores the absolute value of src into dst.
fn build_num_abs(
&mut self,
dst: &Symbol,
src: &Symbol,
layout: &Layout<'a>,
) -> Result<(), String> {
// TODO: when this is expanded to flaots. deal with typecasting here, and then call correct low level method.
match layout {
Layout::Builtin(Builtin::Int64) => self.build_num_abs_i64(dst, src),
x => Err(format!("layout, {:?}, not implemented yet", x)),
}
}
/// build_num_abs stores the absolute value of src into dst.
/// It only deals with inputs and outputs of i64 type.
fn build_num_abs_i64(&mut self, dst: &Symbol, src: &Symbol) -> Result<(), String>;
/// maybe_free will check if the symbol is last seen in the current state. If so, it will free the symbol resources, like registers.
fn maybe_free_symbol(&mut self, sym: &Symbol, stmt: &Stmt<'a>) {
match self.last_seen_map().get(sym) {