Skip to content

Commit a949a90

Browse files
authored
Merge pull request #102 from pythonbpf/fix/enum-constant-local
Fix enum constant assignments to locals
2 parents dd744df + 51d8628 commit a949a90

4 files changed

Lines changed: 37 additions & 5 deletions

File tree

‎pythonbpf/allocation_pass.py‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,12 +324,19 @@ def _allocate_for_name(builder, var_name, rval, local_sym_tab, compilation_conte
324324
"""Allocate memory for variable-to-variable assignment (b = a)."""
325325
source_var = rval.id
326326

327-
# Local first, then a BPF global: the copy takes the source's type either
328-
# way (a c_uint32 global gives a c_uint32 local).
327+
# Same resolution order as every other read of a bare name: local, then
328+
# BPF global, then vmlinux enum constant. A variable source gives the copy
329+
# its type; an enum constant is an immediate with no storage, so the copy
330+
# gets the i64 slot a literal gets.
329331
if source_var in local_sym_tab:
330332
source_symbol = local_sym_tab[source_var]
331333
elif source_var in compilation_context.bpf_globals:
332334
source_symbol = compilation_context.bpf_globals[source_var]
335+
elif VmlinuxHandlerRegistry.handle_name(source_var) is not None:
336+
var = _allocate_with_type(builder, var_name, ir.IntType(64))
337+
local_sym_tab[var_name] = LocalSymbol(var, ir.IntType(64))
338+
logger.info(f"Pre-allocated {var_name} from enum constant {source_var}")
339+
return
333340
else:
334341
logger.error(f"Source variable '{source_var}' not found in symbol table")
335342
return

tests/failing_tests/vmlinux/assignment_handling.py renamed to tests/passing_tests/vmlinux/assignment_handling.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
@bpf
88
@section("kprobe/blk_mq_start_request")
99
def example(ctx: c_void_p) -> c_int64:
10-
d = XDP_PASS # This gives an error, but
11-
e = XDP_PASS + 0 # this does not
10+
d = XDP_PASS # bare enum constant: used to be rejected at allocation
11+
e = XDP_PASS + 0 # through a binop: always worked; the two must agree
1212
print(f"test1 {e} test2 {d}")
1313
return c_int64(0)
1414

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# A local initialised from a vmlinux enum constant, the C shape
2+
# `int act = XDP_PASS;`. Reads of a bare name resolve local, then BPF global,
3+
# then vmlinux enum everywhere else; the allocation pass used to stop one step
4+
# short for this shape and reject it, while `act = XDP_PASS + 0` compiled.
5+
from ctypes import c_int64
6+
from pythonbpf import bpf, section, bpfglobal, compile
7+
from vmlinux import struct_xdp_md
8+
from vmlinux import XDP_PASS, XDP_DROP
9+
10+
11+
@bpf
12+
@section("xdp")
13+
def prog(ctx: struct_xdp_md) -> c_int64:
14+
act = XDP_PASS
15+
if ctx.data_end - ctx.data > 1500:
16+
act = XDP_DROP
17+
return c_int64(act)
18+
19+
20+
@bpf
21+
@bpfglobal
22+
def LICENSE() -> str:
23+
return "GPL"
24+
25+
26+
compile()

‎tests/test_config.toml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929

3030
"failing_tests/vmlinux/args_test.py" = {reason = "struct_trace_event_raw_sys_enter args field access not supported", level = "ir"}
3131

32-
"failing_tests/vmlinux/assignment_handling.py" = {reason = "Assigning vmlinux enum value (XDP_PASS) to a local variable not yet supported", level = "ir"}
3332

3433
"failing_tests/xdp_pass.py" = {reason = "XDP program using vmlinux structs (struct_xdp_md) and complex map/struct interaction not yet supported", level = "ir"}
3534

0 commit comments

Comments
 (0)