1use std::borrow::Cow;
16use std::collections::HashSet;
17use std::fmt;
18use std::fmt::{Debug, Display};
19use crate::architecture::{Architecture, Flag, RegisterId};
26use crate::architecture::{CoreRegister, Register as ArchReg};
27use crate::function::Location;
28
29pub mod block;
30pub mod expression;
31pub mod function;
32pub mod instruction;
33pub mod lifting;
34pub mod operation;
35
36use self::expression::*;
37use self::function::*;
38use self::instruction::*;
39
40pub type LowLevelILRegularFunction = LowLevelILFunction<Finalized, NonSSA>;
42pub type LowLevelILRegularInstruction<'a> = LowLevelILInstruction<'a, Finalized, NonSSA>;
43pub type LowLevelILRegularInstructionKind<'a> = LowLevelILInstructionKind<'a, Finalized, NonSSA>;
44pub type LowLevelILRegularExpression<'a, ReturnType> =
45 LowLevelILExpression<'a, Finalized, NonSSA, ReturnType>;
46pub type LowLevelILRegularExpressionKind<'a> = LowLevelILExpressionKind<'a, Finalized, NonSSA>;
47
48pub type LowLevelILMutableFunction = LowLevelILFunction<Mutable, NonSSA>;
50pub type LowLevelILMutableExpression<'a, ReturnType> =
51 LowLevelILExpression<'a, Mutable, NonSSA, ReturnType>;
52
53pub type LowLevelILSSAFunction = LowLevelILFunction<Finalized, SSA>;
55
56#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
57pub struct LowLevelILTempRegister {
58 temp_id: RegisterId,
62}
63
64impl LowLevelILTempRegister {
65 pub fn new(temp_id: u32) -> Self {
66 Self {
67 temp_id: RegisterId(temp_id),
68 }
69 }
70
71 pub fn from_id(id: RegisterId) -> Option<Self> {
72 match id.is_temporary() {
73 true => {
74 let temp_id = RegisterId(id.0 & 0x7fff_ffff);
75 Some(Self { temp_id })
76 }
77 false => None,
78 }
79 }
80
81 pub fn id(&self) -> RegisterId {
83 RegisterId(self.temp_id.0 | 0x8000_0000)
84 }
85}
86
87impl Debug for LowLevelILTempRegister {
88 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
89 write!(f, "temp{}", self.temp_id)
90 }
91}
92
93impl Display for LowLevelILTempRegister {
94 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95 Debug::fmt(self, f)
96 }
97}
98
99impl TryFrom<RegisterId> for LowLevelILTempRegister {
100 type Error = ();
101
102 fn try_from(value: RegisterId) -> Result<Self, Self::Error> {
103 Self::from_id(value).ok_or(())
104 }
105}
106
107impl From<u32> for LowLevelILTempRegister {
108 fn from(value: u32) -> Self {
109 Self::new(value)
110 }
111}
112
113#[derive(Copy, Clone, PartialEq, Eq)]
114pub enum LowLevelILRegisterKind<R: ArchReg> {
115 Arch(R),
116 Temp(LowLevelILTempRegister),
117}
118
119impl<R: ArchReg> LowLevelILRegisterKind<R> {
120 pub fn from_raw(arch: &impl Architecture<Register = R>, val: RegisterId) -> Option<Self> {
121 match val.is_temporary() {
122 true => {
123 let temp_reg = LowLevelILTempRegister::from_id(val)?;
124 Some(LowLevelILRegisterKind::Temp(temp_reg))
125 }
126 false => {
127 let arch_reg = arch.register_from_id(val)?;
128 Some(LowLevelILRegisterKind::Arch(arch_reg))
129 }
130 }
131 }
132
133 pub fn from_temp(temp: impl Into<LowLevelILTempRegister>) -> Self {
134 LowLevelILRegisterKind::Temp(temp.into())
135 }
136
137 pub fn id(&self) -> RegisterId {
138 match *self {
139 LowLevelILRegisterKind::Arch(ref r) => r.id(),
140 LowLevelILRegisterKind::Temp(temp) => temp.id(),
141 }
142 }
143
144 pub fn name(&self) -> Cow<'_, str> {
145 match *self {
146 LowLevelILRegisterKind::Arch(ref r) => r.name(),
147 LowLevelILRegisterKind::Temp(temp) => Cow::Owned(format!("temp{}", temp.temp_id)),
148 }
149 }
150}
151
152impl<R: ArchReg> Debug for LowLevelILRegisterKind<R> {
153 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
154 match *self {
155 LowLevelILRegisterKind::Arch(ref r) => r.fmt(f),
156 LowLevelILRegisterKind::Temp(ref id) => Debug::fmt(id, f),
157 }
158 }
159}
160
161impl<R: ArchReg> Display for LowLevelILRegisterKind<R> {
162 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
163 match *self {
164 LowLevelILRegisterKind::Arch(ref r) => write!(f, "{}", r.name()),
165 LowLevelILRegisterKind::Temp(ref id) => Display::fmt(id, f),
166 }
167 }
168}
169
170impl From<LowLevelILTempRegister> for LowLevelILRegisterKind<CoreRegister> {
171 fn from(reg: LowLevelILTempRegister) -> Self {
172 LowLevelILRegisterKind::Temp(reg)
173 }
174}
175
176#[derive(Copy, Clone, Debug)]
177pub struct LowLevelILSSARegister<R: ArchReg> {
178 pub reg: LowLevelILRegisterKind<R>,
179 pub version: u32,
181}
182
183impl<R: ArchReg> LowLevelILSSARegister<R> {
184 pub fn new(reg: LowLevelILRegisterKind<R>, version: u32) -> Self {
185 Self { reg, version }
186 }
187
188 pub fn name(&self) -> Cow<'_, str> {
189 self.reg.name()
190 }
191
192 pub fn id(&self) -> RegisterId {
193 self.reg.id()
194 }
195}
196
197impl<R: ArchReg> Display for LowLevelILSSARegister<R> {
198 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
199 write!(f, "{}#{}", self.reg, self.version)
200 }
201}
202
203#[derive(Copy, Clone, Debug)]
214pub enum LowLevelILSSARegisterKind<R: ArchReg> {
215 Full(LowLevelILSSARegister<R>),
217 Partial {
218 full_reg: LowLevelILSSARegister<R>,
226 partial_reg: CoreRegister,
231 },
232}
233
234impl<R: ArchReg> LowLevelILSSARegisterKind<R> {
235 pub fn new_full(kind: LowLevelILRegisterKind<R>, version: u32) -> Self {
236 Self::Full(LowLevelILSSARegister::new(kind, version))
237 }
238
239 pub fn new_partial(
240 full_reg: LowLevelILRegisterKind<R>,
241 version: u32,
242 partial_reg: CoreRegister,
243 ) -> Self {
244 Self::Partial {
245 full_reg: LowLevelILSSARegister::new(full_reg, version),
246 partial_reg,
247 }
248 }
249
250 pub fn physical_reg(&self) -> LowLevelILSSARegister<R> {
257 match *self {
258 LowLevelILSSARegisterKind::Full(reg) => reg,
259 LowLevelILSSARegisterKind::Partial { full_reg, .. } => full_reg,
260 }
261 }
262
263 pub fn name(&self) -> Cow<'_, str> {
269 match *self {
270 LowLevelILSSARegisterKind::Full(ref reg) => reg.reg.name(),
271 LowLevelILSSARegisterKind::Partial {
272 ref partial_reg, ..
273 } => partial_reg.name(),
274 }
275 }
276}
277
278impl<R: ArchReg> AsRef<LowLevelILSSARegister<R>> for LowLevelILSSARegisterKind<R> {
279 fn as_ref(&self) -> &LowLevelILSSARegister<R> {
280 match self {
281 LowLevelILSSARegisterKind::Full(reg) => reg,
282 LowLevelILSSARegisterKind::Partial { full_reg, .. } => full_reg,
283 }
284 }
285}
286
287impl<R: ArchReg> From<LowLevelILSSARegister<R>> for LowLevelILSSARegisterKind<R> {
288 fn from(value: LowLevelILSSARegister<R>) -> Self {
289 LowLevelILSSARegisterKind::Full(value)
290 }
291}
292
293impl<R: ArchReg> From<LowLevelILSSARegisterKind<R>> for LowLevelILSSARegister<R> {
294 fn from(value: LowLevelILSSARegisterKind<R>) -> Self {
295 match value {
296 LowLevelILSSARegisterKind::Full(reg) => reg,
297 LowLevelILSSARegisterKind::Partial { full_reg, .. } => full_reg,
298 }
299 }
300}
301
302#[derive(Copy, Clone, Debug)]
303pub struct LowLevelILSSAFlag<F: Flag> {
304 pub flag: F,
305 pub version: u32,
306}
307
308impl<F: Flag> LowLevelILSSAFlag<F> {
309 pub fn new(flag: F, version: u32) -> Self {
310 Self { flag, version }
311 }
312}
313
314#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
315pub enum VisitorAction {
316 Descend,
317 Sibling,
318 Halt,
319}
320
321#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
322pub enum ILInstructionAttribute {
323 ILAllowDeadStoreElimination,
324 ILPreventDeadStoreElimination,
325 MLILAssumePossibleUse,
326 MLILUnknownSize,
327 SrcInstructionUsesPointerAuth,
328 ILPreventAliasAnalysis,
329 ILIsCFGProtected,
330 MLILPossiblyUnusedIntermediate,
331 HLILFoldableExpr,
332 HLILInvertableCondition,
333 HLILEarlyReturnPossible,
334 HLILSwitchRecoveryPossible,
335 ILTransparentCopy,
336}
337
338impl ILInstructionAttribute {
339 pub fn value(&self) -> u32 {
340 match self {
341 Self::ILAllowDeadStoreElimination => 1,
342 Self::ILPreventDeadStoreElimination => 2,
343 Self::MLILAssumePossibleUse => 4,
344 Self::MLILUnknownSize => 8,
345 Self::SrcInstructionUsesPointerAuth => 16,
346 Self::ILPreventAliasAnalysis => 32,
347 Self::ILIsCFGProtected => 64,
348 Self::MLILPossiblyUnusedIntermediate => 128,
349 Self::HLILFoldableExpr => 256,
350 Self::HLILInvertableCondition => 512,
351 Self::HLILEarlyReturnPossible => 1024,
352 Self::HLILSwitchRecoveryPossible => 2048,
353 Self::ILTransparentCopy => 4096,
354 }
355 }
356}
357
358pub type ILInstructionAttributeSet = HashSet<ILInstructionAttribute>;