use std::borrow::Borrow;
use std::collections::HashMap;
use crate::display::JingleDisplay;
use internment::Intern;
use jingle_sleigh::{SleighArchInfo, VarNode};
use std::fmt::{Display, Formatter};
use crate::analysis::{valuation::SimpleValue, varnode_map::VarNodeMap};
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct SimpleValuation {
pub direct_writes: VarNodeMap<SimpleValue>,
pub indirect_writes: HashMap<SimpleValue, SimpleValue>,
}
impl Default for SimpleValuation {
fn default() -> Self {
Self::new()
}
}
impl SimpleValuation {
pub fn new() -> Self {
Self {
direct_writes: VarNodeMap::new(),
indirect_writes: HashMap::new(),
}
}
pub fn with_contents(
direct_writes: VarNodeMap<SimpleValue>,
indirect_writes: HashMap<SimpleValue, SimpleValue>,
) -> Self {
Self {
direct_writes,
indirect_writes,
}
}
pub fn get<B: Borrow<SingleValuationLocation>>(&self, loc: B) -> Option<&SimpleValue> {
match loc.borrow() {
SingleValuationLocation::Direct(vn_intern) => {
self.direct_writes.get(vn_intern.as_ref())
}
SingleValuationLocation::Indirect(ptr_intern) => {
self.indirect_writes.get(ptr_intern.as_ref())
}
}
}
pub fn iter(&self) -> SimpleValuationIter<'_> {
self.into_iter()
}
}
#[derive(Debug, Clone)]
pub enum SingleValuationLocation {
Direct(Intern<VarNode>),
Indirect(Intern<SimpleValue>),
}
impl SingleValuationLocation {
pub fn new_direct(vn: VarNode) -> Self {
SingleValuationLocation::Direct(Intern::new(vn))
}
pub fn new_indirect(ptr: SimpleValue) -> Self {
SingleValuationLocation::Indirect(Intern::new(ptr))
}
}
impl From<VarNode> for SingleValuationLocation {
fn from(vn: VarNode) -> Self {
SingleValuationLocation::Direct(Intern::new(vn))
}
}
impl From<SimpleValue> for SingleValuationLocation {
fn from(ptr: SimpleValue) -> Self {
SingleValuationLocation::Indirect(Intern::new(ptr))
}
}
#[derive(Debug, Clone)]
pub struct SingleValuation {
location: SingleValuationLocation,
value: Intern<SimpleValue>,
}
impl SingleValuation {
pub fn new(location: SingleValuationLocation, value: SimpleValue) -> Self {
Self {
location,
value: Intern::new(value),
}
}
}
impl SingleValuation {
pub fn new_direct(vn: VarNode, value: SimpleValue) -> Self {
Self {
location: SingleValuationLocation::Direct(Intern::new(vn)),
value: Intern::new(value),
}
}
pub fn new_indirect(ptr: SimpleValue, value: SimpleValue) -> Self {
Self {
location: SingleValuationLocation::Indirect(Intern::new(ptr)),
value: Intern::new(value),
}
}
pub fn location(&self) -> &SingleValuationLocation {
&self.location
}
pub fn value(&self) -> &SimpleValue {
self.value.as_ref()
}
}
impl SimpleValuation {
pub fn add<L, V>(&mut self, loc: L, value: V)
where
L: Into<SingleValuationLocation>,
V: Into<SimpleValue>,
{
let loc = loc.into();
let val = value.into().simplify();
match loc {
SingleValuationLocation::Direct(vn_intern) => {
let vn = vn_intern.as_ref().clone();
self.direct_writes.insert(vn, val);
}
SingleValuationLocation::Indirect(ptr_intern) => {
let ptr = ptr_intern.as_ref().clone();
self.indirect_writes.insert(ptr, val);
}
}
}
}
impl JingleDisplay for SingleValuationLocation {
fn fmt_jingle(&self, f: &mut Formatter<'_>, info: &SleighArchInfo) -> std::fmt::Result {
match self {
SingleValuationLocation::Direct(vn_intern) => vn_intern.as_ref().fmt_jingle(f, info),
SingleValuationLocation::Indirect(ptr_intern) => {
write!(f, "[")?;
ptr_intern.as_ref().fmt_jingle(f, info)?;
write!(f, "]")
}
}
}
}
impl Display for SingleValuationLocation {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
SingleValuationLocation::Direct(vn_intern) => write!(f, "{}", vn_intern.as_ref()),
SingleValuationLocation::Indirect(ptr_intern) => {
write!(f, "[{}]", ptr_intern.as_ref())
}
}
}
}
impl JingleDisplay for SingleValuation {
fn fmt_jingle(&self, f: &mut Formatter<'_>, info: &SleighArchInfo) -> std::fmt::Result {
write!(
f,
"{} = {}",
self.location.display(info),
self.value.as_ref().display(info)
)
}
}
pub struct SimpleValuationIter<'a> {
_valuation: &'a SimpleValuation,
direct_entries: Vec<(Intern<VarNode>, Intern<SimpleValue>)>,
direct_idx: usize,
indirect_entries: Vec<(Intern<SimpleValue>, Intern<SimpleValue>)>,
indirect_idx: usize,
}
impl<'a> SimpleValuationIter<'a> {
pub fn new(valuation: &'a SimpleValuation) -> Self {
let mut direct_entries: Vec<(Intern<VarNode>, Intern<SimpleValue>)> = Vec::new();
for (vn, val) in valuation.direct_writes.items() {
direct_entries.push((Intern::new(vn.clone()), Intern::new(val.clone())));
}
let mut indirect_entries: Vec<(Intern<SimpleValue>, Intern<SimpleValue>)> = Vec::new();
for (ptr, val) in &valuation.indirect_writes {
indirect_entries.push((Intern::new(ptr.clone()), Intern::new(val.clone())));
}
Self {
_valuation: valuation,
direct_entries,
direct_idx: 0,
indirect_entries,
indirect_idx: 0,
}
}
}
impl<'a> Iterator for SimpleValuationIter<'a> {
type Item = SingleValuation;
fn next(&mut self) -> Option<Self::Item> {
if self.direct_idx < self.direct_entries.len() {
let (vn_intern, val_intern) = self.direct_entries[self.direct_idx];
self.direct_idx += 1;
return Some(SingleValuation {
location: SingleValuationLocation::Direct(vn_intern),
value: val_intern,
});
}
if self.indirect_idx < self.indirect_entries.len() {
let (ptr_intern, val_intern) = self.indirect_entries[self.indirect_idx];
self.indirect_idx += 1;
return Some(SingleValuation {
location: SingleValuationLocation::Indirect(ptr_intern),
value: val_intern,
});
}
None
}
}
impl<'a> IntoIterator for &'a SimpleValuation {
type Item = SingleValuation;
type IntoIter = SimpleValuationIter<'a>;
fn into_iter(self) -> Self::IntoIter {
SimpleValuationIter::new(self)
}
}
pub struct SimpleValuationIntoIter {
direct_entries: Vec<(Intern<VarNode>, Intern<SimpleValue>)>,
direct_idx: usize,
indirect_entries: Vec<(Intern<SimpleValue>, Intern<SimpleValue>)>,
indirect_idx: usize,
}
impl Iterator for SimpleValuationIntoIter {
type Item = SingleValuation;
fn next(&mut self) -> Option<Self::Item> {
if self.direct_idx < self.direct_entries.len() {
let (vn_intern, val_intern) = self.direct_entries[self.direct_idx];
self.direct_idx += 1;
return Some(SingleValuation {
location: SingleValuationLocation::Direct(vn_intern),
value: val_intern,
});
}
if self.indirect_idx < self.indirect_entries.len() {
let (ptr_intern, val_intern) = self.indirect_entries[self.indirect_idx];
self.indirect_idx += 1;
return Some(SingleValuation {
location: SingleValuationLocation::Indirect(ptr_intern),
value: val_intern,
});
}
None
}
}
impl<'a> IntoIterator for &'a mut SimpleValuation {
type Item = SingleValuation;
type IntoIter = SimpleValuationIter<'a>;
fn into_iter(self) -> Self::IntoIter {
SimpleValuationIter::new(self)
}
}
impl IntoIterator for SimpleValuation {
type Item = SingleValuation;
type IntoIter = SimpleValuationIntoIter;
fn into_iter(self) -> Self::IntoIter {
let mut direct_entries: Vec<(Intern<VarNode>, Intern<SimpleValue>)> = Vec::new();
for (vn, val) in self.direct_writes.into_iter() {
direct_entries.push((Intern::new(vn), Intern::new(val)));
}
let mut indirect_entries: Vec<(Intern<SimpleValue>, Intern<SimpleValue>)> = Vec::new();
for (ptr, val) in self.indirect_writes.into_iter() {
indirect_entries.push((Intern::new(ptr), Intern::new(val)));
}
SimpleValuationIntoIter {
direct_entries,
direct_idx: 0,
indirect_entries,
indirect_idx: 0,
}
}
}
impl From<Vec<SingleValuation>> for SimpleValuation {
fn from(vs: Vec<SingleValuation>) -> Self {
let mut s = SimpleValuation::new();
for sv in vs.into_iter() {
let val = sv.value();
match sv.location() {
SingleValuationLocation::Direct(vn_intern) => {
s.direct_writes
.insert(vn_intern.as_ref().clone(), val.clone());
}
SingleValuationLocation::Indirect(ptr_intern) => {
s.indirect_writes
.insert(ptr_intern.as_ref().clone(), val.clone());
}
}
}
s
}
}
impl JingleDisplay for SimpleValuation {
fn fmt_jingle(&self, f: &mut Formatter<'_>, info: &SleighArchInfo) -> std::fmt::Result {
write!(f, "SimpleValuation {{")?;
let mut first = true;
for (vn, val) in self.direct_writes.items() {
if !first {
write!(f, ", ")?;
}
first = false;
write!(f, "{} = {}", vn.display(info), val.display(info))?;
}
for (ptr, val) in &self.indirect_writes {
if !first {
write!(f, ", ")?;
}
first = false;
write!(f, "[{}] = {}", ptr.display(info), val.display(info))?;
}
write!(f, "}}")?;
Ok(())
}
}