use crate::common::{NumTy, Result};
use crate::compile::{Ty, LL};
use hashbrown::HashSet;
type SlotSet = HashSet<(NumTy, Ty)>;
#[derive(Default)]
pub(crate) struct SlotOps {
pub(crate) begin_stores: SlotSet,
pub(crate) loop_stores: SlotSet,
}
pub(crate) fn load_slot_instr<'a>(reg: NumTy, ty: Ty, slot: usize) -> Result<Option<LL<'a>>> {
use Ty::*;
match ty {
Int | Float | Str | MapIntInt | MapIntFloat | MapIntStr | MapStrInt | MapStrFloat
| MapStrStr => Ok(Some(LL::LoadSlot {
ty,
dst: reg,
slot: slot as _,
})),
Null => Ok(None),
IterInt | IterStr => err!("unexpected slot type: {:?}", ty),
}
}
pub(crate) fn store_slot_instr<'a>(reg: NumTy, ty: Ty, slot: usize) -> Result<Option<LL<'a>>> {
use Ty::*;
match ty {
Int | Float | Str | MapIntInt | MapIntFloat | MapIntStr | MapStrInt | MapStrFloat
| MapStrStr => Ok(Some(LL::StoreSlot {
ty,
src: reg,
slot: slot as _,
})),
Null => Ok(None),
IterInt | IterStr => err!("unexpected slot type: {:?}", ty),
}
}
fn compute_par(
begin_refs: &HashSet<(NumTy, Ty)>,
loop_refs: &HashSet<(NumTy, Ty)>,
end_refs: &HashSet<(NumTy, Ty)>,
) -> SlotOps {
let begin_loop = begin_refs.intersection(loop_refs);
let loop_end = loop_refs.intersection(end_refs);
let begin_end = || begin_refs.intersection(end_refs);
SlotOps {
begin_stores: begin_loop.chain(begin_end()).cloned().collect(),
loop_stores: loop_end.chain(begin_end()).cloned().collect(),
}
}
pub(crate) fn compute_slots(
begin: &Option<usize>,
main_loop: &Option<usize>,
end: &Option<usize>,
global_refs: Vec<HashSet<(NumTy, Ty)>>,
) -> SlotOps {
let empty: HashSet<(NumTy, Ty)> = Default::default();
let get_ref = |x: &Option<usize>| x.as_ref().map(|i| &global_refs[*i]).unwrap_or(&empty);
compute_par(get_ref(begin), get_ref(main_loop), get_ref(end))
}