Skip to main content

luaur_vm/functions/
getcoverage.rs

1use crate::functions::lua_g_getline::luaG_getline;
2use crate::macros::getstr::getstr;
3use crate::records::proto::Proto;
4use crate::type_aliases::instruction::Instruction;
5use crate::type_aliases::lua_coverage::lua_Coverage;
6use luaur_common::enums::luau_opcode::LuauOpcode;
7use luaur_common::macros::luau_assert::LUAU_ASSERT;
8use luaur_common::macros::luau_insn_e::LUAU_INSN_E;
9use luaur_common::macros::luau_insn_op::LUAU_INSN_OP;
10
11#[allow(non_snake_case)]
12pub(crate) unsafe fn getcoverage(
13    p: *mut Proto,
14    depth: core::ffi::c_int,
15    buffer: *mut core::ffi::c_int,
16    size: usize,
17    context: *mut core::ffi::c_void,
18    callback: lua_Coverage,
19) {
20    core::ptr::write_bytes(buffer, 0xFF, size);
21
22    let p_ref = &*p;
23    for i in 0..p_ref.sizecode {
24        let insn = *p_ref.code.add(i as usize);
25        if LUAU_INSN_OP(insn) != LuauOpcode::LOP_COVERAGE as u32 {
26            continue;
27        }
28
29        let line = luaG_getline(p, i);
30        let hits = LUAU_INSN_E(insn);
31
32        LUAU_ASSERT!((line as usize) < size);
33        let val = *buffer.add(line as usize);
34        if val < hits {
35            *buffer.add(line as usize) = hits;
36        }
37    }
38
39    let debugname = if !p_ref.debugname.is_null() {
40        getstr(p_ref.debugname)
41    } else {
42        core::ptr::null()
43    };
44    let linedefined = p_ref.linedefined;
45
46    if let Some(cb) = callback {
47        cb(context, debugname, linedefined, depth, buffer, size);
48    }
49
50    for i in 0..p_ref.sizep {
51        getcoverage(
52            *p_ref.p.add(i as usize),
53            depth + 1,
54            buffer,
55            size,
56            context,
57            callback,
58        );
59    }
60}