Browse Source

Drop the per-call predicate from FindFlagInitStore.

After the cluster-1/3/4 fixes converged every caller on the same matching
shape (match the slot/kind/type of a reference ILVariable, then check the
init value), the `Predicate<StLoc>` parameter was just a hole through which
each caller restated that logic verbatim. Fold the slot/kind/type check
into the helper and have callers pass just the reference variable and a
value matcher.
pull/3731/head
Siegfried Pammer 3 days ago
parent
commit
391bf28f81
  1. 55
      ICSharpCode.Decompiler/IL/ControlFlow/RuntimeAsyncExceptionRewriteTransform.cs

55
ICSharpCode.Decompiler/IL/ControlFlow/RuntimeAsyncExceptionRewriteTransform.cs

@ -279,14 +279,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -279,14 +279,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return false;
// Pre-try: somewhere among the instructions preceding the TryCatch we expect
// an `stloc obj(ldnull)`. Other (unrelated) stores may be interleaved. After
// SplitVariables, when the try body always throws the pre-init's local is a separate
// ILVariable from the in-handler store, so match by slot/kind/type rather than identity.
var flagInitStore = FindFlagInitStore(parentBlock, tryCatch,
s => s.Variable.Index == objectVariable.Index
&& s.Variable.Kind == objectVariable.Kind
&& s.Variable.Type.IsKnownType(KnownTypeCode.Object)
&& s.Value.MatchLdNull());
// an `stloc obj(ldnull)`. Other (unrelated) stores may be interleaved.
var flagInitStore = FindFlagInitStore(parentBlock, tryCatch, objectVariable, v => v.MatchLdNull());
if (flagInitStore == null)
return false;
@ -383,18 +377,26 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -383,18 +377,26 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
return true;
}
// Scan instructions before `tryCatch` for the runtime-async flag-init store that matches
// `predicate`. The lowering inserts an `stloc obj(ldnull)` (try-finally) or
// `stloc num(ldc.i4 0)` (try-catch) before the try region; the catch handler overwrites it,
// the continuation reads it to decide whether an exception occurred (and which case).
// Returns null when no matching store is found.
static StLoc FindFlagInitStore(Block parentBlock, TryCatch tryCatch, Predicate<StLoc> predicate)
// Scan instructions before `tryCatch` for the runtime-async flag-init store. The lowering
// inserts an `stloc obj(ldnull)` (try-finally) or `stloc num(ldc.i4 0)` (try-catch) before
// the try region; the catch handler overwrites it, and the continuation reads it to decide
// whether an exception occurred (and which case). Match by `referenceVar`'s slot/kind/type
// rather than identity — after SplitVariables, the pre-init's ILVariable may differ from
// the in-handler one. Returns null when no matching store is found.
static StLoc FindFlagInitStore(Block parentBlock, TryCatch tryCatch, ILVariable referenceVar, Predicate<ILInstruction> matchInitValue)
{
int tryIndex = tryCatch.ChildIndex;
for (int i = 0; i < tryIndex; i++)
{
if (parentBlock.Instructions[i] is StLoc s && predicate(s))
return s;
if (parentBlock.Instructions[i] is not StLoc s)
continue;
if (s.Variable.Index != referenceVar.Index || s.Variable.Kind != referenceVar.Kind)
continue;
if (!s.Variable.Type.Equals(referenceVar.Type))
continue;
if (!matchInitValue(s.Value))
continue;
return s;
}
return null;
}
@ -640,15 +642,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -640,15 +642,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
if (prefixCount != 0)
return false;
// Pre-try: somewhere before the TryCatch we expect `stloc num(ldc.i4 0)`. After
// SplitVariables the pre-init's local may be a separate ILVariable, so match the slot
// and type rather than the ILVariable identity (same workaround as the multi-handler
// matcher).
var flagInitStore = FindFlagInitStore(parentBlock, tryCatch,
s => s.Variable.Index == numVariable.Index
&& s.Variable.Kind == numVariable.Kind
&& s.Variable.Type.IsKnownType(KnownTypeCode.Int32)
&& s.Value.MatchLdcI4(0));
// Pre-try: somewhere before the TryCatch we expect `stloc num(ldc.i4 0)`.
var flagInitStore = FindFlagInitStore(parentBlock, tryCatch, numVariable, v => v.MatchLdcI4(0));
if (flagInitStore == null)
return false;
@ -789,14 +784,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -789,14 +784,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
handlerInfos.Add((handler, k, bodyObj, bodyTmp));
}
// Pre-try: stloc num(ldc.i4 0). After SplitVariables the pre-init's local may be a
// separate ILVariable (the in-handler stores form a disjoint use that gets split off),
// so match the slot and type rather than the ILVariable identity.
var flagInitStore = FindFlagInitStore(parentBlock, tryCatch,
s => s.Variable.Index == numVariable.Index
&& s.Variable.Kind == numVariable.Kind
&& s.Variable.Type.IsKnownType(KnownTypeCode.Int32)
&& s.Value.MatchLdcI4(0));
// Pre-try: stloc num(ldc.i4 0).
var flagInitStore = FindFlagInitStore(parentBlock, tryCatch, numVariable, v => v.MatchLdcI4(0));
if (flagInitStore == null)
return false;
// Block continuation { switch (ldloc num) { case K: br case_K ... ; default: leave outer } }

Loading…
Cancel
Save