Refactor dev backend to deal with layouts within specific backends. Just check constraints at high level

This commit is contained in:
Brendan Hansknecht 2021-09-03 10:54:51 -07:00
parent 56d6720d37
commit d9d0d0c0af
2 changed files with 305 additions and 151 deletions

View file

@ -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)),
} }

View file

@ -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;