luaur-code-gen 0.1.1

Native (A64/X64) code generation for Luau (Rust).
Documentation
use crate::functions::dom_children::dom_children;
use crate::records::block_ordering::BlockOrdering;
use crate::records::ir_function::IrFunction;

pub fn compute_cfg_dominance_tree_children(function: &mut IrFunction) {
    let block_count = function.blocks.len();

    function.cfg.dom_children.clear();
    function.cfg.dom_children_offsets.clear();
    function.cfg.dom_children_offsets.resize(block_count, 0);

    for block_idx in 0..block_count {
        let dom_parent = function.cfg.idoms[block_idx];

        if dom_parent != !0u32 {
            function.cfg.dom_children_offsets[dom_parent as usize] += 1;
        }
    }

    let mut total = 0u32;
    for block_idx in 0..block_count {
        let count = function.cfg.dom_children_offsets[block_idx];
        function.cfg.dom_children_offsets[block_idx] = total;
        total += count;
    }

    function.cfg.dom_children.resize(total as usize, 0);

    for block_idx in 0..block_count {
        let dom_parent = function.cfg.idoms[block_idx];

        if dom_parent != !0u32 {
            let offset = function.cfg.dom_children_offsets[dom_parent as usize] as usize;
            function.cfg.dom_children[offset] = block_idx as u32;
            function.cfg.dom_children_offsets[dom_parent as usize] += 1;
        }
    }

    for block_idx in (1..block_count).rev() {
        function.cfg.dom_children_offsets[block_idx] =
            function.cfg.dom_children_offsets[block_idx - 1];
    }

    if block_count != 0 {
        function.cfg.dom_children_offsets[0] = 0;
    }

    compute_dom_child_ordering(function);
}

fn compute_dom_child_ordering(function: &mut IrFunction) {
    let block_count = function.blocks.len();

    function.cfg.dom_ordering.clear();
    function
        .cfg
        .dom_ordering
        .resize(block_count, BlockOrdering::default());

    if block_count == 0 {
        return;
    }

    let mut stack: Vec<(u32, u32)> = Vec::new();
    let mut next_pre_order = 0u32;
    let mut next_post_order = 0u32;

    stack.push((0, 0));
    function.cfg.dom_ordering[0].visited = true;
    function.cfg.dom_ordering[0].preOrder = next_pre_order;
    next_pre_order += 1;

    while let Some((block_idx, mut it_pos)) = stack.pop() {
        let children = dom_children(&function.cfg, block_idx);

        if it_pos < children.size() as u32 {
            let child_idx = children.operator_index(it_pos as usize);
            it_pos += 1;
            stack.push((block_idx, it_pos));

            if !function.cfg.dom_ordering[child_idx as usize].visited {
                function.cfg.dom_ordering[child_idx as usize].visited = true;
                function.cfg.dom_ordering[child_idx as usize].depth = stack.len() as u32;
                function.cfg.dom_ordering[child_idx as usize].preOrder = next_pre_order;
                next_pre_order += 1;
                stack.push((child_idx, 0));
            }
        } else {
            function.cfg.dom_ordering[block_idx as usize].postOrder = next_post_order;
            next_post_order += 1;
        }
    }
}