luaur_compiler/methods/
compiler_compile_expr_binary.rs1use crate::enums::type_constant_folding::Type;
2use crate::records::compiler::Compiler;
3use crate::records::constant::Constant;
4use crate::records::reg_scope::RegScope;
5use luaur_ast::records::ast_expr_binary::{AstExprBinary, AstExprBinaryOp};
6use luaur_common::enums::luau_bytecode_type::LuauBytecodeType;
7use luaur_common::enums::luau_opcode::LuauOpcode;
8use luaur_common::macros::luau_assert::LUAU_ASSERT;
9
10impl Compiler {
11 pub fn compile_expr_binary(
12 &mut self,
13 expr: *mut AstExprBinary,
14 target: u8,
15 _target_temp: bool,
16 ) {
17 unsafe {
18 let expr_ref = &*expr;
19 let mut rs = self.reg_scope_compiler();
20
21 match expr_ref.op {
22 AstExprBinaryOp::Add
23 | AstExprBinaryOp::Sub
24 | AstExprBinaryOp::Mul
25 | AstExprBinaryOp::Div
26 | AstExprBinaryOp::FloorDiv
27 | AstExprBinaryOp::Mod
28 | AstExprBinaryOp::Pow => {
29 let rc = self.get_constant_number(expr_ref.right);
30 if rc >= 0 && rc <= 255 {
31 let rl = self.compile_expr_auto(expr_ref.left, &mut rs);
32 (*self.bytecode).emit_abc(
33 self.get_binary_op_arith(expr_ref.op, true),
34 target,
35 rl,
36 rc as u8,
37 );
38 self.hint_temporary_expr_reg_type(
39 expr_ref.left,
40 rl as i32,
41 LuauBytecodeType(2),
42 1,
43 );
44 } else {
45 if expr_ref.op == AstExprBinaryOp::Sub
46 || expr_ref.op == AstExprBinaryOp::Div
47 {
48 let lc = self.get_constant_number(expr_ref.left);
49 if lc >= 0 && lc <= 255 {
50 let rr = self.compile_expr_auto(expr_ref.right, &mut rs);
51 let op = if expr_ref.op == AstExprBinaryOp::Sub {
52 LuauOpcode::LOP_SUBRK
53 } else {
54 LuauOpcode::LOP_DIVRK
55 };
56 (*self.bytecode).emit_abc(op, target, lc as u8, rr);
57 self.hint_temporary_expr_reg_type(
58 expr_ref.right,
59 rr as i32,
60 LuauBytecodeType(2),
61 1,
62 );
63 return;
64 }
65 } else if self.options.optimization_level >= 2
66 && (expr_ref.op == AstExprBinaryOp::Add
67 || expr_ref.op == AstExprBinaryOp::Mul)
68 {
69 if let Some(ty) = self
73 .expr_types
74 .find(&(expr as *mut luaur_ast::records::ast_expr::AstExpr))
75 .copied()
76 {
77 if ty == LuauBytecodeType(2)
78 || (ty == LuauBytecodeType(8)
79 && expr_ref.op == AstExprBinaryOp::Mul)
80 {
81 let lc = self.get_constant_number(expr_ref.left);
82 if lc >= 0 && lc <= 255 {
83 let rr = self.compile_expr_auto(expr_ref.right, &mut rs);
84 (*self.bytecode).emit_abc(
85 self.get_binary_op_arith(expr_ref.op, true),
86 target,
87 rr,
88 lc as u8,
89 );
90 self.hint_temporary_expr_reg_type(
91 expr_ref.right,
92 rr as i32,
93 LuauBytecodeType(2),
94 1,
95 );
96 return;
97 }
98 }
99 }
100 }
101 let rl = self.compile_expr_auto(expr_ref.left, &mut rs);
102 let rr = self.compile_expr_auto(expr_ref.right, &mut rs);
103 (*self.bytecode).emit_abc(
104 self.get_binary_op_arith(expr_ref.op, false),
105 target,
106 rl,
107 rr,
108 );
109 self.hint_temporary_expr_reg_type(
110 expr_ref.left,
111 rl as i32,
112 LuauBytecodeType(2),
113 1,
114 );
115 self.hint_temporary_expr_reg_type(
116 expr_ref.right,
117 rr as i32,
118 LuauBytecodeType(2),
119 1,
120 );
121 }
122 }
123 AstExprBinaryOp::Concat => {
124 let mut args = vec![expr_ref.left, expr_ref.right];
125 self.unroll_concats(&mut args);
126 let regs = self.alloc_reg(expr as *mut _, args.len() as u32);
127 for (i, &arg) in args.iter().enumerate() {
128 self.compile_expr_temp(arg, regs + i as u8);
129 }
130 (*self.bytecode).emit_abc(
131 LuauOpcode::LOP_CONCAT,
132 target,
133 regs,
134 regs + args.len() as u8 - 1,
135 );
136 }
137 AstExprBinaryOp::CompareNe
138 | AstExprBinaryOp::CompareEq
139 | AstExprBinaryOp::CompareLt
140 | AstExprBinaryOp::CompareLe
141 | AstExprBinaryOp::CompareGt
142 | AstExprBinaryOp::CompareGe => {
143 let jump_label = self.compile_compare_jump(expr, false);
144 (*self.bytecode).emit_abc(LuauOpcode::LOP_LOADB, target, 0, 1);
145 let then_label = (*self.bytecode).emit_label();
146 (*self.bytecode).emit_abc(LuauOpcode::LOP_LOADB, target, 1, 0);
147 self.patch_jump(expr as *mut _, jump_label, then_label);
148 }
149 AstExprBinaryOp::And | AstExprBinaryOp::Or => {
150 self.compile_expr_and_or(expr, target, _target_temp);
151 }
152 _ => LUAU_ASSERT!(false),
153 }
154 }
155 }
156}