|
| 1 | +--- |
| 2 | +name: ir-first-feature |
| 3 | +description: PythonBPF's development loop for implementing a new compiler feature — write a minimal C eBPF reference, compile it to LLVM IR and read that as the spec, stop for a human syntax decision, then implement against the reference. Use whenever adding or extending a PythonBPF language feature (new statement/expression support, map types, globals, helpers, program constructs). |
| 4 | +--- |
| 5 | + |
| 6 | +# The IR-first feature loop |
| 7 | + |
| 8 | +PythonBPF targets LLVM IR via llvmlite. For any new feature, clang's output for the |
| 9 | +equivalent C is the specification — not documentation, not intuition. Follow the loop |
| 10 | +in order; do not skip steps because the feature "looks simple". |
| 11 | + |
| 12 | +## 1. Write the C reference |
| 13 | + |
| 14 | +A minimal `.bpf.c` in `tests/c-form/` exercising **only** the target feature. Small |
| 15 | +enough that every line of the resulting IR is attributable to the feature. Prefer no |
| 16 | +includes (define `SEC` and the `__u*` typedefs by hand) so nothing else pollutes the IR. |
| 17 | +Cover each variant of the feature in one file (e.g. for globals: zero-init, initialized, |
| 18 | +const, const volatile). |
| 19 | + |
| 20 | +## 2. Compile and read the IR — this is the spec |
| 21 | + |
| 22 | +```bash |
| 23 | +clang -target bpf -O2 -g -emit-llvm -S feature.bpf.c -o feature.ll |
| 24 | +llc -march=bpf -filetype=obj feature.ll -o feature.o |
| 25 | +bpftool btf dump file feature.o # what must come out the far end |
| 26 | +``` |
| 27 | + |
| 28 | +Read `feature.ll` and answer, in writing: What top-level symbols/globals appear? What |
| 29 | +do loads/stores/calls look like in the body? What `!DI*` debug metadata exists, and |
| 30 | +what BTF does llc manufacture from it? What did -O2 fold away, and does that folding |
| 31 | +carry semantics (it did for `const` globals)? |
| 32 | + |
| 33 | +Version discipline: llvmlite ≥0.49 emits LLVM 21/22-era attribute spellings |
| 34 | +(`captures(none)`, not `nocapture`). Use a clang/llc generation that accepts them, and |
| 35 | +compare against what `pythonbpf` + the CI's LLVM actually use. |
| 36 | + |
| 37 | +## 3. Diff against current PythonBPF output |
| 38 | + |
| 39 | +Compile the nearest thing PythonBPF can already express and diff the `.ll`s. The delta |
| 40 | +is the actual work item — often smaller than expected (machinery like section placement |
| 41 | +and BTF generation frequently comes free from llc). |
| 42 | + |
| 43 | +## 4. HARD STOP — syntax is a human decision |
| 44 | + |
| 45 | +Present 2–3 Pythonic syntax candidates with trade-offs (declaration site, usage site, |
| 46 | +failure modes, precedents from FastAPI/typing/Triton-style DSLs). **Wait for a human to |
| 47 | +choose. Never proceed on your own judgment, and never treat silence as consent.** The |
| 48 | +maintainers own the language surface. |
| 49 | + |
| 50 | +## 5. Implement against the reference |
| 51 | + |
| 52 | +Emit IR through the existing passes (`globals_pass`, `expr_pass`, `assign_pass`, |
| 53 | +`allocation_pass`, `debuginfo/`). Verify by **diffing your emitted `.ll` against the |
| 54 | +clang reference for the same shapes** — "it compiles and llc accepts it" is not the |
| 55 | +bar; llc accepts plenty of subtly wrong IR. |
| 56 | + |
| 57 | +## 6. Test at the right tier |
| 58 | + |
| 59 | +- Works now → `tests/passing_tests/<category>/`. |
| 60 | +- Documents a gap → `tests/kernel_selftest_equivalent/` with a strict xfail in |
| 61 | + `tests/test_config.toml` (level `"ir"`, `"llc"`, or `"verifier"`). |
| 62 | +- Wrong-input behaviour → `tests/failing_tests/` with a config entry. |
| 63 | +- Kernel verifier level runs in CI; locally it needs the user's sudo — ask, don't |
| 64 | + assume. |
| 65 | + |
| 66 | +## House guardrails (always) |
| 67 | + |
| 68 | +- **Never read/cat/grep `vmlinux.py` or `vmlinux.h`** — generated, enormous, will |
| 69 | + exhaust context. Probe with one-liners: |
| 70 | + `.venv/bin/python -c "import vmlinux; print(vmlinux.struct_x._fields_[:3])"` |
| 71 | +- Use `.venv/bin/python`; the system python has no llvmlite. |
| 72 | +- Atomic commits, `Core:`/`Tests:` subject prefixes, one logical change each. |
0 commit comments