Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions pythonbpf/functions/functions_pass.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,11 +401,11 @@ def process_stmt(
builder, stmt, local_sym_tab, ret_type, compilation_context
)
else:
# Silently dropping a statement makes the program mean something other
# than what it says, so say so.
logger.warning(
f"Unsupported statement on line {getattr(stmt, 'lineno', '?')}, "
f"ignored: {type(stmt).__name__}"
# Dropping a statement makes the program mean something other than what
# it says (a loop compiles to nothing), so refuse rather than warn.
raise NotImplementedError(
f"Unsupported statement on line {getattr(stmt, 'lineno', '?')}: "
f"{type(stmt).__name__}"
)
return did_return

Expand Down
18 changes: 18 additions & 0 deletions tests/failing_tests/assign/annotated_assign.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from pythonbpf import bpf, section, bpfglobal, compile
from ctypes import c_void_p, c_int64


@bpf
@section("tracepoint/syscalls/sys_enter_execve")
def hello(ctx: c_void_p) -> c_int64:
total: c_int64 = 0
return total


@bpf
@bpfglobal
def LICENSE() -> str:
return "GPL"


compile()
22 changes: 22 additions & 0 deletions tests/failing_tests/loops/for_break.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from pythonbpf import bpf, section, bpfglobal, compile
from ctypes import c_void_p, c_int64


@bpf
@section("tracepoint/syscalls/sys_enter_execve")
def hello(ctx: c_void_p) -> c_int64:
total: c_int64 = 0
for i in range(10):
if i == 5:
break
total = total + 1
return total


@bpf
@bpfglobal
def LICENSE() -> str:
return "GPL"


compile()
22 changes: 22 additions & 0 deletions tests/failing_tests/loops/for_continue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from pythonbpf import bpf, section, bpfglobal, compile
from ctypes import c_void_p, c_int64


@bpf
@section("tracepoint/syscalls/sys_enter_execve")
def hello(ctx: c_void_p) -> c_int64:
total: c_int64 = 0
for i in range(10):
if i % 2 == 0:
continue
total = total + i
return total


@bpf
@bpfglobal
def LICENSE() -> str:
return "GPL"


compile()
29 changes: 29 additions & 0 deletions tests/failing_tests/loops/for_map_items.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from pythonbpf import bpf, map, bpfglobal, section, compile
from pythonbpf.maps import HashMap
from ctypes import c_void_p, c_int64, c_int32, c_uint64


@bpf
@map
def mymap() -> HashMap:
return HashMap(key=c_int32, value=c_uint64, max_entries=16)


# Imagined sugar over the kernel's bpf_for_each_map_elem() callback helper:
# iterating a map's entries directly from a `for` statement.
@bpf
@section("tracepoint/syscalls/sys_enter_execve")
def hello(ctx: c_void_p) -> c_int64:
total: c_int64 = 0
for k, v in mymap.items():
total = total + 1
return total


@bpf
@bpfglobal
def LICENSE() -> str:
return "GPL"


compile()
20 changes: 20 additions & 0 deletions tests/failing_tests/loops/for_range_start_stop_step.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from pythonbpf import bpf, section, bpfglobal, compile
from ctypes import c_void_p, c_int64


@bpf
@section("tracepoint/syscalls/sys_enter_execve")
def hello(ctx: c_void_p) -> c_int64:
total: c_int64 = 0
for i in range(0, 10, 2):
total = total + i
return total


@bpf
@bpfglobal
def LICENSE() -> str:
return "GPL"


compile()
20 changes: 20 additions & 0 deletions tests/failing_tests/loops/for_range_sum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from pythonbpf import bpf, section, bpfglobal, compile
from ctypes import c_void_p, c_int64


@bpf
@section("tracepoint/syscalls/sys_enter_execve")
def hello(ctx: c_void_p) -> c_int64:
total: c_int64 = 0
for i in range(10):
total = total + 1
return total


@bpf
@bpfglobal
def LICENSE() -> str:
return "GPL"


compile()
21 changes: 21 additions & 0 deletions tests/failing_tests/loops/nested_for.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from pythonbpf import bpf, section, bpfglobal, compile
from ctypes import c_void_p, c_int64


@bpf
@section("tracepoint/syscalls/sys_enter_execve")
def hello(ctx: c_void_p) -> c_int64:
total: c_int64 = 0
for i in range(3):
for j in range(3):
total = total + 1
return total


@bpf
@bpfglobal
def LICENSE() -> str:
return "GPL"


compile()
20 changes: 20 additions & 0 deletions tests/failing_tests/loops/while_basic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from pythonbpf import bpf, section, bpfglobal, compile
from ctypes import c_void_p, c_int64


@bpf
@section("tracepoint/syscalls/sys_enter_execve")
def hello(ctx: c_void_p) -> c_int64:
i: c_int64 = 0
while i < 10:
i = i + 1
return i


@bpf
@bpfglobal
def LICENSE() -> str:
return "GPL"


compile()
22 changes: 22 additions & 0 deletions tests/failing_tests/loops/while_true_break.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from pythonbpf import bpf, section, bpfglobal, compile
from ctypes import c_void_p, c_int64


@bpf
@section("tracepoint/syscalls/sys_enter_execve")
def hello(ctx: c_void_p) -> c_int64:
total: c_int64 = 0
while True:
total = total + 1
if total == 10:
break
return total


@bpf
@bpfglobal
def LICENSE() -> str:
return "GPL"


compile()
25 changes: 25 additions & 0 deletions tests/test_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,28 @@
"failing_tests/globals_augassign_shadowing.py" = {reason = "`x += 1` on a global name without `global` binds a local and reads it unbound: UnboundLocalError in Python, a compile error here", level = "ir"}

"failing_tests/globals_parameter_and_global.py" = {reason = "A parameter may not be declared global (Python: name is parameter and global)", level = "ir"}

"failing_tests/assign/annotated_assign.py" = {reason = "Annotated assignment (ast.AnnAssign, e.g. `x: c_int64 = 0`) is not handled by process_stmt", level = "ir"}

# Loop constructs: ast.For/ast.While are not handled by the statement dispatcher
# (pythonbpf/functions/functions_pass.py process_stmt only matches Expr, Assign,
# AugAssign, If, Return) and the pre-pass variable scan does not descend into
# loop bodies. A loop is silently skipped rather than erroring, so anything
# that reads a variable assigned in/around the loop afterward blows up later
# with "Undefined variable ..." at the `return` statement. These document the
# intended surface for when loops are implemented.
"failing_tests/loops/for_range_sum.py" = {reason = "for/while loops not implemented: ast.For is silently skipped by the statement dispatcher", level = "ir"}

"failing_tests/loops/for_range_start_stop_step.py" = {reason = "for/while loops not implemented: range() with start/stop/step is not supported", level = "ir"}

"failing_tests/loops/while_basic.py" = {reason = "for/while loops not implemented: ast.While is silently skipped by the statement dispatcher", level = "ir"}

"failing_tests/loops/while_true_break.py" = {reason = "for/while loops not implemented: while True with a break-based exit is not supported", level = "ir"}

"failing_tests/loops/nested_for.py" = {reason = "for/while loops not implemented: nested for loops are not supported", level = "ir"}

"failing_tests/loops/for_break.py" = {reason = "for/while loops not implemented: break is not supported", level = "ir"}

"failing_tests/loops/for_continue.py" = {reason = "for/while loops not implemented: continue is not supported", level = "ir"}

"failing_tests/loops/for_map_items.py" = {reason = "for/while loops not implemented: no sugar over bpf_for_each_map_elem()-style map iteration exists yet", level = "ir"}
Loading