use crate::{gas, visitors};
use super::{BranchTargetKind, Frame};
pub trait Config<'b> {
type GasVisitor<'s>: visitors::VisitOperatorWithOffset<'b, Output = Result<(), gas::Error>>
where
Self: 's;
fn make_visitor<'s>(&'s mut self, state: &'s mut gas::FunctionState) -> Self::GasVisitor<'s>;
fn save_outcomes(
&self,
state: &mut gas::FunctionState,
destination: &mut crate::AnalysisOutcome,
);
}
impl<'b> Config<'b> for crate::NoConfig {
type GasVisitor<'s> = visitors::NoOpVisitor<Result<(), gas::Error>>;
fn make_visitor<'s>(&'s mut self, _: &'s mut gas::FunctionState) -> Self::GasVisitor<'s> {
visitors::NoOpVisitor(Ok(()))
}
fn save_outcomes(&self, _: &mut gas::FunctionState, _: &mut crate::AnalysisOutcome) {}
}
impl<'b, V: wasmparser::VisitSimdOperator<'b, Output = crate::Fee>> Config<'b> for V {
type GasVisitor<'s>
= gas::Visitor<'s, V>
where
Self: 's;
fn make_visitor<'s>(&'s mut self, state: &'s mut gas::FunctionState) -> Self::GasVisitor<'s> {
gas::Visitor {
offset: 0,
model: self,
state,
}
}
fn save_outcomes(&self, state: &mut gas::FunctionState, out: &mut crate::AnalysisOutcome) {
state.optimize();
out.gas_offsets.push(state.offsets.drain(..).collect());
out.gas_kinds.push(state.kinds.drain(..).collect());
out.gas_costs.push(state.costs.drain(..).collect());
state.frame_stack.clear();
state.current_frame = Frame {
stack_polymorphic: false,
kind: BranchTargetKind::UntakenForward,
};
state.scheduled_instrumentation = None;
}
}