Skip to main content

oxilean_codegen/evm_backend/
types.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use std::collections::HashMap;
6
7use std::collections::{HashSet, VecDeque};
8
9/// EVM optimizer pipeline
10#[allow(dead_code)]
11#[derive(Debug, Default)]
12pub struct EvmOptPipeline {
13    pub passes: Vec<EvmOptPass>,
14    pub enabled: bool,
15    pub runs: u32,
16}
17#[allow(dead_code)]
18impl EvmOptPipeline {
19    pub fn new(runs: u32) -> Self {
20        Self {
21            passes: vec![
22                EvmOptPass::ConstantFolding,
23                EvmOptPass::DeadCodeElim,
24                EvmOptPass::CommonSubexprElim,
25                EvmOptPass::Peephole,
26            ],
27            enabled: true,
28            runs,
29        }
30    }
31    pub fn add(&mut self, pass: EvmOptPass) {
32        self.passes.push(pass);
33    }
34    pub fn disable(&mut self) {
35        self.enabled = false;
36    }
37}
38/// EVM diagnostic
39#[allow(dead_code)]
40#[derive(Debug, Clone, PartialEq, Eq)]
41pub enum EvmDiagLevel {
42    Info,
43    Warning,
44    Error,
45}
46/// EVM Yul object
47#[allow(dead_code)]
48#[derive(Debug, Default, Clone)]
49pub struct YulObject {
50    pub name: String,
51    pub code: Vec<YulStmt>,
52    pub functions: Vec<YulFunction>,
53    pub sub_objects: Vec<YulObject>,
54}
55#[allow(dead_code)]
56impl YulObject {
57    pub fn new(name: &str) -> Self {
58        Self {
59            name: name.to_string(),
60            ..Default::default()
61        }
62    }
63    pub fn add_function(&mut self, f: YulFunction) {
64        self.functions.push(f);
65    }
66    pub fn add_sub_object(&mut self, o: YulObject) {
67        self.sub_objects.push(o);
68    }
69}
70#[allow(dead_code)]
71#[derive(Debug, Clone)]
72pub struct EvmDiag {
73    pub level: EvmDiagLevel,
74    pub message: String,
75    pub location: Option<String>,
76}
77/// A basic block of EVM instructions with a named label.
78///
79/// Each block starts with a JUMPDEST if it is a jump target.
80#[derive(Debug, Clone)]
81pub struct EvmBasicBlock {
82    /// Symbolic label for this block (used in assembly output).
83    pub label: String,
84    /// The instructions in this block.
85    pub instructions: Vec<EvmInstruction>,
86    /// Whether this block needs a JUMPDEST at the start.
87    pub is_jump_target: bool,
88}
89impl EvmBasicBlock {
90    /// Create a new basic block with the given label.
91    pub fn new(label: impl Into<String>) -> Self {
92        Self {
93            label: label.into(),
94            instructions: Vec::new(),
95            is_jump_target: false,
96        }
97    }
98    /// Create a new basic block that is a jump target (has JUMPDEST).
99    pub fn new_jump_target(label: impl Into<String>) -> Self {
100        Self {
101            label: label.into(),
102            instructions: Vec::new(),
103            is_jump_target: true,
104        }
105    }
106    /// Append an instruction to this block.
107    pub fn push_instr(&mut self, instr: EvmInstruction) {
108        self.instructions.push(instr);
109    }
110    /// Append a simple opcode (no immediate data) to this block.
111    pub fn push_op(&mut self, opcode: EvmOpcode) {
112        self.instructions.push(EvmInstruction::new(opcode));
113    }
114    /// Total byte count of all instructions in this block (excluding JUMPDEST).
115    pub fn byte_len(&self) -> usize {
116        let jumpdest_len = if self.is_jump_target { 1 } else { 0 };
117        jumpdest_len
118            + self
119                .instructions
120                .iter()
121                .map(|i| i.byte_len())
122                .sum::<usize>()
123    }
124    /// Encode this block to raw bytes.
125    pub fn encode(&self) -> Vec<u8> {
126        let mut out = Vec::new();
127        if self.is_jump_target {
128            out.push(EvmOpcode::Jumpdest.byte());
129        }
130        for instr in &self.instructions {
131            out.extend(instr.encode());
132        }
133        out
134    }
135}
136/// Describes the persistent storage layout of a contract.
137///
138/// Maps variable names to their storage slot (256-bit word index).
139#[derive(Debug, Clone, Default)]
140pub struct StorageLayout {
141    /// Maps variable name → storage slot number.
142    pub slots: HashMap<String, u64>,
143    /// Next available slot index.
144    pub(super) next_slot: u64,
145}
146impl StorageLayout {
147    /// Create an empty storage layout.
148    pub fn new() -> Self {
149        Self::default()
150    }
151    /// Allocate a new slot for a named variable and return the slot index.
152    pub fn allocate(&mut self, name: impl Into<String>) -> u64 {
153        let slot = self.next_slot;
154        self.slots.insert(name.into(), slot);
155        self.next_slot += 1;
156        slot
157    }
158    /// Look up the slot for a variable by name.
159    pub fn slot_of(&self, name: &str) -> Option<u64> {
160        self.slots.get(name).copied()
161    }
162    /// Number of allocated slots.
163    pub fn len(&self) -> usize {
164        self.slots.len()
165    }
166    /// Returns true if no slots have been allocated.
167    pub fn is_empty(&self) -> bool {
168        self.slots.is_empty()
169    }
170}
171/// All EVM opcodes as defined in the Yellow Paper and subsequent EIPs.
172#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
173pub enum EvmOpcode {
174    /// Halts execution.
175    Stop,
176    /// Integer addition.
177    Add,
178    /// Integer multiplication.
179    Mul,
180    /// Integer subtraction.
181    Sub,
182    /// Integer division (unsigned).
183    Div,
184    /// Signed integer division.
185    Sdiv,
186    /// Modulo remainder (unsigned).
187    Mod,
188    /// Modulo remainder (signed).
189    Smod,
190    /// Addition modulo N.
191    Addmod,
192    /// Multiplication modulo N.
193    Mulmod,
194    /// Exponentiation.
195    Exp,
196    /// Sign extend.
197    Signextend,
198    /// Less-than comparison (unsigned).
199    Lt,
200    /// Greater-than comparison (unsigned).
201    Gt,
202    /// Less-than comparison (signed).
203    Slt,
204    /// Greater-than comparison (signed).
205    Sgt,
206    /// Equality comparison.
207    Eq,
208    /// Is-zero check.
209    Iszero,
210    /// Bitwise AND.
211    And,
212    /// Bitwise OR.
213    Or,
214    /// Bitwise XOR.
215    Xor,
216    /// Bitwise NOT.
217    Not,
218    /// Retrieve single byte from word.
219    Byte,
220    /// Left shift.
221    Shl,
222    /// Logical right shift.
223    Shr,
224    /// Arithmetic right shift.
225    Sar,
226    /// Compute Keccak-256 hash.
227    Sha3,
228    /// Address of currently executing account.
229    Address,
230    /// Balance of given account.
231    Balance,
232    /// Address of execution originator.
233    Origin,
234    /// Address of caller.
235    Caller,
236    /// Value deposited by caller.
237    Callvalue,
238    /// Input data of current environment.
239    Calldataload,
240    /// Size of input data.
241    Calldatasize,
242    /// Copy input data to memory.
243    Calldatacopy,
244    /// Size of code at given address.
245    Codesize,
246    /// Copy code to memory.
247    Codecopy,
248    /// Current gas price.
249    Gasprice,
250    /// Size of external code at given address.
251    Extcodesize,
252    /// Copy external code to memory.
253    Extcodecopy,
254    /// Size of return data from last call.
255    Returndatasize,
256    /// Copy return data to memory.
257    Returndatacopy,
258    /// Hash of external code at given address.
259    Extcodehash,
260    /// Hash of a recent block.
261    Blockhash,
262    /// Current block's beneficiary (coinbase).
263    Coinbase,
264    /// Current block's timestamp.
265    Timestamp,
266    /// Current block number.
267    Number,
268    /// Difficulty / prevrandao of current block.
269    Prevrandao,
270    /// Gas limit of current block.
271    Gaslimit,
272    /// Chain ID.
273    Chainid,
274    /// Balance of currently executing account.
275    Selfbalance,
276    /// Base fee of current block.
277    Basefee,
278    /// Blob base fee (EIP-7516).
279    Blobbasefee,
280    /// Remove item from stack.
281    Pop,
282    /// Load word from memory.
283    Mload,
284    /// Save word to memory.
285    Mstore,
286    /// Save byte to memory.
287    Mstore8,
288    /// Load word from storage.
289    Sload,
290    /// Save word to storage.
291    Sstore,
292    /// Alter program counter.
293    Jump,
294    /// Conditionally alter program counter.
295    Jumpi,
296    /// Value of program counter before current instruction.
297    Pc,
298    /// Size of active memory in bytes.
299    Msize,
300    /// Amount of available gas.
301    Gas,
302    /// Mark a valid jump destination.
303    Jumpdest,
304    /// Load word from transient storage.
305    Tload,
306    /// Save word to transient storage.
307    Tstore,
308    /// Copy memory areas.
309    Mcopy,
310    /// Push 1 byte onto stack.
311    Push1,
312    /// Push 2 bytes onto stack.
313    Push2,
314    /// Push 3 bytes onto stack.
315    Push3,
316    /// Push 4 bytes onto stack.
317    Push4,
318    /// Push 5 bytes onto stack.
319    Push5,
320    /// Push 6 bytes onto stack.
321    Push6,
322    /// Push 7 bytes onto stack.
323    Push7,
324    /// Push 8 bytes onto stack.
325    Push8,
326    /// Push 9 bytes onto stack.
327    Push9,
328    /// Push 10 bytes onto stack.
329    Push10,
330    /// Push 11 bytes onto stack.
331    Push11,
332    /// Push 12 bytes onto stack.
333    Push12,
334    /// Push 13 bytes onto stack.
335    Push13,
336    /// Push 14 bytes onto stack.
337    Push14,
338    /// Push 15 bytes onto stack.
339    Push15,
340    /// Push 16 bytes onto stack.
341    Push16,
342    /// Push 17 bytes onto stack.
343    Push17,
344    /// Push 18 bytes onto stack.
345    Push18,
346    /// Push 19 bytes onto stack.
347    Push19,
348    /// Push 20 bytes onto stack.
349    Push20,
350    /// Push 21 bytes onto stack.
351    Push21,
352    /// Push 22 bytes onto stack.
353    Push22,
354    /// Push 23 bytes onto stack.
355    Push23,
356    /// Push 24 bytes onto stack.
357    Push24,
358    /// Push 25 bytes onto stack.
359    Push25,
360    /// Push 26 bytes onto stack.
361    Push26,
362    /// Push 27 bytes onto stack.
363    Push27,
364    /// Push 28 bytes onto stack.
365    Push28,
366    /// Push 29 bytes onto stack.
367    Push29,
368    /// Push 30 bytes onto stack.
369    Push30,
370    /// Push 31 bytes onto stack.
371    Push31,
372    /// Push 32 bytes onto stack.
373    Push32,
374    /// Duplicate 1st stack item.
375    Dup1,
376    /// Duplicate 2nd stack item.
377    Dup2,
378    /// Duplicate 3rd stack item.
379    Dup3,
380    /// Duplicate 4th stack item.
381    Dup4,
382    /// Duplicate 5th stack item.
383    Dup5,
384    /// Duplicate 6th stack item.
385    Dup6,
386    /// Duplicate 7th stack item.
387    Dup7,
388    /// Duplicate 8th stack item.
389    Dup8,
390    /// Duplicate 9th stack item.
391    Dup9,
392    /// Duplicate 10th stack item.
393    Dup10,
394    /// Duplicate 11th stack item.
395    Dup11,
396    /// Duplicate 12th stack item.
397    Dup12,
398    /// Duplicate 13th stack item.
399    Dup13,
400    /// Duplicate 14th stack item.
401    Dup14,
402    /// Duplicate 15th stack item.
403    Dup15,
404    /// Duplicate 16th stack item.
405    Dup16,
406    /// Exchange 1st and 2nd stack items.
407    Swap1,
408    /// Exchange 1st and 3rd stack items.
409    Swap2,
410    /// Exchange 1st and 4th stack items.
411    Swap3,
412    /// Exchange 1st and 5th stack items.
413    Swap4,
414    /// Exchange 1st and 6th stack items.
415    Swap5,
416    /// Exchange 1st and 7th stack items.
417    Swap6,
418    /// Exchange 1st and 8th stack items.
419    Swap7,
420    /// Exchange 1st and 9th stack items.
421    Swap8,
422    /// Exchange 1st and 10th stack items.
423    Swap9,
424    /// Exchange 1st and 11th stack items.
425    Swap10,
426    /// Exchange 1st and 12th stack items.
427    Swap11,
428    /// Exchange 1st and 13th stack items.
429    Swap12,
430    /// Exchange 1st and 14th stack items.
431    Swap13,
432    /// Exchange 1st and 15th stack items.
433    Swap14,
434    /// Exchange 1st and 16th stack items.
435    Swap15,
436    /// Exchange 1st and 17th stack items.
437    Swap16,
438    /// Append log record with no topics.
439    Log0,
440    /// Append log record with 1 topic.
441    Log1,
442    /// Append log record with 2 topics.
443    Log2,
444    /// Append log record with 3 topics.
445    Log3,
446    /// Append log record with 4 topics.
447    Log4,
448    /// Create a new account with associated code.
449    Create,
450    /// Message-call into an account.
451    Call,
452    /// Message-call with another account's code.
453    Callcode,
454    /// Halt, returning output data.
455    Return,
456    /// Message-call into this account with caller's code.
457    Delegatecall,
458    /// Create a new account with deterministic address.
459    Create2,
460    /// Static message-call into an account.
461    Staticcall,
462    /// Halt execution reverting state changes.
463    Revert,
464    /// Designated invalid instruction.
465    Invalid,
466    /// Halt execution and register account for deletion.
467    Selfdestruct,
468}
469impl EvmOpcode {
470    /// Returns the byte value of this opcode.
471    pub fn byte(&self) -> u8 {
472        match self {
473            EvmOpcode::Stop => 0x00,
474            EvmOpcode::Add => 0x01,
475            EvmOpcode::Mul => 0x02,
476            EvmOpcode::Sub => 0x03,
477            EvmOpcode::Div => 0x04,
478            EvmOpcode::Sdiv => 0x05,
479            EvmOpcode::Mod => 0x06,
480            EvmOpcode::Smod => 0x07,
481            EvmOpcode::Addmod => 0x08,
482            EvmOpcode::Mulmod => 0x09,
483            EvmOpcode::Exp => 0x0a,
484            EvmOpcode::Signextend => 0x0b,
485            EvmOpcode::Lt => 0x10,
486            EvmOpcode::Gt => 0x11,
487            EvmOpcode::Slt => 0x12,
488            EvmOpcode::Sgt => 0x13,
489            EvmOpcode::Eq => 0x14,
490            EvmOpcode::Iszero => 0x15,
491            EvmOpcode::And => 0x16,
492            EvmOpcode::Or => 0x17,
493            EvmOpcode::Xor => 0x18,
494            EvmOpcode::Not => 0x19,
495            EvmOpcode::Byte => 0x1a,
496            EvmOpcode::Shl => 0x1b,
497            EvmOpcode::Shr => 0x1c,
498            EvmOpcode::Sar => 0x1d,
499            EvmOpcode::Sha3 => 0x20,
500            EvmOpcode::Address => 0x30,
501            EvmOpcode::Balance => 0x31,
502            EvmOpcode::Origin => 0x32,
503            EvmOpcode::Caller => 0x33,
504            EvmOpcode::Callvalue => 0x34,
505            EvmOpcode::Calldataload => 0x35,
506            EvmOpcode::Calldatasize => 0x36,
507            EvmOpcode::Calldatacopy => 0x37,
508            EvmOpcode::Codesize => 0x38,
509            EvmOpcode::Codecopy => 0x39,
510            EvmOpcode::Gasprice => 0x3a,
511            EvmOpcode::Extcodesize => 0x3b,
512            EvmOpcode::Extcodecopy => 0x3c,
513            EvmOpcode::Returndatasize => 0x3d,
514            EvmOpcode::Returndatacopy => 0x3e,
515            EvmOpcode::Extcodehash => 0x3f,
516            EvmOpcode::Blockhash => 0x40,
517            EvmOpcode::Coinbase => 0x41,
518            EvmOpcode::Timestamp => 0x42,
519            EvmOpcode::Number => 0x43,
520            EvmOpcode::Prevrandao => 0x44,
521            EvmOpcode::Gaslimit => 0x45,
522            EvmOpcode::Chainid => 0x46,
523            EvmOpcode::Selfbalance => 0x47,
524            EvmOpcode::Basefee => 0x48,
525            EvmOpcode::Blobbasefee => 0x4a,
526            EvmOpcode::Pop => 0x50,
527            EvmOpcode::Mload => 0x51,
528            EvmOpcode::Mstore => 0x52,
529            EvmOpcode::Mstore8 => 0x53,
530            EvmOpcode::Sload => 0x54,
531            EvmOpcode::Sstore => 0x55,
532            EvmOpcode::Jump => 0x56,
533            EvmOpcode::Jumpi => 0x57,
534            EvmOpcode::Pc => 0x58,
535            EvmOpcode::Msize => 0x59,
536            EvmOpcode::Gas => 0x5a,
537            EvmOpcode::Jumpdest => 0x5b,
538            EvmOpcode::Tload => 0x5c,
539            EvmOpcode::Tstore => 0x5d,
540            EvmOpcode::Mcopy => 0x5e,
541            EvmOpcode::Push1 => 0x60,
542            EvmOpcode::Push2 => 0x61,
543            EvmOpcode::Push3 => 0x62,
544            EvmOpcode::Push4 => 0x63,
545            EvmOpcode::Push5 => 0x64,
546            EvmOpcode::Push6 => 0x65,
547            EvmOpcode::Push7 => 0x66,
548            EvmOpcode::Push8 => 0x67,
549            EvmOpcode::Push9 => 0x68,
550            EvmOpcode::Push10 => 0x69,
551            EvmOpcode::Push11 => 0x6a,
552            EvmOpcode::Push12 => 0x6b,
553            EvmOpcode::Push13 => 0x6c,
554            EvmOpcode::Push14 => 0x6d,
555            EvmOpcode::Push15 => 0x6e,
556            EvmOpcode::Push16 => 0x6f,
557            EvmOpcode::Push17 => 0x70,
558            EvmOpcode::Push18 => 0x71,
559            EvmOpcode::Push19 => 0x72,
560            EvmOpcode::Push20 => 0x73,
561            EvmOpcode::Push21 => 0x74,
562            EvmOpcode::Push22 => 0x75,
563            EvmOpcode::Push23 => 0x76,
564            EvmOpcode::Push24 => 0x77,
565            EvmOpcode::Push25 => 0x78,
566            EvmOpcode::Push26 => 0x79,
567            EvmOpcode::Push27 => 0x7a,
568            EvmOpcode::Push28 => 0x7b,
569            EvmOpcode::Push29 => 0x7c,
570            EvmOpcode::Push30 => 0x7d,
571            EvmOpcode::Push31 => 0x7e,
572            EvmOpcode::Push32 => 0x7f,
573            EvmOpcode::Dup1 => 0x80,
574            EvmOpcode::Dup2 => 0x81,
575            EvmOpcode::Dup3 => 0x82,
576            EvmOpcode::Dup4 => 0x83,
577            EvmOpcode::Dup5 => 0x84,
578            EvmOpcode::Dup6 => 0x85,
579            EvmOpcode::Dup7 => 0x86,
580            EvmOpcode::Dup8 => 0x87,
581            EvmOpcode::Dup9 => 0x88,
582            EvmOpcode::Dup10 => 0x89,
583            EvmOpcode::Dup11 => 0x8a,
584            EvmOpcode::Dup12 => 0x8b,
585            EvmOpcode::Dup13 => 0x8c,
586            EvmOpcode::Dup14 => 0x8d,
587            EvmOpcode::Dup15 => 0x8e,
588            EvmOpcode::Dup16 => 0x8f,
589            EvmOpcode::Swap1 => 0x90,
590            EvmOpcode::Swap2 => 0x91,
591            EvmOpcode::Swap3 => 0x92,
592            EvmOpcode::Swap4 => 0x93,
593            EvmOpcode::Swap5 => 0x94,
594            EvmOpcode::Swap6 => 0x95,
595            EvmOpcode::Swap7 => 0x96,
596            EvmOpcode::Swap8 => 0x97,
597            EvmOpcode::Swap9 => 0x98,
598            EvmOpcode::Swap10 => 0x99,
599            EvmOpcode::Swap11 => 0x9a,
600            EvmOpcode::Swap12 => 0x9b,
601            EvmOpcode::Swap13 => 0x9c,
602            EvmOpcode::Swap14 => 0x9d,
603            EvmOpcode::Swap15 => 0x9e,
604            EvmOpcode::Swap16 => 0x9f,
605            EvmOpcode::Log0 => 0xa0,
606            EvmOpcode::Log1 => 0xa1,
607            EvmOpcode::Log2 => 0xa2,
608            EvmOpcode::Log3 => 0xa3,
609            EvmOpcode::Log4 => 0xa4,
610            EvmOpcode::Create => 0xf0,
611            EvmOpcode::Call => 0xf1,
612            EvmOpcode::Callcode => 0xf2,
613            EvmOpcode::Return => 0xf3,
614            EvmOpcode::Delegatecall => 0xf4,
615            EvmOpcode::Create2 => 0xf5,
616            EvmOpcode::Staticcall => 0xfa,
617            EvmOpcode::Revert => 0xfd,
618            EvmOpcode::Invalid => 0xfe,
619            EvmOpcode::Selfdestruct => 0xff,
620        }
621    }
622    /// Returns the mnemonic string for assembly output.
623    pub fn mnemonic(&self) -> &'static str {
624        match self {
625            EvmOpcode::Stop => "STOP",
626            EvmOpcode::Add => "ADD",
627            EvmOpcode::Mul => "MUL",
628            EvmOpcode::Sub => "SUB",
629            EvmOpcode::Div => "DIV",
630            EvmOpcode::Sdiv => "SDIV",
631            EvmOpcode::Mod => "MOD",
632            EvmOpcode::Smod => "SMOD",
633            EvmOpcode::Addmod => "ADDMOD",
634            EvmOpcode::Mulmod => "MULMOD",
635            EvmOpcode::Exp => "EXP",
636            EvmOpcode::Signextend => "SIGNEXTEND",
637            EvmOpcode::Lt => "LT",
638            EvmOpcode::Gt => "GT",
639            EvmOpcode::Slt => "SLT",
640            EvmOpcode::Sgt => "SGT",
641            EvmOpcode::Eq => "EQ",
642            EvmOpcode::Iszero => "ISZERO",
643            EvmOpcode::And => "AND",
644            EvmOpcode::Or => "OR",
645            EvmOpcode::Xor => "XOR",
646            EvmOpcode::Not => "NOT",
647            EvmOpcode::Byte => "BYTE",
648            EvmOpcode::Shl => "SHL",
649            EvmOpcode::Shr => "SHR",
650            EvmOpcode::Sar => "SAR",
651            EvmOpcode::Sha3 => "SHA3",
652            EvmOpcode::Address => "ADDRESS",
653            EvmOpcode::Balance => "BALANCE",
654            EvmOpcode::Origin => "ORIGIN",
655            EvmOpcode::Caller => "CALLER",
656            EvmOpcode::Callvalue => "CALLVALUE",
657            EvmOpcode::Calldataload => "CALLDATALOAD",
658            EvmOpcode::Calldatasize => "CALLDATASIZE",
659            EvmOpcode::Calldatacopy => "CALLDATACOPY",
660            EvmOpcode::Codesize => "CODESIZE",
661            EvmOpcode::Codecopy => "CODECOPY",
662            EvmOpcode::Gasprice => "GASPRICE",
663            EvmOpcode::Extcodesize => "EXTCODESIZE",
664            EvmOpcode::Extcodecopy => "EXTCODECOPY",
665            EvmOpcode::Returndatasize => "RETURNDATASIZE",
666            EvmOpcode::Returndatacopy => "RETURNDATACOPY",
667            EvmOpcode::Extcodehash => "EXTCODEHASH",
668            EvmOpcode::Blockhash => "BLOCKHASH",
669            EvmOpcode::Coinbase => "COINBASE",
670            EvmOpcode::Timestamp => "TIMESTAMP",
671            EvmOpcode::Number => "NUMBER",
672            EvmOpcode::Prevrandao => "PREVRANDAO",
673            EvmOpcode::Gaslimit => "GASLIMIT",
674            EvmOpcode::Chainid => "CHAINID",
675            EvmOpcode::Selfbalance => "SELFBALANCE",
676            EvmOpcode::Basefee => "BASEFEE",
677            EvmOpcode::Blobbasefee => "BLOBBASEFEE",
678            EvmOpcode::Pop => "POP",
679            EvmOpcode::Mload => "MLOAD",
680            EvmOpcode::Mstore => "MSTORE",
681            EvmOpcode::Mstore8 => "MSTORE8",
682            EvmOpcode::Sload => "SLOAD",
683            EvmOpcode::Sstore => "SSTORE",
684            EvmOpcode::Jump => "JUMP",
685            EvmOpcode::Jumpi => "JUMPI",
686            EvmOpcode::Pc => "PC",
687            EvmOpcode::Msize => "MSIZE",
688            EvmOpcode::Gas => "GAS",
689            EvmOpcode::Jumpdest => "JUMPDEST",
690            EvmOpcode::Tload => "TLOAD",
691            EvmOpcode::Tstore => "TSTORE",
692            EvmOpcode::Mcopy => "MCOPY",
693            EvmOpcode::Push1 => "PUSH1",
694            EvmOpcode::Push2 => "PUSH2",
695            EvmOpcode::Push3 => "PUSH3",
696            EvmOpcode::Push4 => "PUSH4",
697            EvmOpcode::Push5 => "PUSH5",
698            EvmOpcode::Push6 => "PUSH6",
699            EvmOpcode::Push7 => "PUSH7",
700            EvmOpcode::Push8 => "PUSH8",
701            EvmOpcode::Push9 => "PUSH9",
702            EvmOpcode::Push10 => "PUSH10",
703            EvmOpcode::Push11 => "PUSH11",
704            EvmOpcode::Push12 => "PUSH12",
705            EvmOpcode::Push13 => "PUSH13",
706            EvmOpcode::Push14 => "PUSH14",
707            EvmOpcode::Push15 => "PUSH15",
708            EvmOpcode::Push16 => "PUSH16",
709            EvmOpcode::Push17 => "PUSH17",
710            EvmOpcode::Push18 => "PUSH18",
711            EvmOpcode::Push19 => "PUSH19",
712            EvmOpcode::Push20 => "PUSH20",
713            EvmOpcode::Push21 => "PUSH21",
714            EvmOpcode::Push22 => "PUSH22",
715            EvmOpcode::Push23 => "PUSH23",
716            EvmOpcode::Push24 => "PUSH24",
717            EvmOpcode::Push25 => "PUSH25",
718            EvmOpcode::Push26 => "PUSH26",
719            EvmOpcode::Push27 => "PUSH27",
720            EvmOpcode::Push28 => "PUSH28",
721            EvmOpcode::Push29 => "PUSH29",
722            EvmOpcode::Push30 => "PUSH30",
723            EvmOpcode::Push31 => "PUSH31",
724            EvmOpcode::Push32 => "PUSH32",
725            EvmOpcode::Dup1 => "DUP1",
726            EvmOpcode::Dup2 => "DUP2",
727            EvmOpcode::Dup3 => "DUP3",
728            EvmOpcode::Dup4 => "DUP4",
729            EvmOpcode::Dup5 => "DUP5",
730            EvmOpcode::Dup6 => "DUP6",
731            EvmOpcode::Dup7 => "DUP7",
732            EvmOpcode::Dup8 => "DUP8",
733            EvmOpcode::Dup9 => "DUP9",
734            EvmOpcode::Dup10 => "DUP10",
735            EvmOpcode::Dup11 => "DUP11",
736            EvmOpcode::Dup12 => "DUP12",
737            EvmOpcode::Dup13 => "DUP13",
738            EvmOpcode::Dup14 => "DUP14",
739            EvmOpcode::Dup15 => "DUP15",
740            EvmOpcode::Dup16 => "DUP16",
741            EvmOpcode::Swap1 => "SWAP1",
742            EvmOpcode::Swap2 => "SWAP2",
743            EvmOpcode::Swap3 => "SWAP3",
744            EvmOpcode::Swap4 => "SWAP4",
745            EvmOpcode::Swap5 => "SWAP5",
746            EvmOpcode::Swap6 => "SWAP6",
747            EvmOpcode::Swap7 => "SWAP7",
748            EvmOpcode::Swap8 => "SWAP8",
749            EvmOpcode::Swap9 => "SWAP9",
750            EvmOpcode::Swap10 => "SWAP10",
751            EvmOpcode::Swap11 => "SWAP11",
752            EvmOpcode::Swap12 => "SWAP12",
753            EvmOpcode::Swap13 => "SWAP13",
754            EvmOpcode::Swap14 => "SWAP14",
755            EvmOpcode::Swap15 => "SWAP15",
756            EvmOpcode::Swap16 => "SWAP16",
757            EvmOpcode::Log0 => "LOG0",
758            EvmOpcode::Log1 => "LOG1",
759            EvmOpcode::Log2 => "LOG2",
760            EvmOpcode::Log3 => "LOG3",
761            EvmOpcode::Log4 => "LOG4",
762            EvmOpcode::Create => "CREATE",
763            EvmOpcode::Call => "CALL",
764            EvmOpcode::Callcode => "CALLCODE",
765            EvmOpcode::Return => "RETURN",
766            EvmOpcode::Delegatecall => "DELEGATECALL",
767            EvmOpcode::Create2 => "CREATE2",
768            EvmOpcode::Staticcall => "STATICCALL",
769            EvmOpcode::Revert => "REVERT",
770            EvmOpcode::Invalid => "INVALID",
771            EvmOpcode::Selfdestruct => "SELFDESTRUCT",
772        }
773    }
774    /// Returns the number of immediate data bytes following this opcode (for PUSH).
775    pub fn immediate_size(&self) -> usize {
776        match self {
777            EvmOpcode::Push1 => 1,
778            EvmOpcode::Push2 => 2,
779            EvmOpcode::Push3 => 3,
780            EvmOpcode::Push4 => 4,
781            EvmOpcode::Push5 => 5,
782            EvmOpcode::Push6 => 6,
783            EvmOpcode::Push7 => 7,
784            EvmOpcode::Push8 => 8,
785            EvmOpcode::Push9 => 9,
786            EvmOpcode::Push10 => 10,
787            EvmOpcode::Push11 => 11,
788            EvmOpcode::Push12 => 12,
789            EvmOpcode::Push13 => 13,
790            EvmOpcode::Push14 => 14,
791            EvmOpcode::Push15 => 15,
792            EvmOpcode::Push16 => 16,
793            EvmOpcode::Push17 => 17,
794            EvmOpcode::Push18 => 18,
795            EvmOpcode::Push19 => 19,
796            EvmOpcode::Push20 => 20,
797            EvmOpcode::Push21 => 21,
798            EvmOpcode::Push22 => 22,
799            EvmOpcode::Push23 => 23,
800            EvmOpcode::Push24 => 24,
801            EvmOpcode::Push25 => 25,
802            EvmOpcode::Push26 => 26,
803            EvmOpcode::Push27 => 27,
804            EvmOpcode::Push28 => 28,
805            EvmOpcode::Push29 => 29,
806            EvmOpcode::Push30 => 30,
807            EvmOpcode::Push31 => 31,
808            EvmOpcode::Push32 => 32,
809            _ => 0,
810        }
811    }
812    /// Returns the appropriate PUSH opcode for a given number of bytes.
813    pub fn push_for_size(n: usize) -> Option<EvmOpcode> {
814        match n {
815            1 => Some(EvmOpcode::Push1),
816            2 => Some(EvmOpcode::Push2),
817            3 => Some(EvmOpcode::Push3),
818            4 => Some(EvmOpcode::Push4),
819            8 => Some(EvmOpcode::Push8),
820            20 => Some(EvmOpcode::Push20),
821            32 => Some(EvmOpcode::Push32),
822            _ => None,
823        }
824    }
825}
826#[allow(dead_code)]
827pub struct EVMPassRegistry {
828    pub(super) configs: Vec<EVMPassConfig>,
829    pub(super) stats: std::collections::HashMap<String, EVMPassStats>,
830}
831impl EVMPassRegistry {
832    #[allow(dead_code)]
833    pub fn new() -> Self {
834        EVMPassRegistry {
835            configs: Vec::new(),
836            stats: std::collections::HashMap::new(),
837        }
838    }
839    #[allow(dead_code)]
840    pub fn register(&mut self, config: EVMPassConfig) {
841        self.stats
842            .insert(config.pass_name.clone(), EVMPassStats::new());
843        self.configs.push(config);
844    }
845    #[allow(dead_code)]
846    pub fn enabled_passes(&self) -> Vec<&EVMPassConfig> {
847        self.configs.iter().filter(|c| c.enabled).collect()
848    }
849    #[allow(dead_code)]
850    pub fn get_stats(&self, name: &str) -> Option<&EVMPassStats> {
851        self.stats.get(name)
852    }
853    #[allow(dead_code)]
854    pub fn total_passes(&self) -> usize {
855        self.configs.len()
856    }
857    #[allow(dead_code)]
858    pub fn enabled_count(&self) -> usize {
859        self.enabled_passes().len()
860    }
861    #[allow(dead_code)]
862    pub fn update_stats(&mut self, name: &str, changes: u64, time_ms: u64, iter: u32) {
863        if let Some(stats) = self.stats.get_mut(name) {
864            stats.record_run(changes, time_ms, iter);
865        }
866    }
867}
868#[allow(dead_code)]
869#[derive(Debug, Clone, PartialEq)]
870pub enum EVMPassPhase {
871    Analysis,
872    Transformation,
873    Verification,
874    Cleanup,
875}
876impl EVMPassPhase {
877    #[allow(dead_code)]
878    pub fn name(&self) -> &str {
879        match self {
880            EVMPassPhase::Analysis => "analysis",
881            EVMPassPhase::Transformation => "transformation",
882            EVMPassPhase::Verification => "verification",
883            EVMPassPhase::Cleanup => "cleanup",
884        }
885    }
886    #[allow(dead_code)]
887    pub fn is_modifying(&self) -> bool {
888        matches!(self, EVMPassPhase::Transformation | EVMPassPhase::Cleanup)
889    }
890}
891#[allow(dead_code)]
892#[derive(Debug, Clone)]
893pub struct EVMWorklist {
894    pub(super) items: std::collections::VecDeque<u32>,
895    pub(super) in_worklist: std::collections::HashSet<u32>,
896}
897impl EVMWorklist {
898    #[allow(dead_code)]
899    pub fn new() -> Self {
900        EVMWorklist {
901            items: std::collections::VecDeque::new(),
902            in_worklist: std::collections::HashSet::new(),
903        }
904    }
905    #[allow(dead_code)]
906    pub fn push(&mut self, item: u32) -> bool {
907        if self.in_worklist.insert(item) {
908            self.items.push_back(item);
909            true
910        } else {
911            false
912        }
913    }
914    #[allow(dead_code)]
915    pub fn pop(&mut self) -> Option<u32> {
916        let item = self.items.pop_front()?;
917        self.in_worklist.remove(&item);
918        Some(item)
919    }
920    #[allow(dead_code)]
921    pub fn is_empty(&self) -> bool {
922        self.items.is_empty()
923    }
924    #[allow(dead_code)]
925    pub fn len(&self) -> usize {
926        self.items.len()
927    }
928    #[allow(dead_code)]
929    pub fn contains(&self, item: u32) -> bool {
930        self.in_worklist.contains(&item)
931    }
932}
933#[allow(dead_code)]
934#[derive(Debug, Clone)]
935pub struct EVMLivenessInfo {
936    pub live_in: Vec<std::collections::HashSet<u32>>,
937    pub live_out: Vec<std::collections::HashSet<u32>>,
938    pub defs: Vec<std::collections::HashSet<u32>>,
939    pub uses: Vec<std::collections::HashSet<u32>>,
940}
941impl EVMLivenessInfo {
942    #[allow(dead_code)]
943    pub fn new(block_count: usize) -> Self {
944        EVMLivenessInfo {
945            live_in: vec![std::collections::HashSet::new(); block_count],
946            live_out: vec![std::collections::HashSet::new(); block_count],
947            defs: vec![std::collections::HashSet::new(); block_count],
948            uses: vec![std::collections::HashSet::new(); block_count],
949        }
950    }
951    #[allow(dead_code)]
952    pub fn add_def(&mut self, block: usize, var: u32) {
953        if block < self.defs.len() {
954            self.defs[block].insert(var);
955        }
956    }
957    #[allow(dead_code)]
958    pub fn add_use(&mut self, block: usize, var: u32) {
959        if block < self.uses.len() {
960            self.uses[block].insert(var);
961        }
962    }
963    #[allow(dead_code)]
964    pub fn is_live_in(&self, block: usize, var: u32) -> bool {
965        self.live_in
966            .get(block)
967            .map(|s| s.contains(&var))
968            .unwrap_or(false)
969    }
970    #[allow(dead_code)]
971    pub fn is_live_out(&self, block: usize, var: u32) -> bool {
972        self.live_out
973            .get(block)
974            .map(|s| s.contains(&var))
975            .unwrap_or(false)
976    }
977}
978/// EVM code size analyzer
979#[allow(dead_code)]
980#[derive(Debug, Default, Clone)]
981pub struct EvmCodeSizeStats {
982    pub bytecode_size: usize,
983    pub deploy_bytecode_size: usize,
984    pub constructor_size: usize,
985    pub function_sizes: std::collections::HashMap<String, usize>,
986}
987/// EVM id generator
988#[allow(dead_code)]
989#[derive(Debug, Default)]
990pub struct EvmExtIdGen {
991    pub(super) counter: u64,
992    pub(super) prefix: String,
993}
994#[allow(dead_code)]
995impl EvmExtIdGen {
996    pub fn new(prefix: &str) -> Self {
997        Self {
998            counter: 0,
999            prefix: prefix.to_string(),
1000        }
1001    }
1002    pub fn next(&mut self) -> String {
1003        let id = self.counter;
1004        self.counter += 1;
1005        format!("{}_{}", self.prefix, id)
1006    }
1007}
1008/// EVM storage layout
1009#[allow(dead_code)]
1010#[derive(Debug, Clone)]
1011pub struct EvmStorageSlot {
1012    pub slot: u64,
1013    pub offset: u8,
1014    pub var_name: String,
1015    pub var_type: EvmAbiType,
1016}
1017/// EVM code statistics
1018#[allow(dead_code)]
1019#[derive(Debug, Default, Clone)]
1020pub struct EvmCodeStats {
1021    pub functions: usize,
1022    pub events: usize,
1023    pub modifiers: usize,
1024    pub storage_vars: usize,
1025    pub bytecode_size: usize,
1026}
1027#[allow(dead_code)]
1028#[derive(Debug, Clone)]
1029pub struct EVMAnalysisCache {
1030    pub(super) entries: std::collections::HashMap<String, EVMCacheEntry>,
1031    pub(super) max_size: usize,
1032    pub(super) hits: u64,
1033    pub(super) misses: u64,
1034}
1035impl EVMAnalysisCache {
1036    #[allow(dead_code)]
1037    pub fn new(max_size: usize) -> Self {
1038        EVMAnalysisCache {
1039            entries: std::collections::HashMap::new(),
1040            max_size,
1041            hits: 0,
1042            misses: 0,
1043        }
1044    }
1045    #[allow(dead_code)]
1046    pub fn get(&mut self, key: &str) -> Option<&EVMCacheEntry> {
1047        if self.entries.contains_key(key) {
1048            self.hits += 1;
1049            self.entries.get(key)
1050        } else {
1051            self.misses += 1;
1052            None
1053        }
1054    }
1055    #[allow(dead_code)]
1056    pub fn insert(&mut self, key: String, data: Vec<u8>) {
1057        if self.entries.len() >= self.max_size {
1058            if let Some(oldest) = self.entries.keys().next().cloned() {
1059                self.entries.remove(&oldest);
1060            }
1061        }
1062        self.entries.insert(
1063            key.clone(),
1064            EVMCacheEntry {
1065                key,
1066                data,
1067                timestamp: 0,
1068                valid: true,
1069            },
1070        );
1071    }
1072    #[allow(dead_code)]
1073    pub fn invalidate(&mut self, key: &str) {
1074        if let Some(entry) = self.entries.get_mut(key) {
1075            entry.valid = false;
1076        }
1077    }
1078    #[allow(dead_code)]
1079    pub fn clear(&mut self) {
1080        self.entries.clear();
1081    }
1082    #[allow(dead_code)]
1083    pub fn hit_rate(&self) -> f64 {
1084        let total = self.hits + self.misses;
1085        if total == 0 {
1086            return 0.0;
1087        }
1088        self.hits as f64 / total as f64
1089    }
1090    #[allow(dead_code)]
1091    pub fn size(&self) -> usize {
1092        self.entries.len()
1093    }
1094}
1095/// EVM source buffer
1096#[allow(dead_code)]
1097#[derive(Debug, Default)]
1098pub struct EvmExtSourceBuffer {
1099    pub sections: Vec<(String, String)>,
1100    pub current: String,
1101    pub indent: usize,
1102}
1103#[allow(dead_code)]
1104impl EvmExtSourceBuffer {
1105    pub fn new() -> Self {
1106        Self::default()
1107    }
1108    pub fn write(&mut self, s: &str) {
1109        let pad = "    ".repeat(self.indent);
1110        self.current.push_str(&pad);
1111        self.current.push_str(s);
1112    }
1113    pub fn writeln(&mut self, s: &str) {
1114        let pad = "    ".repeat(self.indent);
1115        self.current.push_str(&pad);
1116        self.current.push_str(s);
1117        self.current.push('\n');
1118    }
1119    pub fn indent(&mut self) {
1120        self.indent += 1;
1121    }
1122    pub fn dedent(&mut self) {
1123        if self.indent > 0 {
1124            self.indent -= 1;
1125        }
1126    }
1127    pub fn begin_section(&mut self, name: &str) {
1128        let done = std::mem::take(&mut self.current);
1129        if !done.is_empty() {
1130            self.sections.push(("anon".to_string(), done));
1131        }
1132        self.current = format!("// === {} ===\n", name);
1133    }
1134    pub fn finish(mut self) -> String {
1135        let done = std::mem::take(&mut self.current);
1136        if !done.is_empty() {
1137            self.sections.push(("anon".to_string(), done));
1138        }
1139        self.sections
1140            .iter()
1141            .map(|(_, s)| s.as_str())
1142            .collect::<Vec<_>>()
1143            .join("")
1144    }
1145}
1146#[allow(dead_code)]
1147#[derive(Debug, Default)]
1148pub struct EvmDiagSink {
1149    pub diags: Vec<EvmDiag>,
1150}
1151#[allow(dead_code)]
1152impl EvmDiagSink {
1153    pub fn new() -> Self {
1154        Self::default()
1155    }
1156    pub fn push(&mut self, level: EvmDiagLevel, msg: &str) {
1157        self.diags.push(EvmDiag {
1158            level,
1159            message: msg.to_string(),
1160            location: None,
1161        });
1162    }
1163    pub fn has_errors(&self) -> bool {
1164        self.diags.iter().any(|d| d.level == EvmDiagLevel::Error)
1165    }
1166}
1167/// A full EVM smart contract.
1168///
1169/// Contains the constructor code, runtime functions, and storage layout.
1170#[derive(Debug, Clone)]
1171pub struct EvmContract {
1172    /// Contract name.
1173    pub name: String,
1174    /// Runtime functions (public entry points).
1175    pub functions: Vec<EvmFunction>,
1176    /// Storage variable layout.
1177    pub storage_layout: StorageLayout,
1178    /// Constructor bytecode (deployed as init code).
1179    pub constructor_code: Vec<EvmInstruction>,
1180    /// Compiler metadata comments.
1181    pub metadata: HashMap<String, String>,
1182}
1183impl EvmContract {
1184    /// Create a new contract with the given name.
1185    pub fn new(name: impl Into<String>) -> Self {
1186        Self {
1187            name: name.into(),
1188            functions: Vec::new(),
1189            storage_layout: StorageLayout::new(),
1190            constructor_code: Vec::new(),
1191            metadata: HashMap::new(),
1192        }
1193    }
1194    /// Add a function to this contract.
1195    pub fn add_function(&mut self, func: EvmFunction) {
1196        self.functions.push(func);
1197    }
1198    /// Allocate a storage slot for a state variable.
1199    pub fn allocate_storage(&mut self, name: impl Into<String>) -> u64 {
1200        self.storage_layout.allocate(name)
1201    }
1202    /// Add a metadata key-value pair.
1203    pub fn set_metadata(&mut self, key: impl Into<String>, value: impl Into<String>) {
1204        self.metadata.insert(key.into(), value.into());
1205    }
1206}
1207/// EVM pass profiler
1208#[allow(dead_code)]
1209#[derive(Debug, Default)]
1210pub struct EvmExtProfiler {
1211    pub timings: Vec<(String, u64)>,
1212}
1213#[allow(dead_code)]
1214impl EvmExtProfiler {
1215    pub fn new() -> Self {
1216        Self::default()
1217    }
1218    pub fn record(&mut self, pass: &str, us: u64) {
1219        self.timings.push((pass.to_string(), us));
1220    }
1221    pub fn total_us(&self) -> u64 {
1222        self.timings.iter().map(|(_, t)| *t).sum()
1223    }
1224}
1225/// EVM Yul IR expression
1226#[allow(dead_code)]
1227#[derive(Debug, Clone)]
1228pub enum YulExpr {
1229    Literal(u64),
1230    Variable(String),
1231    FunctionCall(String, Vec<YulExpr>),
1232}
1233/// EVM Yul function definition
1234#[allow(dead_code)]
1235#[derive(Debug, Clone)]
1236pub struct YulFunction {
1237    pub name: String,
1238    pub params: Vec<String>,
1239    pub returns: Vec<String>,
1240    pub body: Vec<YulStmt>,
1241}
1242#[allow(dead_code)]
1243#[derive(Debug, Clone)]
1244pub struct EVMCacheEntry {
1245    pub key: String,
1246    pub data: Vec<u8>,
1247    pub timestamp: u64,
1248    pub valid: bool,
1249}
1250/// EVM opcode descriptor
1251#[allow(dead_code)]
1252#[derive(Debug, Clone)]
1253pub struct EvmOpcodeDesc {
1254    pub name: String,
1255    pub opcode: u8,
1256    pub stack_in: u8,
1257    pub stack_out: u8,
1258    pub gas: u64,
1259    pub category: EvmOpcodeCategory,
1260    pub description: String,
1261}
1262#[allow(dead_code)]
1263pub struct EVMConstantFoldingHelper;
1264impl EVMConstantFoldingHelper {
1265    #[allow(dead_code)]
1266    pub fn fold_add_i64(a: i64, b: i64) -> Option<i64> {
1267        a.checked_add(b)
1268    }
1269    #[allow(dead_code)]
1270    pub fn fold_sub_i64(a: i64, b: i64) -> Option<i64> {
1271        a.checked_sub(b)
1272    }
1273    #[allow(dead_code)]
1274    pub fn fold_mul_i64(a: i64, b: i64) -> Option<i64> {
1275        a.checked_mul(b)
1276    }
1277    #[allow(dead_code)]
1278    pub fn fold_div_i64(a: i64, b: i64) -> Option<i64> {
1279        if b == 0 {
1280            None
1281        } else {
1282            a.checked_div(b)
1283        }
1284    }
1285    #[allow(dead_code)]
1286    pub fn fold_add_f64(a: f64, b: f64) -> f64 {
1287        a + b
1288    }
1289    #[allow(dead_code)]
1290    pub fn fold_mul_f64(a: f64, b: f64) -> f64 {
1291        a * b
1292    }
1293    #[allow(dead_code)]
1294    pub fn fold_neg_i64(a: i64) -> Option<i64> {
1295        a.checked_neg()
1296    }
1297    #[allow(dead_code)]
1298    pub fn fold_not_bool(a: bool) -> bool {
1299        !a
1300    }
1301    #[allow(dead_code)]
1302    pub fn fold_and_bool(a: bool, b: bool) -> bool {
1303        a && b
1304    }
1305    #[allow(dead_code)]
1306    pub fn fold_or_bool(a: bool, b: bool) -> bool {
1307        a || b
1308    }
1309    #[allow(dead_code)]
1310    pub fn fold_shl_i64(a: i64, b: u32) -> Option<i64> {
1311        a.checked_shl(b)
1312    }
1313    #[allow(dead_code)]
1314    pub fn fold_shr_i64(a: i64, b: u32) -> Option<i64> {
1315        a.checked_shr(b)
1316    }
1317    #[allow(dead_code)]
1318    pub fn fold_rem_i64(a: i64, b: i64) -> Option<i64> {
1319        if b == 0 {
1320            None
1321        } else {
1322            Some(a % b)
1323        }
1324    }
1325    #[allow(dead_code)]
1326    pub fn fold_bitand_i64(a: i64, b: i64) -> i64 {
1327        a & b
1328    }
1329    #[allow(dead_code)]
1330    pub fn fold_bitor_i64(a: i64, b: i64) -> i64 {
1331        a | b
1332    }
1333    #[allow(dead_code)]
1334    pub fn fold_bitxor_i64(a: i64, b: i64) -> i64 {
1335        a ^ b
1336    }
1337    #[allow(dead_code)]
1338    pub fn fold_bitnot_i64(a: i64) -> i64 {
1339        !a
1340    }
1341}
1342#[allow(dead_code)]
1343#[derive(Debug, Clone)]
1344pub struct EVMDepGraph {
1345    pub(super) nodes: Vec<u32>,
1346    pub(super) edges: Vec<(u32, u32)>,
1347}
1348impl EVMDepGraph {
1349    #[allow(dead_code)]
1350    pub fn new() -> Self {
1351        EVMDepGraph {
1352            nodes: Vec::new(),
1353            edges: Vec::new(),
1354        }
1355    }
1356    #[allow(dead_code)]
1357    pub fn add_node(&mut self, id: u32) {
1358        if !self.nodes.contains(&id) {
1359            self.nodes.push(id);
1360        }
1361    }
1362    #[allow(dead_code)]
1363    pub fn add_dep(&mut self, dep: u32, dependent: u32) {
1364        self.add_node(dep);
1365        self.add_node(dependent);
1366        self.edges.push((dep, dependent));
1367    }
1368    #[allow(dead_code)]
1369    pub fn dependents_of(&self, node: u32) -> Vec<u32> {
1370        self.edges
1371            .iter()
1372            .filter(|(d, _)| *d == node)
1373            .map(|(_, dep)| *dep)
1374            .collect()
1375    }
1376    #[allow(dead_code)]
1377    pub fn dependencies_of(&self, node: u32) -> Vec<u32> {
1378        self.edges
1379            .iter()
1380            .filter(|(_, dep)| *dep == node)
1381            .map(|(d, _)| *d)
1382            .collect()
1383    }
1384    #[allow(dead_code)]
1385    pub fn topological_sort(&self) -> Vec<u32> {
1386        let mut in_degree: std::collections::HashMap<u32, u32> = std::collections::HashMap::new();
1387        for &n in &self.nodes {
1388            in_degree.insert(n, 0);
1389        }
1390        for (_, dep) in &self.edges {
1391            *in_degree.entry(*dep).or_insert(0) += 1;
1392        }
1393        let mut queue: std::collections::VecDeque<u32> = self
1394            .nodes
1395            .iter()
1396            .filter(|&&n| in_degree[&n] == 0)
1397            .copied()
1398            .collect();
1399        let mut result = Vec::new();
1400        while let Some(node) = queue.pop_front() {
1401            result.push(node);
1402            for dep in self.dependents_of(node) {
1403                let cnt = in_degree.entry(dep).or_insert(0);
1404                *cnt = cnt.saturating_sub(1);
1405                if *cnt == 0 {
1406                    queue.push_back(dep);
1407                }
1408            }
1409        }
1410        result
1411    }
1412    #[allow(dead_code)]
1413    pub fn has_cycle(&self) -> bool {
1414        self.topological_sort().len() < self.nodes.len()
1415    }
1416}
1417/// EVM feature flags
1418#[allow(dead_code)]
1419#[derive(Debug, Clone, Default)]
1420pub struct EvmFeatureFlags {
1421    pub shanghai: bool,
1422    pub cancun: bool,
1423    pub prague: bool,
1424    pub support_transient_storage: bool,
1425    pub support_push0: bool,
1426}
1427/// EVM selector (function selector for ABI)
1428#[allow(dead_code)]
1429#[derive(Debug, Clone)]
1430pub struct EvmSelector {
1431    pub signature: String,
1432    pub selector: [u8; 4],
1433}
1434#[allow(dead_code)]
1435impl EvmSelector {
1436    pub fn from_signature(sig: &str) -> Self {
1437        let bytes = sig.as_bytes();
1438        let selector = [
1439            bytes.get(0).copied().unwrap_or(0),
1440            bytes.get(1).copied().unwrap_or(0),
1441            bytes.get(2).copied().unwrap_or(0),
1442            bytes.get(3).copied().unwrap_or(0),
1443        ];
1444        Self {
1445            signature: sig.to_string(),
1446            selector,
1447        }
1448    }
1449    pub fn hex(&self) -> String {
1450        format!(
1451            "{:02x}{:02x}{:02x}{:02x}",
1452            self.selector[0], self.selector[1], self.selector[2], self.selector[3]
1453        )
1454    }
1455}
1456/// EVM ABI function descriptor
1457#[allow(dead_code)]
1458#[derive(Debug, Clone)]
1459pub struct EvmAbiFunction {
1460    pub name: String,
1461    pub inputs: Vec<(String, EvmAbiType)>,
1462    pub outputs: Vec<(String, EvmAbiType)>,
1463    pub state_mutability: String,
1464    pub is_payable: bool,
1465    pub is_view: bool,
1466    pub is_pure: bool,
1467}
1468/// EVM bytecode code generation backend.
1469///
1470/// Converts an `EvmContract` into:
1471/// - Raw binary bytecode (`Vec<u8>`)
1472/// - Hex string representation
1473/// - Human-readable assembly text
1474#[derive(Debug, Default)]
1475pub struct EvmBackend {
1476    /// Label-to-offset mapping built during encoding.
1477    pub(super) label_offsets: HashMap<String, usize>,
1478}
1479impl EvmBackend {
1480    /// Create a new EVM backend instance.
1481    pub fn new() -> Self {
1482        Self::default()
1483    }
1484    /// Compute a 4-byte function selector from an ABI signature string.
1485    ///
1486    /// This is a placeholder using a fast mixing hash (not real keccak256).
1487    /// In production this should use a proper keccak256 crate.
1488    pub fn compute_selector(signature: &str) -> [u8; 4] {
1489        let mut hash: u32 = 0x811c9dc5;
1490        for &b in signature.as_bytes() {
1491            hash ^= b as u32;
1492            hash = hash.wrapping_mul(0x01000193);
1493        }
1494        hash.to_be_bytes()
1495    }
1496    /// Emit the standard ABI dispatcher preamble.
1497    ///
1498    /// This code:
1499    /// 1. Loads the first 4 bytes of calldata (the function selector).
1500    /// 2. Compares against each known selector.
1501    /// 3. Jumps to the appropriate handler block.
1502    /// 4. Falls through to REVERT if no selector matches.
1503    pub fn emit_dispatcher(&self, contract: &EvmContract) -> Vec<EvmInstruction> {
1504        let mut instrs = vec![
1505            EvmInstruction::new(EvmOpcode::Push1).with_comment("calldata offset 0"),
1506            EvmInstruction::push1(0).with_comment("offset = 0"),
1507            EvmInstruction::new(EvmOpcode::Calldataload)
1508                .with_comment("load 32 bytes from calldata[0]"),
1509            EvmInstruction::push1(0xe0).with_comment("shift 224 bits"),
1510            EvmInstruction::new(EvmOpcode::Shr).with_comment("selector = calldata >> 224"),
1511        ];
1512        for func in &contract.functions {
1513            let sel_val = u32::from_be_bytes(func.selector);
1514            instrs.push(
1515                EvmInstruction::new(EvmOpcode::Dup1).with_comment(format!("check {}", func.name)),
1516            );
1517            instrs.push(
1518                EvmInstruction::push4(sel_val)
1519                    .with_comment(format!("selector for {}", func.signature)),
1520            );
1521            instrs.push(EvmInstruction::new(EvmOpcode::Eq));
1522            instrs.push(
1523                EvmInstruction::push(vec![0x00, 0x00])
1524                    .expect("push of 2-byte slice is always valid (1..=32 bytes)")
1525                    .with_comment(format!("dest: {}", func.name)),
1526            );
1527            instrs.push(EvmInstruction::new(EvmOpcode::Jumpi));
1528        }
1529        instrs.push(EvmInstruction::push1(0).with_comment("revert size 0"));
1530        instrs.push(EvmInstruction::push1(0).with_comment("revert offset 0"));
1531        instrs.push(EvmInstruction::new(EvmOpcode::Revert).with_comment("no matching selector"));
1532        instrs
1533    }
1534    /// Emit instructions to load a storage variable onto the stack.
1535    pub fn emit_sload(&self, slot: u64) -> Vec<EvmInstruction> {
1536        let mut instrs = Vec::new();
1537        let bytes = slot.to_be_bytes();
1538        let trimmed: Vec<u8> = {
1539            let first_nonzero = bytes.iter().position(|&b| b != 0).unwrap_or(7);
1540            bytes[first_nonzero..].to_vec()
1541        };
1542        let push_instr = EvmInstruction::push(if trimmed.is_empty() {
1543            vec![0x00]
1544        } else {
1545            trimmed
1546        })
1547        .expect("push of 1..=8 byte slot always valid (within 1..=32 byte range)")
1548        .with_comment(format!("storage slot {}", slot));
1549        instrs.push(push_instr);
1550        instrs.push(
1551            EvmInstruction::new(EvmOpcode::Sload).with_comment(format!("SLOAD slot {}", slot)),
1552        );
1553        instrs
1554    }
1555    /// Emit instructions to store the top-of-stack value into a storage slot.
1556    ///
1557    /// Assumes the value to store is already on the stack.
1558    pub fn emit_sstore(&self, slot: u64) -> Vec<EvmInstruction> {
1559        let mut instrs = Vec::new();
1560        let bytes = slot.to_be_bytes();
1561        let trimmed: Vec<u8> = {
1562            let first_nonzero = bytes.iter().position(|&b| b != 0).unwrap_or(7);
1563            bytes[first_nonzero..].to_vec()
1564        };
1565        let push_instr = EvmInstruction::push(if trimmed.is_empty() {
1566            vec![0x00]
1567        } else {
1568            trimmed
1569        })
1570        .expect("push of 1..=8 byte slot always valid (within 1..=32 byte range)")
1571        .with_comment(format!("storage slot {}", slot));
1572        instrs.push(push_instr);
1573        instrs.push(
1574            EvmInstruction::new(EvmOpcode::Sstore).with_comment(format!("SSTORE slot {}", slot)),
1575        );
1576        instrs
1577    }
1578    /// Encode the constructor code portion of a contract to raw bytes.
1579    pub fn emit_constructor_bytes(&self, contract: &EvmContract) -> Vec<u8> {
1580        contract
1581            .constructor_code
1582            .iter()
1583            .flat_map(|i| i.encode())
1584            .collect()
1585    }
1586    /// Encode the full runtime bytecode of a contract to raw bytes.
1587    ///
1588    /// Layout: dispatcher preamble + function bodies (each starting with JUMPDEST).
1589    pub fn emit_runtime_bytes(&self, contract: &EvmContract) -> Vec<u8> {
1590        let mut out = Vec::new();
1591        for instr in self.emit_dispatcher(contract) {
1592            out.extend(instr.encode());
1593        }
1594        for func in &contract.functions {
1595            out.extend(func.encode());
1596        }
1597        out
1598    }
1599    /// Encode the complete init code (constructor + runtime deployment stub).
1600    ///
1601    /// The init code:
1602    /// 1. Runs constructor logic.
1603    /// 2. Returns a copy of the runtime bytecode so the EVM stores it.
1604    pub fn emit_init_code(&self, contract: &EvmContract) -> Vec<u8> {
1605        let runtime = self.emit_runtime_bytes(contract);
1606        let runtime_len = runtime.len();
1607        let constructor = self.emit_constructor_bytes(contract);
1608        let mut init = Vec::new();
1609        init.extend_from_slice(&constructor);
1610        if runtime_len <= 0xffff {
1611            let len_bytes = (runtime_len as u16).to_be_bytes();
1612            init.extend(
1613                EvmInstruction::push(len_bytes.to_vec())
1614                    .expect("2-byte push is always valid")
1615                    .encode(),
1616            );
1617        } else {
1618            let len_bytes = (runtime_len as u32).to_be_bytes();
1619            init.extend(
1620                EvmInstruction::push(len_bytes.to_vec())
1621                    .expect("4-byte push is always valid")
1622                    .encode(),
1623            );
1624        }
1625        init.extend(
1626            EvmInstruction::push(vec![0x00, 0x00])
1627                .expect("2-byte push is always valid")
1628                .encode(),
1629        );
1630        init.extend(EvmInstruction::push1(0x00).encode());
1631        init.push(EvmOpcode::Codecopy.byte());
1632        if runtime_len <= 0xffff {
1633            let len_bytes = (runtime_len as u16).to_be_bytes();
1634            init.extend(
1635                EvmInstruction::push(len_bytes.to_vec())
1636                    .expect("2-byte push is always valid")
1637                    .encode(),
1638            );
1639        } else {
1640            let len_bytes = (runtime_len as u32).to_be_bytes();
1641            init.extend(
1642                EvmInstruction::push(len_bytes.to_vec())
1643                    .expect("4-byte push is always valid")
1644                    .encode(),
1645            );
1646        }
1647        init.extend(EvmInstruction::push1(0x00).encode());
1648        init.push(EvmOpcode::Return.byte());
1649        init.extend_from_slice(&runtime);
1650        init
1651    }
1652    /// Encode the runtime bytecode as a hex string (no 0x prefix).
1653    pub fn emit_hex(&self, contract: &EvmContract) -> String {
1654        let bytes = self.emit_runtime_bytes(contract);
1655        bytes.iter().map(|b| format!("{:02x}", b)).collect()
1656    }
1657    /// Encode the runtime bytecode as a hex string with `0x` prefix.
1658    pub fn emit_hex_prefixed(&self, contract: &EvmContract) -> String {
1659        format!("0x{}", self.emit_hex(contract))
1660    }
1661    /// Encode the full init code as a hex string with `0x` prefix.
1662    pub fn emit_init_hex(&self, contract: &EvmContract) -> String {
1663        let bytes = self.emit_init_code(contract);
1664        format!(
1665            "0x{}",
1666            bytes
1667                .iter()
1668                .map(|b| format!("{:02x}", b))
1669                .collect::<String>()
1670        )
1671    }
1672    /// Format a single instruction as an assembly line with optional byte offset.
1673    pub(super) fn format_instr_line(offset: usize, instr: &EvmInstruction) -> String {
1674        let mut line = format!("{:04x}  {}", offset, instr.opcode.mnemonic());
1675        if let Some(ref data) = instr.data {
1676            line.push(' ');
1677            line.push_str("0x");
1678            for b in data {
1679                line.push_str(&format!("{:02x}", b));
1680            }
1681        }
1682        if let Some(ref c) = instr.comment {
1683            while line.len() < 30 {
1684                line.push(' ');
1685            }
1686            line.push_str("; ");
1687            line.push_str(c);
1688        }
1689        line
1690    }
1691    /// Emit human-readable assembly text for an `EvmContract`.
1692    pub fn emit_assembly(&self, contract: &EvmContract) -> String {
1693        let mut out = String::new();
1694        out.push_str(&format!("; Contract: {}\n", contract.name));
1695        for (k, v) in &contract.metadata {
1696            out.push_str(&format!("; {}: {}\n", k, v));
1697        }
1698        out.push('\n');
1699        if !contract.storage_layout.is_empty() {
1700            out.push_str("; Storage Layout:\n");
1701            let mut slots: Vec<_> = contract.storage_layout.slots.iter().collect();
1702            slots.sort_by_key(|(_, &s)| s);
1703            for (name, slot) in &slots {
1704                out.push_str(&format!(";   slot {:3}: {}\n", slot, name));
1705            }
1706            out.push('\n');
1707        }
1708        if !contract.constructor_code.is_empty() {
1709            out.push_str("constructor:\n");
1710            let mut offset = 0usize;
1711            for instr in &contract.constructor_code {
1712                out.push_str(&format!("  {}\n", Self::format_instr_line(offset, instr)));
1713                offset += instr.byte_len();
1714            }
1715            out.push('\n');
1716        }
1717        out.push_str("runtime_dispatcher:\n");
1718        let dispatcher = self.emit_dispatcher(contract);
1719        let mut offset = 0usize;
1720        for instr in &dispatcher {
1721            out.push_str(&format!("  {}\n", Self::format_instr_line(offset, instr)));
1722            offset += instr.byte_len();
1723        }
1724        out.push('\n');
1725        for func in &contract.functions {
1726            let sel_hex: String = func.selector.iter().map(|b| format!("{:02x}", b)).collect();
1727            out.push_str(&format!(
1728                "function {} (selector: 0x{}) ; {}\n",
1729                func.name, sel_hex, func.signature
1730            ));
1731            if func.is_payable {
1732                out.push_str(";   payable\n");
1733            }
1734            if func.is_view {
1735                out.push_str(";   view\n");
1736            }
1737            for block in &func.blocks {
1738                out.push_str(&format!("  .{}:\n", block.label));
1739                if block.is_jump_target {
1740                    out.push_str(&format!("    {:04x}  JUMPDEST\n", offset));
1741                    offset += 1;
1742                }
1743                for instr in &block.instructions {
1744                    out.push_str(&format!("    {}\n", Self::format_instr_line(offset, instr)));
1745                    offset += instr.byte_len();
1746                }
1747            }
1748            out.push('\n');
1749        }
1750        out
1751    }
1752    /// Build a simple two-argument arithmetic function (e.g. `add(uint256,uint256)`).
1753    ///
1754    /// Loads arg0 from calldata\[4\], arg1 from calldata\[36\], applies `op`, stores
1755    /// result in memory[0..32], and returns 32 bytes.
1756    #[allow(clippy::too_many_arguments)]
1757    pub fn build_arithmetic_function(
1758        name: &str,
1759        signature: &str,
1760        selector: [u8; 4],
1761        op: EvmOpcode,
1762    ) -> EvmFunction {
1763        let mut func = EvmFunction::new(name, selector, signature);
1764        let mut block = EvmBasicBlock::new_jump_target("entry");
1765        block.push_instr(EvmInstruction::push1(4).with_comment("calldata offset for arg0"));
1766        block.push_op(EvmOpcode::Calldataload);
1767        block.push_instr(EvmInstruction::push1(36).with_comment("calldata offset for arg1"));
1768        block.push_op(EvmOpcode::Calldataload);
1769        block.push_instr(EvmInstruction::new(op).with_comment("arithmetic op"));
1770        block.push_instr(EvmInstruction::push1(0).with_comment("mem offset"));
1771        block.push_op(EvmOpcode::Mstore);
1772        block.push_instr(EvmInstruction::push1(32).with_comment("return size"));
1773        block.push_instr(EvmInstruction::push1(0).with_comment("return offset"));
1774        block.push_op(EvmOpcode::Return);
1775        func.add_block(block);
1776        func
1777    }
1778}
1779#[allow(dead_code)]
1780#[derive(Debug, Clone)]
1781pub struct EVMPassConfig {
1782    pub phase: EVMPassPhase,
1783    pub enabled: bool,
1784    pub max_iterations: u32,
1785    pub debug_output: bool,
1786    pub pass_name: String,
1787}
1788impl EVMPassConfig {
1789    #[allow(dead_code)]
1790    pub fn new(name: impl Into<String>, phase: EVMPassPhase) -> Self {
1791        EVMPassConfig {
1792            phase,
1793            enabled: true,
1794            max_iterations: 10,
1795            debug_output: false,
1796            pass_name: name.into(),
1797        }
1798    }
1799    #[allow(dead_code)]
1800    pub fn disabled(mut self) -> Self {
1801        self.enabled = false;
1802        self
1803    }
1804    #[allow(dead_code)]
1805    pub fn with_debug(mut self) -> Self {
1806        self.debug_output = true;
1807        self
1808    }
1809    #[allow(dead_code)]
1810    pub fn max_iter(mut self, n: u32) -> Self {
1811        self.max_iterations = n;
1812        self
1813    }
1814}
1815/// A single EVM instruction, consisting of an opcode and optional immediate data.
1816///
1817/// For PUSH1..PUSH32 opcodes the `data` field holds the bytes to push.
1818/// For all other opcodes `data` is `None`.
1819#[derive(Debug, Clone, PartialEq)]
1820pub struct EvmInstruction {
1821    /// The opcode for this instruction.
1822    pub opcode: EvmOpcode,
1823    /// Optional immediate data bytes (used by PUSH instructions).
1824    pub data: Option<Vec<u8>>,
1825    /// Optional human-readable comment for assembly output.
1826    pub comment: Option<String>,
1827}
1828impl EvmInstruction {
1829    /// Create a plain instruction with no immediate data.
1830    pub fn new(opcode: EvmOpcode) -> Self {
1831        Self {
1832            opcode,
1833            data: None,
1834            comment: None,
1835        }
1836    }
1837    /// Create a PUSH instruction with the given byte vector.
1838    ///
1839    /// Automatically selects the correct PUSH1..PUSH32 opcode.
1840    pub fn push(bytes: Vec<u8>) -> Option<Self> {
1841        let len = bytes.len();
1842        if len == 0 || len > 32 {
1843            return None;
1844        }
1845        let opcode = match len {
1846            1 => EvmOpcode::Push1,
1847            2 => EvmOpcode::Push2,
1848            3 => EvmOpcode::Push3,
1849            4 => EvmOpcode::Push4,
1850            5 => EvmOpcode::Push5,
1851            6 => EvmOpcode::Push6,
1852            7 => EvmOpcode::Push7,
1853            8 => EvmOpcode::Push8,
1854            9 => EvmOpcode::Push9,
1855            10 => EvmOpcode::Push10,
1856            11 => EvmOpcode::Push11,
1857            12 => EvmOpcode::Push12,
1858            13 => EvmOpcode::Push13,
1859            14 => EvmOpcode::Push14,
1860            15 => EvmOpcode::Push15,
1861            16 => EvmOpcode::Push16,
1862            17 => EvmOpcode::Push17,
1863            18 => EvmOpcode::Push18,
1864            19 => EvmOpcode::Push19,
1865            20 => EvmOpcode::Push20,
1866            21 => EvmOpcode::Push21,
1867            22 => EvmOpcode::Push22,
1868            23 => EvmOpcode::Push23,
1869            24 => EvmOpcode::Push24,
1870            25 => EvmOpcode::Push25,
1871            26 => EvmOpcode::Push26,
1872            27 => EvmOpcode::Push27,
1873            28 => EvmOpcode::Push28,
1874            29 => EvmOpcode::Push29,
1875            30 => EvmOpcode::Push30,
1876            31 => EvmOpcode::Push31,
1877            32 => EvmOpcode::Push32,
1878            _ => return None,
1879        };
1880        Some(Self {
1881            opcode,
1882            data: Some(bytes),
1883            comment: None,
1884        })
1885    }
1886    /// Create a PUSH1 instruction for a single byte value.
1887    pub fn push1(byte: u8) -> Self {
1888        Self {
1889            opcode: EvmOpcode::Push1,
1890            data: Some(vec![byte]),
1891            comment: None,
1892        }
1893    }
1894    /// Create a PUSH4 instruction for a 4-byte value (used for function selectors).
1895    pub fn push4(val: u32) -> Self {
1896        let bytes = val.to_be_bytes().to_vec();
1897        Self {
1898            opcode: EvmOpcode::Push4,
1899            data: Some(bytes),
1900            comment: None,
1901        }
1902    }
1903    /// Create a PUSH32 instruction for a 32-byte value.
1904    pub fn push32(val: [u8; 32]) -> Self {
1905        Self {
1906            opcode: EvmOpcode::Push32,
1907            data: Some(val.to_vec()),
1908            comment: None,
1909        }
1910    }
1911    /// Attach a comment to this instruction (for assembly output).
1912    pub fn with_comment(mut self, comment: impl Into<String>) -> Self {
1913        self.comment = Some(comment.into());
1914        self
1915    }
1916    /// Encode this instruction to its raw byte representation.
1917    pub fn encode(&self) -> Vec<u8> {
1918        let mut out = vec![self.opcode.byte()];
1919        if let Some(ref data) = self.data {
1920            out.extend_from_slice(data);
1921        }
1922        out
1923    }
1924    /// Byte length of this instruction (opcode + immediate data).
1925    pub fn byte_len(&self) -> usize {
1926        1 + self.data.as_ref().map(|d| d.len()).unwrap_or(0)
1927    }
1928}
1929/// EVM gas cost table
1930#[allow(dead_code)]
1931#[derive(Debug, Clone)]
1932pub struct EvmGasTable {
1933    pub stop: u64,
1934    pub add: u64,
1935    pub mul: u64,
1936    pub sub: u64,
1937    pub div: u64,
1938    pub sdiv: u64,
1939    pub mload: u64,
1940    pub mstore: u64,
1941    pub sload: u64,
1942    pub sstore_set: u64,
1943    pub sstore_clear: u64,
1944    pub call: u64,
1945    pub create: u64,
1946    pub sha3: u64,
1947    pub sha3_word: u64,
1948    pub log: u64,
1949    pub log_topic: u64,
1950    pub log_byte: u64,
1951}
1952/// EVM stack depth tracker
1953#[allow(dead_code)]
1954#[derive(Debug, Default, Clone)]
1955pub struct EvmStackDepth {
1956    pub current: i32,
1957    pub max: i32,
1958    pub min: i32,
1959}
1960#[allow(dead_code)]
1961impl EvmStackDepth {
1962    pub fn new() -> Self {
1963        Self::default()
1964    }
1965    pub fn push(&mut self, n: i32) {
1966        self.current += n;
1967        self.max = self.max.max(self.current);
1968    }
1969    pub fn pop(&mut self, n: i32) {
1970        self.current -= n;
1971        self.min = self.min.min(self.current);
1972    }
1973    pub fn apply_opcode(&mut self, desc: &EvmOpcodeDesc) {
1974        self.pop(desc.stack_in as i32);
1975        self.push(desc.stack_out as i32);
1976    }
1977    pub fn is_valid(&self) -> bool {
1978        self.current >= 0 && self.current <= 1024
1979    }
1980}
1981/// EVM emit stats
1982#[allow(dead_code)]
1983#[derive(Debug, Default, Clone)]
1984pub struct EvmExtEmitStats {
1985    pub bytes_written: usize,
1986    pub items_emitted: usize,
1987    pub errors: usize,
1988    pub warnings: usize,
1989    pub functions_emitted: usize,
1990    pub events_emitted: usize,
1991}
1992/// EVM name mangler
1993#[allow(dead_code)]
1994#[derive(Debug, Default)]
1995pub struct EvmNameMangler {
1996    pub used: std::collections::HashSet<String>,
1997    pub map: std::collections::HashMap<String, String>,
1998}
1999#[allow(dead_code)]
2000impl EvmNameMangler {
2001    pub fn new() -> Self {
2002        Self::default()
2003    }
2004    pub fn mangle(&mut self, name: &str) -> String {
2005        if let Some(m) = self.map.get(name) {
2006            return m.clone();
2007        }
2008        let mangled: String = name
2009            .chars()
2010            .map(|c| {
2011                if c.is_alphanumeric() || c == '_' {
2012                    c
2013                } else {
2014                    '_'
2015                }
2016            })
2017            .collect();
2018        let reserved = ["receive", "fallback", "constructor"];
2019        let mut candidate = if reserved.contains(&mangled.as_str()) {
2020            format!("ox_{}", mangled)
2021        } else {
2022            mangled.clone()
2023        };
2024        let base = candidate.clone();
2025        let mut cnt = 0;
2026        while self.used.contains(&candidate) {
2027            cnt += 1;
2028            candidate = format!("{}_{}", base, cnt);
2029        }
2030        self.used.insert(candidate.clone());
2031        self.map.insert(name.to_string(), candidate.clone());
2032        candidate
2033    }
2034}
2035/// EVM ABI error
2036#[allow(dead_code)]
2037#[derive(Debug, Clone)]
2038pub struct EvmAbiError {
2039    pub name: String,
2040    pub inputs: Vec<(String, EvmAbiType)>,
2041}
2042/// EVM backend config (extended)
2043#[allow(dead_code)]
2044#[derive(Debug, Clone)]
2045pub struct EvmExtConfig {
2046    pub evm_version: String,
2047    pub optimize: bool,
2048    pub optimize_runs: u32,
2049    pub emit_ir: bool,
2050    pub emit_asm: bool,
2051    pub via_ir: bool,
2052    pub revert_strings: bool,
2053    pub use_yul: bool,
2054}
2055/// EVM ABI event
2056#[allow(dead_code)]
2057#[derive(Debug, Clone)]
2058pub struct EvmAbiEvent {
2059    pub name: String,
2060    pub inputs: Vec<(String, EvmAbiType, bool)>,
2061    pub is_anonymous: bool,
2062}
2063/// EVM Yul statement
2064#[allow(dead_code)]
2065#[derive(Debug, Clone)]
2066pub enum YulStmt {
2067    Let(Vec<String>, Option<YulExpr>),
2068    Assign(Vec<String>, YulExpr),
2069    If(YulExpr, Vec<YulStmt>),
2070    Switch(YulExpr, Vec<(u64, Vec<YulStmt>)>, Option<Vec<YulStmt>>),
2071    For(Vec<YulStmt>, YulExpr, Vec<YulStmt>, Vec<YulStmt>),
2072    Break,
2073    Continue,
2074    Leave,
2075    Return(YulExpr, YulExpr),
2076    Revert(YulExpr, YulExpr),
2077    Pop(YulExpr),
2078    Expr(YulExpr),
2079}
2080/// EVM contract template (standard ERC-20 like)
2081#[allow(dead_code)]
2082pub struct EvmContractTemplate {
2083    pub name: String,
2084    pub spdx: String,
2085    pub pragma: String,
2086}
2087#[allow(dead_code)]
2088impl EvmContractTemplate {
2089    pub fn new(name: &str) -> Self {
2090        Self {
2091            name: name.to_string(),
2092            spdx: "MIT".to_string(),
2093            pragma: "^0.8.0".to_string(),
2094        }
2095    }
2096    pub fn emit_header(&self) -> String {
2097        format!(
2098            "// SPDX-License-Identifier: {}\npragma solidity {};\n\ncontract {} {{\n",
2099            self.spdx, self.pragma, self.name
2100        )
2101    }
2102    pub fn emit_footer(&self) -> String {
2103        "}\n".to_string()
2104    }
2105}
2106/// EVM opcode category
2107#[allow(dead_code)]
2108#[derive(Debug, Clone, PartialEq, Eq)]
2109pub enum EvmOpcodeCategory {
2110    Stop,
2111    Arithmetic,
2112    Comparison,
2113    Bitwise,
2114    Sha3,
2115    EnvInfo,
2116    BlockInfo,
2117    MemStack,
2118    Storage,
2119    Control,
2120    Log,
2121    System,
2122    Push,
2123    Dup,
2124    Swap,
2125}
2126/// EVM pass summary
2127#[allow(dead_code)]
2128#[derive(Debug, Clone, Default)]
2129pub struct EvmPassSummary {
2130    pub pass_name: String,
2131    pub functions_compiled: usize,
2132    pub bytecodes_generated: usize,
2133    pub optimizations_applied: usize,
2134    pub duration_us: u64,
2135}
2136/// EVM code optimizer pass
2137#[allow(dead_code)]
2138#[derive(Debug, Clone, PartialEq, Eq)]
2139pub enum EvmOptPass {
2140    DeadCodeElim,
2141    ConstantFolding,
2142    CommonSubexprElim,
2143    InlineFunctions,
2144    JumpElim,
2145    PushPop,
2146    Peephole,
2147}
2148/// An EVM function / entry point within a contract.
2149///
2150/// Each function has a 4-byte ABI selector and a sequence of basic blocks.
2151#[derive(Debug, Clone)]
2152pub struct EvmFunction {
2153    /// Human-readable name of the function.
2154    pub name: String,
2155    /// 4-byte function selector (first 4 bytes of keccak256(signature)).
2156    pub selector: [u8; 4],
2157    /// ABI signature string, e.g. `"transfer(address,uint256)"`.
2158    pub signature: String,
2159    /// Basic blocks forming the function body.
2160    pub blocks: Vec<EvmBasicBlock>,
2161    /// Whether this function is payable.
2162    pub is_payable: bool,
2163    /// Whether this function is a view (does not modify state).
2164    pub is_view: bool,
2165}
2166impl EvmFunction {
2167    /// Create a new function with the given name, selector, and signature.
2168    pub fn new(name: impl Into<String>, selector: [u8; 4], signature: impl Into<String>) -> Self {
2169        Self {
2170            name: name.into(),
2171            selector,
2172            signature: signature.into(),
2173            blocks: Vec::new(),
2174            is_payable: false,
2175            is_view: false,
2176        }
2177    }
2178    /// Add a basic block to this function.
2179    pub fn add_block(&mut self, block: EvmBasicBlock) {
2180        self.blocks.push(block);
2181    }
2182    /// Total byte count of all blocks in this function.
2183    pub fn byte_len(&self) -> usize {
2184        self.blocks.iter().map(|b| b.byte_len()).sum()
2185    }
2186    /// Encode this function's blocks to raw bytes.
2187    pub fn encode(&self) -> Vec<u8> {
2188        self.blocks.iter().flat_map(|b| b.encode()).collect()
2189    }
2190}
2191#[allow(dead_code)]
2192#[derive(Debug, Clone, Default)]
2193pub struct EVMPassStats {
2194    pub total_runs: u32,
2195    pub successful_runs: u32,
2196    pub total_changes: u64,
2197    pub time_ms: u64,
2198    pub iterations_used: u32,
2199}
2200impl EVMPassStats {
2201    #[allow(dead_code)]
2202    pub fn new() -> Self {
2203        Self::default()
2204    }
2205    #[allow(dead_code)]
2206    pub fn record_run(&mut self, changes: u64, time_ms: u64, iterations: u32) {
2207        self.total_runs += 1;
2208        self.successful_runs += 1;
2209        self.total_changes += changes;
2210        self.time_ms += time_ms;
2211        self.iterations_used = iterations;
2212    }
2213    #[allow(dead_code)]
2214    pub fn average_changes_per_run(&self) -> f64 {
2215        if self.total_runs == 0 {
2216            return 0.0;
2217        }
2218        self.total_changes as f64 / self.total_runs as f64
2219    }
2220    #[allow(dead_code)]
2221    pub fn success_rate(&self) -> f64 {
2222        if self.total_runs == 0 {
2223            return 0.0;
2224        }
2225        self.successful_runs as f64 / self.total_runs as f64
2226    }
2227    #[allow(dead_code)]
2228    pub fn format_summary(&self) -> String {
2229        format!(
2230            "Runs: {}/{}, Changes: {}, Time: {}ms",
2231            self.successful_runs, self.total_runs, self.total_changes, self.time_ms
2232        )
2233    }
2234}
2235/// EVM memory model
2236#[allow(dead_code)]
2237#[derive(Debug, Clone)]
2238pub struct EvmMemoryLayout {
2239    pub scratch_space: (u64, u64),
2240    pub free_mem_ptr: u64,
2241    pub zero_slot: u64,
2242    pub initial_free: u64,
2243}
2244/// EVM ABI type
2245#[allow(dead_code)]
2246#[derive(Debug, Clone, PartialEq)]
2247pub enum EvmAbiType {
2248    Uint(u16),
2249    Int(u16),
2250    Address,
2251    Bool,
2252    Bytes(u8),
2253    BytesDyn,
2254    StringDyn,
2255    Tuple(Vec<EvmAbiType>),
2256    Array(Box<EvmAbiType>, Option<u64>),
2257}
2258#[allow(dead_code)]
2259#[derive(Debug, Clone)]
2260pub struct EVMDominatorTree {
2261    pub idom: Vec<Option<u32>>,
2262    pub dom_children: Vec<Vec<u32>>,
2263    pub dom_depth: Vec<u32>,
2264}
2265impl EVMDominatorTree {
2266    #[allow(dead_code)]
2267    pub fn new(size: usize) -> Self {
2268        EVMDominatorTree {
2269            idom: vec![None; size],
2270            dom_children: vec![Vec::new(); size],
2271            dom_depth: vec![0; size],
2272        }
2273    }
2274    #[allow(dead_code)]
2275    pub fn set_idom(&mut self, node: usize, idom: u32) {
2276        self.idom[node] = Some(idom);
2277    }
2278    #[allow(dead_code)]
2279    pub fn dominates(&self, a: usize, b: usize) -> bool {
2280        if a == b {
2281            return true;
2282        }
2283        let mut cur = b;
2284        loop {
2285            match self.idom[cur] {
2286                Some(parent) if parent as usize == a => return true,
2287                Some(parent) if parent as usize == cur => return false,
2288                Some(parent) => cur = parent as usize,
2289                None => return false,
2290            }
2291        }
2292    }
2293    #[allow(dead_code)]
2294    pub fn depth(&self, node: usize) -> u32 {
2295        self.dom_depth.get(node).copied().unwrap_or(0)
2296    }
2297}