Invariants that involve types (stack type of a variable against its IType,
the element type of an array access, the operand types of a comparison)
need a type system to resolve them against, and the only correct one is the
type system the instruction tree was decoded with. Until now CheckInvariant
took only the phase, so such a check had no compilation to use:
DeconstructInstruction.CheckInvariant called IsAssignment with a null type
system, which only held up because the targets it sees are ldloc, whose
InferType never touches the compilation; a ldflda-wrapped or pointer target
would have failed inside the invariant instead of reporting a violation.
Every call site already has that type system in scope: the ILReader's
compilation, the ILTransformContext of the running transform, or the
decompiler's own IDecompilerTypeSystem. It is now passed explicitly and the
base implementation asserts it is present, so a future invariant can rely
on it without re-plumbing the callers.
Assisted-by: Claude:claude-fable-5:Claude Code
Collecting from the two EventSource providers differs by tooling, not by
platform: dotnet-trace/EventPipe works the same everywhere, with ETW/PerfView
as the Windows-only alternative. The doc lists the keyword masks and levels
so sessions can enable only the areas of interest.
Assisted-by: Claude:claude-fable-5:Claude Code
* Add decompiler architecture document
* Add StatementBuilder section to architecture doc, fix foreach story
* Correct architecture doc per review by the decompiler author
* Use releaseTag with fallback to downloadUrl in updates.xml
* Add tests
* Prevent arbitrary downloadUrl - must start with BaseUrl as well
* Remove custom domain ilspy.net in end-user visible places
* Use NaturalSort.Extension instead of Interop
* Update to latest NaturalSort.Extensions and update 3rd party notices
* Remove old interop implementation
It's not actually all that hard once you realize:
a) the ECMA-335 specification is incorrect, whether to sign- or zero-extend does not always depends on the source type
b) the C# compilator generates completely weird code when casting between (U)IntPtr and integers.
Map all IntPtr casts to a few semi-sane cases, and we can obtain the correct semantics without introducing any helper methods.