@@ -78,6 +78,161 @@ impl<'ctx> EbpfContext<'ctx> {
7878 }
7979 Expr :: SpecialVar ( name) => self . handle_special_variable ( name) ,
8080 Expr :: BinaryOp { left, op, right } => {
81+ // Implement short-circuit for logical OR (||) and logical AND (&&)
82+ if matches ! ( op, BinaryOp :: LogicalOr ) {
83+ // Evaluate LHS to boolean (non-zero => true)
84+ let lhs_val = self . compile_expr ( left) ?;
85+ let lhs_int = match lhs_val {
86+ BasicValueEnum :: IntValue ( iv) => iv,
87+ _ => {
88+ return Err ( CodeGenError :: TypeError (
89+ "Logical OR requires integer operands" . to_string ( ) ,
90+ ) )
91+ }
92+ } ;
93+ let lhs_zero = lhs_int. get_type ( ) . const_zero ( ) ;
94+ let lhs_bool = self
95+ . builder
96+ . build_int_compare (
97+ inkwell:: IntPredicate :: NE ,
98+ lhs_int,
99+ lhs_zero,
100+ "lor_lhs_nz" ,
101+ )
102+ . map_err ( |e| CodeGenError :: Builder ( e. to_string ( ) ) ) ?;
103+
104+ // Prepare control flow blocks
105+ let curr_block = self . builder . get_insert_block ( ) . ok_or_else ( || {
106+ CodeGenError :: LLVMError ( "No current basic block" . to_string ( ) )
107+ } ) ?;
108+ let func = curr_block
109+ . get_parent ( )
110+ . ok_or_else ( || CodeGenError :: LLVMError ( "No parent function" . to_string ( ) ) ) ?;
111+ let rhs_block = self . context . append_basic_block ( func, "lor_rhs" ) ;
112+ let merge_block = self . context . append_basic_block ( func, "lor_merge" ) ;
113+
114+ // If lhs is true, jump directly to merge (short-circuit)
115+ self . builder
116+ . build_conditional_branch ( lhs_bool, merge_block, rhs_block)
117+ . map_err ( |e| CodeGenError :: LLVMError ( e. to_string ( ) ) ) ?;
118+
119+ // RHS path: compute boolean only if needed
120+ self . builder . position_at_end ( rhs_block) ;
121+ let rhs_val = self . compile_expr ( right) ?;
122+ let rhs_int = match rhs_val {
123+ BasicValueEnum :: IntValue ( iv) => iv,
124+ _ => {
125+ return Err ( CodeGenError :: TypeError (
126+ "Logical OR requires integer operands" . to_string ( ) ,
127+ ) )
128+ }
129+ } ;
130+ let rhs_zero = rhs_int. get_type ( ) . const_zero ( ) ;
131+ let rhs_bool = self
132+ . builder
133+ . build_int_compare (
134+ inkwell:: IntPredicate :: NE ,
135+ rhs_int,
136+ rhs_zero,
137+ "lor_rhs_nz" ,
138+ )
139+ . map_err ( |e| CodeGenError :: Builder ( e. to_string ( ) ) ) ?;
140+ // Capture the actual block where RHS computation ended
141+ let rhs_end_block = self . builder . get_insert_block ( ) . ok_or_else ( || {
142+ CodeGenError :: LLVMError ( "No current basic block after RHS" . to_string ( ) )
143+ } ) ?;
144+ self . builder
145+ . build_unconditional_branch ( merge_block)
146+ . map_err ( |e| CodeGenError :: LLVMError ( e. to_string ( ) ) ) ?;
147+
148+ // Merge: phi of i1: true from LHS-true, RHS bool from rhs_block
149+ self . builder . position_at_end ( merge_block) ;
150+ let i1 = self . context . bool_type ( ) ;
151+ let phi = self
152+ . builder
153+ . build_phi ( i1, "lor_phi" )
154+ . map_err ( |e| CodeGenError :: LLVMError ( e. to_string ( ) ) ) ?;
155+ let one = i1. const_int ( 1 , false ) ;
156+ phi. add_incoming ( & [ ( & one, curr_block) , ( & rhs_bool, rhs_end_block) ] ) ;
157+ return Ok ( phi. as_basic_value ( ) ) ;
158+ } else if matches ! ( op, BinaryOp :: LogicalAnd ) {
159+ // Evaluate LHS to boolean (non-zero => true)
160+ let lhs_val = self . compile_expr ( left) ?;
161+ let lhs_int = match lhs_val {
162+ BasicValueEnum :: IntValue ( iv) => iv,
163+ _ => {
164+ return Err ( CodeGenError :: TypeError (
165+ "Logical AND requires integer operands" . to_string ( ) ,
166+ ) )
167+ }
168+ } ;
169+ let lhs_zero = lhs_int. get_type ( ) . const_zero ( ) ;
170+ let lhs_bool = self
171+ . builder
172+ . build_int_compare (
173+ inkwell:: IntPredicate :: NE ,
174+ lhs_int,
175+ lhs_zero,
176+ "land_lhs_nz" ,
177+ )
178+ . map_err ( |e| CodeGenError :: Builder ( e. to_string ( ) ) ) ?;
179+
180+ // Prepare control flow: if lhs is true, evaluate rhs; else short-circuit to false
181+ let curr_block = self . builder . get_insert_block ( ) . ok_or_else ( || {
182+ CodeGenError :: LLVMError ( "No current basic block" . to_string ( ) )
183+ } ) ?;
184+ let func = curr_block
185+ . get_parent ( )
186+ . ok_or_else ( || CodeGenError :: LLVMError ( "No parent function" . to_string ( ) ) ) ?;
187+ let rhs_block = self . context . append_basic_block ( func, "land_rhs" ) ;
188+ let merge_block = self . context . append_basic_block ( func, "land_merge" ) ;
189+
190+ // If lhs is true, go compute rhs; else jump to merge with false
191+ self . builder
192+ . build_conditional_branch ( lhs_bool, rhs_block, merge_block)
193+ . map_err ( |e| CodeGenError :: LLVMError ( e. to_string ( ) ) ) ?;
194+
195+ // RHS path
196+ self . builder . position_at_end ( rhs_block) ;
197+ let rhs_val = self . compile_expr ( right) ?;
198+ let rhs_int = match rhs_val {
199+ BasicValueEnum :: IntValue ( iv) => iv,
200+ _ => {
201+ return Err ( CodeGenError :: TypeError (
202+ "Logical AND requires integer operands" . to_string ( ) ,
203+ ) )
204+ }
205+ } ;
206+ let rhs_zero = rhs_int. get_type ( ) . const_zero ( ) ;
207+ let rhs_bool = self
208+ . builder
209+ . build_int_compare (
210+ inkwell:: IntPredicate :: NE ,
211+ rhs_int,
212+ rhs_zero,
213+ "land_rhs_nz" ,
214+ )
215+ . map_err ( |e| CodeGenError :: Builder ( e. to_string ( ) ) ) ?;
216+ let rhs_end_block = self . builder . get_insert_block ( ) . ok_or_else ( || {
217+ CodeGenError :: LLVMError ( "No current basic block after RHS" . to_string ( ) )
218+ } ) ?;
219+ self . builder
220+ . build_unconditional_branch ( merge_block)
221+ . map_err ( |e| CodeGenError :: LLVMError ( e. to_string ( ) ) ) ?;
222+
223+ // Merge: phi(i1) with false from LHS=false path, RHS bool from rhs path
224+ self . builder . position_at_end ( merge_block) ;
225+ let i1 = self . context . bool_type ( ) ;
226+ let phi = self
227+ . builder
228+ . build_phi ( i1, "land_phi" )
229+ . map_err ( |e| CodeGenError :: LLVMError ( e. to_string ( ) ) ) ?;
230+ let zero = i1. const_zero ( ) ;
231+ phi. add_incoming ( & [ ( & rhs_bool, rhs_end_block) , ( & zero, curr_block) ] ) ;
232+ return Ok ( phi. as_basic_value ( ) ) ;
233+ }
234+
235+ // Default eager evaluation for other binary ops
81236 let left_val = self . compile_expr ( left) ?;
82237 let right_val = self . compile_expr ( right) ?;
83238 self . compile_binary_op ( left_val, op. clone ( ) , right_val)
0 commit comments