mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 23:31:12 +00:00
Refactor dev backend to deal with layouts within specific backends. Just check constraints at high level
This commit is contained in:
parent
56d6720d37
commit
d9d0d0c0af
2 changed files with 305 additions and 151 deletions
|
@ -200,6 +200,7 @@ pub struct Backend64Bit<
|
||||||
relocs: Vec<'a, Relocation>,
|
relocs: Vec<'a, Relocation>,
|
||||||
|
|
||||||
last_seen_map: MutMap<Symbol, *const Stmt<'a>>,
|
last_seen_map: MutMap<Symbol, *const Stmt<'a>>,
|
||||||
|
layout_map: MutMap<Symbol, *const Layout<'a>>,
|
||||||
free_map: MutMap<*const Stmt<'a>, Vec<'a, Symbol>>,
|
free_map: MutMap<*const Stmt<'a>, Vec<'a, Symbol>>,
|
||||||
symbol_storage_map: MutMap<Symbol, SymbolStorage<GeneralReg, FloatReg>>,
|
symbol_storage_map: MutMap<Symbol, SymbolStorage<GeneralReg, FloatReg>>,
|
||||||
literal_map: MutMap<Symbol, Literal<'a>>,
|
literal_map: MutMap<Symbol, Literal<'a>>,
|
||||||
|
@ -237,9 +238,10 @@ impl<
|
||||||
phantom_asm: PhantomData,
|
phantom_asm: PhantomData,
|
||||||
phantom_cc: PhantomData,
|
phantom_cc: PhantomData,
|
||||||
env,
|
env,
|
||||||
buf: bumpalo::vec!(in env.arena),
|
buf: bumpalo::vec![in env.arena],
|
||||||
relocs: bumpalo::vec!(in env.arena),
|
relocs: bumpalo::vec![in env.arena],
|
||||||
last_seen_map: MutMap::default(),
|
last_seen_map: MutMap::default(),
|
||||||
|
layout_map: MutMap::default(),
|
||||||
free_map: MutMap::default(),
|
free_map: MutMap::default(),
|
||||||
symbol_storage_map: MutMap::default(),
|
symbol_storage_map: MutMap::default(),
|
||||||
literal_map: MutMap::default(),
|
literal_map: MutMap::default(),
|
||||||
|
@ -262,6 +264,7 @@ impl<
|
||||||
self.stack_size = 0;
|
self.stack_size = 0;
|
||||||
self.fn_call_stack_size = 0;
|
self.fn_call_stack_size = 0;
|
||||||
self.last_seen_map.clear();
|
self.last_seen_map.clear();
|
||||||
|
self.layout_map.clear();
|
||||||
self.free_map.clear();
|
self.free_map.clear();
|
||||||
self.symbol_storage_map.clear();
|
self.symbol_storage_map.clear();
|
||||||
self.buf.clear();
|
self.buf.clear();
|
||||||
|
@ -285,6 +288,10 @@ impl<
|
||||||
&mut self.last_seen_map
|
&mut self.last_seen_map
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn layout_map(&mut self) -> &mut MutMap<Symbol, *const Layout<'a>> {
|
||||||
|
&mut self.layout_map
|
||||||
|
}
|
||||||
|
|
||||||
fn set_free_map(&mut self, map: MutMap<*const Stmt<'a>, Vec<'a, Symbol>>) {
|
fn set_free_map(&mut self, map: MutMap<*const Stmt<'a>, Vec<'a, Symbol>>) {
|
||||||
self.free_map = map;
|
self.free_map = map;
|
||||||
}
|
}
|
||||||
|
@ -428,7 +435,7 @@ impl<
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
x => Err(format!(
|
x => Err(format!(
|
||||||
"receiving return type, {:?}, is not yet implemented",
|
"FnCall: receiving return type, {:?}, is not yet implemented",
|
||||||
x
|
x
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
|
@ -475,7 +482,7 @@ impl<
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"branch info, {:?}, is not yet implemented in switch statemens",
|
"Switch: branch info, {:?}, is not yet implemented",
|
||||||
branch_info
|
branch_info
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -497,86 +504,116 @@ impl<
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(format!(
|
Err(format!(
|
||||||
"branch info, {:?}, is not yet implemented in switch statemens",
|
"Switch: branch info, {:?}, is not yet implemented",
|
||||||
branch_info
|
branch_info
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_num_abs_i64(&mut self, dst: &Symbol, src: &Symbol) -> Result<(), String> {
|
fn build_num_abs(
|
||||||
let dst_reg = self.claim_general_reg(dst)?;
|
&mut self,
|
||||||
let src_reg = self.load_to_general_reg(src)?;
|
dst: &Symbol,
|
||||||
ASM::abs_reg64_reg64(&mut self.buf, dst_reg, src_reg);
|
src: &Symbol,
|
||||||
Ok(())
|
layout: &Layout<'a>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
match layout {
|
||||||
|
Layout::Builtin(Builtin::Int64) => {
|
||||||
|
let dst_reg = self.claim_general_reg(dst)?;
|
||||||
|
let src_reg = self.load_to_general_reg(src)?;
|
||||||
|
ASM::abs_reg64_reg64(&mut self.buf, dst_reg, src_reg);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Layout::Builtin(Builtin::Float64) => {
|
||||||
|
let dst_reg = self.claim_float_reg(dst)?;
|
||||||
|
let src_reg = self.load_to_float_reg(src)?;
|
||||||
|
ASM::abs_freg64_freg64(&mut self.buf, &mut self.relocs, dst_reg, src_reg);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
x => Err(format!("NumAbs: layout, {:?}, not implemented yet", x)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_num_abs_f64(&mut self, dst: &Symbol, src: &Symbol) -> Result<(), String> {
|
fn build_num_add(
|
||||||
let dst_reg = self.claim_float_reg(dst)?;
|
|
||||||
let src_reg = self.load_to_float_reg(src)?;
|
|
||||||
|
|
||||||
ASM::abs_freg64_freg64(&mut self.buf, &mut self.relocs, dst_reg, src_reg);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_num_add_i64(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
dst: &Symbol,
|
dst: &Symbol,
|
||||||
src1: &Symbol,
|
src1: &Symbol,
|
||||||
src2: &Symbol,
|
src2: &Symbol,
|
||||||
|
layout: &Layout<'a>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let dst_reg = self.claim_general_reg(dst)?;
|
match layout {
|
||||||
let src1_reg = self.load_to_general_reg(src1)?;
|
Layout::Builtin(Builtin::Int64) => {
|
||||||
let src2_reg = self.load_to_general_reg(src2)?;
|
let dst_reg = self.claim_general_reg(dst)?;
|
||||||
ASM::add_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
let src1_reg = self.load_to_general_reg(src1)?;
|
||||||
Ok(())
|
let src2_reg = self.load_to_general_reg(src2)?;
|
||||||
|
ASM::add_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Layout::Builtin(Builtin::Float64) => {
|
||||||
|
let dst_reg = self.claim_float_reg(dst)?;
|
||||||
|
let src1_reg = self.load_to_float_reg(src1)?;
|
||||||
|
let src2_reg = self.load_to_float_reg(src2)?;
|
||||||
|
ASM::add_freg64_freg64_freg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
x => Err(format!("NumAdd: layout, {:?}, not implemented yet", x)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_num_add_f64(
|
fn build_num_mul(
|
||||||
&mut self,
|
&mut self,
|
||||||
dst: &Symbol,
|
dst: &Symbol,
|
||||||
src1: &Symbol,
|
src1: &Symbol,
|
||||||
src2: &Symbol,
|
src2: &Symbol,
|
||||||
|
layout: &Layout<'a>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let dst_reg = self.claim_float_reg(dst)?;
|
match layout {
|
||||||
let src1_reg = self.load_to_float_reg(src1)?;
|
Layout::Builtin(Builtin::Int64) => {
|
||||||
let src2_reg = self.load_to_float_reg(src2)?;
|
let dst_reg = self.claim_general_reg(dst)?;
|
||||||
ASM::add_freg64_freg64_freg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
let src1_reg = self.load_to_general_reg(src1)?;
|
||||||
Ok(())
|
let src2_reg = self.load_to_general_reg(src2)?;
|
||||||
|
ASM::imul_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
x => Err(format!("NumMul: layout, {:?}, not implemented yet", x)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_num_mul_i64(
|
fn build_num_sub(
|
||||||
&mut self,
|
&mut self,
|
||||||
dst: &Symbol,
|
dst: &Symbol,
|
||||||
src1: &Symbol,
|
src1: &Symbol,
|
||||||
src2: &Symbol,
|
src2: &Symbol,
|
||||||
|
layout: &Layout<'a>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let dst_reg = self.claim_general_reg(dst)?;
|
match layout {
|
||||||
let src1_reg = self.load_to_general_reg(src1)?;
|
Layout::Builtin(Builtin::Int64) => {
|
||||||
let src2_reg = self.load_to_general_reg(src2)?;
|
let dst_reg = self.claim_general_reg(dst)?;
|
||||||
ASM::imul_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
let src1_reg = self.load_to_general_reg(src1)?;
|
||||||
Ok(())
|
let src2_reg = self.load_to_general_reg(src2)?;
|
||||||
|
ASM::sub_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
x => Err(format!("NumSub: layout, {:?}, not implemented yet", x)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_num_sub_i64(
|
fn build_eq(
|
||||||
&mut self,
|
&mut self,
|
||||||
dst: &Symbol,
|
dst: &Symbol,
|
||||||
src1: &Symbol,
|
src1: &Symbol,
|
||||||
src2: &Symbol,
|
src2: &Symbol,
|
||||||
|
arg_layout: &Layout<'a>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let dst_reg = self.claim_general_reg(dst)?;
|
match arg_layout {
|
||||||
let src1_reg = self.load_to_general_reg(src1)?;
|
Layout::Builtin(Builtin::Int64) => {
|
||||||
let src2_reg = self.load_to_general_reg(src2)?;
|
let dst_reg = self.claim_general_reg(dst)?;
|
||||||
ASM::sub_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
let src1_reg = self.load_to_general_reg(src1)?;
|
||||||
Ok(())
|
let src2_reg = self.load_to_general_reg(src2)?;
|
||||||
}
|
ASM::eq_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||||
|
Ok(())
|
||||||
fn build_eq_i64(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol) -> Result<(), String> {
|
}
|
||||||
let dst_reg = self.claim_general_reg(dst)?;
|
x => Err(format!("NumEq: layout, {:?}, not implemented yet", x)),
|
||||||
let src1_reg = self.load_to_general_reg(src1)?;
|
}
|
||||||
let src2_reg = self.load_to_general_reg(src2)?;
|
|
||||||
ASM::eq_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_struct(
|
fn create_struct(
|
||||||
|
@ -849,7 +886,7 @@ impl<
|
||||||
Ok(reg)
|
Ok(reg)
|
||||||
}
|
}
|
||||||
Some(SymbolStorage::GeneralReg(_)) | Some(SymbolStorage::BaseAndGeneralReg(_, _)) => {
|
Some(SymbolStorage::GeneralReg(_)) | Some(SymbolStorage::BaseAndGeneralReg(_, _)) => {
|
||||||
Err("Cannot load integer point symbol into FloatReg".to_string())
|
Err("Cannot load integer symbol into FloatReg".to_string())
|
||||||
}
|
}
|
||||||
None => Err(format!("Unknown symbol: {}", sym)),
|
None => Err(format!("Unknown symbol: {}", sym)),
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,9 @@ where
|
||||||
fn build_proc(&mut self, proc: Proc<'a>) -> Result<(&'a [u8], &[Relocation]), String> {
|
fn build_proc(&mut self, proc: Proc<'a>) -> Result<(&'a [u8], &[Relocation]), String> {
|
||||||
self.reset();
|
self.reset();
|
||||||
self.load_args(proc.args, &proc.ret_layout)?;
|
self.load_args(proc.args, &proc.ret_layout)?;
|
||||||
|
for (layout, sym) in proc.args {
|
||||||
|
self.set_layout_map(*sym, layout)?;
|
||||||
|
}
|
||||||
// let start = std::time::Instant::now();
|
// let start = std::time::Instant::now();
|
||||||
self.scan_ast(&proc.body);
|
self.scan_ast(&proc.body);
|
||||||
self.create_free_map();
|
self.create_free_map();
|
||||||
|
@ -94,6 +97,7 @@ where
|
||||||
match stmt {
|
match stmt {
|
||||||
Stmt::Let(sym, expr, layout, following) => {
|
Stmt::Let(sym, expr, layout, following) => {
|
||||||
self.build_expr(sym, expr, layout)?;
|
self.build_expr(sym, expr, layout)?;
|
||||||
|
self.set_layout_map(*sym, layout)?;
|
||||||
self.free_symbols(stmt);
|
self.free_symbols(stmt);
|
||||||
self.build_stmt(following, ret_layout)?;
|
self.build_stmt(following, ret_layout)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -165,42 +169,76 @@ where
|
||||||
} => {
|
} => {
|
||||||
// For most builtins instead of calling a function, we can just inline the low level.
|
// For most builtins instead of calling a function, we can just inline the low level.
|
||||||
match *func_sym {
|
match *func_sym {
|
||||||
Symbol::NUM_ABS => {
|
Symbol::NUM_ABS => self.build_run_low_level(
|
||||||
self.build_run_low_level(sym, &LowLevel::NumAbs, arguments, layout)
|
sym,
|
||||||
}
|
&LowLevel::NumAbs,
|
||||||
Symbol::NUM_ADD => {
|
arguments,
|
||||||
self.build_run_low_level(sym, &LowLevel::NumAdd, arguments, layout)
|
arg_layouts,
|
||||||
}
|
ret_layout,
|
||||||
Symbol::NUM_ACOS => {
|
),
|
||||||
self.build_run_low_level(sym, &LowLevel::NumAcos, arguments, layout)
|
Symbol::NUM_ADD => self.build_run_low_level(
|
||||||
}
|
sym,
|
||||||
Symbol::NUM_ASIN => {
|
&LowLevel::NumAdd,
|
||||||
self.build_run_low_level(sym, &LowLevel::NumAsin, arguments, layout)
|
arguments,
|
||||||
}
|
arg_layouts,
|
||||||
Symbol::NUM_ATAN => {
|
ret_layout,
|
||||||
self.build_run_low_level(sym, &LowLevel::NumAtan, arguments, layout)
|
),
|
||||||
}
|
Symbol::NUM_ACOS => self.build_run_low_level(
|
||||||
Symbol::NUM_MUL => {
|
sym,
|
||||||
self.build_run_low_level(sym, &LowLevel::NumMul, arguments, layout)
|
&LowLevel::NumAcos,
|
||||||
}
|
arguments,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
Symbol::NUM_ASIN => self.build_run_low_level(
|
||||||
|
sym,
|
||||||
|
&LowLevel::NumAsin,
|
||||||
|
arguments,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
Symbol::NUM_ATAN => self.build_run_low_level(
|
||||||
|
sym,
|
||||||
|
&LowLevel::NumAtan,
|
||||||
|
arguments,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
Symbol::NUM_MUL => self.build_run_low_level(
|
||||||
|
sym,
|
||||||
|
&LowLevel::NumMul,
|
||||||
|
arguments,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
Symbol::NUM_POW_INT => self.build_run_low_level(
|
Symbol::NUM_POW_INT => self.build_run_low_level(
|
||||||
sym,
|
sym,
|
||||||
&LowLevel::NumPowInt,
|
&LowLevel::NumPowInt,
|
||||||
arguments,
|
arguments,
|
||||||
layout,
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
Symbol::NUM_SUB => self.build_run_low_level(
|
||||||
|
sym,
|
||||||
|
&LowLevel::NumSub,
|
||||||
|
arguments,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
),
|
),
|
||||||
Symbol::NUM_SUB => {
|
|
||||||
self.build_run_low_level(sym, &LowLevel::NumSub, arguments, layout)
|
|
||||||
}
|
|
||||||
Symbol::NUM_ROUND => self.build_run_low_level(
|
Symbol::NUM_ROUND => self.build_run_low_level(
|
||||||
sym,
|
sym,
|
||||||
&LowLevel::NumRound,
|
&LowLevel::NumRound,
|
||||||
arguments,
|
arguments,
|
||||||
layout,
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
Symbol::BOOL_EQ => self.build_run_low_level(
|
||||||
|
sym,
|
||||||
|
&LowLevel::Eq,
|
||||||
|
arguments,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
),
|
),
|
||||||
Symbol::BOOL_EQ => {
|
|
||||||
self.build_run_low_level(sym, &LowLevel::Eq, arguments, layout)
|
|
||||||
}
|
|
||||||
x if x
|
x if x
|
||||||
.module_string(&self.env().interns)
|
.module_string(&self.env().interns)
|
||||||
.starts_with(ModuleName::APP) =>
|
.starts_with(ModuleName::APP) =>
|
||||||
|
@ -217,7 +255,24 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
CallType::LowLevel { op: lowlevel, .. } => {
|
CallType::LowLevel { op: lowlevel, .. } => {
|
||||||
self.build_run_low_level(sym, lowlevel, arguments, layout)
|
let mut arg_layouts: bumpalo::collections::Vec<Layout<'a>> =
|
||||||
|
bumpalo::vec![in self.env().arena];
|
||||||
|
arg_layouts.reserve(arguments.len());
|
||||||
|
let layout_map = self.layout_map();
|
||||||
|
for arg in *arguments {
|
||||||
|
if let Some(layout) = layout_map.get(arg) {
|
||||||
|
arg_layouts.push(unsafe { *(*layout) });
|
||||||
|
} else {
|
||||||
|
return Err(format!("the argument, {:?}, has no know layout", arg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.build_run_low_level(
|
||||||
|
sym,
|
||||||
|
lowlevel,
|
||||||
|
arguments,
|
||||||
|
arg_layouts.into_bump_slice(),
|
||||||
|
layout,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
x => Err(format!("the call type, {:?}, is not yet implemented", x)),
|
x => Err(format!("the call type, {:?}, is not yet implemented", x)),
|
||||||
}
|
}
|
||||||
|
@ -242,76 +297,119 @@ where
|
||||||
sym: &Symbol,
|
sym: &Symbol,
|
||||||
lowlevel: &LowLevel,
|
lowlevel: &LowLevel,
|
||||||
args: &'a [Symbol],
|
args: &'a [Symbol],
|
||||||
layout: &Layout<'a>,
|
arg_layouts: &[Layout<'a>],
|
||||||
|
ret_layout: &Layout<'a>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
// Now that the arguments are needed, load them if they are literals.
|
// Now that the arguments are needed, load them if they are literals.
|
||||||
self.load_literal_symbols(args)?;
|
self.load_literal_symbols(args)?;
|
||||||
match lowlevel {
|
match lowlevel {
|
||||||
LowLevel::NumAbs => {
|
LowLevel::NumAbs => {
|
||||||
// TODO: when this is expanded to floats. deal with typecasting here, and then call correct low level method.
|
debug_assert_eq!(
|
||||||
match layout {
|
1,
|
||||||
Layout::Builtin(Builtin::Int64) => self.build_num_abs_i64(sym, &args[0]),
|
args.len(),
|
||||||
Layout::Builtin(Builtin::Float64) => self.build_num_abs_f64(sym, &args[0]),
|
"NumAbs: expected to have exactly one argument"
|
||||||
x => Err(format!("layout, {:?}, not implemented yet", x)),
|
);
|
||||||
}
|
debug_assert_eq!(
|
||||||
|
arg_layouts[0], *ret_layout,
|
||||||
|
"NumAbs: expected to have the same argument and return layout"
|
||||||
|
);
|
||||||
|
self.build_num_abs(sym, &args[0], ret_layout)
|
||||||
}
|
}
|
||||||
LowLevel::NumAdd => {
|
LowLevel::NumAdd => {
|
||||||
// TODO: when this is expanded to floats. deal with typecasting here, and then call correct low level method.
|
debug_assert_eq!(
|
||||||
match layout {
|
2,
|
||||||
Layout::Builtin(Builtin::Int64) => {
|
args.len(),
|
||||||
self.build_num_add_i64(sym, &args[0], &args[1])
|
"NumAdd: expected to have exactly two argument"
|
||||||
}
|
);
|
||||||
Layout::Builtin(Builtin::Float64) => {
|
debug_assert_eq!(
|
||||||
self.build_num_add_f64(sym, &args[0], &args[1])
|
arg_layouts[0], arg_layouts[1],
|
||||||
}
|
"NumAdd: expected all arguments of to have the same layout"
|
||||||
x => Err(format!("layout, {:?}, not implemented yet", x)),
|
);
|
||||||
}
|
debug_assert_eq!(
|
||||||
}
|
arg_layouts[0], *ret_layout,
|
||||||
LowLevel::NumAcos => {
|
"NumAdd: expected to have the same argument and return layout"
|
||||||
self.build_fn_call(sym, bitcode::NUM_ACOS.to_string(), args, &[*layout], layout)
|
);
|
||||||
}
|
self.build_num_add(sym, &args[0], &args[1], ret_layout)
|
||||||
LowLevel::NumAsin => {
|
|
||||||
self.build_fn_call(sym, bitcode::NUM_ASIN.to_string(), args, &[*layout], layout)
|
|
||||||
}
|
|
||||||
LowLevel::NumAtan => {
|
|
||||||
self.build_fn_call(sym, bitcode::NUM_ATAN.to_string(), args, &[*layout], layout)
|
|
||||||
}
|
}
|
||||||
|
LowLevel::NumAcos => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::NUM_ACOS.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
LowLevel::NumAsin => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::NUM_ASIN.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
|
LowLevel::NumAtan => self.build_fn_call(
|
||||||
|
sym,
|
||||||
|
bitcode::NUM_ATAN.to_string(),
|
||||||
|
args,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
),
|
||||||
LowLevel::NumMul => {
|
LowLevel::NumMul => {
|
||||||
// TODO: when this is expanded to floats. deal with typecasting here, and then call correct low level method.
|
debug_assert_eq!(
|
||||||
match layout {
|
2,
|
||||||
Layout::Builtin(Builtin::Int64) => {
|
args.len(),
|
||||||
self.build_num_mul_i64(sym, &args[0], &args[1])
|
"NumMul: expected to have exactly two argument"
|
||||||
}
|
);
|
||||||
x => Err(format!("layout, {:?}, not implemented yet", x)),
|
debug_assert_eq!(
|
||||||
}
|
arg_layouts[0], arg_layouts[1],
|
||||||
|
"NumMul: expected all arguments of to have the same layout"
|
||||||
|
);
|
||||||
|
debug_assert_eq!(
|
||||||
|
arg_layouts[0], *ret_layout,
|
||||||
|
"NumMul: expected to have the same argument and return layout"
|
||||||
|
);
|
||||||
|
self.build_num_mul(sym, &args[0], &args[1], ret_layout)
|
||||||
}
|
}
|
||||||
LowLevel::NumPowInt => self.build_fn_call(
|
LowLevel::NumPowInt => self.build_fn_call(
|
||||||
sym,
|
sym,
|
||||||
bitcode::NUM_POW_INT.to_string(),
|
bitcode::NUM_POW_INT.to_string(),
|
||||||
args,
|
args,
|
||||||
&[*layout, *layout],
|
arg_layouts,
|
||||||
layout,
|
ret_layout,
|
||||||
),
|
),
|
||||||
LowLevel::NumSub => {
|
LowLevel::NumSub => {
|
||||||
// TODO: when this is expanded to floats. deal with typecasting here, and then call correct low level method.
|
debug_assert_eq!(
|
||||||
match layout {
|
2,
|
||||||
Layout::Builtin(Builtin::Int64) => {
|
args.len(),
|
||||||
self.build_num_sub_i64(sym, &args[0], &args[1])
|
"NumSub: expected to have exactly two argument"
|
||||||
}
|
);
|
||||||
x => Err(format!("layout, {:?}, not implemented yet", x)),
|
debug_assert_eq!(
|
||||||
}
|
arg_layouts[0], arg_layouts[1],
|
||||||
|
"NumSub: expected all arguments of to have the same layout"
|
||||||
|
);
|
||||||
|
debug_assert_eq!(
|
||||||
|
arg_layouts[0], *ret_layout,
|
||||||
|
"NumSub: expected to have the same argument and return layout"
|
||||||
|
);
|
||||||
|
self.build_num_sub(sym, &args[0], &args[1], ret_layout)
|
||||||
|
}
|
||||||
|
LowLevel::Eq => {
|
||||||
|
debug_assert_eq!(2, args.len(), "Eq: expected to have exactly two argument");
|
||||||
|
debug_assert_eq!(
|
||||||
|
arg_layouts[0], arg_layouts[1],
|
||||||
|
"Eq: expected all arguments of to have the same layout"
|
||||||
|
);
|
||||||
|
debug_assert_eq!(
|
||||||
|
Layout::Builtin(Builtin::Int1),
|
||||||
|
*ret_layout,
|
||||||
|
"Eq: expected to have return layout of type I1"
|
||||||
|
);
|
||||||
|
self.build_eq(sym, &args[0], &args[1], &arg_layouts[0])
|
||||||
}
|
}
|
||||||
LowLevel::Eq => match layout {
|
|
||||||
Layout::Builtin(Builtin::Int1) => self.build_eq_i64(sym, &args[0], &args[1]),
|
|
||||||
// Should we panic?
|
|
||||||
x => Err(format!("wrong layout, {:?}, for LowLevel::Eq", x)),
|
|
||||||
},
|
|
||||||
LowLevel::NumRound => self.build_fn_call(
|
LowLevel::NumRound => self.build_fn_call(
|
||||||
sym,
|
sym,
|
||||||
bitcode::NUM_ROUND.to_string(),
|
bitcode::NUM_ROUND.to_string(),
|
||||||
args,
|
args,
|
||||||
&[Layout::Builtin(Builtin::Float64)],
|
arg_layouts,
|
||||||
layout,
|
ret_layout,
|
||||||
),
|
),
|
||||||
x => Err(format!("low level, {:?}. is not yet implemented", x)),
|
x => Err(format!("low level, {:?}. is not yet implemented", x)),
|
||||||
}
|
}
|
||||||
|
@ -328,54 +426,50 @@ where
|
||||||
ret_layout: &Layout<'a>,
|
ret_layout: &Layout<'a>,
|
||||||
) -> Result<(), String>;
|
) -> Result<(), String>;
|
||||||
|
|
||||||
/// build_num_abs_i64 stores the absolute value of src into dst.
|
/// 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(
|
||||||
fn build_num_abs_i64(&mut self, dst: &Symbol, src: &Symbol) -> Result<(), String>;
|
&mut self,
|
||||||
|
dst: &Symbol,
|
||||||
|
src: &Symbol,
|
||||||
|
layout: &Layout<'a>,
|
||||||
|
) -> Result<(), String>;
|
||||||
|
|
||||||
/// build_num_abs_f64 stores the absolute value of src into dst.
|
/// build_num_add stores the sum of src1 and src2 into dst.
|
||||||
/// It only deals with inputs and outputs of f64 type.
|
fn build_num_add(
|
||||||
fn build_num_abs_f64(&mut self, dst: &Symbol, src: &Symbol) -> Result<(), String>;
|
|
||||||
|
|
||||||
/// build_num_add_i64 stores the sum of src1 and src2 into dst.
|
|
||||||
/// It only deals with inputs and outputs of i64 type.
|
|
||||||
fn build_num_add_i64(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
dst: &Symbol,
|
dst: &Symbol,
|
||||||
src1: &Symbol,
|
src1: &Symbol,
|
||||||
src2: &Symbol,
|
src2: &Symbol,
|
||||||
|
layout: &Layout<'a>,
|
||||||
) -> Result<(), String>;
|
) -> Result<(), String>;
|
||||||
|
|
||||||
/// build_num_add_f64 stores the sum of src1 and src2 into dst.
|
/// build_num_mul stores `src1 * src2` into dst.
|
||||||
/// It only deals with inputs and outputs of f64 type.
|
fn build_num_mul(
|
||||||
fn build_num_add_f64(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
dst: &Symbol,
|
dst: &Symbol,
|
||||||
src1: &Symbol,
|
src1: &Symbol,
|
||||||
src2: &Symbol,
|
src2: &Symbol,
|
||||||
|
layout: &Layout<'a>,
|
||||||
) -> Result<(), String>;
|
) -> Result<(), String>;
|
||||||
|
|
||||||
/// build_num_mul_i64 stores `src1 * src2` into dst.
|
/// build_num_sub stores the `src1 - src2` difference into dst.
|
||||||
/// It only deals with inputs and outputs of i64 type.
|
fn build_num_sub(
|
||||||
fn build_num_mul_i64(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
dst: &Symbol,
|
dst: &Symbol,
|
||||||
src1: &Symbol,
|
src1: &Symbol,
|
||||||
src2: &Symbol,
|
src2: &Symbol,
|
||||||
|
layout: &Layout<'a>,
|
||||||
) -> Result<(), String>;
|
) -> Result<(), String>;
|
||||||
|
|
||||||
/// build_num_sub_i64 stores the `src1 - src2` difference into dst.
|
/// build_eq stores the result of `src1 == src2` into dst.
|
||||||
/// It only deals with inputs and outputs of i64 type.
|
fn build_eq(
|
||||||
fn build_num_sub_i64(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
dst: &Symbol,
|
dst: &Symbol,
|
||||||
src1: &Symbol,
|
src1: &Symbol,
|
||||||
src2: &Symbol,
|
src2: &Symbol,
|
||||||
|
arg_layout: &Layout<'a>,
|
||||||
) -> Result<(), String>;
|
) -> Result<(), String>;
|
||||||
|
|
||||||
/// build_eq_i64 stores the result of `src1 == src2` into dst.
|
|
||||||
/// It only deals with inputs and outputs of i64 type.
|
|
||||||
fn build_eq_i64(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol) -> Result<(), String>;
|
|
||||||
|
|
||||||
/// literal_map gets the map from symbol to literal, used for lazy loading and literal folding.
|
/// literal_map gets the map from symbol to literal, used for lazy loading and literal folding.
|
||||||
fn literal_map(&mut self) -> &mut MutMap<Symbol, Literal<'a>>;
|
fn literal_map(&mut self) -> &mut MutMap<Symbol, Literal<'a>>;
|
||||||
|
|
||||||
|
@ -434,6 +528,29 @@ where
|
||||||
/// last_seen_map gets the map from symbol to when it is last seen in the function.
|
/// 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>>;
|
fn last_seen_map(&mut self) -> &mut MutMap<Symbol, *const Stmt<'a>>;
|
||||||
|
|
||||||
|
/// set_layout_map sets the layout for a specific symbol.
|
||||||
|
fn set_layout_map(&mut self, sym: Symbol, layout: &Layout<'a>) -> Result<(), String> {
|
||||||
|
if let Some(x) = self.layout_map().insert(sym, layout) {
|
||||||
|
// Layout map already contains the symbol. We should never need to overwrite.
|
||||||
|
// If the layout is not the same, that is a bug.
|
||||||
|
// There is always an old layout value and this dereference is safe.
|
||||||
|
let old_layout = unsafe { *x };
|
||||||
|
if old_layout != *layout {
|
||||||
|
Err(format!(
|
||||||
|
"Overwriting layout for symbol, {:?}. This should never happen. got {:?}, want {:?}",
|
||||||
|
sym, layout, old_layout
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// layout_map gets the map from symbol to layout.
|
||||||
|
fn layout_map(&mut self) -> &mut MutMap<Symbol, *const Layout<'a>>;
|
||||||
|
|
||||||
fn create_free_map(&mut self) {
|
fn create_free_map(&mut self) {
|
||||||
let mut free_map = MutMap::default();
|
let mut free_map = MutMap::default();
|
||||||
let arena = self.env().arena;
|
let arena = self.env().arena;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue