Commit 54da073
transform: add inline rewrite-mode forms (expr: and stmt:)
Adds two inline forms to `mode: rewrite` for patch specifications,
alongside the existing patch-function form. Both are compiled
through clang/clangCIR and spliced at the matched op's site
without going through a library patch module.
`expr:` — single C expression, value substitution
- Wrapper return type matches the matched op's first result.
- Captures bind by-reference (`T *__cap_NAME`, `$NAME` →
`(*__cap_NAME)`); writes to source-storage captures propagate
to caller storage.
- Strict parse-time rule: leading control-flow keyword, leading
`{`, or any top-level `;` is rejected with a "use stmt:" hint.
`stmt:` — C statement body, spliced as CFG
- Wrapper is always void-returning. Body is preprocessed so each
`return X;` / `return;` becomes a `__patchestry_return(...)`
marker call (typed by the enclosing function's return type and
marked `noreturn`).
- Inliner clones the wrapper's entry block before the matched op,
skipping top-level `cir.return` / `cir.br` so fall-through
becomes natural sequential flow into the matched op's tail.
- MVP scope: matched op must be 0-result, wrapper must be a
single function-level block, and surviving `__patchestry_*`
calls (i.e. user wrote `return X;`) are loud-rejected — the
marker → CFG rewrite is a follow-up phase.
`patch:` — unchanged, but `mode: replace` keyword retired in favor
of unified `mode: rewrite`. The parser rejects `mode: replace` with
a migration error pointing at `mode: rewrite` + `patch:` +
`arguments:`. `mode: rewrite` requires exactly one of `expr:` /
`stmt:` / `patch:`.
Capture write semantics (shared between expr: and stmt:)
- Source-storage captures (`cir.load %alloca` / `cir.load
%global`): wrapper receives `&%alloca`. Writes propagate.
- Non-storage captures (binop result, constant, unalloca'd block
arg): wrapper receives the address of a freshly materialised
`arg_ref` temp. Reads work. Writes are loud-rejected — the
validator walks transitive uses through `cir.get_member`,
`cir.ptr_stride`, and `cir.cast` chains rooted at the wrapper
block-arg, so by-value-struct field writes and array-element
writes are caught alongside direct `cir.store v, %arg`.
- The chain stops at `cir.load` so writes through a *loaded*
pointer (which target real caller storage) stay permitted.
Inliner safety
- `rewriteWithExpression`'s `fail()` lambda rolls back both the
cloned ops and the `arg_ref` temps materialised by
`pass.create_reference`, restoring the "no IR drift on error"
contract.
- Both inliners route the matched-op erase through
`pass.erase_op`, scrubbing `inline_worklists` so chained
patches (`apply_after` followed by a `mode: rewrite` matching
the emitted patch call by name) can't leave a dangling pointer
for the post-pass `inline_call` loop.
Implementation surface
- YAML schema (`include/patchestry/YAML/PatchSpec.hpp`): add
`stmt` field to `Action` / `PatchActionObject` / `PatchEntry`;
three-way mutual-exclusion validation in both surfaces.
- Fragment compiler (`lib/patchestry/Passes/FragmentCompiler.cpp`,
`.hpp`): `compile_fragment` + `compile_stmt_fragment` with a
process-scoped content-keyed cache. Marker preprocessor
(`preprocess_return_markers`, string-aware over strings/char/
comments). Strict-expr validator
(`looks_like_statement`).
- Inliners (`lib/patchestry/Passes/PatchOperationImpl.{cpp,hpp}`):
`rewriteWithExpression` (expr-form) and `rewriteWithStatements`
(stmt-form). Shared `find_capture_source_alloca`,
`promote_parameter_slots`, `reaches_store_via_addr` storage-
write validator. `replaceCallWithPatch` /
`replaceOperationWithPatch` for the `patch:` form.
- Dispatch (`lib/patchestry/Passes/InstrumentationPass.cpp`):
function-mode and operation-mode branches both route REWRITE
to the right inliner based on which inline-form field is set.
- Documentation (`docs/GettingStarted/patch_specifications.md`):
three-form rewrite mode documented with examples for each.
- Test fixtures: `rewrite_emit_*.yaml` for expr-form coverage,
`rewrite_stmt_*.yaml` for stmt-form (free-and-null, if-guarded
free, while-with-locals, compound block with declaration).
Reject fixtures verify storage-write rejection and the
parser-time three-way exclusion.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 3ff95f4 commit 54da073
80 files changed
Lines changed: 3101 additions & 193 deletions
File tree
- .claude/rules
- docs/GettingStarted
- include/patchestry
- Passes
- YAML
- lib/patchestry/Passes
- test
- patchir-klee-verifier
- patchir-transform
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
27 | 31 | | |
28 | 32 | | |
29 | 33 | | |
| |||
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
108 | 108 | | |
109 | 109 | | |
110 | 110 | | |
111 | | - | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
112 | 117 | | |
113 | 118 | | |
114 | 119 | | |
| |||
163 | 168 | | |
164 | 169 | | |
165 | 170 | | |
166 | | - | |
| 171 | + | |
167 | 172 | | |
168 | 173 | | |
169 | 174 | | |
| |||
332 | 337 | | |
333 | 338 | | |
334 | 339 | | |
| 340 | + | |
335 | 341 | | |
336 | 342 | | |
337 | | - | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
338 | 346 | | |
339 | 347 | | |
340 | 348 | | |
341 | 349 | | |
342 | 350 | | |
343 | 351 | | |
| 352 | + | |
344 | 353 | | |
345 | 354 | | |
346 | 355 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | | - | |
27 | | - | |
| 26 | + | |
| 27 | + | |
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
48 | | - | |
49 | | - | |
| 48 | + | |
| 49 | + | |
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
| |||
0 commit comments