Skip to main content

luaur_vm/functions/
lua_g_breakpoint.rs

1use crate::functions::lua_g_getline::luaG_getline;
2use crate::macros::lua_m_newarray::luaM_newarray;
3use crate::records::global_state::global_State;
4use crate::records::proto::Proto;
5use crate::type_aliases::lua_state::lua_State;
6use luaur_common::enums::luau_opcode::LuauOpcode;
7use luaur_common::macros::luau_assert::LUAU_ASSERT;
8use luaur_common::macros::luau_insn_op::LUAU_INSN_OP;
9
10/// C++ `void luaG_breakpoint(lua_State* L, Proto* p, int line, bool enable)`.
11#[allow(non_snake_case)]
12pub unsafe fn lua_g_breakpoint(
13    L: *mut lua_State,
14    p: *mut Proto,
15    line: core::ffi::c_int,
16    enable: bool,
17) {
18    let ondisable = (*(*L).global).ecb.disable;
19
20    if !(*p).lineinfo.is_null() && (ondisable.is_some() || (*p).execdata.is_null()) {
21        for i in 0..(*p).sizecode {
22            if LUAU_INSN_OP(*(*p).code.add(i as usize)) == LuauOpcode::LOP_PREPVARARGS as u32 {
23                continue;
24            }
25
26            if luaG_getline(p, i as core::ffi::c_int) != line {
27                continue;
28            }
29
30            if (*p).debuginsn.is_null() {
31                (*p).debuginsn =
32                    luaM_newarray!(L, (*p).sizecode, core::ffi::c_uchar, (*p).hdr.memcat);
33                for j in 0..(*p).sizecode {
34                    *((*p).debuginsn.add(j as usize)) =
35                        LUAU_INSN_OP(*(*p).code.add(j as usize)) as core::ffi::c_uchar;
36                }
37            }
38
39            let op = if enable {
40                LuauOpcode::LOP_BREAK as u32
41            } else {
42                *((*p).debuginsn.add(i as usize)) as u32
43            };
44
45            (*(*p).code.add(i as usize)) &=
46                !(0xff as crate::type_aliases::instruction::Instruction);
47            (*(*p).code.add(i as usize)) |= op as crate::type_aliases::instruction::Instruction;
48            LUAU_ASSERT!(LUAU_INSN_OP(*(*p).code.add(i as usize)) == op);
49
50            if enable && !(*p).execdata.is_null() && ondisable.is_some() {
51                ondisable.unwrap()(L, p);
52            }
53
54            break;
55        }
56    }
57
58    for i in 0..(*p).sizep {
59        lua_g_breakpoint(L, *((*p).p.add(i as usize)), line, enable);
60    }
61}