luaur-bytecode 0.1.3

Luau bytecode format and builder (Rust).
Documentation
use crate::enums::bc_block_flag::BcBlockFlag;
use crate::enums::bc_op_kind::BcOpKind;
use crate::records::bc_block::BcBlock;
use crate::records::bc_block_edge::BcBlockEdge;
use crate::records::call_inliner::CallInliner;
use crate::type_aliases::bc_edges::BcEdges;

impl<'a> CallInliner<'a> {
    pub fn validate_cfg(&self) -> bool {
        let validate_edges =
            |from: u32, edges: &BcEdges, mirror_dir: fn(&BcBlock) -> &BcEdges| -> bool {
                for edge in edges {
                    if edge.target.kind != BcOpKind::Block
                        || edge.target.index as usize >= self.caller.blocks.len()
                    {
                        return false;
                    }

                    let other = &self.caller.blocks[edge.target.index as usize];

                    if (other.flags & BcBlockFlag::Dead as u8) != 0 {
                        return false;
                    }

                    let mirror = mirror_dir(other);
                    if !mirror.iter().any(|e| {
                        e.kind == edge.kind
                            && e.target.kind == BcOpKind::Block
                            && e.target.index == from
                    }) {
                        return false;
                    }
                }
                true
            };

        for i in 0..self.caller.blocks.len() {
            let block = &self.caller.blocks[i];

            if (block.flags & BcBlockFlag::Dead as u8) != 0 {
                continue;
            }

            if !validate_edges(i as u32, &block.successors, |b| &b.predecessors) {
                return false;
            }

            if !validate_edges(i as u32, &block.predecessors, |b| &b.successors) {
                return false;
            }
        }

        true
    }
}