Skip to content

Commit 5ab6281

Browse files
Core: Lower if-branches in the function's return type
handle_if processed its branches without passing ret_type down, so a return inside an if fell back to process_stmt's i64 default: a -> c_int32 function got `ret i64 7`, which llc rejects. The branches now go through process_block, which threads ret_type and stops at a statement that ends the block instead of emitting after its terminator.
1 parent cd3cb1b commit 5ab6281

2 files changed

Lines changed: 43 additions & 13 deletions

File tree

‎pythonbpf/functions/functions_pass.py‎

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ def handle_cond(func, compilation_context, builder, cond, local_sym_tab):
318318
return convert_to_bool(builder, val)
319319

320320

321-
def handle_if(func, compilation_context, builder, stmt, local_sym_tab):
321+
def handle_if(func, compilation_context, builder, stmt, local_sym_tab, ret_type):
322322
"""Handle if statements in the function body."""
323323
logger.info("Handling if statement")
324324
# start = builder.block.parent
@@ -336,22 +336,17 @@ def handle_if(func, compilation_context, builder, stmt, local_sym_tab):
336336
builder.cbranch(cond, then_block, merge_block)
337337

338338
builder.position_at_end(then_block)
339-
for s in stmt.body:
340-
process_stmt(func, compilation_context, builder, s, local_sym_tab, False)
339+
process_block(
340+
func, compilation_context, builder, stmt.body, local_sym_tab, ret_type
341+
)
341342
if not builder.block.is_terminated:
342343
builder.branch(merge_block)
343344

344345
if else_block:
345346
builder.position_at_end(else_block)
346-
for s in stmt.orelse:
347-
process_stmt(
348-
func,
349-
compilation_context,
350-
builder,
351-
s,
352-
local_sym_tab,
353-
False,
354-
)
347+
process_block(
348+
func, compilation_context, builder, stmt.orelse, local_sym_tab, ret_type
349+
)
355350
if not builder.block.is_terminated:
356351
builder.branch(merge_block)
357352

@@ -413,7 +408,7 @@ def process_stmt(
413408
elif isinstance(stmt, ast.Global):
414409
logger.debug(f"global declaration of {', '.join(stmt.names)} already bound")
415410
elif isinstance(stmt, ast.If):
416-
handle_if(func, compilation_context, builder, stmt, local_sym_tab)
411+
handle_if(func, compilation_context, builder, stmt, local_sym_tab, ret_type)
417412
elif isinstance(stmt, ast.Return):
418413
did_return = handle_return(
419414
func, builder, stmt, local_sym_tab, ret_type, compilation_context
@@ -428,6 +423,19 @@ def process_stmt(
428423
return did_return
429424

430425

426+
def process_block(func, compilation_context, builder, stmts, local_sym_tab, ret_type):
427+
"""Process a nested statement list, such as an if-branch, in the
428+
enclosing function's return type. Stops at the first statement that ends
429+
the block (a return), because whatever follows it in the same list can
430+
never run, and would otherwise be emitted after a terminator."""
431+
for s in stmts:
432+
if builder.block.is_terminated:
433+
break
434+
process_stmt(
435+
func, compilation_context, builder, s, local_sym_tab, False, ret_type
436+
)
437+
438+
431439
# ============================================================================
432440
# SECTION 3: Function Body Processing
433441
# ============================================================================
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# A return inside an if-branch is lowered in the function's declared return
2+
# type (i32 here), not a default i64 that llc rejects.
3+
from pythonbpf import bpf, section, bpfglobal, compile
4+
from ctypes import c_void_p, c_int32
5+
6+
7+
@bpf
8+
@section("tracepoint/syscalls/sys_enter_execve")
9+
def hello(ctx: c_void_p) -> c_int32:
10+
x = 1
11+
if x == 1:
12+
return 7
13+
return 0
14+
15+
16+
@bpf
17+
@bpfglobal
18+
def LICENSE() -> str:
19+
return "GPL"
20+
21+
22+
compile()

0 commit comments

Comments
 (0)