|
|
@ -61,6 +61,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow |
|
|
|
readonly SymbolicEvaluationContext evalContext; |
|
|
|
|
|
|
|
readonly Dictionary<Block, LongSet> ranges = new Dictionary<Block, LongSet>(); |
|
|
|
readonly Dictionary<BlockContainer, LongSet>? rangesForLeave; // used only for AwaitInFinally
|
|
|
|
readonly internal Dictionary<IMethod, LongSet>? finallyMethodToStateRange; // used only for IteratorDispose
|
|
|
|
|
|
|
|
internal ILVariable? doFinallyBodies; |
|
|
@ -74,6 +75,10 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow |
|
|
|
{ |
|
|
|
finallyMethodToStateRange = new Dictionary<IMethod, LongSet>(); |
|
|
|
} |
|
|
|
if (mode == StateRangeAnalysisMode.AwaitInFinally) |
|
|
|
{ |
|
|
|
rangesForLeave = new Dictionary<BlockContainer, LongSet>(); |
|
|
|
} |
|
|
|
|
|
|
|
evalContext = new SymbolicEvaluationContext(stateField); |
|
|
|
if (cachedStateVar != null) |
|
|
@ -177,6 +182,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow |
|
|
|
case Branch br: |
|
|
|
AddStateRange(br.TargetBlock, stateRange); |
|
|
|
return LongSet.Empty; |
|
|
|
case Leave leave when mode == StateRangeAnalysisMode.AwaitInFinally: |
|
|
|
AddStateRangeForLeave(leave.TargetContainer, stateRange); |
|
|
|
return LongSet.Empty; |
|
|
|
case Nop nop: |
|
|
|
return stateRange; |
|
|
|
case StLoc stloc when stloc.Variable == doFinallyBodies || stloc.Variable == skipFinallyBodies: |
|
|
@ -233,6 +241,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow |
|
|
|
ranges.Add(block, stateRange); |
|
|
|
} |
|
|
|
|
|
|
|
private void AddStateRangeForLeave(BlockContainer target, LongSet stateRange) |
|
|
|
{ |
|
|
|
if (rangesForLeave!.TryGetValue(target, out var existingRange)) |
|
|
|
rangesForLeave[target] = stateRange.UnionWith(existingRange); |
|
|
|
else |
|
|
|
rangesForLeave.Add(target, stateRange); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets a mapping from states to blocks.
|
|
|
|
///
|
|
|
@ -262,5 +279,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
public LongDict<BlockContainer> GetBlockStateSetMappingForLeave() |
|
|
|
{ |
|
|
|
return LongDict.Create(rangesForLeave.Select(kv => (kv.Value, kv.Key))); |
|
|
|
} |
|
|
|
} |
|
|
|
} |