use crate::builder::*;
use crate::*;
use std::collections::{BTreeMap, HashMap};
#[derive(Clone, Debug)]
pub struct RoutineHandler<Label> {
name: Label,
routine_labels: Vec<Label>,
label_map: HashMap<String, usize>,
labels: Vec<Label>,
temp_buffer: bool,
forward: bool,
}
#[derive(Clone, Debug, thiserror::Error)]
pub enum RoutineHandlerSimpleError {
#[error("RoutineHandler {0}: Label {1} already exists")]
LabelAlreadyExists(String, String),
#[error("RoutineHandler {0}: Label {1} not found")]
LabelNotFound(String, String),
}
#[derive(Clone, Debug, thiserror::Error)]
pub enum RoutineHandlerError<LAE, BAE> {
#[error("RoutineHandler {0}: ReturnBits over usize length")]
ReturnBitsOverLength(String),
#[error("RoutineHandler {0}: ReturnBits too small to hold {1} returns")]
ReturnBitsTooSmall(String, usize),
#[error("RoutineHandler {0}: LabelError {1}")]
LabelError(String, LAE),
#[error("RoutineHandler {0}: BuilderError {1}")]
BuilderError(String, BAE),
}
impl<Label> RoutineHandler<Label>
where
Label: Clone + std::fmt::Display + From<String>,
MinInfRel<Label>: From<Label>,
{
pub fn new(name: &str, temp_buffer: bool, forward: bool) -> Self {
Self {
name: name.to_string().into(),
routine_labels: vec![name.to_string().into()],
label_map: HashMap::new(),
labels: vec![],
temp_buffer,
forward,
}
}
pub fn new_mem_address_backward(name: &str) -> Self {
Self::new(name, false, false)
}
pub fn new_mem_address_forward(name: &str) -> Self {
Self::new(name, false, true)
}
pub fn new_temp_buffer_backward(name: &str) -> Self {
Self::new(name, true, false)
}
pub fn new_temp_buffer_forward(name: &str) -> Self {
Self::new(name, true, true)
}
pub fn new_r<L>(name: &str, rlabel: L, temp_buffer: bool, forward: bool) -> Self
where
Label: From<L>,
{
Self {
name: name.to_string().into(),
routine_labels: vec![rlabel.into()],
label_map: HashMap::new(),
labels: vec![],
temp_buffer,
forward,
}
}
pub fn new_rl(name: Label, rlabel: Label, temp_buffer: bool, forward: bool) -> Self {
Self {
name,
routine_labels: vec![rlabel],
label_map: HashMap::new(),
labels: vec![],
temp_buffer,
forward,
}
}
pub fn new_ll(name: Label, temp_buffer: bool, forward: bool) -> Self {
Self {
name: name.clone(),
routine_labels: vec![name],
label_map: HashMap::new(),
labels: vec![],
temp_buffer,
forward,
}
}
pub fn new_l<L: Clone>(name: L, temp_buffer: bool, forward: bool) -> Self
where
Label: From<L>,
{
Self {
name: name.clone().into(),
routine_labels: vec![name.into()],
label_map: HashMap::new(),
labels: vec![],
temp_buffer,
forward,
}
}
pub fn new_mem_address_backward_l<L: Clone>(name: L) -> Self
where
Label: From<L>,
{
Self::new_l(name, false, false)
}
pub fn new_mem_address_forward_l<L: Clone>(name: L) -> Self
where
Label: From<L>,
{
Self::new_l(name, false, true)
}
pub fn new_temp_buffer_backward_l<L: Clone>(name: L) -> Self
where
Label: From<L>,
{
Self::new_l(name, true, false)
}
pub fn new_temp_buffer_forward_l<L: Clone>(name: L) -> Self
where
Label: From<L>,
{
Self::new_l(name, true, true)
}
pub fn new_with_labels<I>(name: &str, rlabels: I, temp_buffer: bool, forward: bool) -> Self
where
I: IntoIterator<Item = Label>,
{
Self {
name: name.to_string().into(),
routine_labels: rlabels.into_iter().collect(),
label_map: HashMap::new(),
labels: vec![],
temp_buffer,
forward,
}
}
pub fn new_with_labels_l<L, I>(name: &str, rlabels: I, temp_buffer: bool, forward: bool) -> Self
where
I: IntoIterator<Item = L>,
Label: From<L>,
{
Self {
name: name.to_string().into(),
routine_labels: rlabels.into_iter().map(|x| x.into()).collect(),
label_map: HashMap::new(),
labels: vec![],
temp_buffer,
forward,
}
}
pub fn name(&self) -> &Label {
&self.name
}
pub fn routine_label(&self) -> &Label {
&self.routine_labels[0]
}
pub fn routine_labels(&self) -> &[Label] {
&self.routine_labels
}
pub fn temp_buffer(&self) -> bool {
self.temp_buffer
}
pub fn forward(&self) -> bool {
self.forward
}
pub fn try_add_label_l(
&mut self,
label_name: &str,
label: Label,
) -> Result<(), RoutineHandlerSimpleError> {
let count = self.label_map.len();
if self
.label_map
.insert(label_name.to_string(), count)
.is_some()
{
return Err(RoutineHandlerSimpleError::LabelAlreadyExists(
self.name.to_string(),
label_name.to_string(),
));
}
self.labels.push(label);
Ok(())
}
pub fn try_add_label<L>(
&mut self,
label_name: &str,
label: L,
) -> Result<(), RoutineHandlerSimpleError>
where
Label: From<L>,
{
self.try_add_label_l(label_name, label.into())
}
pub fn add_label<L>(&mut self, label_name: &str, label: L)
where
Label: From<L>,
{
self.try_add_label(label_name, label).unwrap();
}
pub fn try_jump_to_call_rl(
&self,
label_name: &str,
rli: usize,
) -> Result<Label, RoutineHandlerSimpleError> {
if let Some(id) = self.label_map.get(label_name) {
Ok(format!("{}_{}_putret_x_{:b}", self.name, rli, id).into())
} else {
return Err(RoutineHandlerSimpleError::LabelAlreadyExists(
self.name.to_string(),
label_name.to_string(),
));
}
}
pub fn try_jump_to_call(&self, label_name: &str) -> Result<Label, RoutineHandlerSimpleError> {
self.try_jump_to_call_rl(label_name, 0)
}
pub fn jump_to_call_rl(&self, label_name: &str, rli: usize) -> Label {
self.try_jump_to_call_rl(label_name, rli).unwrap()
}
pub fn jump_to_call(&self, label_name: &str) -> Label {
self.try_jump_to_call(label_name).unwrap()
}
pub fn jump_to_next_call_rl(&self, rli: usize, extra: usize) -> Label {
format!(
"{}_{}_putret_x_{:b}",
self.name,
rli,
self.label_map.len() + extra
)
.into()
}
pub fn jump_to_next_call(&self, extra: usize) -> Label {
format!(
"{}_0_putret_x_{:b}",
self.name,
self.label_map.len() + extra
)
.into()
}
pub fn jump_to_first_call_rl(name: Label, rli: usize, extra: usize) -> Label {
format!("{}_{}_putret_x_{:b}", name, rli, extra).into()
}
pub fn jump_to_first_call(name: Label, extra: usize) -> Label {
format!("{}_0_putret_x_{:b}", name, extra).into()
}
pub fn jump_to_return(&self) -> Label {
format!("{}_return", self.name).into()
}
pub fn jump_to_return_before(name: Label) -> Label {
format!("{}_return", name).into()
}
pub fn label_count(&self) -> usize {
self.label_map.len()
}
pub fn try_install<Builder, Instr>(
self,
return_bits: Option<usize>,
builder: &mut Builder,
) -> Result<
usize,
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
{
let return_bits = return_bits.unwrap_or(calc_log_bits(self.label_map.len()));
if !(return_bits <= (usize::BITS as usize)) {
return Err(RoutineHandlerError::ReturnBitsOverLength(
self.name.to_string(),
));
}
if !((1usize << return_bits) >= self.label_map.len()) {
return Err(RoutineHandlerError::ReturnBitsTooSmall(
self.name.to_string(),
self.label_map.len(),
));
}
self.try_install_put_return(return_bits, builder)?;
self.try_install_return_return(return_bits, builder)
.map(|_| return_bits)
}
pub fn install<Builder, Instr>(self, return_bits: Option<usize>, builder: &mut Builder) -> usize
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
{
self.try_install(return_bits, builder).unwrap()
}
#[inline]
fn b_label<Builder, Instr, L>(
&self,
builder: &mut Builder,
label: L,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
L: Clone + Debug,
Label: From<L>,
{
builder
.try_add_label(label)
.map_err(|e| RoutineHandlerError::LabelError(self.name.to_string(), e))
}
#[inline]
fn b_instr<Builder, Instr, I>(
&self,
builder: &mut Builder,
instr: I,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<I>,
{
builder
.try_add_instr(instr)
.map_err(|e| RoutineHandlerError::BuilderError(self.name.to_string(), e))
}
fn try_install_put_return<Builder, Instr>(
&self,
return_bits: usize,
builder: &mut Builder,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
{
if self.label_map.is_empty() {
return Ok(());
}
let (xxb, xxrw0, xxrw1) = if self.temp_buffer {
(
if self.forward { MINF_TBRF } else { MINF_TBB },
MINF_TBRW0,
MINF_TBRW1,
)
} else {
(
if self.forward { MINF_MARF } else { MINF_MAB },
MINF_MARW0,
MINF_MARW1,
)
};
for (rli, routine_label) in self.routine_labels.iter().enumerate() {
if return_bits == 0 {
let label = format!("{}_{}_putret_x_{:b}", self.name, rli, 0).into();
self.b_label(builder, label)?;
self.b_instr(
builder,
(
MINF_MR,
MINF_MR,
routine_label.clone().into(),
routine_label.clone().into(),
),
)?;
continue;
}
let label_num = self.label_map.len();
for b in 0..return_bits {
let level = return_bits - b - 1;
for id_shifted in 0..((label_num + ((1 << b) - 1)) >> b) {
let label = if level + 1 != return_bits {
format!(
"{}_{}_putret_{2}_{3:02$b}",
self.name,
rli,
level + 1,
id_shifted
)
} else {
format!("{}_{}_putret_x_{:b}", self.name, rli, id_shifted)
}
.into();
self.b_label(builder, label)?;
let bit = (id_shifted & 1) != 0;
let rw = if bit { xxrw1 } else { xxrw0 };
if b + 1 == return_bits {
self.b_instr(builder, (rw, rw, 1isize.into(), 1isize.into()))?;
self.b_instr(
builder,
(
xxb,
xxb,
routine_label.clone().into(),
routine_label.clone().into(),
),
)?;
} else {
let label: Label = if level != return_bits {
format!(
"{}_{}_putret_{2}_{3:02$b}",
self.name,
rli,
level,
id_shifted >> 1
)
} else {
format!("{}_{}_putret_x_{:b}", self.name, rli, id_shifted)
}
.into();
self.b_instr(builder, (rw, rw, 1isize.into(), 1isize.into()))?;
self.b_instr(builder, (xxb, xxb, label.clone().into(), label.into()))?;
}
}
}
}
Ok(())
}
fn try_install_return_return<Builder, Instr>(
&self,
return_bits: usize,
builder: &mut Builder,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
{
self.b_label(builder, format!("{}_return", self.name))?;
if self.label_map.is_empty() {
return Ok(());
}
if return_bits == 0 {
self.b_instr(
builder,
(
MINF_MR,
MINF_MR,
self.labels[0].clone().into(),
self.labels[0].clone().into(),
),
)?;
return Ok(());
}
let (xxrw0, xxb) = if self.temp_buffer {
(MINF_TBRW0, if self.forward { MINF_TBB } else { MINF_TBRF })
} else {
(MINF_MARW0, if self.forward { MINF_MAB } else { MINF_MARF })
};
let label_num = self.label_map.len();
self.b_instr(builder, (xxb, xxb, 1isize.into(), 1isize.into()))?;
for b in (0..return_bits).rev() {
for id_shifted in 0..((label_num + ((1 << (b + 1)) - 1)) >> (b + 1)) {
let id = id_shifted << (b + 1);
let level = return_bits - b - 1;
let root_name =
format!("{}_return_id_{1}_{2:01$b}", self.name, level, id_shifted).into();
self.b_label(builder, root_name)?;
self.b_instr(builder, (xxrw0, xxrw0, 1isize.into(), 1isize.into()))?;
let label_num_shifted_2 = (label_num + ((1 << b) - 1)) >> b;
if b != 0 {
let child0_name: Label = format!(
"{}_return_id_{1}_{2:01$b}",
self.name,
level + 1,
(id_shifted << 1)
)
.into();
let child1_name = if (id_shifted << 1) + 1 < label_num_shifted_2 {
format!(
"{}_return_id_{1}_{2:01$b}",
self.name,
level + 1,
(id_shifted << 1) + 1
)
.into()
} else {
child0_name.clone()
};
self.b_instr(builder, (xxb, xxb, child0_name.into(), child1_name.into()))?;
} else {
let next_label = if id + 1 < label_num {
self.labels[id + 1].clone()
} else {
self.labels[id].clone()
};
self.b_instr(
builder,
(
MINF_MR,
MINF_MR,
self.labels[id].clone().into(),
next_label.into(),
),
)?;
}
}
}
Ok(())
}
}
pub fn jump_to_return(name: &str) -> String {
format!("{}_return", name).into()
}
pub fn try_routine_call_01<Builder, Label, Instr>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func: MinInfFunc,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
{
try_routine_call(rh, builder, func, func)
}
pub fn try_routine_call<Builder, Label, Instr>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
{
let ret_label = format!("{}_after_ret_{}", rh.name, rh.label_map.len());
rh.add_label(&ret_label, ret_label.clone().into());
rh.b_instr(
builder,
(
func_fr0,
func_fr1,
rh.jump_to_call(&ret_label).into(),
rh.jump_to_call(&ret_label).into(),
)
.into(),
)?;
rh.b_label(builder, ret_label.clone())?;
Ok(())
}
pub fn try_routine_call_01_jumps<Builder, Label, Instr, L, L2>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func: MinInfFunc,
label_fr0: L,
label_fr1: L2,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String> + From<L> + From<L2>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
{
try_routine_call_jumps(rh, builder, func, func, label_fr0, label_fr1)
}
pub fn try_routine_call_jumps<Builder, Label, Instr, L, L2>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
label_fr0: L,
label_fr1: L2,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String> + From<L> + From<L2>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
{
let ret0_label = format!("{}_after_ret_{}", rh.name, rh.label_map.len());
rh.add_label(&ret0_label, label_fr0);
let ret1_label = format!("{}_after_ret_{}", rh.name, rh.label_map.len());
rh.add_label(&ret1_label, label_fr1);
rh.b_instr(
builder,
(
func_fr0,
func_fr1,
rh.jump_to_call(&ret0_label).into(),
rh.jump_to_call(&ret1_label).into(),
)
.into(),
)?;
Ok(())
}
pub fn try_routine_call_fr0_01<Builder, Label, Instr, IntoRel>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, Label, IntoRel)>,
MinInfRel<Label>: From<Label> + From<IntoRel>,
{
try_routine_call_fr0(rh, builder, func, func, rel)
}
pub fn try_routine_call_fr0<Builder, Label, Instr, IntoRel>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, Label, IntoRel)>,
MinInfRel<Label>: From<Label> + From<IntoRel>,
{
let ret_label = format!("{}_after_ret_{}", rh.name, rh.label_map.len());
rh.add_label(&ret_label, ret_label.clone().into());
rh.b_instr(
builder,
(func_fr0, func_fr1, rh.jump_to_call(&ret_label), rel).into(),
)?;
rh.b_label(builder, ret_label.clone())?;
Ok(())
}
pub fn try_routine_call_fr1_01<Builder, Label, Instr, IntoRel>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, IntoRel, Label)>,
MinInfRel<Label>: From<Label> + From<IntoRel>,
{
try_routine_call_fr1(rh, builder, func, func, rel)
}
pub fn try_routine_call_fr1<Builder, Label, Instr, IntoRel>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, IntoRel, Label)>,
MinInfRel<Label>: From<Label> + From<IntoRel>,
{
let ret_label = format!("{}_after_ret_{}", rh.name, rh.label_map.len());
rh.add_label(&ret_label, ret_label.clone().into());
rh.b_instr(
builder,
(func_fr0, func_fr1, rel, rh.jump_to_call(&ret_label)).into(),
)?;
rh.b_label(builder, ret_label.clone())?;
Ok(())
}
pub fn try_routine_call_2_01<Builder, Label, Instr>(
rh_fr0: &mut RoutineHandler<Label>,
rh_fr1: &mut RoutineHandler<Label>,
builder: &mut Builder,
func: MinInfFunc,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
{
try_routine_call_2(rh_fr0, rh_fr1, builder, func, func)
}
pub fn try_routine_call_2<Builder, Label, Instr>(
rh_fr0: &mut RoutineHandler<Label>,
rh_fr1: &mut RoutineHandler<Label>,
builder: &mut Builder,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
{
let ret_label_fr0 = format!("{}_after_ret_{}", rh_fr0.name, rh_fr0.label_map.len());
let ret_label_fr1 = format!("{}_after_ret_{}", rh_fr1.name, rh_fr1.label_map.len());
rh_fr0.add_label(&ret_label_fr0, ret_label_fr1.clone().into());
rh_fr1.add_label(&ret_label_fr1, ret_label_fr1.clone().into());
rh_fr0.b_instr(
builder,
(
func_fr0,
func_fr1,
rh_fr0.jump_to_call(&ret_label_fr0).into(),
rh_fr1.jump_to_call(&ret_label_fr1).into(),
)
.into(),
)?;
rh_fr0.b_label(builder, ret_label_fr0.clone())?;
rh_fr1.b_label(builder, ret_label_fr1.clone())?;
Ok(())
}
pub fn try_routine_call_2_01_jumps<Builder, Label, Instr, L, L2>(
rh_fr0: &mut RoutineHandler<Label>,
rh_fr1: &mut RoutineHandler<Label>,
builder: &mut Builder,
func: MinInfFunc,
jump_fr0: L,
jump_fr1: L2,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String> + From<String> + From<L> + From<L2>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
{
try_routine_call_2_jumps(rh_fr0, rh_fr1, builder, func, func, jump_fr0, jump_fr1)
}
pub fn try_routine_call_2_jumps<Builder, Label, Instr, L, L2>(
rh_fr0: &mut RoutineHandler<Label>,
rh_fr1: &mut RoutineHandler<Label>,
builder: &mut Builder,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
jump_fr0: L,
jump_fr1: L2,
) -> Result<
(),
RoutineHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String> + From<L> + From<L2>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
{
let ret_label_fr0 = format!("{}_after_ret_{}", rh_fr0.name, rh_fr0.label_map.len());
let ret_label_fr1 = format!("{}_after_ret_{}", rh_fr1.name, rh_fr1.label_map.len());
rh_fr0.add_label(&ret_label_fr0, jump_fr0);
rh_fr1.add_label(&ret_label_fr1, jump_fr1);
rh_fr0.b_instr(
builder,
(
func_fr0,
func_fr1,
rh_fr0.jump_to_call(&ret_label_fr0).into(),
rh_fr1.jump_to_call(&ret_label_fr1).into(),
)
.into(),
)?;
Ok(())
}
pub fn routine_call_01<Builder, Label, Instr>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func: MinInfFunc,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
{
try_routine_call_01(rh, builder, func).unwrap();
}
pub fn routine_call<Builder, Label, Instr>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
{
try_routine_call(rh, builder, func_fr0, func_fr1).unwrap();
}
pub fn routine_call_fr0_01<Builder, Label, Instr, IntoRel>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func: MinInfFunc,
rel: IntoRel,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, Label, IntoRel)>,
MinInfRel<Label>: From<Label> + From<IntoRel>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
{
try_routine_call_fr0_01(rh, builder, func, rel).unwrap();
}
pub fn routine_call_fr0<Builder, Label, Instr, IntoRel>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, Label, IntoRel)>,
MinInfRel<Label>: From<Label> + From<IntoRel>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
{
try_routine_call_fr0(rh, builder, func_fr0, func_fr1, rel).unwrap();
}
pub fn routine_call_fr1_01<Builder, Label, Instr, IntoRel>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func: MinInfFunc,
rel: IntoRel,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, IntoRel, Label)>,
MinInfRel<Label>: From<Label> + From<IntoRel>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
{
try_routine_call_fr1_01(rh, builder, func, rel).unwrap();
}
pub fn routine_call_fr1<Builder, Label, Instr, IntoRel>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, IntoRel, Label)>,
MinInfRel<Label>: From<Label> + From<IntoRel>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
{
try_routine_call_fr1(rh, builder, func_fr0, func_fr1, rel).unwrap();
}
pub fn routine_call_2_01<Builder, Label, Instr>(
rh_fr0: &mut RoutineHandler<Label>,
rh_fr1: &mut RoutineHandler<Label>,
builder: &mut Builder,
func: MinInfFunc,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
{
try_routine_call_2_01(rh_fr0, rh_fr1, builder, func).unwrap();
}
pub fn routine_call_2<Builder, Label, Instr>(
rh_fr0: &mut RoutineHandler<Label>,
rh_fr1: &mut RoutineHandler<Label>,
builder: &mut Builder,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
{
try_routine_call_2(rh_fr0, rh_fr1, builder, func_fr0, func_fr1).unwrap();
}
pub fn routine_call_01_jumps<Builder, Label, Instr, L, L2>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func: MinInfFunc,
label_fr0: L,
label_fr1: L2,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String> + From<L> + From<L2>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
{
try_routine_call_01_jumps(rh, builder, func, label_fr0, label_fr1).unwrap()
}
pub fn routine_call_jumps<Builder, Label, Instr, L, L2>(
rh: &mut RoutineHandler<Label>,
builder: &mut Builder,
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
label_fr0: L,
label_fr1: L2,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Label: Clone + std::fmt::Display + From<String> + From<L> + From<L2>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
{
try_routine_call_jumps(rh, builder, func_fr0, func_fr1, label_fr0, label_fr1).unwrap()
}
#[derive(Clone, Debug, thiserror::Error)]
pub enum DataHandlerError<LAE, BAE> {
#[error("DataHandler {0}: LabelError {1}")]
LabelError(String, LAE),
#[error("DataHandler {0}: BuilderError {1}")]
BuilderError(String, BAE),
}
#[derive(Clone, Debug)]
pub struct DataHandler<Label> {
name: Label,
data_bits: usize,
per_bits: usize,
jump: Label,
values: Vec<bool>,
temp_buffer: bool,
}
impl<Label> DataHandler<Label>
where
Label: Clone + std::fmt::Display + From<String>,
{
pub fn new(
name: &str,
data_bits: usize,
per_bits: usize,
jump: Label,
temp_buffer: bool,
) -> Self {
assert!(data_bits < usize::BITS as usize);
assert!(1 <= per_bits);
Self {
name: name.to_string().into(),
jump,
per_bits,
data_bits,
values: vec![false; 1 << data_bits],
temp_buffer,
}
}
pub fn new_l<L>(
name: L,
data_bits: usize,
per_bits: usize,
jump: Label,
temp_buffer: bool,
) -> Self
where
Label: From<L>,
{
assert!(data_bits < usize::BITS as usize);
assert!(1 <= per_bits);
Self {
name: name.into(),
jump,
per_bits,
data_bits,
values: vec![false; 1 << data_bits],
temp_buffer,
}
}
pub fn new_ll<L, L2>(
name: L,
data_bits: usize,
per_bits: usize,
jump: L2,
temp_buffer: bool,
) -> Self
where
Label: From<L>,
Label: From<L2>,
{
assert!(data_bits < usize::BITS as usize);
assert!(1 <= per_bits);
Self {
name: name.into(),
jump: jump.into(),
per_bits,
data_bits,
values: vec![false; 1 << data_bits],
temp_buffer,
}
}
pub fn name(&self) -> &Label {
&self.name
}
pub fn data_bits(&self) -> usize {
self.data_bits
}
pub fn jump(&self) -> Label {
self.jump.clone()
}
pub fn temp_buffer(&self) -> bool {
self.temp_buffer
}
pub fn data_jump(&mut self, data: usize) -> Label {
format!("{}_putdata_{1}_{2:01$b}", self.name, self.data_bits, data).into()
}
pub fn put_data(&mut self, data: usize) -> Label {
self.values[data] = true;
self.data_jump(data)
}
#[inline]
fn b_label<Builder, Instr, L>(
&self,
builder: &mut Builder,
label: L,
) -> Result<
(),
DataHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
L: Clone + Debug,
Label: From<L>,
{
builder
.try_add_label(label)
.map_err(|e| DataHandlerError::LabelError(self.name.to_string(), e))
}
#[inline]
fn b_instr<Builder, Instr, I>(
&self,
builder: &mut Builder,
instr: I,
) -> Result<
(),
DataHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<I>,
{
builder
.try_add_instr(instr)
.map_err(|e| DataHandlerError::BuilderError(self.name.to_string(), e))
}
pub fn try_install<Builder, Instr>(
self,
builder: &mut Builder,
) -> Result<
(),
DataHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
{
if self.data_bits == 0 {
let label = format!("{}_putdata_0_0", self.name);
self.b_label(builder, label)?;
self.b_instr(
builder,
(
MINF_MR,
MINF_MR,
self.jump.clone().into(),
self.jump.clone().into(),
),
)?;
return Ok(());
}
let (xxrw0, xxrw1, xxmv) = if self.temp_buffer {
(MINF_TBRW0, MINF_TBRW1, MINF_TBRF)
} else {
(MINF_MARW0, MINF_MARW1, MINF_MARF)
};
let mut values = self.values.clone();
for level in (0..self.data_bits).rev() {
for (id_shifted, used) in values.iter().enumerate() {
if *used {
let label =
format!("{}_putdata_{1}_{2:01$b}", self.name, level + 1, id_shifted);
self.b_label(builder, label)?;
let bit = (id_shifted & 1) != 0;
let rw = if bit { xxrw1 } else { xxrw0 };
self.b_instr(builder, (rw, rw, 1isize.into(), 1isize.into()))?;
for _ in 1..self.per_bits {
self.b_instr(builder, (xxmv, xxmv, 1isize.into(), 1isize.into()))?;
}
if level == 0 {
self.b_instr(
builder,
(
xxmv,
xxmv,
self.jump.clone().into(),
self.jump.clone().into(),
),
)?;
} else {
let label: Label =
format!("{}_putdata_{1}_{2:01$b}", self.name, level, id_shifted >> 1)
.into();
self.b_instr(
builder,
(xxmv, xxmv, label.clone().into(), label.clone().into()),
)?;
}
}
}
values = values.chunks(2).map(|v| v[0] | v[1]).collect::<Vec<_>>();
}
Ok(())
}
pub fn install<Builder, Instr>(self, builder: &mut Builder)
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
{
self.try_install(builder).unwrap();
}
}
#[derive(Clone, Debug, thiserror::Error)]
pub enum IndirectJumpHandlerError<LAE, BAE> {
#[error("IndirectJumpHandler {0}: JumpBits over usize length")]
JumpBitsOverLength(String),
#[error("IndirectJumpHandler {0}: JumpBits too small to hold {1} jumps")]
JumpBitsTooSmall(String, usize),
#[error("IndirectJumpHandler {0}: No jumps")]
NoJumps(String),
#[error("IndirectJumpHandler {0}: LabelError {1}")]
LabelError(String, LAE),
#[error("IndirectJumpHandler {0}: BuilderError {1}")]
BuilderError(String, BAE),
}
#[derive(Clone, Debug)]
pub struct IndirectJumpHandler<Label> {
name: Label,
labels: Vec<Label>,
temp_buffer: bool,
reuse: bool,
}
impl<Label> IndirectJumpHandler<Label>
where
Label: Clone + std::fmt::Display + From<String>,
MinInfRel<Label>: From<Label>,
{
pub fn new<I: IntoIterator<Item = Label>>(
name: &str,
labels: I,
temp_buffer: bool,
reuse: bool,
) -> Self {
Self {
name: name.to_string().into(),
labels: labels.into_iter().collect(),
temp_buffer,
reuse,
}
}
pub fn new_l<L, I: IntoIterator<Item = Label>>(
name: L,
labels: I,
temp_buffer: bool,
reuse: bool,
) -> Self
where
Label: From<L>,
{
Self {
name: name.into(),
labels: labels.into_iter().collect(),
temp_buffer,
reuse,
}
}
pub fn new_ll<L, L2, I: IntoIterator<Item = L2>>(
name: L,
labels: I,
temp_buffer: bool,
reuse: bool,
) -> Self
where
Label: From<L>,
Label: From<L2>,
{
Self {
name: name.into(),
labels: labels.into_iter().map(|l| l.into()).collect(),
temp_buffer,
reuse,
}
}
pub fn name(&self) -> &Label {
&self.name
}
pub fn labels(&self) -> &[Label] {
&self.labels
}
pub fn temp_buffer(&self) -> bool {
self.temp_buffer
}
pub fn reuse(&self) -> bool {
self.reuse
}
pub fn ind_jump(&self) -> Label {
format!("{}_indjump", self.name).into()
}
#[inline]
fn b_label<Builder, Instr, L>(
&self,
builder: &mut Builder,
label: L,
) -> Result<
(),
IndirectJumpHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
L: Clone + Debug,
Label: From<L>,
{
builder
.try_add_label(label)
.map_err(|e| IndirectJumpHandlerError::LabelError(self.name.to_string(), e))
}
#[inline]
fn b_instr<Builder, Instr, I>(
&self,
builder: &mut Builder,
instr: I,
) -> Result<
(),
IndirectJumpHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<I>,
{
builder
.try_add_instr(instr)
.map_err(|e| IndirectJumpHandlerError::BuilderError(self.name.to_string(), e))
}
pub fn try_install<Builder, Instr>(
self,
jump_bits: Option<usize>,
builder: &mut Builder,
) -> Result<
usize,
IndirectJumpHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
{
let jump_bits = jump_bits.unwrap_or(calc_log_bits(self.labels.len()));
if !(jump_bits <= (usize::BITS as usize)) {
return Err(IndirectJumpHandlerError::JumpBitsOverLength(
self.name.to_string(),
));
}
if !((1usize << jump_bits) >= self.labels.len()) {
return Err(IndirectJumpHandlerError::JumpBitsTooSmall(
self.name.to_string(),
self.labels.len(),
));
}
if self.labels.is_empty() {
return Err(IndirectJumpHandlerError::NoJumps(self.name.to_string()));
}
assert!(jump_bits <= (usize::BITS as usize));
assert!((1usize << jump_bits) >= self.labels.len());
assert!(!self.labels.is_empty());
self.b_label(builder, format!("{}_indjump", self.name))?;
if jump_bits == 0 {
self.b_instr(
builder,
(
MINF_MR,
MINF_MR,
self.labels[0].clone().into(),
self.labels[0].clone().into(),
),
)?;
return Ok(jump_bits);
}
let (xxr, xxb, xxrf) = if self.temp_buffer {
(
if self.reuse { MINF_TBR } else { MINF_TBRW0 },
MINF_TBB,
MINF_TBRF,
)
} else {
(
if self.reuse { MINF_MAR } else { MINF_MARW0 },
MINF_MAB,
MINF_MARF,
)
};
let label_num = self.labels.len();
self.b_instr(builder, (xxb, xxb, 1isize.into(), 1isize.into()))?;
for b in (0..jump_bits).rev() {
for id_shifted in 0..((label_num + ((1 << (b + 1)) - 1)) >> (b + 1)) {
let id = id_shifted << (b + 1);
let level = jump_bits - b - 1;
let root_name =
format!("{}_indjump_id_{1}_{2:01$b}", self.name, level, id_shifted).into();
self.b_label(builder, root_name)?;
self.b_instr(builder, (xxr, xxr, 1isize.into(), 1isize.into()))?;
let label_num_shifted_2 = (label_num + ((1 << b) - 1)) >> b;
if b != 0 {
let child0_name: Label = format!(
"{}_indjump_id_{1}_{2:01$b}",
self.name,
level + 1,
(id_shifted << 1)
)
.into();
let child1_name = if (id_shifted << 1) + 1 < label_num_shifted_2 {
format!(
"{}_indjump_id_{1}_{2:01$b}",
self.name,
level + 1,
(id_shifted << 1) + 1
)
.into()
} else {
child0_name.clone()
};
self.b_instr(builder, (xxb, xxb, child0_name.into(), child1_name.into()))?;
} else {
let next_label = if id + 1 < label_num {
self.labels[id + 1].clone()
} else {
self.labels[id].clone()
};
if self.reuse {
let same_label = id + 1 >= label_num;
if same_label || jump_bits == 1 {
for _ in 0..jump_bits - 1 {
self.b_instr(builder, (xxrf, xxrf, 1isize.into(), 1isize.into()))?;
}
self.b_instr(
builder,
(
xxrf,
xxrf,
self.labels[id].clone().into(),
next_label.into(),
),
)?;
} else {
let label0: Label =
format!("{}_indjump_fork_{1}", self.name, id).into();
let label1: Label =
format!("{}_indjump_fork_{1}", self.name, id + 1).into();
self.b_instr(
builder,
(xxrf, xxrf, label0.clone().into(), label1.clone().into()),
)?;
self.b_label(builder, label0.to_string())?;
for _ in 0..jump_bits - 2 {
self.b_instr(builder, (xxrf, xxrf, 1isize.into(), 1isize.into()))?;
}
self.b_instr(
builder,
(
xxrf,
xxrf,
self.labels[id].clone().into(),
self.labels[id].clone().into(),
),
)?;
self.b_label(builder, label1.to_string())?;
for _ in 0..jump_bits - 2 {
self.b_instr(builder, (xxrf, xxrf, 1isize.into(), 1isize.into()))?;
}
self.b_instr(
builder,
(
xxrf,
xxrf,
self.labels[id + 1].clone().into(),
self.labels[id + 1].clone().into(),
),
)?;
}
} else {
self.b_instr(
builder,
(
MINF_MR,
MINF_MR,
self.labels[id].clone().into(),
next_label.into(),
),
)?;
}
}
}
}
Ok(jump_bits)
}
pub fn install<Builder, Instr>(self, jump_bits: Option<usize>, builder: &mut Builder) -> usize
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
MinInfRel<Label>: From<Label>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
{
self.try_install(jump_bits, builder).unwrap()
}
}
#[derive(Clone, Debug, thiserror::Error)]
pub enum LongDataSetError {
#[error("LastBits out of range (0..8)")]
LastBitsOutOfRange,
}
#[derive(Clone, Debug, thiserror::Error)]
pub enum LongDataHandlerError<LAE, BAE> {
#[error("LongDataHandler {0}: LabelError {1}")]
LabelError(String, LAE),
#[error("LongDataHandler {0}: BuilderError {1}")]
BuilderError(String, BAE),
#[error("LongDataHandler {0}: RoutineHandlerError: {1}")]
RoutineHandlerError(String, RoutineHandlerError<LAE, BAE>),
}
#[derive(Clone, Debug)]
pub struct LongDataHandler<Label> {
name: Label,
count: u64,
temp_buffer: bool,
per_bits: usize,
chunks: BTreeMap<(u64, u8), RoutineHandler<Label>>,
last_chunks: BTreeMap<(u8, u8), Vec<(u64, Label)>>,
counter: u128,
}
impl<Label> LongDataHandler<Label>
where
Label: From<String>,
{
pub fn new(name: &str, temp_buffer: bool, per_bits: usize) -> Self {
assert!(1 <= per_bits);
Self {
name: name.to_string().into(),
count: 0,
temp_buffer,
per_bits,
chunks: BTreeMap::new(),
last_chunks: BTreeMap::new(),
counter: 0,
}
}
pub fn new_l<L>(name: L, temp_buffer: bool, per_bits: usize) -> Self
where
Label: From<L>,
{
assert!(1 <= per_bits);
Self {
name: name.into(),
count: 0,
temp_buffer,
per_bits,
chunks: BTreeMap::new(),
last_chunks: BTreeMap::new(),
counter: 0,
}
}
pub fn name(&self) -> &Label {
&self.name
}
pub fn temp_buffer(&self) -> bool {
self.temp_buffer
}
pub fn per_bits(&self) -> usize {
self.per_bits
}
}
#[derive(Clone, Debug)]
enum ChunkJump<Label> {
Label(Label),
Chunk(u64, u8),
}
impl<Label> LongDataHandler<Label>
where
Label: Clone + std::fmt::Display + From<String>,
MinInfRel<Label>: From<Label>,
{
fn chunk_label(&self, data: u64, bits: u8) -> Label {
format!("{}_chunk_{:x}_{}", self.name, data, bits).into()
}
fn create_chunk(&mut self, data: u64, bits: u8, jump: ChunkJump<Label>, inside: bool) -> Label {
let ch_label = self.chunk_label(data, bits);
if bits >= 4 {
if bits.count_ones() == 1 {
if bits > 4 {
if !self.chunks.contains_key(&(data, bits)) {
let data_l = data & ((1 << (bits >> 1)) - 1);
let data_h = data >> (bits >> 1);
let next_label = if let Some(rh) = self.chunks.get(&(data_h, bits >> 1)) {
rh.jump_to_next_call(usize::from(data_l == data_h))
} else {
let l = self.chunk_label(data_h, bits >> 1);
RoutineHandler::jump_to_first_call(l, usize::from(data_l == data_h))
};
let chunk_start = self.create_chunk(
data_l,
bits >> 1,
ChunkJump::Label(next_label),
true,
);
let ret_label = RoutineHandler::jump_to_return_before(ch_label.clone());
self.create_chunk(data_h, bits >> 1, ChunkJump::Label(ret_label), true);
self.chunks.insert(
(data, bits),
RoutineHandler::new_rl(
ch_label,
chunk_start,
!self.temp_buffer, true,
),
);
}
} else if !self.chunks.contains_key(&(data, bits)) {
self.chunks.insert(
(data, bits),
RoutineHandler::new_ll(
ch_label,
!self.temp_buffer, true,
),
);
}
} else {
let bits_last_pos = u8::BITS - bits.leading_zeros() - 1;
let l_bits = 1 << bits_last_pos;
let h_bits = bits - l_bits;
let data_l = data & ((1 << l_bits) - 1);
let data_h = data >> l_bits;
let next_label = if h_bits >= 4 {
ChunkJump::Chunk(data_h, h_bits)
} else {
ChunkJump::Label(
format!(
"{}_intlastchunk_{}_{}_{}",
self.name, ch_label, data_h, h_bits
)
.into(),
)
};
let chunk_start = self.create_chunk(data_l, l_bits, next_label, true);
if h_bits >= 4 {
let ret_label = RoutineHandler::jump_to_return_before(ch_label.clone());
self.create_chunk(data_h, h_bits, ChunkJump::Label(ret_label), true);
}
if !self.chunks.contains_key(&(data, bits)) {
self.chunks.insert(
(data, bits),
RoutineHandler::new_rl(
ch_label,
chunk_start,
!self.temp_buffer, true,
),
);
}
}
let tlabel = match jump {
ChunkJump::Label(jump) => jump,
ChunkJump::Chunk(cdata, cbits) => {
if let Some(nrh) = self.chunks.get(&(cdata, cbits)) {
nrh.jump_to_next_call(0)
} else {
let l = self.chunk_label(cdata, cbits);
RoutineHandler::jump_to_first_call(l, 0)
}
}
};
let rh = self.chunks.get_mut(&(data, bits)).unwrap();
let l = format!("{}", rh.label_count());
let call_l = rh.jump_to_next_call(0);
rh.try_add_label_l(&l, tlabel).unwrap();
call_l
} else if inside {
format!("{}_intlastchunk_{}_{}_{}", self.name, ch_label, data, bits).into()
} else {
let data8 = u8::try_from(data).unwrap();
let jump = match jump {
ChunkJump::Label(label) => label,
_ => {
panic!("Unexpected!");
}
};
if let Some(list) = self.last_chunks.get_mut(&(data8, bits)) {
list.push((self.count, jump));
} else {
self.last_chunks
.insert((data8, bits), vec![(self.count, jump)]);
}
format!("{}_lastchunk_{}_{}_{}", self.name, data, bits, self.count).into()
}
}
pub fn try_add_data<L>(
&mut self,
(data, last, last_bits): (&[u8], u8, u8),
jump: L,
) -> Result<Label, LongDataSetError>
where
Label: From<L>,
{
if last_bits > 7 {
return Err(LongDataSetError::LastBitsOutOfRange);
}
let last = last & ((1 << last_bits) - 1);
let jump = Label::from(jump);
let len = data.len();
let len8 = len >> 3;
let len8_rest = len - (len8 << 3);
let start = if len8 != 0 {
let v = u64::from_le_bytes(data[0..8].try_into().unwrap());
let l = self.chunk_label(v, 64);
if let Some(rh) = self.chunks.get(&(v, 64)) {
rh.jump_to_next_call(0)
} else {
RoutineHandler::jump_to_first_call(l, 0)
}
} else if len != 0 || last_bits != 0 {
if len != 0 || last_bits >= 4 {
let mut d = [0; 8];
d[0..len8_rest].copy_from_slice(&data[..]);
let (v, bits) = (
u64::from_le_bytes(d)
| (u64::from(last) & ((1 << last_bits) - 1)) << (len8_rest * 8),
u8::try_from(len8_rest).unwrap() * 8 + last_bits,
);
let l = self.chunk_label(v, bits);
if let Some(rh) = self.chunks.get(&(v, bits)) {
rh.jump_to_next_call(0)
} else {
RoutineHandler::jump_to_first_call(l, 0)
}
} else {
format!(
"{}_lastchunk_{}_{}_{}",
self.name, last, last_bits, self.count
)
.into()
}
} else {
jump.clone()
};
for i in 0..len8 {
let v = u64::from_le_bytes(data[i << 3..(i + 1) << 3].try_into().unwrap());
let nextch = if i + 1 < len8 {
Some((
u64::from_le_bytes(data[(i + 1) << 3..(i + 2) << 3].try_into().unwrap()),
64u8,
))
} else if (len8 << 3) != len8 || last_bits != 0 {
let mut d = [0; 8];
d[0..len8_rest].copy_from_slice(&data[(len8 << 3)..]);
Some((
u64::from_le_bytes(d)
| (u64::from(last) & ((1 << last_bits) - 1)) << (len8_rest * 8),
u8::try_from(len8_rest).unwrap() * 8 + last_bits,
))
} else {
None
};
let next_label = if let Some((nextv, nextbits)) = nextch {
if nextbits == 64 {
if let Some(rh) = self.chunks.get(&(nextv, nextbits)) {
ChunkJump::Label(
rh.jump_to_next_call(usize::from(nextv == v && nextbits == 64)),
)
} else {
let l = self.chunk_label(nextv, nextbits);
ChunkJump::Label(RoutineHandler::jump_to_first_call(
l,
usize::from(nextv == v && nextbits == 64),
))
}
} else if nextbits >= 4 {
ChunkJump::Chunk(nextv, nextbits)
} else if nextbits != 0 {
ChunkJump::Label(
format!(
"{}_lastchunk_{}_{}_{}",
self.name, nextv, nextbits, self.count
)
.into(),
)
} else {
ChunkJump::Label(jump.clone())
}
} else {
ChunkJump::Label(jump.clone())
};
self.create_chunk(v, 64, next_label, false);
}
if len8_rest != 0 || last_bits != 0 {
let mut d = [0; 8];
d[0..len8_rest].copy_from_slice(&data[(len8 << 3)..]);
let (v, bits) = (
u64::from_le_bytes(d)
| (u64::from(last) & ((1 << last_bits) - 1)) << (len8_rest * 8),
u8::try_from(len8_rest).unwrap() * 8 + last_bits,
);
self.create_chunk(v, bits, ChunkJump::Label(jump.clone()), false);
}
self.count += 1;
Ok(start)
}
pub fn add_data<L>(&mut self, data: (&[u8], u8, u8), jump: L) -> Label
where
Label: From<L>,
{
self.try_add_data(data, jump).unwrap()
}
#[inline]
fn b_label<Builder, Instr, L>(
&self,
builder: &mut Builder,
label: L,
) -> Result<
(),
LongDataHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
L: Clone + Debug,
Label: From<L>,
{
builder
.try_add_label(label)
.map_err(|e| LongDataHandlerError::LabelError(self.name.to_string(), e))
}
#[inline]
fn b_instr<Builder, Instr, I>(
&self,
builder: &mut Builder,
instr: I,
) -> Result<
(),
LongDataHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<I>,
{
builder
.try_add_instr(instr)
.map_err(|e| LongDataHandlerError::BuilderError(self.name.to_string(), e))
}
fn gen_data_code<Builder, Instr>(
&self,
builder: &mut Builder,
data: u64,
bits: u8,
jump: Option<Label>,
) -> Result<
(),
LongDataHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
{
let (rw0, rw1, rf) = if self.temp_buffer {
(MINF_TBRW0, MINF_TBRW1, MINF_TBRF)
} else {
(MINF_MARW0, MINF_MARW1, MINF_MARF)
};
for bit in 0..bits {
let dv = ((data >> bit) & 1) != 0;
let xrw = if dv { rw1 } else { rw0 };
self.b_instr(builder, (xrw, xrw, 1isize.into(), 1isize.into()))?;
for _ in 0..self.per_bits - 1 {
self.b_instr(builder, (rf, rf, 1isize.into(), 1isize.into()))?;
}
if bit == bits - 1 {
if let Some(jump) = jump.as_ref() {
self.b_instr(builder, (rf, rf, jump.clone().into(), jump.clone().into()))?;
} else {
self.b_instr(builder, (rf, rf, 1isize.into(), 1isize.into()))?;
}
} else {
self.b_instr(builder, (rf, rf, 1isize.into(), 1isize.into()))?;
}
}
Ok(())
}
fn calc_chunk_ret_bits(
map: &mut BTreeMap<(u64, u8), (usize, Option<usize>)>,
(data, bits): (u64, u8),
inside: bool,
) -> usize {
if inside && bits < 4 {
return 0;
}
let (ret_bits, all_ret_bits) = *map.get(&(data, bits)).unwrap();
if let Some(all_ret_bits) = all_ret_bits {
return all_ret_bits;
}
let all_ret_bits = if bits >= 4 {
if bits.count_ones() == 1 {
if bits > 4 {
let data_l = data & ((1 << (bits >> 1)) - 1);
let data_h = data >> (bits >> 1);
ret_bits
+ std::cmp::max(
Self::calc_chunk_ret_bits(map, (data_l, bits >> 1), true),
Self::calc_chunk_ret_bits(map, (data_h, bits >> 1), true),
)
} else {
ret_bits
}
} else {
let bits_last_pos = u8::BITS - bits.leading_zeros() - 1;
let l_bits = 1 << bits_last_pos;
let h_bits = bits - l_bits;
let data_l = data & ((1 << l_bits) - 1);
let data_h = data >> l_bits;
ret_bits
+ std::cmp::max(
Self::calc_chunk_ret_bits(map, (data_l, l_bits), true),
Self::calc_chunk_ret_bits(map, (data_h, h_bits), true),
)
}
} else {
ret_bits
};
map.insert((data, bits), (ret_bits, Some(all_ret_bits)));
all_ret_bits
}
pub fn try_install<Builder, Instr>(
mut self,
builder: &mut Builder,
) -> Result<
usize,
LongDataHandlerError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
{
let mut chunk_ret_bits = BTreeMap::<(u64, u8), (usize, Option<usize>)>::new();
let chunk_keys = self.chunks.keys().copied().collect::<Vec<_>>();
let mut chunks = BTreeMap::new();
std::mem::swap(&mut chunks, &mut self.chunks);
for (key, rh) in chunks {
let ch_label = self.chunk_label(key.0, key.1);
if key.1 == 4 {
self.b_label(builder, ch_label.to_string())?;
self.gen_data_code(builder, key.0, key.1, Some(rh.jump_to_return()))?;
} else if (key.1 & !3).count_ones() == 1 && (key.1 & 3) != 0 {
let h_bit_start = key.1 & !3;
let label = format!(
"{}_intlastchunk_{}_{}_{}",
self.name,
ch_label,
key.0 >> h_bit_start,
key.1 & 3,
);
self.b_label(builder, label)?;
self.gen_data_code(
builder,
key.0 >> h_bit_start,
key.1 & 3,
Some(rh.jump_to_return()),
)?;
}
let ret_bits = rh
.try_install(None, builder)
.map_err(|x| LongDataHandlerError::RoutineHandlerError(self.name.to_string(), x))?;
chunk_ret_bits.insert(key, (ret_bits, None));
}
let mut max_ret_bits = 0;
for key in chunk_keys {
let chunk_max_ret_bits = Self::calc_chunk_ret_bits(&mut chunk_ret_bits, key, false);
max_ret_bits = std::cmp::max(max_ret_bits, chunk_max_ret_bits);
}
let mut last_chunks = BTreeMap::new();
std::mem::swap(&mut last_chunks, &mut self.last_chunks);
for (key, list) in last_chunks {
for (c, jump) in list {
let label = format!("{}_lastchunk_{}_{}_{}", self.name, key.0, key.1, c);
self.b_label(builder, label)?;
self.gen_data_code(builder, key.0 as u64, key.1, Some(jump))?;
}
}
Ok(max_ret_bits)
}
pub fn install<Builder, Instr>(self, builder: &mut Builder) -> usize
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
{
self.try_install(builder).unwrap()
}
}
#[derive(Clone, Debug, thiserror::Error)]
pub enum LongDataCallError<LAE, BAE> {
#[error("Call:LongDataHandler {0}: SetError: {1}")]
Set(String, LongDataSetError),
#[error("LongDataHandlerError: {0}")]
Handler(#[from] LongDataHandlerError<LAE, BAE>),
}
impl<Label> LongDataHandler<Label>
where
Label: Clone + Debug + std::fmt::Display + From<String> + From<Label>,
MinInfRel<Label>: From<Label>,
{
fn next_label(&mut self) -> Label {
let old_counter = self.counter;
self.counter += 1;
format!("{}_next_{}", self.name, old_counter).into()
}
pub fn try_call_01<Builder, Instr>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func: MinInfFunc,
) -> Result<
(),
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
{
self.try_call(builder, data, func, func)
}
pub fn try_call<Builder, Instr>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) -> Result<
(),
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
{
let nextl = self.next_label();
let l = self
.try_add_data(data, nextl.clone())
.map_err(|e| LongDataCallError::Set(self.name.clone().to_string(), e))?;
self.b_instr(builder, (func_fr0, func_fr1, l.clone().into(), l.into()))?;
self.b_label(builder, nextl)?;
Ok(())
}
pub fn try_call_01_jump<Builder, Instr, L>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func: MinInfFunc,
jump: L,
) -> Result<
(),
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
Label: From<L>,
{
self.try_call_jump(builder, data, func, func, jump)
}
pub fn try_call_jump<Builder, Instr, L>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
jump: L,
) -> Result<
(),
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
Label: From<L>,
{
let l = self
.try_add_data(data, jump)
.map_err(|e| LongDataCallError::Set(self.name.clone().to_string(), e))?;
self.b_instr(builder, (func_fr0, func_fr1, l.clone().into(), l.into()))?;
Ok(())
}
pub fn try_call_fr0_01<Builder, Instr, IntoRel>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, IntoRel)>,
MinInfRel<Label>: From<IntoRel>,
{
self.try_call_fr0(builder, data, func, func, rel)
}
pub fn try_call_fr0<Builder, Instr, IntoRel>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, IntoRel)>,
MinInfRel<Label>: From<IntoRel>,
{
let nextl = self.next_label();
let l = self
.try_add_data(data, nextl.clone())
.map_err(|e| LongDataCallError::Set(self.name.clone().to_string(), e))?;
self.b_instr(builder, (func_fr0, func_fr1, l.into(), rel.into()))?;
self.b_label(builder, nextl)?;
Ok(())
}
pub fn try_call_fr1_01<Builder, Instr, IntoRel>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, IntoRel, MinInfRel<Label>)>,
MinInfRel<Label>: From<IntoRel>,
{
self.try_call_fr1(builder, data, func, func, rel)
}
pub fn try_call_fr1<Builder, Instr, IntoRel>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) -> Result<
(),
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, IntoRel, MinInfRel<Label>)>,
MinInfRel<Label>: From<IntoRel>,
{
let nextl = self.next_label();
let l = self
.try_add_data(data, nextl.clone())
.map_err(|e| LongDataCallError::Set(self.name.clone().to_string(), e))?;
self.b_instr(builder, (func_fr0, func_fr1, rel.into(), l.into()))?;
self.b_label(builder, nextl)?;
Ok(())
}
pub fn try_call_2_01<Builder, Instr>(
&mut self,
builder: &mut Builder,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func: MinInfFunc,
) -> Result<
(),
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
{
self.try_call_2(builder, data_fr0, data_fr1, func, func)
}
pub fn try_call_2<Builder, Instr>(
&mut self,
builder: &mut Builder,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) -> Result<
(),
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
{
let nextl = self.next_label();
let l0 = self
.try_add_data(data_fr0, nextl.clone())
.map_err(|e| LongDataCallError::Set(self.name.clone().to_string(), e))?;
let l1 = self
.try_add_data(data_fr1, nextl.clone())
.map_err(|e| LongDataCallError::Set(self.name.clone().to_string(), e))?;
self.b_instr(builder, (func_fr0, func_fr1, l0.clone().into(), l1.into()))?;
self.b_label(builder, nextl)?;
Ok(())
}
pub fn try_call_2x_01<Builder, Instr>(
&mut self,
ldh2: &mut Self,
builder: &mut Builder,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func: MinInfFunc,
) -> Result<
(),
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
{
self.try_call_2x(ldh2, builder, data_fr0, data_fr1, func, func)
}
pub fn try_call_2x<Builder, Instr>(
&mut self,
ldh2: &mut Self,
builder: &mut Builder,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) -> Result<
(),
LongDataCallError<
<Builder as MinInfLabelTrait<Label>>::Error,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error,
>,
>
where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
{
let nextl = self.next_label();
let l0 = self
.try_add_data(data_fr0, nextl.clone())
.map_err(|e| LongDataCallError::Set(self.name.clone().to_string(), e))?;
let l1 = ldh2
.try_add_data(data_fr1, nextl.clone())
.map_err(|e| LongDataCallError::Set(self.name.clone().to_string(), e))?;
self.b_instr(builder, (func_fr0, func_fr1, l0.clone().into(), l1.into()))?;
self.b_label(builder, nextl)?;
Ok(())
}
pub fn call_01<Builder, Instr>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func: MinInfFunc,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
self.try_call_01(builder, data, func).unwrap();
}
pub fn call<Builder, Instr>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
self.try_call(builder, data, func_fr0, func_fr1).unwrap();
}
pub fn call_fr0_01<Builder, Instr, IntoRel>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func: MinInfFunc,
rel: IntoRel,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, IntoRel)>,
MinInfRel<Label>: From<IntoRel>,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
self.try_call_fr0_01(builder, data, func, rel).unwrap();
}
pub fn call_fr0<Builder, Instr, IntoRel>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, IntoRel)>,
MinInfRel<Label>: From<IntoRel>,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
self.try_call_fr0(builder, data, func_fr0, func_fr1, rel)
.unwrap();
}
pub fn call_fr1_01<Builder, Instr, IntoRel>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func: MinInfFunc,
rel: IntoRel,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, IntoRel, MinInfRel<Label>)>,
MinInfRel<Label>: From<IntoRel>,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
self.try_call_fr1_01(builder, data, func, rel).unwrap();
}
pub fn call_fr1<Builder, Instr, IntoRel>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
rel: IntoRel,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, IntoRel, MinInfRel<Label>)>,
MinInfRel<Label>: From<IntoRel>,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
self.try_call_fr1(builder, data, func_fr0, func_fr1, rel)
.unwrap();
}
pub fn call_2_01<Builder, Instr>(
&mut self,
builder: &mut Builder,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func: MinInfFunc,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
self.try_call_2_01(builder, data_fr0, data_fr1, func)
.unwrap();
}
pub fn call_2<Builder, Instr>(
&mut self,
builder: &mut Builder,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
self.try_call_2(builder, data_fr0, data_fr1, func_fr0, func_fr1)
.unwrap();
}
pub fn call_2x_01<Builder, Instr>(
&mut self,
ldh2: &mut Self,
builder: &mut Builder,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func: MinInfFunc,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
self.try_call_2x_01(ldh2, builder, data_fr0, data_fr1, func)
.unwrap();
}
pub fn call_2x<Builder, Instr>(
&mut self,
ldh2: &mut Self,
builder: &mut Builder,
data_fr0: (&[u8], u8, u8),
data_fr1: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
self.try_call_2x(ldh2, builder, data_fr0, data_fr1, func_fr0, func_fr1)
.unwrap();
}
pub fn call_01_jump<Builder, Instr, L>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func: MinInfFunc,
jump: L,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
Label: From<L>,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
self.try_call_01_jump(builder, data, func, jump).unwrap()
}
pub fn call_jump<Builder, Instr, L>(
&mut self,
builder: &mut Builder,
data: (&[u8], u8, u8),
func_fr0: MinInfFunc,
func_fr1: MinInfFunc,
jump: L,
) where
Builder: MinInfBuilderTrait<Label, Instr> + MinInfLabelTrait<Label>,
Instr: From<(MinInfFunc, MinInfFunc, MinInfRel<Label>, MinInfRel<Label>)>,
Label: From<L>,
<Builder as MinInfBuilderTrait<Label, Instr>>::Error: Debug,
<Builder as MinInfLabelTrait<Label>>::Error: Debug,
{
self.try_call_jump(builder, data, func_fr0, func_fr1, jump)
.unwrap()
}
}
pub fn vecu32_to_longdata(data: Vec<u32>, bits: usize) -> (Vec<u8>, u8, u8) {
let mut out = data
.into_iter()
.map(|v| v.to_le_bytes())
.flatten()
.take((bits + 7) >> 3)
.collect::<Vec<_>>();
let (last, last_bits) = if (bits & 7) != 0 {
let last_bits = u8::try_from(bits & 7).unwrap();
(out.pop().unwrap() & ((1 << last_bits) - 1), last_bits)
} else {
(0, 0)
};
(out, last, last_bits)
}