luaur_code_gen/functions/
translate_builtin_table_insert.rs1use crate::enums::builtin_impl_type::BuiltinImplType;
2use crate::enums::ir_cmd::IrCmd;
3use crate::enums::ir_const_kind::IrConstKind;
4use crate::enums::ir_op_kind::IrOpKind;
5use crate::functions::vm_const_op::vm_const_op;
6use crate::macros::codegen_assert::CODEGEN_ASSERT;
7use crate::records::builtin_impl_result::BuiltinImplResult;
8use crate::records::ir_builder::IrBuilder;
9use crate::records::ir_op::IrOp;
10use luaur_vm::enums::lua_type::lua_Type;
11
12pub fn translate_builtin_table_insert(
13 build: &mut IrBuilder,
14 nparams: i32,
15 ra: i32,
16 arg: i32,
17 args: IrOp,
18 nresults: i32,
19 pcpos: i32,
20) -> BuiltinImplResult {
21 if nparams != 2 || nresults > 0 {
22 return BuiltinImplResult {
23 r#type: BuiltinImplType::None,
24 actual_result_count: -1,
25 };
26 }
27
28 let arg_reg = build.vm_reg(arg as u8);
29 let exit = build.vm_exit(pcpos as u32);
30 build.load_and_check_tag(arg_reg, lua_Type::LUA_TTABLE as u8, exit);
31
32 let arg_reg = build.vm_reg(arg as u8);
33 let table = build.inst_ir_cmd_ir_op(IrCmd::LOAD_POINTER, arg_reg);
34 let exit = build.vm_exit(pcpos as u32);
35 build.inst_ir_cmd_ir_op_ir_op(IrCmd::CHECK_READONLY, table, exit);
36
37 let len = build.inst_ir_cmd_ir_op(IrCmd::TABLE_LEN, table);
38 let one = build.const_int(1);
39 let pos = build.inst_ir_cmd_ir_op_ir_op(IrCmd::ADD_INT, len, one);
40 let setnum = build.inst_ir_cmd_ir_op_ir_op(IrCmd::TABLE_SETNUM, table, pos);
41
42 if args.kind() == IrOpKind::Constant {
43 CODEGEN_ASSERT!(build.function.const_op(args).kind == IrConstKind::Double);
44 build.inst_ir_cmd_ir_op_ir_op(IrCmd::STORE_DOUBLE, setnum, args);
45 let tag = build.const_tag(lua_Type::LUA_TNUMBER as u8);
46 build.inst_ir_cmd_ir_op_ir_op(IrCmd::STORE_TAG, setnum, tag);
47 } else {
48 let va = build.inst_ir_cmd_ir_op(IrCmd::LOAD_TVALUE, args);
49 build.inst_ir_cmd_ir_op_ir_op(IrCmd::STORE_TVALUE, setnum, va);
50
51 CODEGEN_ASSERT!(!build.function.proto.is_null());
52 let argstag = if args.kind() == IrOpKind::VmConst {
53 let tag = unsafe {
54 (*build.function.proto)
55 .k
56 .add(vm_const_op(args) as usize)
57 .read()
58 .tt
59 };
60 build.const_tag(tag as u8)
61 } else {
62 build.undef()
63 };
64 build.inst_ir_cmd_ir_op_ir_op_ir_op(IrCmd::BARRIER_TABLE_FORWARD, table, args, argstag);
65 }
66
67 BuiltinImplResult {
68 r#type: BuiltinImplType::Full,
69 actual_result_count: 0,
70 }
71}