Skip to content

Add IlProjection Typed depth via an importer per-instruction trace#616

Merged
richlander merged 1 commit into
mainfrom
feature/il-projection-typed
Jun 18, 2026
Merged

Add IlProjection Typed depth via an importer per-instruction trace#616
richlander merged 1 commit into
mainfrom
feature/il-projection-typed

Conversation

@richlander

Copy link
Copy Markdown
Owner

What

Completes IlProjection's parity with the old AnnotatedILEmitter's three depths (#615 shipped Raw/Structured). The Typed depth annotates each instruction with the evaluation-stack types after it:

IL_0000: ldarg.0  // [string]
IL_0004: callvirt string::get_Length()  // [int]
IL_000A: ceq  // [bool]
IL_000C: ret  // []

How — one simulation, not two

The stack types come from the importer's own stack simulation, not a second pass. The importer optionally emits a per-instruction trace as a byproduct of the single import it already runs:

  • An optional List<IlTracePoint>? trace threaded BuildBuildBlock.
  • Recorded right after each opcode's switch arm, capturing the live Stack<IrExpression>'s ResultTypes. Prefix opcodes (constrained./volatile./…) continue past it and are correctly excluded; honest stops return before it.
  • Null in the product import path, so IrImporter.Build is byte-identical there (trace?.Add is a no-op).

Project(…, Typed) runs the traced import for the types and reuses Decode for the instruction text + resolved operands — one decode, one simulation.

Parity note

The new view shows post-instruction stack state with the pipeline's richer typing (bool for ceq); the old emitter showed pre-instruction state and Int32. Same information, an improved spelling — consistent with the "exact-or-better" gate. The eventual annotated-IL consumer migration will diff against the old emitter and accept these as improvements.

Scope

Adds IlProjectionDepth.Typed and an internal IlTracePoint record. Still non-disruptive — no consumers migrated; IlProjection now has all three depths, completing the foundation before the consumer migration (MemberCodeProvider, harness DumpStages) and deletion of MethodBodyContext/MethodAnalysis/AnnotatedILEmitter.

Tests

+1 (Typed_AnnotatesPerInstructionStackTypes); ILInspector.Decompiler.Tests 441 pass. The product import path is unchanged (trace null), so no golden-output impact.

🤖 Generated with Claude Code

Completes IlProjection's parity with the old AnnotatedILEmitter's three depths.
The Typed view annotates each instruction with the evaluation-stack types after
it. Rather than a second stack simulator, the importer optionally emits a
per-instruction trace (offset -> stack ResultTypes) as a byproduct of the single
import it already runs: an optional `List<IlTracePoint>? trace` threaded
Build -> BuildBlock, recorded right after each opcode's switch arm (prefix
opcodes `continue` past it and are correctly excluded; honest stops `return`
before it). Null in the product import path, so that path is byte-identical.

IlProjection.Project(..., Typed) runs the traced import for types and reuses
Decode for the instruction text + resolved operands — one decode, one
simulation. The new view is post-instruction stack state with the pipeline's
richer typing (e.g. `bool` for `ceq`), vs the old emitter's pre-instruction
state; same information, an improved spelling (the gate is exact-or-better).

Tests: +1 (per-instruction stack-type annotation); ILInspector.Decompiler.Tests
441 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@richlander richlander merged commit 11a1569 into main Jun 18, 2026
10 checks passed
@richlander richlander deleted the feature/il-projection-typed branch June 18, 2026 14:21
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.

1 participant