Skip to content

Add arena IR SignatureConversion patterns#460

Merged
Kroisse merged 3 commits intomainfrom
feature/arena-signature-conversion
Feb 26, 2026
Merged

Add arena IR SignatureConversion patterns#460
Kroisse merged 3 commits intomainfrom
feature/arena-signature-conversion

Conversation

@Kroisse
Copy link
Owner

@Kroisse Kroisse commented Feb 26, 2026

Summary

Completes the remaining work from #438 by porting SignatureConversion patterns to the arena IR rewrite infrastructure.

  • Add set_block_arg_type and detach_region to IrContext to support in-place mutation of block argument types and region ownership transfer
  • Add type_converter() accessor to PatternRewriter<'a> (with lifetime), propagated from PatternApplicator
  • Add FuncSignatureConversionPattern and WasmFuncSignatureConversionPattern in crates/trunk-ir/src/arena/rewrite/signature_conversion.rs
  • Both patterns convert func.fn type signatures (params and return) via ArenaTypeConverter, update entry block argument types in-place, and rebuild the function op with the new signature
  • Preserve the effect attribute on func.fn types across conversion

Test plan

  • 5 unit tests in signature_conversion.rs:
    • func_signature_i32_to_i64: full param + return conversion for func.func
    • no_change_when_types_not_matched: verifies the pattern is a no-op when no types match
    • wasm_func_signature_conversion: multi-param conversion for wasm.func
    • effect_attribute_preserved: verifies effect attribute survives conversion
    • partial_conversion_only_params: verifies partial conversion (params change, return already converted)
  • Run cargo nextest run -p trunk-ir to verify all tests pass

Closes #438

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Signature conversion patterns for automated function signature transformations with type adaptation.
    • Ability to detach regions from parent operations for safer region manipulation.
    • Synchronized block-argument and value types to keep IR consistent during updates.
    • Rewrite engine now integrates type conversion to perform type-aware pattern rewrites.

Implement MLIR-style function signature conversion for the arena IR
rewrite infrastructure, closing issue #438.

- Add `set_block_arg_type` and `detach_region` to `IrContext` to
  support in-place block arg mutation and region transplanting
- Thread `&ArenaTypeConverter` lifetime through `PatternRewriter<'a>`
  so patterns can call the type converter during rewrites
- Update `ArenaRewritePattern::match_and_rewrite` to accept
  `PatternRewriter<'_>` (breaking change within crate, no public API
  impact)
- Add `signature_conversion` module with:
  - `FuncSignatureConversionPattern`: converts `func.func` signatures
  - `WasmFuncSignatureConversionPattern`: converts `wasm.func` signatures
  Both patterns convert param/result types via the type converter,
  update entry block arg types in-place, and replace the op with a
  rebuilt function carrying the new signature and the original body.
- 5 unit tests covering: i32→i64 conversion, no-change guard, wasm.func,
  effect attribute preservation, and partial (params-only) conversion

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 47fdf7a and 16098e6.

📒 Files selected for processing (1)
  • crates/trunk-ir/src/arena/rewrite/signature_conversion.rs

📝 Walkthrough

Walkthrough

Adds arena IR function signature-conversion rewrite patterns, threads an ArenaTypeConverter into the PatternRewriter, and adds IrContext helpers to update block-argument types and detach regions used by the new patterns.

Changes

Cohort / File(s) Summary
IrContext utilities
crates/trunk-ir/src/arena/context.rs
Added IrContext::set_block_arg_type(block, index, new_ty) to update BlockArgData and the corresponding ValueData in sync, and IrContext::detach_region(region) to remove a region from its parent op.
PatternRewriter core
crates/trunk-ir/src/arena/rewrite/rewriter.rs
Made PatternRewriter generic over a lifetime (PatternRewriter<'a>) and added a type_converter: &'a ArenaTypeConverter field; constructor now requires the converter and a type_converter() accessor was added.
Rewriter integration
crates/trunk-ir/src/arena/rewrite/applicator.rs, crates/trunk-ir/src/arena/rewrite/pattern.rs
Updated instantiation and signatures to create and accept PatternRewriter<'_> and pass the ArenaTypeConverter where the rewriter is constructed.
Rewrite exports
crates/trunk-ir/src/arena/rewrite/mod.rs
Added new signature_conversion module and re-exported FuncSignatureConversionPattern and WasmFuncSignatureConversionPattern.
Signature conversion patterns
crates/trunk-ir/src/arena/rewrite/signature_conversion.rs
New module implementing FuncSignatureConversionPattern and WasmFuncSignatureConversionPattern: converts func signatures via ArenaTypeConverter, updates entry-block arg types, rebuilds func types (preserving effect attrs), detaches/reuses body regions, and includes unit tests for conversion scenarios.

Sequence Diagram

sequenceDiagram
    participant Pattern as SignatureConversion Pattern
    participant Converter as ArenaTypeConverter
    participant Context as IrContext
    participant Block as EntryBlock
    participant Op as func/wasm.func

    Pattern->>Op: match and extract func signature
    Pattern->>Converter: convert return types
    Converter-->>Pattern: converted return types
    Pattern->>Converter: convert param types
    Converter-->>Pattern: converted param types
    Pattern->>Pattern: build ConvertedSignature
    alt params changed
        Pattern->>Block: request entry arg updates
        Block->>Context: set_block_arg_type(block, index, new_ty)
        Context-->>Block: BlockArgData + ValueData updated
    end
    Pattern->>Pattern: rebuild func.fn TypeRef
    Pattern->>Context: detach_region(region)
    Context-->>Pattern: region detached
    Pattern->>Op: replace op with new type and reused body
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰
I nibble at types in moonlit code,
I hop block-args down a tidy road,
Regions unhook and bound so free,
Converters hum — a quiet spree,
Rewrites bloom where rabbits go.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add arena IR SignatureConversion patterns' clearly and concisely summarizes the main change: introducing signature conversion patterns to the arena IR infrastructure.
Linked Issues check ✅ Passed The PR successfully implements the coding requirements from issue #438: SignatureConversion patterns handle arena function types, TypeConverter integration is present via PatternRewriter, and functionality is demonstrated through comprehensive tests.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing SignatureConversion patterns: IrContext utility methods support block argument mutation, PatternRewriter gains type_converter access, and the new signature_conversion module implements the core requirement.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/arena-signature-conversion

Comment @coderabbitai help to get the list of available commands and usage tips.

@Kroisse Kroisse self-assigned this Feb 26, 2026
@codecov
Copy link

codecov bot commented Feb 26, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.54%. Comparing base (0cc6e12) to head (16098e6).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #460   +/-   ##
=======================================
  Coverage   78.54%   78.54%           
=======================================
  Files          10       10           
  Lines        4935     4935           
=======================================
  Hits         3876     3876           
  Misses       1059     1059           
Components Coverage Δ
TrunkIR ∅ <ø> (∅)
Frontend ∅ <ø> (∅)
Middle End ∅ <ø> (∅)
Driver 78.54% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
crates/trunk-ir/src/arena/rewrite/signature_conversion.rs (1)

127-218: Consider extracting shared rewrite flow for func.func and wasm.func.

Both pattern implementations are structurally identical aside from dialect-specific wrappers/builders. A shared helper would reduce drift risk and keep future fixes synchronized.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/trunk-ir/src/arena/rewrite/signature_conversion.rs` around lines 127 -
218, Both match_and_rewrite implementations in FuncSignatureConversionPattern
and WasmFuncSignatureConversionPattern duplicate the same rewrite flow; extract
that flow into a shared helper (e.g., perform_signature_rewrite) that takes the
OpRef plus small dialect-specific callbacks or a trait object for:
validating/casting the op (the initial func::Func::from_op /
wasm::Func::from_op), obtaining r#type, getting sym_name, getting body, and
constructing the replacement op (currently func::func vs wasm::func). Inside the
helper reuse convert_func_signature, update_entry_block_args, rebuild_func_type,
ctx.detach_region, and rewriter.replace_op, then call this helper from each
pattern's match_and_rewrite with the appropriate dialect lambdas so
FuncSignatureConversionPattern and WasmFuncSignatureConversionPattern only
provide dialect-specific pieces.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/trunk-ir/src/arena/rewrite/signature_conversion.rs`:
- Around line 127-218: Both match_and_rewrite implementations in
FuncSignatureConversionPattern and WasmFuncSignatureConversionPattern duplicate
the same rewrite flow; extract that flow into a shared helper (e.g.,
perform_signature_rewrite) that takes the OpRef plus small dialect-specific
callbacks or a trait object for: validating/casting the op (the initial
func::Func::from_op / wasm::Func::from_op), obtaining r#type, getting sym_name,
getting body, and constructing the replacement op (currently func::func vs
wasm::func). Inside the helper reuse convert_func_signature,
update_entry_block_args, rebuild_func_type, ctx.detach_region, and
rewriter.replace_op, then call this helper from each pattern's match_and_rewrite
with the appropriate dialect lambdas so FuncSignatureConversionPattern and
WasmFuncSignatureConversionPattern only provide dialect-specific pieces.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0cc6e12 and 4bf1bee.

📒 Files selected for processing (6)
  • crates/trunk-ir/src/arena/context.rs
  • crates/trunk-ir/src/arena/rewrite/applicator.rs
  • crates/trunk-ir/src/arena/rewrite/mod.rs
  • crates/trunk-ir/src/arena/rewrite/pattern.rs
  • crates/trunk-ir/src/arena/rewrite/rewriter.rs
  • crates/trunk-ir/src/arena/rewrite/signature_conversion.rs

…re conversion

`update_entry_block_args` previously updated block args in a partial loop
when the entry block arg count differed from the new param count, leaving
the IR in an inconsistent state. Change the function to return `bool` and
bail out with `false` on any arity mismatch, leaving the IR untouched.
Both `FuncSignatureConversionPattern` and `WasmFuncSignatureConversionPattern`
now propagate that failure by returning `false` (no match). A new test
`arity_mismatch_returns_unchanged` verifies that no changes are recorded
and the original type is preserved when arities differ.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
crates/trunk-ir/src/arena/rewrite/signature_conversion.rs (2)

132-223: Extract shared rewrite flow between func.func and wasm.func patterns.

Both match_and_rewrite implementations are nearly identical (convert signature, update entry args, detach body, rebuild op, replace). A shared helper would reduce drift risk and keep future safety fixes in one place.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/trunk-ir/src/arena/rewrite/signature_conversion.rs` around lines 132 -
223, Extract the duplicated flow in
FuncSignatureConversionPattern::match_and_rewrite and
WasmFuncSignatureConversionPattern::match_and_rewrite into a single helper (e.g.
rewrite_function_signature) that performs: call convert_func_signature, call
update_entry_block_args when needed, call rebuild_func_type, detach the body
region via ctx.detach_region, create the replacement op, and invoke
rewriter.replace_op. The helper should accept the OpRef plus small
accessors/constructors (closures or a trait) to get the op type, entry body,
symbol name, and to construct the new op (so it can work for both func::Func and
wasm::Func); then simplify both match_and_rewrite implementations to call this
helper and return its boolean result, reusing existing functions
convert_func_signature, update_entry_block_args, rebuild_func_type,
ctx.detach_region, and rewriter.replace_op.

528-551: Consider adding a wasm arity-mismatch regression test for symmetry.

You already lock this behavior for func.func; mirroring it for wasm.func would guard against regressions in one pattern path only.

➕ Suggested test addition
+    #[test]
+    fn wasm_arity_mismatch_returns_unchanged() {
+        let (mut ctx, loc) = test_ctx();
+        let i32_ty = i32_type(&mut ctx);
+        let i64_ty = i64_type(&mut ctx);
+
+        // Signature has 2 params, but entry block has only 1 arg (arity mismatch)
+        let func_ty = make_func_type(&mut ctx, &[i32_ty, i32_ty], i32_ty);
+        let func_op = make_wasm_func_op(&mut ctx, loc, "wasm_mismatched", func_ty, &[i32_ty]);
+        let module = make_module(&mut ctx, loc, vec![func_op]);
+
+        let tc = i32_to_i64_converter(i32_ty, i64_ty);
+        let applicator = PatternApplicator::new(tc).add_pattern(WasmFuncSignatureConversionPattern);
+        let target = ArenaConversionTarget::new();
+
+        let result = applicator.apply(&mut ctx, module, &target).unwrap();
+        assert_eq!(result.total_changes, 0);
+
+        let ops = module.ops(&ctx);
+        let original_func = wasm::Func::from_op(&ctx, ops[0]).unwrap();
+        assert_eq!(original_func.r#type(&ctx), func_ty);
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@crates/trunk-ir/src/arena/rewrite/signature_conversion.rs` around lines 528 -
551, Add a mirror test for wasm.func that follows
arity_mismatch_returns_unchanged: create a wasm function type with two params
but construct the wasm.func op with only one entry argument (arity mismatch),
then apply the same i32_to_i64_converter + PatternApplicator but using the wasm
signature conversion pattern (WasmFuncSignatureConversionPattern) and
ArenaConversionTarget, assert result.total_changes == 0 and that the wasm.func's
original type is preserved; mirror the existing test's setup symbols (i32_type,
i64_type, make_func_type -> for wasm func type helper, make_wasm_func_op,
make_module, i32_to_i64_converter, PatternApplicator, and ArenaConversionTarget)
and name the test e.g. arity_mismatch_returns_unchanged_for_wasm.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@crates/trunk-ir/src/arena/rewrite/signature_conversion.rs`:
- Around line 132-223: Extract the duplicated flow in
FuncSignatureConversionPattern::match_and_rewrite and
WasmFuncSignatureConversionPattern::match_and_rewrite into a single helper (e.g.
rewrite_function_signature) that performs: call convert_func_signature, call
update_entry_block_args when needed, call rebuild_func_type, detach the body
region via ctx.detach_region, create the replacement op, and invoke
rewriter.replace_op. The helper should accept the OpRef plus small
accessors/constructors (closures or a trait) to get the op type, entry body,
symbol name, and to construct the new op (so it can work for both func::Func and
wasm::Func); then simplify both match_and_rewrite implementations to call this
helper and return its boolean result, reusing existing functions
convert_func_signature, update_entry_block_args, rebuild_func_type,
ctx.detach_region, and rewriter.replace_op.
- Around line 528-551: Add a mirror test for wasm.func that follows
arity_mismatch_returns_unchanged: create a wasm function type with two params
but construct the wasm.func op with only one entry argument (arity mismatch),
then apply the same i32_to_i64_converter + PatternApplicator but using the wasm
signature conversion pattern (WasmFuncSignatureConversionPattern) and
ArenaConversionTarget, assert result.total_changes == 0 and that the wasm.func's
original type is preserved; mirror the existing test's setup symbols (i32_type,
i64_type, make_func_type -> for wasm func type helper, make_wasm_func_op,
make_module, i32_to_i64_converter, PatternApplicator, and ArenaConversionTarget)
and name the test e.g. arity_mismatch_returns_unchanged_for_wasm.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4bf1bee and 47fdf7a.

📒 Files selected for processing (1)
  • crates/trunk-ir/src/arena/rewrite/signature_conversion.rs

… wasm arity test

Extract the duplicated match_and_rewrite logic from FuncSignatureConversionPattern
and WasmFuncSignatureConversionPattern into a shared rewrite_function_signature
helper that accepts a constructor closure. Also add a mirror arity mismatch test
for wasm.func.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Kroisse Kroisse merged commit 0ad3bb6 into main Feb 26, 2026
12 checks passed
@Kroisse Kroisse deleted the feature/arena-signature-conversion branch February 26, 2026 10:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Port ConversionTarget and TypeConverter to arena IR

1 participant