Skip to main content

luaur_code_gen/methods/
ir_lowering_x_64_buffer_addr_op.rs

1use crate::enums::ir_op_kind::IrOpKind;
2use crate::enums::size_x_64::SizeX64;
3use crate::macros::codegen_assert::CODEGEN_ASSERT;
4use crate::records::ir_lowering_x_64::IrLoweringX64;
5use crate::records::ir_op::IrOp;
6use crate::records::operand_x_64::OperandX64;
7use crate::records::register_x_64::RegisterX64;
8use luaur_vm::enums::lua_type::lua_Type;
9use luaur_vm::records::luau_buffer::LuauBuffer;
10use luaur_vm::records::udata::Udata;
11
12impl IrLoweringX64 {
13    pub fn buffer_addr_op(&mut self, buffer_op: IrOp, index_op: IrOp, tag: u8) -> OperandX64 {
14        CODEGEN_ASSERT!(tag == lua_Type::LUA_TUSERDATA as u8 || tag == lua_Type::LUA_TBUFFER as u8);
15        let data_offset = if tag == lua_Type::LUA_TBUFFER as u8 {
16            core::mem::size_of::<LuauBuffer>() - core::mem::size_of::<[core::ffi::c_char; 1]>()
17        } else {
18            core::mem::offset_of!(Udata, data)
19        };
20
21        if index_op.kind() == IrOpKind::Inst {
22            let inst_op = unsafe { (*self.function).inst_op(index_op) };
23            CODEGEN_ASSERT!(!crate::functions::produces_dirty_high_register_bits::produces_dirty_high_register_bits(inst_op.cmd));
24
25            let buffer_reg = self.reg_op(buffer_op);
26            let index_reg = self.reg_op(index_op);
27            let scaled_index = crate::functions::qword_reg::qword_reg(index_reg);
28            return OperandX64::operand_x_64_size_x_64_register_x_64_u8_register_x_64_i32(
29                SizeX64::qword,
30                scaled_index,
31                1,
32                buffer_reg,
33                data_offset as i32,
34            );
35        } else if index_op.kind() == IrOpKind::Constant {
36            let buffer_reg = self.reg_op(buffer_op);
37            let index_val = self.int_op(index_op);
38            return OperandX64::operand_x_64_size_x_64_register_x_64_u8_register_x_64_i32(
39                SizeX64::qword,
40                RegisterX64::noreg,
41                1,
42                buffer_reg,
43                index_val + data_offset as i32,
44            );
45        }
46
47        CODEGEN_ASSERT!(false, "Unsupported instruction form");
48        OperandX64::operand_x_64_register_x_64(RegisterX64::noreg)
49    }
50}