Delay exceptions when copy-propagating an address into a StObj target - #3964
Open
siegfriedpammer wants to merge 1 commit into
Open
Delay exceptions when copy-propagating an address into a StObj target#3964siegfriedpammer wants to merge 1 commit into
siegfriedpammer wants to merge 1 commit into
Conversation
Below C# 7 ref locals are unavailable, so CopyPropagation is allowed to copy LdFlda/LdElema. When such a copy lands in a StObj target slot whose value is impure, it violates the invariant checked by StObj.CheckTargetSlot: C# computes the value to be stored before dereferencing the target, so the exception moves. ILInlining resolves the same conflict by marking the address as delayed rather than falling back to a ref local; copy propagation now does the same, which keeps the generated code unchanged and only repairs the IL. Refusing the propagation instead would emit a ref local at a language version that cannot express one. The relaxation is bound to the setting that gates InliningOptions.AllowChangingOrderOfEvaluationForExceptions, and the check sits in DoPropagate rather than CanPerformCopyPropagation because the public Propagate() entry point bypasses the latter -- AsyncAwaitDecompiler copies an ldflda of the builder field through it irrespective of the setting. Assisted-by: Claude:claude-opus-5:Claude Code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Decompiling with a language version below C# 7 can trip a debug assertion in
StObj.CheckTargetSlot:Reproduces on the existing test assemblies, e.g.
CompoundAssignmentTest.ShortUnsignedRightShiftTestat C# 6 and below, andDynamicTests.StructMemberAccessat C# 3 and below. Minimal case:CanPerformCopyPropagationpermits copyingLdFlda/LdElemawhenUseRefLocalsForAccurateOrderOfEvaluationis off, butDoPropagateputs the clone into aStObjtarget slot without consultingStObj.SatisfiesSlotRestrictionForInlining, leavingstobj(ldflda F(ldloc C_0), <impure value>).ILInlining.FindLoadInNextalready handles the same conflict by settingDelayExceptionson the address instead of falling back to a ref local. Copy propagation now does the same, gated on the same setting that drivesInliningOptions.AllowChangingOrderOfEvaluationForExceptions. The check sits inDoPropagaterather thanCanPerformCopyPropagationbecause the publicPropagate()entry point bypasses the latter --AsyncAwaitDecompilercopies anldfldaof the builder field through it regardless of the setting.Decompiled output for
DynamicTestsandCompoundAssignmentTestat C# 3 and C# 6 is byte-identical before and after; only the IL invariant changes.New Ugly test
NoUnsignedRightShift(decompiled atLanguageVersion.CSharp6) fails on master and passes with the fix.Prepared by an AI agent (Claude) on Siegfried's behalf.