1use std::collections::HashMap;
2
3use crate::semantic::meaning::{AttachLiteral, AttachNumber, AttachVarnode};
4use crate::semantic::{
5 AttachLiteralId, AttachNumberId, AttachVarnodeId, BitrangeId, ContextId,
6 GlobalScope, PcodeMacroId, SpaceId, TableId, TokenFieldId, TokenId,
7 UserFunctionId, VarnodeId,
8};
9use crate::syntax::define::TokenFieldAttribute;
10use crate::{
11 syntax, Endian, NumberNonZeroUnsigned, NumberUnsigned, SleighError, Span,
12 IDENT_EPSILON, IDENT_INSTRUCTION, IDENT_INST_NEXT, IDENT_INST_START,
13};
14
15use super::space::Space;
16use super::token::Token;
17use super::user_function::UserFunction;
18use super::varnode::{Bitrange, Varnode};
19use super::{Epsilon, InstNext, InstStart, PrintBase, ValueFmt};
20
21pub mod attach;
22pub mod disassembly;
23pub mod display;
24pub mod execution;
25pub mod pattern;
26pub mod pcode_macro;
27pub mod space;
28pub mod table;
29pub mod token;
30pub mod varnode;
31pub mod with_block;
32
33use self::execution::FieldSize;
34use self::pattern::Pattern;
35use self::pcode_macro::PcodeMacro;
36use self::table::Table;
37use self::token::TokenField;
38use self::varnode::Context;
39use self::with_block::WithBlockCurrent;
40
41#[derive(Copy, Clone, Debug)]
42pub struct PrintFlags {
43 pub signed_set: bool,
45 pub base: Option<PrintBase>,
47}
48
49impl PrintFlags {
50 pub fn from_token_att<'a>(
51 src: &Span,
52 att: impl Iterator<Item = &'a TokenFieldAttribute>,
53 ) -> Result<Self, SleighError> {
54 let (mut signed_set, mut base) = (false, None);
55 for att in att {
56 use syntax::define::TokenFieldAttribute::*;
57 match att {
58 Hex if base.is_none() => base = Some(PrintBase::Hex),
59 Dec if base.is_none() => base = Some(PrintBase::Dec),
60 Hex | Dec => {
61 return Err(SleighError::TokenFieldAttachDup(src.clone()))
62 }
63 Signed if !signed_set => signed_set = true,
64 Signed => {
65 return Err(SleighError::TokenFieldAttDup(src.clone()))
66 }
67 }
68 }
69 Ok(Self { signed_set, base })
70 }
71 pub fn is_set(&self) -> bool {
72 self.signed_set || self.base.is_some()
73 }
74}
75
76impl From<PrintFlags> for ValueFmt {
77 fn from(flags: PrintFlags) -> Self {
78 let signed = flags.signed_set;
80 let base = flags.base.unwrap_or(PrintBase::Hex);
82 ValueFmt { signed, base }
83 }
84}
85
86pub trait SolverStatus<T: SolverStatus = Self> {
87 fn iam_not_finished_location(
88 &mut self,
89 location: &Span,
90 file: &'static str,
91 line: u32,
92 );
93 fn i_did_a_thing(&mut self);
94 fn we_finished(&self) -> bool;
95 fn we_did_a_thing(&self) -> bool;
96 fn unfinished_locations(&self) -> &[(Span, &'static str, u32)];
97 fn combine(&mut self, other: &Self);
98}
99
100#[derive(Clone, Copy, Debug)]
101pub struct Solved {
102 did_a_thing: bool,
103 finished: bool,
104}
105
106impl SolverStatus for Solved {
107 fn iam_not_finished_location(
108 &mut self,
109 _location: &Span,
110 _file: &'static str,
111 _line: u32,
112 ) {
113 self.finished = false;
114 }
115 fn i_did_a_thing(&mut self) {
116 self.did_a_thing = true;
117 }
118 fn we_finished(&self) -> bool {
119 self.finished
120 }
121 fn we_did_a_thing(&self) -> bool {
122 self.did_a_thing
123 }
124 fn unfinished_locations(&self) -> &[(Span, &'static str, u32)] {
125 &[]
126 }
127 fn combine(&mut self, other: &Self) {
128 self.did_a_thing |= other.we_did_a_thing();
129 self.finished &= other.we_finished();
130 }
131}
132
133impl Default for Solved {
134 fn default() -> Self {
135 Self {
136 did_a_thing: false,
137 finished: true,
138 }
139 }
140}
141
142#[derive(Clone, Debug, Default)]
143pub struct SolvedLocation {
144 solved: Solved,
145 locations: Vec<(Span, &'static str, u32)>,
146}
147
148impl SolverStatus for SolvedLocation {
149 fn iam_not_finished_location(
150 &mut self,
151 location: &Span,
152 file: &'static str,
153 line: u32,
154 ) {
155 self.solved.iam_not_finished_location(location, file, line);
156 self.locations.push((location.clone(), file, line));
157 }
158 fn i_did_a_thing(&mut self) {
159 self.solved.i_did_a_thing();
160 }
161 fn we_finished(&self) -> bool {
162 self.solved.we_finished()
163 }
164 fn we_did_a_thing(&self) -> bool {
165 self.solved.we_did_a_thing()
166 }
167 fn unfinished_locations(&self) -> &[(Span, &'static str, u32)] {
168 &self.locations
169 }
170 fn combine(&mut self, other: &Self) {
171 self.solved.combine(&other.solved);
172 self.locations
173 .extend(other.unfinished_locations().iter().cloned());
174 }
175}
176
177#[derive(Debug)]
178pub struct Sleigh {
179 pub default_space: Option<SpaceId>,
181 pub instruction_table: TableId,
182
183 pub endian: Option<Endian>,
186 pub alignment: Option<NumberUnsigned>,
188 pub global_scope: HashMap<String, GlobalScope>,
190
191 pub spaces: Vec<Space>,
192 pub varnodes: Vec<Varnode>,
193 pub contexts: Vec<Context>,
194 pub bitranges: Vec<Bitrange>,
195 pub tokens: Vec<Token>,
196 pub token_fields: Vec<TokenField>,
197 pub user_functions: Vec<UserFunction>,
198 pub pcode_macros: Vec<PcodeMacro>,
199 pub tables: Vec<Table>,
200
201 pub attach_varnodes: Vec<AttachVarnode>,
202 pub attach_literals: Vec<AttachLiteral>,
203 pub attach_numbers: Vec<AttachNumber>,
204}
205
206impl Sleigh {
207 pub fn space(&self, space: SpaceId) -> &Space {
208 &self.spaces[space.0]
209 }
210 pub fn varnode(&self, varnode: VarnodeId) -> &Varnode {
211 &self.varnodes[varnode.0]
212 }
213 pub fn context(&self, context: ContextId) -> &Context {
214 &self.contexts[context.0]
215 }
216 pub fn context_mut(&mut self, context: ContextId) -> &mut Context {
217 &mut self.contexts[context.0]
218 }
219 pub fn bitrange(&self, bitrange: BitrangeId) -> &Bitrange {
220 &self.bitranges[bitrange.0]
221 }
222 pub fn token(&self, token: TokenId) -> &Token {
223 &self.tokens[token.0]
224 }
225 pub fn token_field(&self, token_field: TokenFieldId) -> &TokenField {
226 &self.token_fields[token_field.0]
227 }
228 pub fn token_field_mut(
229 &mut self,
230 token_field: TokenFieldId,
231 ) -> &mut TokenField {
232 &mut self.token_fields[token_field.0]
233 }
234 pub fn user_function(
235 &self,
236 user_function: UserFunctionId,
237 ) -> &UserFunction {
238 &self.user_functions[user_function.0]
239 }
240 pub fn pcode_macro(&self, pcode_macro: PcodeMacroId) -> &PcodeMacro {
241 &self.pcode_macros[pcode_macro.0]
242 }
243 pub fn table(&self, table: TableId) -> &Table {
244 &self.tables[table.0]
245 }
246 pub fn table_mut(&mut self, table: TableId) -> &mut Table {
247 &mut self.tables[table.0]
248 }
249 pub fn attach_varnode(&self, id: AttachVarnodeId) -> &AttachVarnode {
250 &self.attach_varnodes[id.0]
251 }
252 pub fn attach_number(&self, id: AttachNumberId) -> &AttachNumber {
253 &self.attach_numbers[id.0]
254 }
255 pub fn attach_literal(&self, id: AttachLiteralId) -> &AttachLiteral {
256 &self.attach_literals[id.0]
257 }
258 pub fn default_space(&self) -> Option<SpaceId> {
259 self.default_space
260 }
261 pub fn get_global(&self, name: &str) -> Option<GlobalScope> {
262 self.global_scope.get(name).copied()
263 }
264 pub fn set_endian(&mut self, endian: Endian) -> Result<(), SleighError> {
265 self.endian
266 .replace(endian)
267 .map(|_old| Err(SleighError::EndianMultiple))
268 .unwrap_or(Ok(()))
269 }
270 pub fn set_alignment(
271 &mut self,
272 align: syntax::define::Alignment,
273 ) -> Result<(), SleighError> {
274 self.alignment
275 .replace(align.0)
276 .map(|_| Err(SleighError::AlignmentMultiple))
277 .unwrap_or(Ok(()))
278 }
279 fn process(
280 &mut self,
281 with_block_current: &mut WithBlockCurrent,
282 syntax: syntax::Sleigh,
283 ) -> Result<(), SleighError> {
284 for assertation in syntax.assertations.into_iter() {
285 use syntax::define::Define::*;
286 use syntax::Assertation::*;
287 match assertation {
288 Define(Endian(endian)) => self.set_endian(endian)?,
289 Define(Alignment(x)) => self.set_alignment(x)?,
290 Define(Space(x)) => self.create_space(x)?,
291 Define(Varnode(x)) => self.create_memory(x)?,
292 Define(Bitrange(x)) => self.create_bitrange(x)?,
293 Define(UserFunction(x)) => self.create_user_function(x)?,
294 Define(Context(x)) => self.create_context(x)?,
295 Define(Token(x)) => self.create_token(x)?,
296 Attach(x) => self.attach_meaning(x)?,
297 TableConstructor(x) => {
298 self.insert_table_constructor(with_block_current, x)?
299 }
300 PcodeMacro(x) => self.create_pcode_macro(x)?,
301 WithBlock(with_block) => {
302 let body = with_block_current.push(with_block);
304 self.process(with_block_current, body)?;
305 with_block_current.pop();
306 }
307 }
308 }
309 Ok(())
310 }
311
312 pub fn addr_bytes(&self) -> Option<NumberNonZeroUnsigned> {
313 let space_id = self.default_space?;
314 let space = self.space(space_id);
315 Some(space.addr_bytes)
316 }
317
318 pub fn new(syntax: syntax::Sleigh) -> Result<Self, SleighError> {
319 let instruction_table =
320 Table::new_empty(true, IDENT_INSTRUCTION.to_owned());
321 let instruction_table_id = TableId(0);
322 let mut sleigh = Sleigh {
323 tables: vec![instruction_table],
324 global_scope: HashMap::from([
325 (
326 IDENT_INST_START.to_string(),
327 GlobalScope::InstStart(InstStart),
328 ),
329 (IDENT_INST_NEXT.to_string(), GlobalScope::InstNext(InstNext)),
330 (IDENT_EPSILON.to_string(), GlobalScope::Epsilon(Epsilon)),
331 (
332 IDENT_INSTRUCTION.to_string(),
333 GlobalScope::Table(instruction_table_id),
334 ),
335 ]),
336 instruction_table: instruction_table_id,
337 default_space: None,
338 endian: None,
339 alignment: None,
340 spaces: vec![],
341 varnodes: vec![],
342 contexts: vec![],
343 bitranges: vec![],
344 tokens: vec![],
345 token_fields: vec![],
346 user_functions: vec![],
347 pcode_macros: vec![],
348 attach_varnodes: vec![],
349 attach_literals: vec![],
350 attach_numbers: vec![],
351 };
352
353 sleigh.process(&mut WithBlockCurrent::default(), syntax)?;
354
355 Ok(sleigh)
356 }
357}