luaur_code_gen/functions/
call_step_gc.rs1use crate::enums::condition_x_64::ConditionX64;
2use crate::enums::size_x_64::SizeX64;
3use crate::functions::emit_update_base_emit_common_x_64::emit_update_base;
4use crate::records::assembly_builder_x_64::AssemblyBuilderX64;
5use crate::records::ir_call_wrapper_x_64::IrCallWrapperX64;
6use crate::records::ir_data::k_invalid_inst_idx;
7use crate::records::ir_op::IrOp;
8use crate::records::ir_reg_alloc_x_64::IrRegAllocX64;
9use crate::records::label::Label;
10use crate::records::native_context::NativeContext;
11use crate::records::operand_x_64::OperandX64;
12use crate::records::register_x_64::RegisterX64;
13use crate::records::scoped_reg_x_64::ScopedRegX64;
14use crate::records::scoped_spills::ScopedSpills;
15use luaur_vm::records::global_state::global_State;
16use luaur_vm::records::lua_state::lua_State;
17
18pub fn call_step_gc(regs: &mut IrRegAllocX64, build: &mut AssemblyBuilderX64) {
19 let mut skip = Label::default();
20
21 {
22 let mut tmp1 = ScopedRegX64 {
23 owner: core::ptr::null_mut(),
24 reg: RegisterX64::noreg,
25 };
26 tmp1.scoped_reg_x_64_ir_reg_alloc_x_64_size_x_64(regs, SizeX64::qword);
27
28 let mut tmp2 = ScopedRegX64 {
29 owner: core::ptr::null_mut(),
30 reg: RegisterX64::noreg,
31 };
32 tmp2.scoped_reg_x_64_ir_reg_alloc_x_64_size_x_64(regs, SizeX64::qword);
33
34 build.mov(
35 OperandX64::reg(tmp1.reg),
36 mem(
37 SizeX64::qword,
38 r_state(),
39 core::mem::offset_of!(lua_State, global) as i32,
40 ),
41 );
42 build.mov(
43 OperandX64::reg(tmp2.reg),
44 mem(
45 SizeX64::qword,
46 tmp1.reg,
47 core::mem::offset_of!(global_State, totalbytes) as i32,
48 ),
49 );
50 build.cmp(
51 OperandX64::reg(tmp2.reg),
52 mem(
53 SizeX64::qword,
54 tmp1.reg,
55 core::mem::offset_of!(global_State, GCthreshold) as i32,
56 ),
57 );
58 build.jcc(ConditionX64::Below, &mut skip);
59 }
60
61 {
62 let _spill_guard = {
63 let mut guard = ScopedSpills {
64 owner: regs as *mut _,
65 start_spill_id: 0,
66 };
67 guard.scoped_spills_scoped_spills_ir_reg_alloc_x_64(regs);
68 guard
69 };
70
71 let mut call_wrap = IrCallWrapperX64::ir_call_wrapper_x_64_ir_call_wrapper_x_64(
72 regs,
73 build,
74 k_invalid_inst_idx,
75 );
76 call_wrap.add_argument_size_x_64_operand_x_64_ir_op(
77 SizeX64::qword,
78 OperandX64::reg(r_state()),
79 IrOp::ir_op(),
80 );
81 call_wrap.add_argument_size_x_64_operand_x_64_ir_op(
82 SizeX64::dword,
83 OperandX64::imm(1),
84 IrOp::ir_op(),
85 );
86 call_wrap.call(&mem(
87 SizeX64::qword,
88 r_native_context(),
89 core::mem::offset_of!(NativeContext, luaC_step) as i32,
90 ));
91 emit_update_base(build);
92 }
93
94 build.set_label_label(&mut skip);
95}
96
97const fn reg(index: u8, size: SizeX64) -> RegisterX64 {
98 RegisterX64 {
99 bits: (index << RegisterX64::INDEX_SHIFT) | size as u8,
100 }
101}
102
103const fn r_state() -> RegisterX64 {
104 reg(15, SizeX64::qword)
105}
106
107const fn r_native_context() -> RegisterX64 {
108 reg(13, SizeX64::qword)
109}
110
111fn mem(size: SizeX64, base: RegisterX64, disp: i32) -> OperandX64 {
112 OperandX64::mem(size, RegisterX64::noreg, 1, base, disp)
113}