Skip to content

Commit 919d994

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 c340ebf commit 919d994

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

@@ -427,7 +422,7 @@ def process_stmt(
427422
elif isinstance(stmt, ast.Global):
428423
logger.debug(f"global declaration of {', '.join(stmt.names)} already bound")
429424
elif isinstance(stmt, ast.If):
430-
handle_if(func, compilation_context, builder, stmt, local_sym_tab)
425+
handle_if(func, compilation_context, builder, stmt, local_sym_tab, ret_type)
431426
elif isinstance(stmt, ast.Return):
432427
did_return = handle_return(
433428
func, builder, stmt, local_sym_tab, ret_type, compilation_context
@@ -442,6 +437,19 @@ def process_stmt(
442437
return did_return
443438

444439

440+
def process_block(func, compilation_context, builder, stmts, local_sym_tab, ret_type):
441+
"""Process a nested statement list, such as an if-branch, in the
442+
enclosing function's return type. Stops at the first statement that ends
443+
the block (a return), because whatever follows it in the same list can
444+
never run, and would otherwise be emitted after a terminator."""
445+
for s in stmts:
446+
if builder.block.is_terminated:
447+
break
448+
process_stmt(
449+
func, compilation_context, builder, s, local_sym_tab, False, ret_type
450+
)
451+
452+
445453
# ============================================================================
446454
# SECTION 3: Function Body Processing
447455
# ============================================================================
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)