Skip to main content

binaryninja/low_level_il/
operation.rs

1// Copyright 2021-2026 Vector 35 Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use binaryninjacore_sys::{
16    BNGetCachedLowLevelILPossibleValueSet, BNLowLevelILFreeOperandList, BNLowLevelILGetOperandList,
17    BNLowLevelILInstruction,
18};
19
20use super::*;
21use crate::architecture::{
22    CoreFlag, CoreFlagGroup, CoreFlagWrite, CoreIntrinsic, CoreRegister, CoreRegisterStack,
23    FlagGroupId, FlagId, FlagWriteId, IntrinsicId, RegisterStackId,
24};
25use crate::variable::PossibleValueSet;
26use std::collections::BTreeMap;
27use std::fmt::{Debug, Formatter};
28use std::marker::PhantomData;
29use std::mem;
30
31pub struct Operation<'func, M, F, O>
32where
33    M: FunctionMutability,
34    F: FunctionForm,
35    O: OperationArguments,
36{
37    pub(crate) function: &'func LowLevelILFunction<M, F>,
38    pub(crate) op: BNLowLevelILInstruction,
39    pub(crate) expr_idx: LowLevelExpressionIndex,
40    _args: PhantomData<O>,
41}
42
43impl<'func, M, F, O> Operation<'func, M, F, O>
44where
45    M: FunctionMutability,
46    F: FunctionForm,
47    O: OperationArguments,
48{
49    pub(crate) fn new(
50        function: &'func LowLevelILFunction<M, F>,
51        op: BNLowLevelILInstruction,
52        expr_idx: LowLevelExpressionIndex,
53    ) -> Self {
54        Self {
55            function,
56            op,
57            expr_idx,
58            _args: PhantomData,
59        }
60    }
61
62    pub fn address(&self) -> u64 {
63        self.op.address
64    }
65
66    fn get_operand_list(&self, operand_idx: usize) -> Vec<u64> {
67        let mut count = 0;
68        let raw_list_ptr = unsafe {
69            BNLowLevelILGetOperandList(
70                self.function.handle,
71                self.expr_idx.0,
72                operand_idx,
73                &mut count,
74            )
75        };
76        assert!(!raw_list_ptr.is_null());
77        let list = unsafe { std::slice::from_raw_parts(raw_list_ptr, count).to_vec() };
78        unsafe { BNLowLevelILFreeOperandList(raw_list_ptr) };
79        list
80    }
81
82    fn get_constraint(&self, operand_idx: usize) -> PossibleValueSet {
83        let raw_pvs = unsafe {
84            BNGetCachedLowLevelILPossibleValueSet(
85                self.function.handle,
86                self.op.operands[operand_idx] as usize,
87            )
88        };
89        PossibleValueSet::from_owned_core_raw(raw_pvs)
90    }
91
92    /// Get the raw operand from the operand list.
93    ///
94    /// This has no type information associated with it. It's up to the caller to know what the correct type of the
95    /// underlying u64 should be.
96    ///
97    /// # Panic
98    /// `idx` must be less than 4. This is to protect against an out of bounds access.
99    ///
100    /// # Safety
101    /// Even if `idx` is valid, it may index to an uninitialized or unused value. Make sure you index into an operand that
102    /// you know should be initialized properly.
103    pub unsafe fn get_operand(&self, idx: usize) -> u64 {
104        assert!(idx < 4);
105        self.op.operands[idx]
106    }
107}
108
109impl<M, O> Operation<'_, M, NonSSA, O>
110where
111    M: FunctionMutability,
112    O: OperationArguments,
113{
114    /// Get the [`CoreFlagWrite`] for the operation.
115    ///
116    /// NOTE: This is only expected to be present for lifted IL.
117    pub fn flag_write(&self) -> Option<CoreFlagWrite> {
118        match self.op.flags {
119            0 => None,
120            id => self.function.arch().flag_write_from_id(FlagWriteId(id)),
121        }
122    }
123}
124
125// LLIL_NOP, LLIL_NORET, LLIL_BP, LLIL_UNDEF, LLIL_UNIMPL
126pub struct NoArgs;
127
128impl<M, F> Debug for Operation<'_, M, F, NoArgs>
129where
130    M: FunctionMutability,
131    F: FunctionForm,
132{
133    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
134        f.debug_struct("NoArgs").finish()
135    }
136}
137
138// LLIL_POP
139pub struct Pop;
140
141impl<M, F> Operation<'_, M, F, Pop>
142where
143    M: FunctionMutability,
144    F: FunctionForm,
145{
146    pub fn size(&self) -> usize {
147        self.op.size
148    }
149}
150
151impl<M, F> Debug for Operation<'_, M, F, Pop>
152where
153    M: FunctionMutability,
154    F: FunctionForm,
155{
156    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
157        f.debug_struct("Pop")
158            .field("address", &self.address())
159            .field("size", &self.size())
160            .finish()
161    }
162}
163
164// LLIL_SYSCALL
165pub struct Syscall;
166
167impl<M, F> Debug for Operation<'_, M, F, Syscall>
168where
169    M: FunctionMutability,
170    F: FunctionForm,
171{
172    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
173        f.debug_struct("Syscall").finish()
174    }
175}
176
177// LLIL_SYSCALL_SSA
178pub struct SyscallSsa;
179
180impl<'func, M, F> Operation<'func, M, F, SyscallSsa>
181where
182    M: FunctionMutability,
183    F: FunctionForm,
184{
185    /// Get the output expression of the call.
186    ///
187    /// NOTE: This is currently always [`CallOutputSsa`].
188    pub fn output_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
189        LowLevelILExpression::new(
190            self.function,
191            LowLevelExpressionIndex(self.op.operands[0] as usize),
192        )
193    }
194
195    /// Get the parameter expression of the call.
196    ///
197    /// NOTE: This is currently always [`CallParamSsa`].
198    pub fn param_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
199        LowLevelILExpression::new(
200            self.function,
201            LowLevelExpressionIndex(self.op.operands[2] as usize),
202        )
203    }
204
205    /// Get the stack expression of the call.
206    ///
207    /// NOTE: This is currently always [`CallStackSsa`].
208    pub fn stack_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
209        LowLevelILExpression::new(
210            self.function,
211            LowLevelExpressionIndex(self.op.operands[1] as usize),
212        )
213    }
214}
215
216impl<M, F> Debug for Operation<'_, M, F, SyscallSsa>
217where
218    M: FunctionMutability,
219    F: FunctionForm,
220{
221    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
222        f.debug_struct("SyscallSsa")
223            .field("output_expr", &self.output_expr())
224            .field("param_expr", &self.param_expr())
225            .field("stack_expr", &self.stack_expr())
226            .finish()
227    }
228}
229
230// LLIL_INTRINSIC, LLIL_INTRINSIC_SSA
231pub struct Intrinsic;
232
233#[derive(Debug, Clone, Copy, PartialEq)]
234pub enum IntrinsicOutput {
235    Reg(CoreRegister),
236    Flag(CoreFlag),
237}
238
239impl From<CoreRegister> for IntrinsicOutput {
240    fn from(value: CoreRegister) -> Self {
241        Self::Reg(value)
242    }
243}
244
245impl From<CoreFlag> for IntrinsicOutput {
246    fn from(value: CoreFlag) -> Self {
247        Self::Flag(value)
248    }
249}
250
251impl<'func, M, F> Operation<'func, M, F, Intrinsic>
252where
253    M: FunctionMutability,
254    F: FunctionForm,
255{
256    pub fn intrinsic(&self) -> Option<CoreIntrinsic> {
257        let raw_id = self.op.operands[2] as u32;
258        self.function.arch().intrinsic_from_id(IntrinsicId(raw_id))
259    }
260
261    /// Get the output list.
262    pub fn outputs(&self) -> Vec<IntrinsicOutput> {
263        // Convert the operand to either a register or flag id.
264        let operand_to_output = |o: u64| {
265            if o & (1 << 32) != 0 {
266                self.function
267                    .arch()
268                    .flag_from_id(FlagId((o & 0xffffffff) as u32))
269                    .expect("Invalid core flag ID")
270                    .into()
271            } else {
272                self.function
273                    .arch()
274                    .register_from_id(RegisterId((o & 0xffffffff) as u32))
275                    .expect("Invalid register ID")
276                    .into()
277            }
278        };
279
280        self.get_operand_list(0)
281            .into_iter()
282            .map(operand_to_output)
283            .collect::<Vec<_>>()
284    }
285
286    /// Get the input list for the intrinsic.
287    ///
288    /// This will just be a CallParamSsa expression.
289    #[inline]
290    pub fn inputs(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
291        LowLevelILExpression::new(
292            self.function,
293            LowLevelExpressionIndex(self.op.operands[3] as usize),
294        )
295    }
296}
297
298impl<M, F> Debug for Operation<'_, M, F, Intrinsic>
299where
300    M: FunctionMutability,
301    F: FunctionForm,
302{
303    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
304        use crate::architecture::Intrinsic;
305        f.debug_struct("Intrinsic")
306            .field("address", &self.address())
307            .field(
308                "intrinsic",
309                &self.intrinsic().expect("Valid intrinsic").name(),
310            )
311            .field("outputs", &self.outputs())
312            .field("inputs", &self.inputs())
313            .finish()
314    }
315}
316
317// LLIL_SET_REG
318pub struct SetReg;
319
320impl<'func, M, F> Operation<'func, M, F, SetReg>
321where
322    M: FunctionMutability,
323    F: FunctionForm,
324{
325    pub fn size(&self) -> usize {
326        self.op.size
327    }
328
329    pub fn dest_reg(&self) -> LowLevelILRegisterKind<CoreRegister> {
330        let raw_id = RegisterId(self.op.operands[0] as u32);
331        LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
332    }
333
334    pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
335        LowLevelILExpression::new(
336            self.function,
337            LowLevelExpressionIndex(self.op.operands[1] as usize),
338        )
339    }
340}
341
342impl<M, F> Debug for Operation<'_, M, F, SetReg>
343where
344    M: FunctionMutability,
345    F: FunctionForm,
346{
347    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
348        f.debug_struct("SetReg")
349            .field("address", &self.address())
350            .field("size", &self.size())
351            .field("dest_reg", &self.dest_reg())
352            .field("source_expr", &self.source_expr())
353            .finish()
354    }
355}
356
357// LLIL_SET_REG_SSA
358pub struct SetRegSsa;
359
360impl<'func, M, F> Operation<'func, M, F, SetRegSsa>
361where
362    M: FunctionMutability,
363    F: FunctionForm,
364{
365    pub fn size(&self) -> usize {
366        self.op.size
367    }
368
369    pub fn dest_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
370        let raw_id = RegisterId(self.op.operands[0] as u32);
371        let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
372            .expect("Bad register ID");
373        let version = self.op.operands[1] as u32;
374        LowLevelILSSARegisterKind::new_full(reg_kind, version)
375    }
376
377    pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
378        LowLevelILExpression::new(
379            self.function,
380            LowLevelExpressionIndex(self.op.operands[2] as usize),
381        )
382    }
383}
384
385impl<M, F> Debug for Operation<'_, M, F, SetRegSsa>
386where
387    M: FunctionMutability,
388    F: FunctionForm,
389{
390    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
391        f.debug_struct("SetRegSsa")
392            .field("address", &self.address())
393            .field("size", &self.size())
394            .field("dest_reg", &self.dest_reg())
395            .field("source_expr", &self.source_expr())
396            .finish()
397    }
398}
399
400// LLIL_SET_REG_PARTIAL_SSA
401pub struct SetRegPartialSsa;
402
403impl<'func, M, F> Operation<'func, M, F, SetRegPartialSsa>
404where
405    M: FunctionMutability,
406    F: FunctionForm,
407{
408    pub fn size(&self) -> usize {
409        self.op.size
410    }
411
412    pub fn dest_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
413        let full_raw_id = RegisterId(self.op.operands[0] as u32);
414        let version = self.op.operands[1] as u32;
415        let partial_raw_id = RegisterId(self.op.operands[2] as u32);
416        let full_reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), full_raw_id)
417            .expect("Bad register ID");
418        let partial_reg =
419            CoreRegister::new(self.function.arch(), partial_raw_id).expect("Bad register ID");
420        LowLevelILSSARegisterKind::new_partial(full_reg_kind, version, partial_reg)
421    }
422
423    pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
424        LowLevelILExpression::new(
425            self.function,
426            LowLevelExpressionIndex(self.op.operands[3] as usize),
427        )
428    }
429}
430
431impl<M, F> Debug for Operation<'_, M, F, SetRegPartialSsa>
432where
433    M: FunctionMutability,
434    F: FunctionForm,
435{
436    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
437        f.debug_struct("SetRegPartialSsa")
438            .field("address", &self.address())
439            .field("size", &self.size())
440            .field("dest_reg", &self.dest_reg())
441            .field("source_expr", &self.source_expr())
442            .finish()
443    }
444}
445
446// LLIL_SET_REG_SPLIT
447pub struct SetRegSplit;
448
449impl<'func, M, F> Operation<'func, M, F, SetRegSplit>
450where
451    M: FunctionMutability,
452    F: FunctionForm,
453{
454    pub fn size(&self) -> usize {
455        self.op.size
456    }
457
458    pub fn dest_reg_high(&self) -> LowLevelILRegisterKind<CoreRegister> {
459        let raw_id = RegisterId(self.op.operands[0] as u32);
460        LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
461    }
462
463    pub fn dest_reg_low(&self) -> LowLevelILRegisterKind<CoreRegister> {
464        let raw_id = RegisterId(self.op.operands[1] as u32);
465        LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
466    }
467
468    pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
469        LowLevelILExpression::new(
470            self.function,
471            LowLevelExpressionIndex(self.op.operands[2] as usize),
472        )
473    }
474}
475
476impl<M, F> Debug for Operation<'_, M, F, SetRegSplit>
477where
478    M: FunctionMutability,
479    F: FunctionForm,
480{
481    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
482        f.debug_struct("SetRegSplit")
483            .field("address", &self.address())
484            .field("size", &self.size())
485            .field("dest_reg_high", &self.dest_reg_high())
486            .field("dest_reg_low", &self.dest_reg_low())
487            .field("source_expr", &self.source_expr())
488            .finish()
489    }
490}
491
492// LLIL_SET_REG_SPLIT_SSA
493pub struct SetRegSplitSsa;
494
495impl<'func, M, F> Operation<'func, M, F, SetRegSplitSsa>
496where
497    M: FunctionMutability,
498    F: FunctionForm,
499{
500    pub fn size(&self) -> usize {
501        self.op.size
502    }
503
504    /// Because of the fixed operand list size we use another expression for the dest high register.
505    ///
506    /// NOTE: This should always be an expression of [`RegSsa`].
507    pub fn dest_expr_high(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
508        LowLevelILExpression::new(
509            self.function,
510            LowLevelExpressionIndex(self.op.operands[0] as usize),
511        )
512    }
513
514    /// Because of the fixed operand list size we use another expression for the dest low register.
515    ///
516    /// NOTE: This should always be an expression of [`RegSsa`].
517    pub fn dest_expr_low(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
518        LowLevelILExpression::new(
519            self.function,
520            LowLevelExpressionIndex(self.op.operands[1] as usize),
521        )
522    }
523
524    pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
525        LowLevelILExpression::new(
526            self.function,
527            LowLevelExpressionIndex(self.op.operands[2] as usize),
528        )
529    }
530}
531
532impl<M, F> Debug for Operation<'_, M, F, SetRegSplitSsa>
533where
534    M: FunctionMutability,
535    F: FunctionForm,
536{
537    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
538        f.debug_struct("SetRegSplitSsa")
539            .field("address", &self.address())
540            .field("size", &self.size())
541            .field("dest_expr_high", &self.dest_expr_high())
542            .field("dest_expr_low", &self.dest_expr_low())
543            .field("source_expr", &self.source_expr())
544            .finish()
545    }
546}
547
548// LLIL_SET_FLAG
549pub struct SetFlag;
550
551impl<'func, M, F> Operation<'func, M, F, SetFlag>
552where
553    M: FunctionMutability,
554    F: FunctionForm,
555{
556    pub fn dest_flag(&self) -> CoreFlag {
557        self.function
558            .arch()
559            .flag_from_id(FlagId(self.op.operands[0] as u32))
560            .expect("Bad flag ID")
561    }
562
563    pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
564        LowLevelILExpression::new(
565            self.function,
566            LowLevelExpressionIndex(self.op.operands[1] as usize),
567        )
568    }
569}
570
571impl<M, F> Debug for Operation<'_, M, F, SetFlag>
572where
573    M: FunctionMutability,
574    F: FunctionForm,
575{
576    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
577        f.debug_struct("SetFlag")
578            .field("address", &self.address())
579            .field("dest_flag", &self.dest_flag())
580            .field("source_expr", &self.source_expr())
581            .finish()
582    }
583}
584
585// LLIL_SET_FLAG_SSA
586pub struct SetFlagSsa;
587
588impl<'func, M, F> Operation<'func, M, F, SetFlagSsa>
589where
590    M: FunctionMutability,
591    F: FunctionForm,
592{
593    pub fn dest_flag(&self) -> LowLevelILSSAFlag<CoreFlag> {
594        let flag = self
595            .function
596            .arch()
597            .flag_from_id(FlagId(self.op.operands[0] as u32))
598            .expect("Bad flag ID");
599        let version = self.op.operands[1] as u32;
600        LowLevelILSSAFlag::new(flag, version)
601    }
602
603    pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
604        LowLevelILExpression::new(
605            self.function,
606            LowLevelExpressionIndex(self.op.operands[2] as usize),
607        )
608    }
609}
610
611impl<M, F> Debug for Operation<'_, M, F, SetFlagSsa>
612where
613    M: FunctionMutability,
614    F: FunctionForm,
615{
616    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
617        f.debug_struct("SetFlagSsa")
618            .field("address", &self.address())
619            .field("dest_flag", &self.dest_flag())
620            .field("source_expr", &self.source_expr())
621            .finish()
622    }
623}
624// LLIL_LOAD
625pub struct Load;
626
627impl<'func, M, F> Operation<'func, M, F, Load>
628where
629    M: FunctionMutability,
630    F: FunctionForm,
631{
632    pub fn size(&self) -> usize {
633        self.op.size
634    }
635
636    pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
637        LowLevelILExpression::new(
638            self.function,
639            LowLevelExpressionIndex(self.op.operands[0] as usize),
640        )
641    }
642}
643
644impl<M, F> Debug for Operation<'_, M, F, Load>
645where
646    M: FunctionMutability,
647    F: FunctionForm,
648{
649    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
650        f.debug_struct("Load")
651            .field("address", &self.address())
652            .field("size", &self.size())
653            .field("source_expr", &self.source_expr())
654            .finish()
655    }
656}
657
658// LLIL_LOAD_SSA
659pub struct LoadSsa;
660
661impl<'func, M, F> Operation<'func, M, F, LoadSsa>
662where
663    M: FunctionMutability,
664    F: FunctionForm,
665{
666    pub fn size(&self) -> usize {
667        self.op.size
668    }
669
670    pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
671        LowLevelILExpression::new(
672            self.function,
673            LowLevelExpressionIndex(self.op.operands[0] as usize),
674        )
675    }
676
677    pub fn source_memory_version(&self) -> u64 {
678        self.op.operands[1]
679    }
680}
681
682impl<M, F> Debug for Operation<'_, M, F, LoadSsa>
683where
684    M: FunctionMutability,
685    F: FunctionForm,
686{
687    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
688        f.debug_struct("LoadSsa")
689            .field("address", &self.address())
690            .field("size", &self.size())
691            .field("source_expr", &self.source_expr())
692            .finish()
693    }
694}
695
696// LLIL_STORE
697pub struct Store;
698
699impl<'func, M, F> Operation<'func, M, F, Store>
700where
701    M: FunctionMutability,
702    F: FunctionForm,
703{
704    pub fn size(&self) -> usize {
705        self.op.size
706    }
707
708    pub fn dest_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
709        LowLevelILExpression::new(
710            self.function,
711            LowLevelExpressionIndex(self.op.operands[0] as usize),
712        )
713    }
714
715    pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
716        LowLevelILExpression::new(
717            self.function,
718            LowLevelExpressionIndex(self.op.operands[1] as usize),
719        )
720    }
721}
722
723impl<M, F> Debug for Operation<'_, M, F, Store>
724where
725    M: FunctionMutability,
726    F: FunctionForm,
727{
728    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
729        f.debug_struct("Store")
730            .field("address", &self.address())
731            .field("size", &self.size())
732            .field("dest_expr", &self.dest_expr())
733            .field("source_expr", &self.source_expr())
734            .finish()
735    }
736}
737
738// LLIL_STORE_SSA
739pub struct StoreSsa;
740
741impl<'func, M, F> Operation<'func, M, F, StoreSsa>
742where
743    M: FunctionMutability,
744    F: FunctionForm,
745{
746    pub fn size(&self) -> usize {
747        self.op.size
748    }
749
750    pub fn dest_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
751        LowLevelILExpression::new(
752            self.function,
753            LowLevelExpressionIndex(self.op.operands[0] as usize),
754        )
755    }
756
757    pub fn dest_memory_version(&self) -> u64 {
758        self.op.operands[1]
759    }
760
761    pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
762        LowLevelILExpression::new(
763            self.function,
764            LowLevelExpressionIndex(self.op.operands[3] as usize),
765        )
766    }
767
768    pub fn source_memory_version(&self) -> u64 {
769        self.op.operands[2]
770    }
771}
772
773impl<M, F> Debug for Operation<'_, M, F, StoreSsa>
774where
775    M: FunctionMutability,
776    F: FunctionForm,
777{
778    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
779        f.debug_struct("StoreSsa")
780            .field("address", &self.address())
781            .field("size", &self.size())
782            .field("dest_expr", &self.dest_expr())
783            .field("source_expr", &self.source_expr())
784            .finish()
785    }
786}
787
788// LLIL_REG
789pub struct Reg;
790
791impl<M, F> Operation<'_, M, F, Reg>
792where
793    M: FunctionMutability,
794    F: FunctionForm,
795{
796    pub fn size(&self) -> usize {
797        self.op.size
798    }
799
800    pub fn source_reg(&self) -> LowLevelILRegisterKind<CoreRegister> {
801        let raw_id = RegisterId(self.op.operands[0] as u32);
802        LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
803    }
804}
805
806impl<M, F> Debug for Operation<'_, M, F, Reg>
807where
808    M: FunctionMutability,
809    F: FunctionForm,
810{
811    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
812        f.debug_struct("Reg")
813            .field("address", &self.address())
814            .field("size", &self.size())
815            .field("source_reg", &self.source_reg())
816            .finish()
817    }
818}
819
820// LLIL_REG_SSA
821pub struct RegSsa;
822
823impl<M, F> Operation<'_, M, F, RegSsa>
824where
825    M: FunctionMutability,
826    F: FunctionForm,
827{
828    pub fn size(&self) -> usize {
829        self.op.size
830    }
831
832    pub fn source_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
833        let raw_id = RegisterId(self.op.operands[0] as u32);
834        let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
835            .expect("Bad register ID");
836        let version = self.op.operands[1] as u32;
837        LowLevelILSSARegisterKind::new_full(reg_kind, version)
838    }
839}
840
841impl<M, F> Debug for Operation<'_, M, F, RegSsa>
842where
843    M: FunctionMutability,
844    F: FunctionForm,
845{
846    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
847        f.debug_struct("RegSsa")
848            .field("address", &self.address())
849            .field("size", &self.size())
850            .field("source_reg", &self.source_reg())
851            .finish()
852    }
853}
854
855// LLIL_REG_SSA_PARTIAL
856pub struct RegPartialSsa;
857
858impl<M, F> Operation<'_, M, F, RegPartialSsa>
859where
860    M: FunctionMutability,
861    F: FunctionForm,
862{
863    pub fn size(&self) -> usize {
864        self.op.size
865    }
866
867    pub fn source_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
868        let full_raw_id = RegisterId(self.op.operands[0] as u32);
869        let version = self.op.operands[1] as u32;
870        let partial_raw_id = RegisterId(self.op.operands[2] as u32);
871        let full_reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), full_raw_id)
872            .expect("Bad register ID");
873        let partial_reg =
874            CoreRegister::new(self.function.arch(), partial_raw_id).expect("Bad register ID");
875        LowLevelILSSARegisterKind::new_partial(full_reg_kind, version, partial_reg)
876    }
877}
878
879impl<M, F> Debug for Operation<'_, M, F, RegPartialSsa>
880where
881    M: FunctionMutability,
882    F: FunctionForm,
883{
884    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
885        f.debug_struct("RegPartialSsa")
886            .field("address", &self.address())
887            .field("size", &self.size())
888            .field("source_reg", &self.source_reg())
889            .finish()
890    }
891}
892
893// LLIL_REG_SPLIT
894pub struct RegSplit;
895
896impl<M, F> Operation<'_, M, F, RegSplit>
897where
898    M: FunctionMutability,
899    F: FunctionForm,
900{
901    pub fn size(&self) -> usize {
902        self.op.size
903    }
904
905    pub fn high_reg(&self) -> LowLevelILRegisterKind<CoreRegister> {
906        let raw_id = RegisterId(self.op.operands[0] as u32);
907        LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
908    }
909
910    pub fn low_reg(&self) -> LowLevelILRegisterKind<CoreRegister> {
911        let raw_id = RegisterId(self.op.operands[1] as u32);
912        LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
913    }
914}
915
916impl<M, F> Debug for Operation<'_, M, F, RegSplit>
917where
918    M: FunctionMutability,
919    F: FunctionForm,
920{
921    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
922        f.debug_struct("RegSplit")
923            .field("address", &self.address())
924            .field("size", &self.size())
925            .field("high_reg", &self.high_reg())
926            .field("low_reg", &self.low_reg())
927            .finish()
928    }
929}
930
931// LLIL_REG_SPLIT_SSA
932pub struct RegSplitSsa;
933
934impl<M, F> Operation<'_, M, F, RegSplitSsa>
935where
936    M: FunctionMutability,
937    F: FunctionForm,
938{
939    pub fn size(&self) -> usize {
940        self.op.size
941    }
942
943    pub fn high_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
944        let raw_id = RegisterId(self.op.operands[0] as u32);
945        let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
946            .expect("Bad register ID");
947        let version = self.op.operands[1] as u32;
948        LowLevelILSSARegisterKind::new_full(reg_kind, version)
949    }
950
951    pub fn low_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
952        let raw_id = RegisterId(self.op.operands[2] as u32);
953        let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
954            .expect("Bad register ID");
955        let version = self.op.operands[3] as u32;
956        LowLevelILSSARegisterKind::new_full(reg_kind, version)
957    }
958}
959
960impl<M, F> Debug for Operation<'_, M, F, RegSplitSsa>
961where
962    M: FunctionMutability,
963    F: FunctionForm,
964{
965    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
966        f.debug_struct("RegSplitSsa")
967            .field("address", &self.address())
968            .field("size", &self.size())
969            .field("high_reg", &self.high_reg())
970            .field("low_reg", &self.low_reg())
971            .finish()
972    }
973}
974
975// LLIL_REG_STACK_PUSH
976pub struct RegStackPush;
977
978impl<'func, M, F> Operation<'func, M, F, RegStackPush>
979where
980    M: FunctionMutability,
981    F: FunctionForm,
982{
983    pub fn size(&self) -> usize {
984        self.op.size
985    }
986
987    pub fn dest_reg_stack(&self) -> CoreRegisterStack {
988        let raw_id = self.op.operands[0] as u32;
989        self.function
990            .arch()
991            .register_stack_from_id(RegisterStackId(raw_id))
992            .expect("Bad register stack ID")
993    }
994
995    pub fn source_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
996        LowLevelILExpression::new(
997            self.function,
998            LowLevelExpressionIndex(self.op.operands[1] as usize),
999        )
1000    }
1001}
1002
1003impl<M, F> Debug for Operation<'_, M, F, RegStackPush>
1004where
1005    M: FunctionMutability,
1006    F: FunctionForm,
1007{
1008    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1009        f.debug_struct("RegStackPush")
1010            .field("address", &self.address())
1011            .field("size", &self.size())
1012            .field("dest_reg_stack", &self.dest_reg_stack())
1013            .field("source_expr", &self.source_expr())
1014            .finish()
1015    }
1016}
1017
1018// LLIL_REG_STACK_POP
1019pub struct RegStackPop;
1020
1021impl<M, F> Operation<'_, M, F, RegStackPop>
1022where
1023    M: FunctionMutability,
1024    F: FunctionForm,
1025{
1026    pub fn size(&self) -> usize {
1027        self.op.size
1028    }
1029
1030    pub fn source_reg_stack(&self) -> CoreRegisterStack {
1031        let raw_id = self.op.operands[0] as u32;
1032        self.function
1033            .arch()
1034            .register_stack_from_id(RegisterStackId(raw_id))
1035            .expect("Bad register stack ID")
1036    }
1037}
1038
1039impl<M, F> Debug for Operation<'_, M, F, RegStackPop>
1040where
1041    M: FunctionMutability,
1042    F: FunctionForm,
1043{
1044    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1045        f.debug_struct("RegStackPop")
1046            .field("address", &self.address())
1047            .field("size", &self.size())
1048            .field("source_reg_stack", &self.source_reg_stack())
1049            .finish()
1050    }
1051}
1052
1053// LLIL_REG_STACK_FREE_REG
1054pub struct RegStackFreeReg;
1055
1056impl<M, F> Operation<'_, M, F, RegStackFreeReg>
1057where
1058    M: FunctionMutability,
1059    F: FunctionForm,
1060{
1061    pub fn size(&self) -> usize {
1062        self.op.size
1063    }
1064
1065    pub fn dest_reg(&self) -> CoreRegister {
1066        let raw_id = self.op.operands[0] as u32;
1067        self.function
1068            .arch()
1069            .register_from_id(RegisterId(raw_id))
1070            .expect("Bad register ID")
1071    }
1072}
1073
1074impl<M, F> Debug for Operation<'_, M, F, RegStackFreeReg>
1075where
1076    M: FunctionMutability,
1077    F: FunctionForm,
1078{
1079    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1080        f.debug_struct("RegStackFreeReg")
1081            .field("address", &self.address())
1082            .field("size", &self.size())
1083            .field("dest_reg", &self.dest_reg())
1084            .finish()
1085    }
1086}
1087
1088// LLIL_FLAG, LLIL_FLAG_SSA
1089pub struct Flag;
1090
1091impl<M, F> Operation<'_, M, F, Flag>
1092where
1093    M: FunctionMutability,
1094    F: FunctionForm,
1095{
1096    pub fn source_flag(&self) -> CoreFlag {
1097        self.function
1098            .arch()
1099            .flag_from_id(FlagId(self.op.operands[0] as u32))
1100            .expect("Bad flag ID")
1101    }
1102}
1103
1104impl<M, F> Debug for Operation<'_, M, F, Flag>
1105where
1106    M: FunctionMutability,
1107    F: FunctionForm,
1108{
1109    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1110        f.debug_struct("Flag")
1111            .field("source_flag", &self.source_flag())
1112            .finish()
1113    }
1114}
1115
1116// LLIL_FLAG_BIT, LLIL_FLAG_BIT_SSA
1117pub struct FlagBit;
1118
1119impl<M, F> Debug for Operation<'_, M, F, FlagBit>
1120where
1121    M: FunctionMutability,
1122    F: FunctionForm,
1123{
1124    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1125        f.debug_struct("FlagBit").finish()
1126    }
1127}
1128
1129// LLIL_JUMP
1130pub struct Jump;
1131
1132impl<'func, M, F> Operation<'func, M, F, Jump>
1133where
1134    M: FunctionMutability,
1135    F: FunctionForm,
1136{
1137    pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1138        LowLevelILExpression::new(
1139            self.function,
1140            LowLevelExpressionIndex(self.op.operands[0] as usize),
1141        )
1142    }
1143}
1144
1145impl<M, F> Debug for Operation<'_, M, F, Jump>
1146where
1147    M: FunctionMutability,
1148    F: FunctionForm,
1149{
1150    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1151        f.debug_struct("Jump")
1152            .field("target", &self.target())
1153            .finish()
1154    }
1155}
1156
1157// LLIL_JUMP_TO
1158pub struct JumpTo;
1159
1160impl<'func, M, F> Operation<'func, M, F, JumpTo>
1161where
1162    M: FunctionMutability,
1163    F: FunctionForm,
1164{
1165    pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1166        LowLevelILExpression::new(
1167            self.function,
1168            LowLevelExpressionIndex(self.op.operands[0] as usize),
1169        )
1170    }
1171
1172    pub fn target_list(&self) -> BTreeMap<u64, LowLevelInstructionIndex> {
1173        self.get_operand_list(1)
1174            .as_chunks::<2>()
1175            .0
1176            .iter()
1177            .map(|pair| (pair[0], LowLevelInstructionIndex(pair[1] as usize)))
1178            .collect()
1179    }
1180}
1181
1182impl<M, F> Debug for Operation<'_, M, F, JumpTo>
1183where
1184    M: FunctionMutability,
1185    F: FunctionForm,
1186{
1187    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1188        f.debug_struct("JumpTo")
1189            .field("target", &self.target())
1190            .field("target_list", &self.target_list())
1191            .finish()
1192    }
1193}
1194
1195// LLIL_CALL, LLIL_CALL_STACK_ADJUST
1196pub struct Call;
1197
1198impl<'func, M, F> Operation<'func, M, F, Call>
1199where
1200    M: FunctionMutability,
1201    F: FunctionForm,
1202{
1203    pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1204        LowLevelILExpression::new(
1205            self.function,
1206            LowLevelExpressionIndex(self.op.operands[0] as usize),
1207        )
1208    }
1209
1210    pub fn stack_adjust(&self) -> Option<u64> {
1211        use binaryninjacore_sys::BNLowLevelILOperation::LLIL_CALL_STACK_ADJUST;
1212
1213        if self.op.operation == LLIL_CALL_STACK_ADJUST {
1214            Some(self.op.operands[1])
1215        } else {
1216            None
1217        }
1218    }
1219}
1220
1221impl<M, F> Debug for Operation<'_, M, F, Call>
1222where
1223    M: FunctionMutability,
1224    F: FunctionForm,
1225{
1226    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1227        f.debug_struct("Call")
1228            .field("target", &self.target())
1229            .field("stack_adjust", &self.stack_adjust())
1230            .finish()
1231    }
1232}
1233
1234// LLIL_CALL_SSA
1235pub struct CallSsa;
1236
1237impl<'func, M, F> Operation<'func, M, F, CallSsa>
1238where
1239    M: FunctionMutability,
1240    F: FunctionForm,
1241{
1242    pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1243        LowLevelILExpression::new(
1244            self.function,
1245            LowLevelExpressionIndex(self.op.operands[1] as usize),
1246        )
1247    }
1248
1249    /// Get the output expression of the call.
1250    ///
1251    /// NOTE: This is currently always [`CallOutputSsa`].
1252    pub fn output_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1253        LowLevelILExpression::new(
1254            self.function,
1255            LowLevelExpressionIndex(self.op.operands[0] as usize),
1256        )
1257    }
1258
1259    /// Get the parameter expression of the call.
1260    ///
1261    /// NOTE: This is currently always [`CallParamSsa`].
1262    pub fn param_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1263        LowLevelILExpression::new(
1264            self.function,
1265            LowLevelExpressionIndex(self.op.operands[3] as usize),
1266        )
1267    }
1268
1269    /// Get the stack expression of the call.
1270    ///
1271    /// NOTE: This is currently always [`CallStackSsa`].
1272    pub fn stack_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1273        LowLevelILExpression::new(
1274            self.function,
1275            LowLevelExpressionIndex(self.op.operands[2] as usize),
1276        )
1277    }
1278}
1279
1280impl<M, F> Debug for Operation<'_, M, F, CallSsa>
1281where
1282    M: FunctionMutability,
1283    F: FunctionForm,
1284{
1285    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1286        f.debug_struct("CallSsa")
1287            .field("target", &self.target())
1288            .field("output_expr", &self.output_expr())
1289            .field("param_expr", &self.param_expr())
1290            .field("stack_expr", &self.stack_expr())
1291            .finish()
1292    }
1293}
1294
1295// LLIL_CALL_OUTPUT_SSA
1296pub struct CallOutputSsa;
1297
1298impl<M, F> Operation<'_, M, F, CallOutputSsa>
1299where
1300    M: FunctionMutability,
1301    F: FunctionForm,
1302{
1303    pub fn dest_regs(&self) -> Vec<LowLevelILSSARegisterKind<CoreRegister>> {
1304        let operand_list = self.get_operand_list(1);
1305
1306        // The operand list contains a list of ([0: reg, 1: version], ...).
1307        let paired_ssa_reg = |paired: &[u64; 2]| {
1308            let raw_id = RegisterId(paired[0] as u32);
1309            let version = paired[1] as u32;
1310            let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
1311                .expect("Bad register ID");
1312            LowLevelILSSARegisterKind::new_full(reg_kind, version)
1313        };
1314
1315        operand_list
1316            .as_chunks::<2>()
1317            .0
1318            .iter()
1319            .map(paired_ssa_reg)
1320            .collect()
1321    }
1322
1323    pub fn dest_memory_version(&self) -> u64 {
1324        self.op.operands[0]
1325    }
1326}
1327
1328impl<M, F> Debug for Operation<'_, M, F, CallOutputSsa>
1329where
1330    M: FunctionMutability,
1331    F: FunctionForm,
1332{
1333    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1334        f.debug_struct("CallOutputSsa")
1335            .field("dest_regs", &self.dest_regs())
1336            .finish()
1337    }
1338}
1339
1340// LLIL_CALL_PARAM_SSA
1341pub struct CallParamSsa;
1342
1343impl<'func, M, F> Operation<'func, M, F, CallParamSsa>
1344where
1345    M: FunctionMutability,
1346    F: FunctionForm,
1347{
1348    pub fn param_exprs(&self) -> Vec<LowLevelILExpression<'func, M, F, ValueExpr>> {
1349        self.get_operand_list(0)
1350            .into_iter()
1351            .map(|val| LowLevelExpressionIndex(val as usize))
1352            .map(|expr_idx| LowLevelILExpression::new(self.function, expr_idx))
1353            .collect()
1354    }
1355}
1356
1357impl<M, F> Debug for Operation<'_, M, F, CallParamSsa>
1358where
1359    M: FunctionMutability,
1360    F: FunctionForm,
1361{
1362    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1363        f.debug_struct("CallParamSsa")
1364            .field("param_exprs", &self.param_exprs())
1365            .finish()
1366    }
1367}
1368
1369// LLIL_CALL_STACK_SSA
1370pub struct CallStackSsa;
1371
1372impl<M, F> Operation<'_, M, F, CallStackSsa>
1373where
1374    M: FunctionMutability,
1375    F: FunctionForm,
1376{
1377    pub fn source_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
1378        let raw_id = RegisterId(self.op.operands[0] as u32);
1379        let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
1380            .expect("Bad register ID");
1381        let version = self.op.operands[1] as u32;
1382        LowLevelILSSARegisterKind::new_full(reg_kind, version)
1383    }
1384}
1385
1386impl<M, F> Debug for Operation<'_, M, F, CallStackSsa>
1387where
1388    M: FunctionMutability,
1389    F: FunctionForm,
1390{
1391    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1392        f.debug_struct("CallStackSsa")
1393            .field("source_reg", &self.source_reg())
1394            .finish()
1395    }
1396}
1397
1398// LLIL_RET
1399pub struct Ret;
1400
1401impl<'func, M, F> Operation<'func, M, F, Ret>
1402where
1403    M: FunctionMutability,
1404    F: FunctionForm,
1405{
1406    pub fn target(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1407        LowLevelILExpression::new(
1408            self.function,
1409            LowLevelExpressionIndex(self.op.operands[0] as usize),
1410        )
1411    }
1412}
1413
1414impl<M, F> Debug for Operation<'_, M, F, Ret>
1415where
1416    M: FunctionMutability,
1417    F: FunctionForm,
1418{
1419    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1420        f.debug_struct("Ret")
1421            .field("target", &self.target())
1422            .finish()
1423    }
1424}
1425
1426// LLIL_IF
1427pub struct If;
1428
1429impl<'func, M, F> Operation<'func, M, F, If>
1430where
1431    M: FunctionMutability,
1432    F: FunctionForm,
1433{
1434    pub fn condition(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1435        LowLevelILExpression::new(
1436            self.function,
1437            LowLevelExpressionIndex(self.op.operands[0] as usize),
1438        )
1439    }
1440
1441    pub fn true_target(&self) -> LowLevelILInstruction<'func, M, F> {
1442        LowLevelILInstruction::new(
1443            self.function,
1444            LowLevelInstructionIndex(self.op.operands[1] as usize),
1445        )
1446    }
1447
1448    pub fn false_target(&self) -> LowLevelILInstruction<'func, M, F> {
1449        LowLevelILInstruction::new(
1450            self.function,
1451            LowLevelInstructionIndex(self.op.operands[2] as usize),
1452        )
1453    }
1454}
1455
1456impl<M, F> Debug for Operation<'_, M, F, If>
1457where
1458    M: FunctionMutability,
1459    F: FunctionForm,
1460{
1461    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1462        f.debug_struct("If")
1463            .field("condition", &self.condition())
1464            .field("true_target", &self.true_target())
1465            .field("false_target", &self.false_target())
1466            .finish()
1467    }
1468}
1469
1470// LLIL_GOTO
1471pub struct Goto;
1472
1473impl<'func, M, F> Operation<'func, M, F, Goto>
1474where
1475    M: FunctionMutability,
1476    F: FunctionForm,
1477{
1478    pub fn target(&self) -> LowLevelILInstruction<'func, M, F> {
1479        LowLevelILInstruction::new(
1480            self.function,
1481            LowLevelInstructionIndex(self.op.operands[0] as usize),
1482        )
1483    }
1484}
1485
1486impl<M, F> Debug for Operation<'_, M, F, Goto>
1487where
1488    M: FunctionMutability,
1489    F: FunctionForm,
1490{
1491    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1492        f.debug_struct("Goto")
1493            .field("target", &self.target())
1494            .finish()
1495    }
1496}
1497
1498// LLIL_FLAG_COND
1499// Valid only in Lifted IL
1500pub struct FlagCond;
1501
1502impl<M, F> Debug for Operation<'_, M, F, FlagCond>
1503where
1504    M: FunctionMutability,
1505    F: FunctionForm,
1506{
1507    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1508        f.debug_struct("FlagCond").finish()
1509    }
1510}
1511
1512// LLIL_FLAG_GROUP
1513// Valid only in Lifted IL
1514pub struct FlagGroup;
1515
1516impl<M, F> Operation<'_, M, F, FlagGroup>
1517where
1518    M: FunctionMutability,
1519    F: FunctionForm,
1520{
1521    pub fn flag_group(&self) -> CoreFlagGroup {
1522        let id = self.op.operands[0] as u32;
1523        self.function
1524            .arch()
1525            .flag_group_from_id(FlagGroupId(id))
1526            .unwrap()
1527    }
1528}
1529
1530impl<M, F> Debug for Operation<'_, M, F, FlagGroup>
1531where
1532    M: FunctionMutability,
1533    F: FunctionForm,
1534{
1535    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1536        f.debug_struct("FlagGroup")
1537            .field("flag_group", &self.flag_group())
1538            .finish()
1539    }
1540}
1541
1542// LLIL_TRAP
1543pub struct Trap;
1544
1545impl<M, F> Operation<'_, M, F, Trap>
1546where
1547    M: FunctionMutability,
1548    F: FunctionForm,
1549{
1550    pub fn vector(&self) -> u64 {
1551        self.op.operands[0]
1552    }
1553}
1554
1555impl<M, F> Debug for Operation<'_, M, F, Trap>
1556where
1557    M: FunctionMutability,
1558    F: FunctionForm,
1559{
1560    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1561        f.debug_struct("Trap")
1562            .field("vector", &self.vector())
1563            .finish()
1564    }
1565}
1566
1567// LLIL_REG_PHI
1568pub struct RegPhi;
1569impl<M, F> Operation<'_, M, F, RegPhi>
1570where
1571    M: FunctionMutability,
1572    F: FunctionForm,
1573{
1574    pub fn dest_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
1575        let raw_id = RegisterId(self.op.operands[0] as u32);
1576        let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
1577            .expect("Bad register ID");
1578        let version = self.op.operands[1] as u32;
1579        LowLevelILSSARegisterKind::new_full(reg_kind, version)
1580    }
1581
1582    pub fn source_regs(&self) -> Vec<LowLevelILSSARegisterKind<CoreRegister>> {
1583        let operand_list = self.get_operand_list(2);
1584        let arch = self.function.arch();
1585        operand_list
1586            .as_chunks::<2>()
1587            .0
1588            .iter()
1589            .map(|chunk| {
1590                let (register, version) = (chunk[0], chunk[1]);
1591                LowLevelILSSARegisterKind::new_full(
1592                    LowLevelILRegisterKind::from_raw(&arch, RegisterId(register as u32))
1593                        .expect("Bad register ID"),
1594                    version as u32,
1595                )
1596            })
1597            .collect()
1598    }
1599}
1600
1601impl<M, F> Debug for Operation<'_, M, F, RegPhi>
1602where
1603    M: FunctionMutability,
1604    F: FunctionForm,
1605{
1606    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1607        f.debug_struct("RegPhi")
1608            .field("dest_reg", &self.dest_reg())
1609            .field("source_regs", &self.source_regs())
1610            .finish()
1611    }
1612}
1613
1614// LLIL_FLAG_PHI
1615pub struct FlagPhi;
1616
1617impl<M, F> Operation<'_, M, F, FlagPhi>
1618where
1619    M: FunctionMutability,
1620    F: FunctionForm,
1621{
1622    pub fn dest_flag(&self) -> LowLevelILSSAFlag<CoreFlag> {
1623        let flag = self
1624            .function
1625            .arch()
1626            .flag_from_id(FlagId(self.op.operands[0] as u32))
1627            .expect("Bad flag ID");
1628        let version = self.op.operands[1] as u32;
1629        LowLevelILSSAFlag::new(flag, version)
1630    }
1631
1632    pub fn source_flags(&self) -> Vec<LowLevelILSSAFlag<CoreFlag>> {
1633        let operand_list = self.get_operand_list(2);
1634        operand_list
1635            .as_chunks::<2>()
1636            .0
1637            .iter()
1638            .map(|chunk| {
1639                let (flag, version) = (chunk[0], chunk[1]);
1640                let flag = self
1641                    .function
1642                    .arch()
1643                    .flag_from_id(FlagId(flag as u32))
1644                    .expect("Bad flag ID");
1645                LowLevelILSSAFlag::new(flag, version as u32)
1646            })
1647            .collect()
1648    }
1649}
1650
1651impl<M, F> Debug for Operation<'_, M, F, FlagPhi>
1652where
1653    M: FunctionMutability,
1654    F: FunctionForm,
1655{
1656    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1657        f.debug_struct("FlagPhi")
1658            .field("dest_flag", &self.dest_flag())
1659            .field("source_flags", &self.source_flags())
1660            .finish()
1661    }
1662}
1663
1664// LLIL_MEM_PHI
1665pub struct MemPhi;
1666
1667impl<M, F> Operation<'_, M, F, MemPhi>
1668where
1669    M: FunctionMutability,
1670    F: FunctionForm,
1671{
1672    pub fn dest_memory_version(&self) -> usize {
1673        self.op.operands[0] as usize
1674    }
1675
1676    pub fn source_memory_versions(&self) -> Vec<usize> {
1677        let operand_list = self.get_operand_list(1);
1678        operand_list.into_iter().map(|op| op as usize).collect()
1679    }
1680}
1681
1682impl<M, F> Debug for Operation<'_, M, F, MemPhi>
1683where
1684    M: FunctionMutability,
1685    F: FunctionForm,
1686{
1687    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1688        f.debug_struct("MemPhi")
1689            .field("dest_memory_version", &self.dest_memory_version())
1690            .field("source_memory_versions", &self.source_memory_versions())
1691            .finish()
1692    }
1693}
1694
1695// LLIL_CONST, LLIL_CONST_PTR
1696pub struct Const;
1697
1698impl<M, F> Operation<'_, M, F, Const>
1699where
1700    M: FunctionMutability,
1701    F: FunctionForm,
1702{
1703    pub fn size(&self) -> usize {
1704        self.op.size
1705    }
1706
1707    pub fn value(&self) -> u64 {
1708        #[cfg(debug_assertions)]
1709        {
1710            let raw = self.op.operands[0] as i64;
1711
1712            let is_safe = match raw.overflowing_shr(self.op.size as u32 * 8) {
1713                (_, true) => true,
1714                (res, false) => [-1, 0].contains(&res),
1715            };
1716
1717            if !is_safe {
1718                tracing::error!(
1719                    "il expr @ {:x} contains constant 0x{:x} as {} byte value (doesn't fit!)",
1720                    self.op.address,
1721                    self.op.operands[0],
1722                    self.op.size
1723                );
1724            }
1725        }
1726
1727        let mask: u64 = if self.op.size == 0 {
1728            1
1729        } else if self.op.size < mem::size_of::<u64>() {
1730            let m = -1i64 << (self.op.size * 8);
1731            !m as u64
1732        } else {
1733            (-1i64) as u64
1734        };
1735
1736        self.op.operands[0] & mask
1737    }
1738}
1739
1740impl<M, F> Debug for Operation<'_, M, F, Const>
1741where
1742    M: FunctionMutability,
1743    F: FunctionForm,
1744{
1745    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1746        f.debug_struct("Const")
1747            .field("size", &self.size())
1748            .field("value", &self.value())
1749            .finish()
1750    }
1751}
1752
1753// LLIL_FLOAT_CONST
1754pub struct FloatConst;
1755
1756impl<M, F> Operation<'_, M, F, FloatConst>
1757where
1758    M: FunctionMutability,
1759    F: FunctionForm,
1760{
1761    pub fn size(&self) -> usize {
1762        self.op.size
1763    }
1764
1765    pub fn raw_value(&self) -> u64 {
1766        self.op.operands[0]
1767    }
1768
1769    pub fn float_value(&self) -> f64 {
1770        let raw_bits = self.raw_value();
1771        match self.op.size {
1772            4 => {
1773                // For f32, take the lower 32 bits and convert to f32
1774                let bits32 = (raw_bits & 0xFFFFFFFF) as u32;
1775                f32::from_bits(bits32) as f64
1776            }
1777            8 => {
1778                // For f64, use all 64 bits
1779                f64::from_bits(raw_bits)
1780            }
1781            _ => {
1782                // Log error for unexpected sizes
1783                tracing::error!(
1784                    "il expr @ {:x} has invalid float size {} (expected 4 or 8 bytes)",
1785                    self.op.address,
1786                    self.op.size
1787                );
1788                f64::NAN
1789            }
1790        }
1791    }
1792}
1793
1794impl<M, F> Debug for Operation<'_, M, F, FloatConst>
1795where
1796    M: FunctionMutability,
1797    F: FunctionForm,
1798{
1799    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1800        f.debug_struct("FloatConst")
1801            .field("size", &self.size())
1802            .field("float_value", &self.float_value())
1803            .field("raw_value", &self.raw_value())
1804            .finish()
1805    }
1806}
1807
1808// LLIL_EXTERN_PTR
1809pub struct Extern;
1810
1811impl<M, F> Operation<'_, M, F, Extern>
1812where
1813    M: FunctionMutability,
1814    F: FunctionForm,
1815{
1816    pub fn size(&self) -> usize {
1817        self.op.size
1818    }
1819
1820    pub fn value(&self) -> u64 {
1821        #[cfg(debug_assertions)]
1822        {
1823            let raw = self.op.operands[0] as i64;
1824
1825            let is_safe = match raw.overflowing_shr(self.op.size as u32 * 8) {
1826                (_, true) => true,
1827                (res, false) => [-1, 0].contains(&res),
1828            };
1829
1830            if !is_safe {
1831                tracing::error!(
1832                    "il expr @ {:x} contains extern 0x{:x} as {} byte value (doesn't fit!)",
1833                    self.op.address,
1834                    self.op.operands[0],
1835                    self.op.size
1836                );
1837            }
1838        }
1839
1840        let mut mask = -1i64 as u64;
1841
1842        if self.op.size < mem::size_of::<u64>() {
1843            mask <<= self.op.size * 8;
1844            mask = !mask;
1845        }
1846
1847        self.op.operands[0] & mask
1848    }
1849}
1850
1851impl<M, F> Debug for Operation<'_, M, F, Extern>
1852where
1853    M: FunctionMutability,
1854    F: FunctionForm,
1855{
1856    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1857        f.debug_struct("Extern")
1858            .field("size", &self.size())
1859            .field("value", &self.value())
1860            .finish()
1861    }
1862}
1863
1864// LLIL_ADD, LLIL_SUB, LLIL_AND, LLIL_OR
1865// LLIL_XOR, LLIL_LSL, LLIL_LSR, LLIL_ASR
1866// LLIL_ROL, LLIL_ROR, LLIL_MUL, LLIL_MULU_DP,
1867// LLIL_MULS_DP, LLIL_DIVU, LLIL_DIVS, LLIL_MODU,
1868// LLIL_MODS
1869pub struct BinaryOp;
1870
1871impl<'func, M, F> Operation<'func, M, F, BinaryOp>
1872where
1873    M: FunctionMutability,
1874    F: FunctionForm,
1875{
1876    pub fn size(&self) -> usize {
1877        self.op.size
1878    }
1879
1880    pub fn left(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1881        LowLevelILExpression::new(
1882            self.function,
1883            LowLevelExpressionIndex(self.op.operands[0] as usize),
1884        )
1885    }
1886
1887    pub fn right(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1888        LowLevelILExpression::new(
1889            self.function,
1890            LowLevelExpressionIndex(self.op.operands[1] as usize),
1891        )
1892    }
1893}
1894
1895impl<M, F> Debug for Operation<'_, M, F, BinaryOp>
1896where
1897    M: FunctionMutability,
1898    F: FunctionForm,
1899{
1900    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1901        f.debug_struct("BinaryOp")
1902            .field("size", &self.size())
1903            .field("left", &self.left())
1904            .field("right", &self.right())
1905            .finish()
1906    }
1907}
1908
1909// LLIL_ADC, LLIL_SBB, LLIL_RLC, LLIL_RRC
1910pub struct BinaryOpCarry;
1911
1912impl<'func, M, F> Operation<'func, M, F, BinaryOpCarry>
1913where
1914    M: FunctionMutability,
1915    F: FunctionForm,
1916{
1917    pub fn size(&self) -> usize {
1918        self.op.size
1919    }
1920
1921    pub fn left(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1922        LowLevelILExpression::new(
1923            self.function,
1924            LowLevelExpressionIndex(self.op.operands[0] as usize),
1925        )
1926    }
1927
1928    pub fn right(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1929        LowLevelILExpression::new(
1930            self.function,
1931            LowLevelExpressionIndex(self.op.operands[1] as usize),
1932        )
1933    }
1934
1935    pub fn carry(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1936        LowLevelILExpression::new(
1937            self.function,
1938            LowLevelExpressionIndex(self.op.operands[2] as usize),
1939        )
1940    }
1941}
1942
1943impl<M, F> Debug for Operation<'_, M, F, BinaryOpCarry>
1944where
1945    M: FunctionMutability,
1946    F: FunctionForm,
1947{
1948    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1949        f.debug_struct("BinaryOpCarry")
1950            .field("size", &self.size())
1951            .field("left", &self.left())
1952            .field("right", &self.right())
1953            .field("carry", &self.carry())
1954            .finish()
1955    }
1956}
1957
1958// LLIL_PUSH, LLIL_NEG, LLIL_NOT, LLIL_SX,
1959// LLIL_ZX, LLIL_LOW_PART, LLIL_BOOL_TO_INT, LLIL_UNIMPL_MEM
1960pub struct UnaryOp;
1961
1962impl<'func, M, F> Operation<'func, M, F, UnaryOp>
1963where
1964    M: FunctionMutability,
1965    F: FunctionForm,
1966{
1967    pub fn size(&self) -> usize {
1968        self.op.size
1969    }
1970
1971    pub fn operand(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
1972        LowLevelILExpression::new(
1973            self.function,
1974            LowLevelExpressionIndex(self.op.operands[0] as usize),
1975        )
1976    }
1977}
1978
1979impl<M, F> Debug for Operation<'_, M, F, UnaryOp>
1980where
1981    M: FunctionMutability,
1982    F: FunctionForm,
1983{
1984    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1985        f.debug_struct("UnaryOp")
1986            .field("size", &self.size())
1987            .field("operand", &self.operand())
1988            .finish()
1989    }
1990}
1991
1992// LLIL_CMP_X
1993pub struct Condition;
1994
1995impl<'func, M, F> Operation<'func, M, F, Condition>
1996where
1997    M: FunctionMutability,
1998    F: FunctionForm,
1999{
2000    pub fn size(&self) -> usize {
2001        self.op.size
2002    }
2003
2004    pub fn left(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
2005        LowLevelILExpression::new(
2006            self.function,
2007            LowLevelExpressionIndex(self.op.operands[0] as usize),
2008        )
2009    }
2010
2011    pub fn right(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
2012        LowLevelILExpression::new(
2013            self.function,
2014            LowLevelExpressionIndex(self.op.operands[1] as usize),
2015        )
2016    }
2017}
2018
2019impl<M, F> Debug for Operation<'_, M, F, Condition>
2020where
2021    M: FunctionMutability,
2022    F: FunctionForm,
2023{
2024    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2025        f.debug_struct("Condition")
2026            .field("size", &self.size())
2027            .field("left", &self.left())
2028            .field("right", &self.right())
2029            .finish()
2030    }
2031}
2032
2033// LLIL_UNIMPL_MEM
2034pub struct UnimplMem;
2035
2036impl<'func, M, F> Operation<'func, M, F, UnimplMem>
2037where
2038    M: FunctionMutability,
2039    F: FunctionForm,
2040{
2041    pub fn size(&self) -> usize {
2042        self.op.size
2043    }
2044
2045    pub fn mem_expr(&self) -> LowLevelILExpression<'func, M, F, ValueExpr> {
2046        LowLevelILExpression::new(
2047            self.function,
2048            LowLevelExpressionIndex(self.op.operands[0] as usize),
2049        )
2050    }
2051}
2052
2053impl<M, F> Debug for Operation<'_, M, F, UnimplMem>
2054where
2055    M: FunctionMutability,
2056    F: FunctionForm,
2057{
2058    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2059        f.debug_struct("UnimplMem")
2060            .field("size", &self.size())
2061            .field("mem_expr", &self.mem_expr())
2062            .finish()
2063    }
2064}
2065
2066// LLIL_ASSERT
2067pub struct Assert;
2068
2069impl<M, F> Operation<'_, M, F, Assert>
2070where
2071    M: FunctionMutability,
2072    F: FunctionForm,
2073{
2074    pub fn size(&self) -> usize {
2075        self.op.size
2076    }
2077
2078    pub fn source_reg(&self) -> LowLevelILRegisterKind<CoreRegister> {
2079        let raw_id = RegisterId(self.op.operands[0] as u32);
2080        LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
2081    }
2082
2083    pub fn constraint(&self) -> PossibleValueSet {
2084        self.get_constraint(1)
2085    }
2086}
2087
2088impl<M, F> Debug for Operation<'_, M, F, Assert>
2089where
2090    M: FunctionMutability,
2091    F: FunctionForm,
2092{
2093    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2094        f.debug_struct("Assert")
2095            .field("size", &self.size())
2096            .field("source_reg", &self.source_reg())
2097            .field("constraint", &self.constraint())
2098            .finish()
2099    }
2100}
2101
2102// LLIL_ASSERT_SSA
2103pub struct AssertSsa;
2104
2105impl<M, F> Operation<'_, M, F, AssertSsa>
2106where
2107    M: FunctionMutability,
2108    F: FunctionForm,
2109{
2110    pub fn size(&self) -> usize {
2111        self.op.size
2112    }
2113
2114    pub fn source_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
2115        let raw_id = RegisterId(self.op.operands[0] as u32);
2116        let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
2117            .expect("Bad register ID");
2118        let version = self.op.operands[1] as u32;
2119        LowLevelILSSARegisterKind::new_full(reg_kind, version)
2120    }
2121
2122    pub fn constraint(&self) -> PossibleValueSet {
2123        self.get_constraint(2)
2124    }
2125}
2126
2127impl<M, F> Debug for Operation<'_, M, F, AssertSsa>
2128where
2129    M: FunctionMutability,
2130    F: FunctionForm,
2131{
2132    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2133        f.debug_struct("AssertSsa")
2134            .field("size", &self.size())
2135            .field("source_reg", &self.source_reg())
2136            .field("constraint", &self.constraint())
2137            .finish()
2138    }
2139}
2140
2141// LLIL_FORCE_VER
2142pub struct ForceVersion;
2143
2144impl<M, F> Operation<'_, M, F, ForceVersion>
2145where
2146    M: FunctionMutability,
2147    F: FunctionForm,
2148{
2149    pub fn size(&self) -> usize {
2150        self.op.size
2151    }
2152
2153    pub fn dest_reg(&self) -> LowLevelILRegisterKind<CoreRegister> {
2154        let raw_id = RegisterId(self.op.operands[0] as u32);
2155        LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id).expect("Bad register ID")
2156    }
2157}
2158
2159impl<M, F> Debug for Operation<'_, M, F, ForceVersion>
2160where
2161    M: FunctionMutability,
2162    F: FunctionForm,
2163{
2164    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2165        f.debug_struct("ForceVersion")
2166            .field("size", &self.size())
2167            .field("dest_reg", &self.dest_reg())
2168            .finish()
2169    }
2170}
2171
2172// LLIL_FORCE_VER_SSA
2173pub struct ForceVersionSsa;
2174
2175impl<M, F> Operation<'_, M, F, ForceVersionSsa>
2176where
2177    M: FunctionMutability,
2178    F: FunctionForm,
2179{
2180    pub fn size(&self) -> usize {
2181        self.op.size
2182    }
2183
2184    pub fn dest_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
2185        let raw_id = RegisterId(self.op.operands[0] as u32);
2186        let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
2187            .expect("Bad register ID");
2188        let version = self.op.operands[1] as u32;
2189        LowLevelILSSARegisterKind::new_full(reg_kind, version)
2190    }
2191
2192    pub fn source_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
2193        let raw_id = RegisterId(self.op.operands[2] as u32);
2194        let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
2195            .expect("Bad register ID");
2196        let version = self.op.operands[3] as u32;
2197        LowLevelILSSARegisterKind::new_full(reg_kind, version)
2198    }
2199}
2200
2201impl<M, F> Debug for Operation<'_, M, F, ForceVersionSsa>
2202where
2203    M: FunctionMutability,
2204    F: FunctionForm,
2205{
2206    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2207        f.debug_struct("ForceVersionSsa")
2208            .field("size", &self.size())
2209            .field("dest_reg", &self.dest_reg())
2210            .field("source_reg", &self.source_reg())
2211            .finish()
2212    }
2213}
2214
2215// LLIL_SEPARATE_PARAM_LIST_SSA
2216pub struct SeparateParamListSsa;
2217
2218impl<'func, M, F> Operation<'func, M, F, SeparateParamListSsa>
2219where
2220    M: FunctionMutability,
2221    F: FunctionForm,
2222{
2223    pub fn param_exprs(&self) -> Vec<LowLevelILExpression<'func, M, F, ValueExpr>> {
2224        self.get_operand_list(0)
2225            .into_iter()
2226            .map(|val| LowLevelExpressionIndex(val as usize))
2227            .map(|expr_idx| LowLevelILExpression::new(self.function, expr_idx))
2228            .collect()
2229    }
2230}
2231
2232impl<M, F> Debug for Operation<'_, M, F, SeparateParamListSsa>
2233where
2234    M: FunctionMutability,
2235    F: FunctionForm,
2236{
2237    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2238        f.debug_struct("SeparateParamListSsa")
2239            .field("param_exprs", &self.param_exprs())
2240            .finish()
2241    }
2242}
2243
2244// TODO TEST_BIT
2245
2246pub trait OperationArguments: 'static {}
2247
2248impl OperationArguments for NoArgs {}
2249impl OperationArguments for Pop {}
2250impl OperationArguments for Syscall {}
2251impl OperationArguments for SyscallSsa {}
2252impl OperationArguments for Intrinsic {}
2253impl OperationArguments for SetReg {}
2254impl OperationArguments for SetRegSsa {}
2255impl OperationArguments for SetRegPartialSsa {}
2256impl OperationArguments for SetRegSplit {}
2257impl OperationArguments for SetRegSplitSsa {}
2258impl OperationArguments for SetFlag {}
2259impl OperationArguments for SetFlagSsa {}
2260impl OperationArguments for Load {}
2261impl OperationArguments for LoadSsa {}
2262impl OperationArguments for Store {}
2263impl OperationArguments for StoreSsa {}
2264impl OperationArguments for Reg {}
2265impl OperationArguments for RegSsa {}
2266impl OperationArguments for RegPartialSsa {}
2267impl OperationArguments for RegSplit {}
2268impl OperationArguments for RegSplitSsa {}
2269impl OperationArguments for RegStackPush {}
2270impl OperationArguments for RegStackPop {}
2271impl OperationArguments for RegStackFreeReg {}
2272impl OperationArguments for Flag {}
2273impl OperationArguments for FlagBit {}
2274impl OperationArguments for Jump {}
2275impl OperationArguments for JumpTo {}
2276impl OperationArguments for Call {}
2277impl OperationArguments for CallSsa {}
2278impl OperationArguments for CallOutputSsa {}
2279impl OperationArguments for CallParamSsa {}
2280impl OperationArguments for CallStackSsa {}
2281impl OperationArguments for Ret {}
2282impl OperationArguments for If {}
2283impl OperationArguments for Goto {}
2284impl OperationArguments for FlagCond {}
2285impl OperationArguments for FlagGroup {}
2286impl OperationArguments for Trap {}
2287impl OperationArguments for RegPhi {}
2288impl OperationArguments for FlagPhi {}
2289impl OperationArguments for MemPhi {}
2290impl OperationArguments for Const {}
2291impl OperationArguments for FloatConst {}
2292impl OperationArguments for Extern {}
2293impl OperationArguments for BinaryOp {}
2294impl OperationArguments for BinaryOpCarry {}
2295impl OperationArguments for UnaryOp {}
2296impl OperationArguments for Condition {}
2297impl OperationArguments for UnimplMem {}
2298impl OperationArguments for Assert {}
2299impl OperationArguments for AssertSsa {}
2300impl OperationArguments for ForceVersion {}
2301impl OperationArguments for ForceVersionSsa {}
2302impl OperationArguments for SeparateParamListSsa {}