1use crate::{BinaryOperator, Expression, PcodeResolver, SpaceId, UnaryOperator};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
6pub enum SpaceRef {
7 Resolved(SpaceId),
10 Deferred(Box<str>),
12}
13
14impl SpaceRef {
15 pub fn resolved(&self) -> SpaceId {
22 match self {
23 SpaceRef::Resolved(id) => *id,
24 SpaceRef::Deferred(name) => panic!("unresolved space `{name}` reached runtime"),
25 }
26 }
27}
28
29#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
31pub enum RangeParam {
32 Literal(usize),
34
35 MacroArg(crate::LocalVarId),
38}
39
40#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
45pub struct Range<S = ()> {
46 pub value: Box<Expression<S>>,
48 pub start: RangeParam,
50 pub size: RangeParam,
52}
53
54impl<S> Range<S> {
55 pub fn strip_span(self) -> Range<()> {
57 Range {
58 value: Box::new(self.value.strip_span()),
59 start: self.start,
60 size: self.size,
61 }
62 }
63}
64
65impl Range {
66 pub fn pretty_print(&self, spec: &impl PcodeResolver) -> String {
68 format!(
69 "range({}, {}, {})",
70 self.value.pretty_print(spec),
71 pretty_print_range_param(&self.start),
72 pretty_print_range_param(&self.size)
73 )
74 }
75}
76
77#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
82pub struct Load<S = ()> {
83 pub space: Option<SpaceRef>,
85
86 pub size: Option<usize>,
89
90 pub ptr: Box<Expression<S>>,
92}
93
94impl<S> Load<S> {
95 pub fn strip_span(self) -> Load<()> {
97 Load {
98 space: self.space,
99 size: self.size,
100 ptr: Box::new(self.ptr.strip_span()),
101 }
102 }
103}
104
105impl Load {
106 pub fn pretty_print(&self, spec: &impl PcodeResolver) -> String {
108 let mut parts = Vec::new();
109 if let Some(space) = &self.space {
110 let name = match space {
111 SpaceRef::Resolved(id) => pretty_print_space(spec, *id),
112 SpaceRef::Deferred(name) => format!("?{name}"),
113 };
114 parts.push(format!("space={name}"));
115 }
116 if let Some(size) = self.size {
117 parts.push(format!("size={size}"));
118 }
119 parts.push(format!("ptr={}", self.ptr.pretty_print(spec)));
120 format!("load({})", parts.join(", "))
121 }
122}
123
124#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
126pub struct Unop<S = ()> {
127 pub op: UnaryOperator,
129 pub e: Box<Expression<S>>,
131}
132
133impl<S> Unop<S> {
134 pub fn strip_span(self) -> Unop<()> {
136 Unop {
137 op: self.op,
138 e: Box::new(self.e.strip_span()),
139 }
140 }
141}
142
143impl Unop {
144 pub fn pretty_print(&self, spec: &impl PcodeResolver) -> String {
146 let expr = self.e.pretty_print(spec);
147 match self.op {
148 UnaryOperator::LogicalNot => format!("!{expr}"),
149 UnaryOperator::BitwiseNot => format!("~{expr}"),
150 UnaryOperator::Minus => format!("-{expr}"),
151 UnaryOperator::FloatMinus => format!("f-{expr}"),
152 UnaryOperator::AddressOf(Some(size)) => format!("&:{size} {expr}"),
153 UnaryOperator::AddressOf(None) => format!("&{expr}"),
154 }
155 }
156}
157
158#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
160pub struct Binop<S = ()> {
161 pub op: BinaryOperator,
163 pub lhs: Box<Expression<S>>,
165 pub rhs: Box<Expression<S>>,
167}
168
169impl<S> Binop<S> {
170 pub fn strip_span(self) -> Binop<()> {
172 Binop {
173 op: self.op,
174 lhs: Box::new(self.lhs.strip_span()),
175 rhs: Box::new(self.rhs.strip_span()),
176 }
177 }
178}
179
180impl Binop {
181 pub fn pretty_print(&self, spec: &impl PcodeResolver) -> String {
183 format!(
184 "({} {} {})",
185 self.lhs.pretty_print(spec),
186 self.op.pretty_print(),
187 self.rhs.pretty_print(spec)
188 )
189 }
190}
191
192fn pretty_print_range_param(param: &RangeParam) -> String {
193 match param {
194 RangeParam::Literal(value) => value.to_string(),
195 RangeParam::MacroArg(id) => format!("arg{}", id.0),
196 }
197}
198
199fn pretty_print_space(spec: &impl PcodeResolver, id: SpaceId) -> String {
200 spec.space_name(id)
201}