1mod ids;
2mod ops;
3mod types;
4
5pub use ids::LocalVarInterner;
6pub use ids::{Builtin, LocalVarId};
7pub use ops::{BinaryOperator, UnaryOperator};
8pub use types::{Binop, Load, Range, RangeParam, SpaceRef, Unop};
9
10use crate::{BitRangeFieldId, FieldId, PCodeOpId, PMacroId, RegisterId, TableId};
11use serde::{Deserialize, Serialize};
12
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
21pub enum Ident {
22 Named(LocalVarId),
26
27 Register(RegisterId),
29
30 BitRange(BitRangeFieldId),
34
35 Field(FieldId),
39
40 Table(TableId),
43 Global(Box<str>),
46}
47
48#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
52pub enum ExpressionTy<S = ()> {
53 SizedInt {
55 value: u64,
57 size: Option<usize>,
60 },
61
62 SubPieceMsb {
64 src: Box<Expression<S>>,
66 count: usize,
68 },
69
70 SubPieceLsb {
72 src: Box<Expression<S>>,
74 count: usize,
76 },
77
78 Load(Load<S>),
80
81 Range(Range<S>),
83
84 FunctionCall {
86 builtin: Builtin,
88 args: Vec<Expression<S>>,
90 },
91
92 PcodeOp {
97 id: PCodeOpId,
99 args: Vec<Expression<S>>,
101 },
102
103 MacroCall {
106 id: PMacroId,
108 args: Vec<Expression<S>>,
110 },
111
112 DeferredCall {
116 name: Box<str>,
118 args: Vec<Expression<S>>,
120 },
121
122 Ident(Ident),
124
125 Unop(Unop<S>),
127
128 Binop(Binop<S>),
130}
131
132impl From<ExpressionTy> for Expression {
133 fn from(ty: ExpressionTy) -> Self {
134 Self {
135 ty,
136 size: None,
137 span: (),
138 }
139 }
140}
141
142impl ExpressionTy {
143 pub fn with_size(self, size: usize) -> Expression {
145 Expression {
146 ty: self,
147 size: Some(size),
148 span: (),
149 }
150 }
151
152 pub(crate) fn pretty_print(&self, spec: &impl crate::PcodeResolver) -> String {
153 match self {
154 ExpressionTy::SizedInt { value, size } => match size {
155 Some(size) => format!("{value}:{size}"),
156 None => value.to_string(),
157 },
158 ExpressionTy::SubPieceMsb { src, count } => {
159 format!("subpiece_msb({}, {})", src.pretty_print(spec), count)
160 }
161 ExpressionTy::SubPieceLsb { src, count } => {
162 format!("subpiece_lsb({}, {})", src.pretty_print(spec), count)
163 }
164 ExpressionTy::Load(load) => load.pretty_print(spec),
165 ExpressionTy::Range(range) => range.pretty_print(spec),
166 ExpressionTy::FunctionCall { builtin, args } => {
167 format!("{}({})", builtin.as_str(), pretty_print_args(args, spec))
168 }
169 ExpressionTy::PcodeOp { id, args } => format!(
170 "{}({})",
171 spec.pcode_op_name(*id),
172 pretty_print_args(args, spec)
173 ),
174 ExpressionTy::MacroCall { id, args } => format!(
175 "{}({})",
176 spec.macro_name(*id),
177 pretty_print_args(args, spec)
178 ),
179 ExpressionTy::DeferredCall { name, args } => {
180 format!("{}({})", name, pretty_print_args(args, spec))
181 }
182 ExpressionTy::Ident(ident) => pretty_print_ident(spec, ident),
183 ExpressionTy::Unop(unop) => unop.pretty_print(spec),
184 ExpressionTy::Binop(binop) => binop.pretty_print(spec),
185 }
186 }
187}
188
189impl<S> ExpressionTy<S> {
190 pub fn strip_span(self) -> ExpressionTy<()> {
192 match self {
193 ExpressionTy::SizedInt { value, size } => ExpressionTy::SizedInt { value, size },
194 ExpressionTy::SubPieceMsb { src, count } => ExpressionTy::SubPieceMsb {
195 src: Box::new(src.strip_span()),
196 count,
197 },
198 ExpressionTy::SubPieceLsb { src, count } => ExpressionTy::SubPieceLsb {
199 src: Box::new(src.strip_span()),
200 count,
201 },
202 ExpressionTy::Load(load) => ExpressionTy::Load(load.strip_span()),
203 ExpressionTy::Range(range) => ExpressionTy::Range(range.strip_span()),
204 ExpressionTy::FunctionCall { builtin, args } => ExpressionTy::FunctionCall {
205 builtin,
206 args: args.into_iter().map(Expression::strip_span).collect(),
207 },
208 ExpressionTy::PcodeOp { id, args } => ExpressionTy::PcodeOp {
209 id,
210 args: args.into_iter().map(Expression::strip_span).collect(),
211 },
212 ExpressionTy::MacroCall { id, args } => ExpressionTy::MacroCall {
213 id,
214 args: args.into_iter().map(Expression::strip_span).collect(),
215 },
216 ExpressionTy::DeferredCall { name, args } => ExpressionTy::DeferredCall {
217 name,
218 args: args.into_iter().map(Expression::strip_span).collect(),
219 },
220 ExpressionTy::Ident(ident) => ExpressionTy::Ident(ident),
221 ExpressionTy::Unop(unop) => ExpressionTy::Unop(unop.strip_span()),
222 ExpressionTy::Binop(binop) => ExpressionTy::Binop(binop.strip_span()),
223 }
224 }
225}
226
227#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
233pub struct Expression<S = ()> {
234 pub ty: ExpressionTy<S>,
236
237 pub size: Option<usize>,
244
245 pub span: S,
248}
249
250impl<S: std::fmt::Debug> std::fmt::Debug for Expression<S> {
251 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
252 if let Some(size) = self.size {
253 write!(f, "{:?} (size: {:?})", self.ty, size)
254 } else {
255 self.ty.fmt(f)
256 }
257 }
258}
259
260impl<S> Expression<S> {
261 pub fn strip_span(self) -> Expression<()> {
263 Expression {
264 ty: self.ty.strip_span(),
265 size: self.size,
266 span: (),
267 }
268 }
269}
270
271impl Expression {
272 pub fn pretty_print(&self, spec: &impl crate::PcodeResolver) -> String {
275 self.ty.pretty_print(spec)
276 }
277}
278
279impl Expression<(usize, usize)> {
280 pub fn new_int(value: u64, size: Option<usize>, span: (usize, usize)) -> Self {
282 Self {
283 ty: ExpressionTy::SizedInt { value, size },
284 size,
285 span,
286 }
287 }
288}
289
290fn pretty_print_args(args: &[Expression], spec: &impl crate::PcodeResolver) -> String {
291 args.iter()
292 .map(|arg| arg.pretty_print(spec))
293 .collect::<Vec<_>>()
294 .join(", ")
295}
296
297pub fn pretty_print_ident(spec: &impl crate::PcodeResolver, ident: &Ident) -> String {
298 match ident {
299 Ident::Named(id) => format!("v{}", id.0),
300 Ident::Register(_) => spec.ident_name(ident),
301 Ident::BitRange(_) => spec.ident_name(ident),
302 Ident::Field(_) => spec.ident_name(ident),
303 Ident::Table(id) => format!("table{}", usize::from(*id)),
304 Ident::Global(name) => format!("?{name}"),
305 }
306}