Skip to main content

luaur_code_gen/functions/
emit_fallback_emit_common_x_64.rs

1use crate::enums::size_x_64::SizeX64;
2use crate::functions::emit_update_base_emit_common_x_64::emit_update_base;
3use crate::records::assembly_builder_x_64::AssemblyBuilderX64;
4use crate::records::ir_call_wrapper_x_64::IrCallWrapperX64;
5use crate::records::ir_data::k_invalid_inst_idx;
6use crate::records::ir_op::IrOp;
7use crate::records::ir_reg_alloc_x_64::IrRegAllocX64;
8use crate::records::operand_x_64::OperandX64;
9use crate::records::register_x_64::RegisterX64;
10
11const fn r_state() -> RegisterX64 {
12    RegisterX64 {
13        bits: (15u8 << RegisterX64::INDEX_SHIFT) | SizeX64::qword as u8,
14    }
15}
16
17// C++ EmitCommonX64.h: `constexpr RegisterX64 rConstants = r12;`
18const fn r_constants() -> RegisterX64 {
19    RegisterX64 {
20        bits: (12u8 << RegisterX64::INDEX_SHIFT) | SizeX64::qword as u8,
21    }
22}
23
24// C++ EmitCommonX64.h: `constexpr RegisterX64 rNativeContext = r13;`
25const fn r_native_context() -> RegisterX64 {
26    RegisterX64 {
27        bits: (13u8 << RegisterX64::INDEX_SHIFT) | SizeX64::qword as u8,
28    }
29}
30
31const K_STACK_OFFSET_TO_LOCALS: i32 = 16 + 32;
32
33fn s_code() -> OperandX64 {
34    OperandX64::mem(
35        SizeX64::qword,
36        RegisterX64::noreg,
37        1,
38        RegisterX64::rsp,
39        K_STACK_OFFSET_TO_LOCALS + 8,
40    )
41}
42
43const SIZEOF_INSTRUCTION: i32 = 4;
44
45pub fn emit_fallback(
46    regs: &mut IrRegAllocX64,
47    build: &mut AssemblyBuilderX64,
48    offset: i32,
49    pcpos: i32,
50) {
51    // fallback(L, instruction, base, k)
52    let mut call_wrap = IrCallWrapperX64::ir_call_wrapper_x_64_ir_call_wrapper_x_64(
53        regs,
54        build,
55        k_invalid_inst_idx,
56    );
57
58    call_wrap.add_argument_size_x_64_operand_x_64_ir_op(
59        SizeX64::qword,
60        OperandX64::reg(r_state()),
61        IrOp::ir_op(),
62    );
63
64    let reg = call_wrap.suggest_next_argument_register(SizeX64::qword);
65    build.mov(OperandX64::reg(reg), s_code());
66    call_wrap.add_argument_size_x_64_operand_x_64_ir_op(
67        SizeX64::qword,
68        OperandX64::mem(
69            SizeX64::none,
70            RegisterX64::noreg,
71            1,
72            reg,
73            pcpos * SIZEOF_INSTRUCTION,
74        ),
75        IrOp::ir_op(),
76    );
77
78    // rBase = rbp in this crate.
79    call_wrap.add_argument_size_x_64_operand_x_64_ir_op(
80        SizeX64::qword,
81        OperandX64::reg(RegisterX64::rbp),
82        IrOp::ir_op(),
83    );
84    call_wrap.add_argument_size_x_64_operand_x_64_ir_op(
85        SizeX64::qword,
86        OperandX64::reg(r_constants()),
87        IrOp::ir_op(),
88    );
89
90    call_wrap.call(&OperandX64::mem(
91        SizeX64::qword,
92        RegisterX64::noreg,
93        1,
94        r_native_context(),
95        offset,
96    ));
97
98    emit_update_base(build);
99}