neo-decompiler 0.8.1

Neo N3 NEF decompiler: parse, disassemble, lift bytecode to high-level pseudocode and C# skeletons, with a CLI, JSON reports, and optional WebAssembly bindings.
Documentation
use crate::instruction::OpCode;

use super::CfgBuilder;

impl<'a> CfgBuilder<'a> {
    pub(super) fn find_leaders(&mut self) {
        if let Some(first) = self.instructions.first() {
            self.leaders.insert(first.offset);
        }

        for (i, instr) in self.instructions.iter().enumerate() {
            match instr.opcode {
                OpCode::Jmp | OpCode::Jmp_L | OpCode::Endtry | OpCode::EndtryL => {
                    if let Some(target) = self.jump_target(i, instr) {
                        self.leaders.insert(target);
                    }
                    if let Some(next) = self.instructions.get(i + 1) {
                        self.leaders.insert(next.offset);
                    }
                }

                OpCode::Jmpif
                | OpCode::Jmpif_L
                | OpCode::Jmpifnot
                | OpCode::Jmpifnot_L
                | OpCode::JmpEq
                | OpCode::JmpEq_L
                | OpCode::JmpNe
                | OpCode::JmpNe_L
                | OpCode::JmpGt
                | OpCode::JmpGt_L
                | OpCode::JmpGe
                | OpCode::JmpGe_L
                | OpCode::JmpLt
                | OpCode::JmpLt_L
                | OpCode::JmpLe
                | OpCode::JmpLe_L => {
                    if let Some(target) = self.jump_target(i, instr) {
                        self.leaders.insert(target);
                    }
                    if let Some(next) = self.instructions.get(i + 1) {
                        self.leaders.insert(next.offset);
                    }
                }

                OpCode::Try | OpCode::TryL => {
                    if let Some((catch_off, finally_off)) = self.try_targets(i, instr) {
                        if let Some(c) = catch_off {
                            self.leaders.insert(c);
                        }
                        if let Some(f) = finally_off {
                            self.leaders.insert(f);
                        }
                    }
                    if let Some(next) = self.instructions.get(i + 1) {
                        self.leaders.insert(next.offset);
                    }
                }

                OpCode::Ret
                | OpCode::Throw
                | OpCode::Abort
                | OpCode::Abortmsg
                | OpCode::Endfinally => {
                    if let Some(next) = self.instructions.get(i + 1) {
                        self.leaders.insert(next.offset);
                    }
                }

                OpCode::Call | OpCode::Call_L | OpCode::CallA | OpCode::Syscall => {}

                _ => {}
            }
        }
    }
}