44import logging
55from typing import Dict
66
7- from .type_deducer import ctypes_to_ir , is_ctypes
7+ from pythonbpf .type_deducer import ctypes_to_ir , is_ctypes
8+ from .type_normalization import convert_to_bool , handle_comparator
89
910logger : Logger = logging .getLogger (__name__ )
1011
@@ -22,12 +23,10 @@ def _handle_name_expr(expr: ast.Name, local_sym_tab: Dict, builder: ir.IRBuilder
2223
2324def _handle_constant_expr (expr : ast .Constant ):
2425 """Handle ast.Constant expressions."""
25- if isinstance (expr .value , int ):
26- return ir .Constant (ir .IntType (64 ), expr .value ), ir .IntType (64 )
27- elif isinstance (expr .value , bool ):
28- return ir .Constant (ir .IntType (1 ), int (expr .value )), ir .IntType (1 )
26+ if isinstance (expr .value , int ) or isinstance (expr .value , bool ):
27+ return ir .Constant (ir .IntType (64 ), int (expr .value )), ir .IntType (64 )
2928 else :
30- logger .info ("Unsupported constant type" )
29+ logger .error ("Unsupported constant type" )
3130 return None
3231
3332
@@ -45,7 +44,6 @@ def _handle_attribute_expr(
4544 var_ptr , var_type , var_metadata = local_sym_tab [var_name ]
4645 logger .info (f"Loading attribute { attr_name } from variable { var_name } " )
4746 logger .info (f"Variable type: { var_type } , Variable ptr: { var_ptr } " )
48-
4947 metadata = structs_sym_tab [var_metadata ]
5048 if attr_name in metadata .fields :
5149 gep = metadata .gep (builder , var_ptr , attr_name )
@@ -132,6 +130,199 @@ def _handle_ctypes_call(
132130 return val
133131
134132
133+ def _handle_compare (
134+ func , module , builder , cond , local_sym_tab , map_sym_tab , structs_sym_tab = None
135+ ):
136+ """Handle ast.Compare expressions."""
137+
138+ if len (cond .ops ) != 1 or len (cond .comparators ) != 1 :
139+ logger .error ("Only single comparisons are supported" )
140+ return None
141+ lhs = eval_expr (
142+ func ,
143+ module ,
144+ builder ,
145+ cond .left ,
146+ local_sym_tab ,
147+ map_sym_tab ,
148+ structs_sym_tab ,
149+ )
150+ rhs = eval_expr (
151+ func ,
152+ module ,
153+ builder ,
154+ cond .comparators [0 ],
155+ local_sym_tab ,
156+ map_sym_tab ,
157+ structs_sym_tab ,
158+ )
159+
160+ if lhs is None or rhs is None :
161+ logger .error ("Failed to evaluate comparison operands" )
162+ return None
163+
164+ lhs , _ = lhs
165+ rhs , _ = rhs
166+ return handle_comparator (func , builder , cond .ops [0 ], lhs , rhs )
167+
168+
169+ def _handle_unary_op (
170+ func ,
171+ module ,
172+ builder ,
173+ expr : ast .UnaryOp ,
174+ local_sym_tab ,
175+ map_sym_tab ,
176+ structs_sym_tab = None ,
177+ ):
178+ """Handle ast.UnaryOp expressions."""
179+ if not isinstance (expr .op , ast .Not ):
180+ logger .error ("Only 'not' unary operator is supported" )
181+ return None
182+
183+ operand = eval_expr (
184+ func , module , builder , expr .operand , local_sym_tab , map_sym_tab , structs_sym_tab
185+ )
186+ if operand is None :
187+ logger .error ("Failed to evaluate operand for unary operation" )
188+ return None
189+
190+ operand_val , operand_type = operand
191+ true_const = ir .Constant (ir .IntType (1 ), 1 )
192+ result = builder .xor (convert_to_bool (builder , operand_val ), true_const )
193+ return result , ir .IntType (1 )
194+
195+
196+ def _handle_and_op (func , builder , expr , local_sym_tab , map_sym_tab , structs_sym_tab ):
197+ """Handle `and` boolean operations."""
198+
199+ logger .debug (f"Handling 'and' operator with { len (expr .values )} operands" )
200+
201+ merge_block = func .append_basic_block (name = "and.merge" )
202+ false_block = func .append_basic_block (name = "and.false" )
203+
204+ incoming_values = []
205+
206+ for i , value in enumerate (expr .values ):
207+ is_last = i == len (expr .values ) - 1
208+
209+ # Evaluate current operand
210+ operand_result = eval_expr (
211+ func , None , builder , value , local_sym_tab , map_sym_tab , structs_sym_tab
212+ )
213+ if operand_result is None :
214+ logger .error (f"Failed to evaluate operand { i } in 'and' expression" )
215+ return None
216+
217+ operand_val , operand_type = operand_result
218+
219+ # Convert to boolean if needed
220+ operand_bool = convert_to_bool (builder , operand_val )
221+ current_block = builder .block
222+
223+ if is_last :
224+ # Last operand: result is this value
225+ builder .branch (merge_block )
226+ incoming_values .append ((operand_bool , current_block ))
227+ else :
228+ # Not last: check if true, continue or short-circuit
229+ next_check = func .append_basic_block (name = f"and.check_{ i + 1 } " )
230+ builder .cbranch (operand_bool , next_check , false_block )
231+ builder .position_at_end (next_check )
232+
233+ # False block: short-circuit with false
234+ builder .position_at_end (false_block )
235+ builder .branch (merge_block )
236+ false_value = ir .Constant (ir .IntType (1 ), 0 )
237+ incoming_values .append ((false_value , false_block ))
238+
239+ # Merge block: phi node
240+ builder .position_at_end (merge_block )
241+ phi = builder .phi (ir .IntType (1 ), name = "and.result" )
242+ for val , block in incoming_values :
243+ phi .add_incoming (val , block )
244+
245+ logger .debug (f"Generated 'and' with { len (incoming_values )} incoming values" )
246+ return phi , ir .IntType (1 )
247+
248+
249+ def _handle_or_op (func , builder , expr , local_sym_tab , map_sym_tab , structs_sym_tab ):
250+ """Handle `or` boolean operations."""
251+
252+ logger .debug (f"Handling 'or' operator with { len (expr .values )} operands" )
253+
254+ merge_block = func .append_basic_block (name = "or.merge" )
255+ true_block = func .append_basic_block (name = "or.true" )
256+
257+ incoming_values = []
258+
259+ for i , value in enumerate (expr .values ):
260+ is_last = i == len (expr .values ) - 1
261+
262+ # Evaluate current operand
263+ operand_result = eval_expr (
264+ func , None , builder , value , local_sym_tab , map_sym_tab , structs_sym_tab
265+ )
266+ if operand_result is None :
267+ logger .error (f"Failed to evaluate operand { i } in 'or' expression" )
268+ return None
269+
270+ operand_val , operand_type = operand_result
271+
272+ # Convert to boolean if needed
273+ operand_bool = convert_to_bool (builder , operand_val )
274+ current_block = builder .block
275+
276+ if is_last :
277+ # Last operand: result is this value
278+ builder .branch (merge_block )
279+ incoming_values .append ((operand_bool , current_block ))
280+ else :
281+ # Not last: check if false, continue or short-circuit
282+ next_check = func .append_basic_block (name = f"or.check_{ i + 1 } " )
283+ builder .cbranch (operand_bool , true_block , next_check )
284+ builder .position_at_end (next_check )
285+
286+ # True block: short-circuit with true
287+ builder .position_at_end (true_block )
288+ builder .branch (merge_block )
289+ true_value = ir .Constant (ir .IntType (1 ), 1 )
290+ incoming_values .append ((true_value , true_block ))
291+
292+ # Merge block: phi node
293+ builder .position_at_end (merge_block )
294+ phi = builder .phi (ir .IntType (1 ), name = "or.result" )
295+ for val , block in incoming_values :
296+ phi .add_incoming (val , block )
297+
298+ logger .debug (f"Generated 'or' with { len (incoming_values )} incoming values" )
299+ return phi , ir .IntType (1 )
300+
301+
302+ def _handle_boolean_op (
303+ func ,
304+ module ,
305+ builder ,
306+ expr : ast .BoolOp ,
307+ local_sym_tab ,
308+ map_sym_tab ,
309+ structs_sym_tab = None ,
310+ ):
311+ """Handle `and` and `or` boolean operations."""
312+
313+ if isinstance (expr .op , ast .And ):
314+ return _handle_and_op (
315+ func , builder , expr , local_sym_tab , map_sym_tab , structs_sym_tab
316+ )
317+ elif isinstance (expr .op , ast .Or ):
318+ return _handle_or_op (
319+ func , builder , expr , local_sym_tab , map_sym_tab , structs_sym_tab
320+ )
321+ else :
322+ logger .error (f"Unsupported boolean operator: { type (expr .op ).__name__ } " )
323+ return None
324+
325+
135326def eval_expr (
136327 func ,
137328 module ,
@@ -212,6 +403,18 @@ def eval_expr(
212403 from pythonbpf .binary_ops import handle_binary_op
213404
214405 return handle_binary_op (expr , builder , None , local_sym_tab )
406+ elif isinstance (expr , ast .Compare ):
407+ return _handle_compare (
408+ func , module , builder , expr , local_sym_tab , map_sym_tab , structs_sym_tab
409+ )
410+ elif isinstance (expr , ast .UnaryOp ):
411+ return _handle_unary_op (
412+ func , module , builder , expr , local_sym_tab , map_sym_tab , structs_sym_tab
413+ )
414+ elif isinstance (expr , ast .BoolOp ):
415+ return _handle_boolean_op (
416+ func , module , builder , expr , local_sym_tab , map_sym_tab , structs_sym_tab
417+ )
215418 logger .info ("Unsupported expression evaluation" )
216419 return None
217420
0 commit comments