luaur_compiler/methods/
compiler_compile_expr_select_vararg.rs1use crate::records::compile_error::CompileError;
2use crate::records::compiler::Compiler;
3use luaur_ast::records::ast_expr::AstExpr;
4use luaur_ast::records::ast_expr_call::AstExprCall;
5use luaur_ast::records::ast_expr_varargs::AstExprVarargs;
6use luaur_ast::records::ast_node::AstNode;
7use luaur_ast::rtti;
8use luaur_common::enums::luau_opcode::LuauOpcode;
9use luaur_common::macros::luau_assert::LUAU_ASSERT;
10
11impl Compiler {
12 pub fn compile_expr_select_vararg(
13 &mut self,
14 expr: *mut AstExprCall,
15 target: u8,
16 target_count: u8,
17 target_top: bool,
18 mult_ret: bool,
19 regs: u8,
20 ) {
21 LUAU_ASSERT!(target_count == 1);
22 let expr_ref = unsafe { &*expr };
23 LUAU_ASSERT!(!expr_ref.self_);
24 LUAU_ASSERT!(expr_ref.args.size == 2);
25 let arg = unsafe { *expr_ref.args.data.add(0) };
26 let arg_varargs = unsafe { *expr_ref.args.data.add(1) };
27 LUAU_ASSERT!(
28 !unsafe { rtti::ast_node_as::<AstExprVarargs>(arg_varargs as *mut AstNode) }.is_null()
29 );
30
31 let argreg: u8;
32 let reg = self.get_expr_local_reg(arg);
33 if reg >= 0 {
34 argreg = reg as u8;
35 } else {
36 argreg = regs + 1;
37 self.compile_expr_temp_top(arg, argreg);
38 }
39
40 let fastcall_label = unsafe { (*self.bytecode).emit_label() };
41
42 unsafe {
43 (*self.bytecode).emit_abc(
44 LuauOpcode::LOP_FASTCALL1,
45 luaur_common::enums::luau_builtin_function::LuauBuiltinFunction::LBF_SELECT_VARARG
46 as u8,
47 argreg,
48 0,
49 );
50 }
51
52 self.compile_expr_temp(expr_ref.func, regs);
53
54 if argreg != regs + 1 {
55 unsafe {
56 (*self.bytecode).emit_abc(LuauOpcode::LOP_MOVE, regs + 1, argreg, 0);
57 }
58 }
59
60 unsafe {
61 (*self.bytecode).emit_abc(LuauOpcode::LOP_GETVARARGS, regs + 2, 0, 0);
62 }
63
64 let call_label = unsafe { (*self.bytecode).emit_label() };
65 if !unsafe { (*self.bytecode).patch_skip_c(fastcall_label, call_label) } {
66 CompileError::raise(
67 unsafe { &(*expr_ref.func).base.location },
68 core::format_args!("Exceeded jump distance limit; simplify the code to compile"),
69 );
70 }
71
72 unsafe {
73 (*self.bytecode).emit_abc(
74 LuauOpcode::LOP_CALL,
75 regs,
76 0,
77 if mult_ret { 0 } else { target_count + 1 },
78 );
79 }
80
81 if !target_top {
82 for i in 0..target_count {
83 unsafe {
84 (*self.bytecode).emit_abc(LuauOpcode::LOP_MOVE, target + i, regs + i, 0);
85 }
86 }
87 }
88 }
89}