Skip to content

Commit 52e80c8

Browse files
expr_pass: add bpf_passthrough attributes to make tests pass
1 parent d9cd072 commit 52e80c8

4 files changed

Lines changed: 30 additions & 8 deletions

File tree

‎pythonbpf/context.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ def __init__(self, module: ir.Module):
7272
# Helper management
7373
self.scratch_pool = ScratchPoolManager()
7474

75+
# Sequence numbers for llvm.bpf.passthrough barriers; each call needs a
76+
# distinct one so the optimizer cannot CSE two barriers together.
77+
self.passthrough_seq = 0
78+
7579
# Vmlinux handling (optional, specialized)
7680
self.vmlinux_handler = None # Can be VmlinuxHandler instance
7781

‎pythonbpf/expr/expr_pass.py‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,28 @@ def _handle_unary_op(
407407
# ============================================================================
408408

409409

410+
def _bpf_passthrough(builder, compilation_context, val):
411+
"""Wrap an i1 in llvm.bpf.passthrough, an optimization barrier the BPF
412+
backend strips before instruction selection.
413+
414+
Without it, opt's SimplifyCFG speculates a short-circuit operand's compare
415+
into the preceding block, and SelectionDAG then folds the two null checks
416+
of `p1 or p2` into `(p1 | p2) != 0`. The verifier rejects that with
417+
"pointer |= pointer prohibited". BPFAdjustOpt uses the same intrinsic to
418+
keep compares serialized for the verifier.
419+
"""
420+
module = compilation_context.module
421+
name = "llvm.bpf.passthrough.i1.i1"
422+
fn = module.globals.get(name)
423+
if fn is None:
424+
fn_type = ir.FunctionType(ir.IntType(1), [ir.IntType(32), ir.IntType(1)])
425+
fn = ir.Function(module, fn_type, name=name)
426+
427+
seq = ir.Constant(ir.IntType(32), compilation_context.passthrough_seq)
428+
compilation_context.passthrough_seq += 1
429+
return builder.call(fn, [seq, val])
430+
431+
410432
def _handle_and_op(func, builder, expr, local_sym_tab, compilation_context):
411433
"""Handle `and` boolean operations."""
412434

@@ -432,6 +454,8 @@ def _handle_and_op(func, builder, expr, local_sym_tab, compilation_context):
432454

433455
# Convert to boolean if needed
434456
operand_bool = convert_to_bool(builder, operand_val)
457+
if i > 0:
458+
operand_bool = _bpf_passthrough(builder, compilation_context, operand_bool)
435459
current_block = builder.block
436460

437461
if is_last:
@@ -485,6 +509,8 @@ def _handle_or_op(func, builder, expr, local_sym_tab, compilation_context):
485509

486510
# Convert to boolean if needed
487511
operand_bool = convert_to_bool(builder, operand_val)
512+
if i > 0:
513+
operand_bool = _bpf_passthrough(builder, compilation_context, operand_bool)
488514
current_block = builder.block
489515

490516
if is_last:

‎tests/test_config.toml‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,6 @@
1515

1616
"failing_tests/conditionals/struct_ptr.py" = {reason = "Struct pointer used directly as boolean condition not supported", level = "ir"}
1717

18-
# Compiles cleanly; rejected by the kernel. The `data + 34 < data_end` guard is
19-
# emitted as a signed compare over values round-tripped through the stack, so the
20-
# verifier never narrows the packet range (it stays r=0) and the later
21-
# `iph.saddr` read fails with "invalid access to packet, off=26 size=4" /
22-
# "R1 offset is outside of the packet". Direct packet access needs bounds checks
23-
# in a form the verifier can follow.
24-
"failing_tests/xdp/xdp_test_1.py" = {reason = "XDP direct packet access: the data/data_end guard does not establish a packet range the verifier can use", level = "verifier"}
25-
2618
"failing_tests/license.py" = {reason = "Missing LICENSE global produces IR that llc rejects — should be caught earlier with a clear error message", level = "llc"}
2719

2820
"failing_tests/undeclared_values.py" = {reason = "Undeclared variable used in f-string — should raise SyntaxError (correct behaviour, test documents it)", level = "ir"}

0 commit comments

Comments
 (0)