|
|
@ -74,29 +74,29 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow |
|
|
|
ILTransformContext context; |
|
|
|
ILTransformContext context; |
|
|
|
|
|
|
|
|
|
|
|
// These fields are set by MatchTaskCreationPattern() or MatchEnumeratorCreationNewObj()
|
|
|
|
// These fields are set by MatchTaskCreationPattern() or MatchEnumeratorCreationNewObj()
|
|
|
|
IType taskType; // return type of the async method; or IAsyncEnumerable{T}/IAsyncEnumerator{T}
|
|
|
|
IType? taskType; // return type of the async method; or IAsyncEnumerable{T}/IAsyncEnumerator{T}
|
|
|
|
IType underlyingReturnType; // return type of the method (only the "T" for Task{T}), for async enumerators this is the type being yielded
|
|
|
|
IType? underlyingReturnType; // return type of the method (only the "T" for Task{T}), for async enumerators this is the type being yielded
|
|
|
|
AsyncMethodType methodType; |
|
|
|
AsyncMethodType methodType; |
|
|
|
ITypeDefinition stateMachineType; |
|
|
|
ITypeDefinition? stateMachineType; |
|
|
|
IType builderType; |
|
|
|
IType? builderType; |
|
|
|
IField builderField; |
|
|
|
IField? builderField; |
|
|
|
IField stateField; |
|
|
|
IField? stateField; |
|
|
|
int initialState; |
|
|
|
int initialState; |
|
|
|
Dictionary<IField, ILVariable> fieldToParameterMap = new Dictionary<IField, ILVariable>(); |
|
|
|
Dictionary<IField, ILVariable> fieldToParameterMap = new Dictionary<IField, ILVariable>(); |
|
|
|
Dictionary<ILVariable, ILVariable> cachedFieldToParameterMap = new Dictionary<ILVariable, ILVariable>(); |
|
|
|
Dictionary<ILVariable, ILVariable> cachedFieldToParameterMap = new Dictionary<ILVariable, ILVariable>(); |
|
|
|
IField disposeModeField; // 'disposeMode' field (IAsyncEnumerable/IAsyncEnumerator only)
|
|
|
|
IField? disposeModeField; // 'disposeMode' field (IAsyncEnumerable/IAsyncEnumerator only)
|
|
|
|
|
|
|
|
|
|
|
|
// These fields are set by AnalyzeMoveNext():
|
|
|
|
// These fields are set by AnalyzeMoveNext():
|
|
|
|
ILFunction moveNextFunction; |
|
|
|
ILFunction? moveNextFunction; |
|
|
|
ILVariable cachedStateVar; // variable in MoveNext that caches the stateField.
|
|
|
|
ILVariable? cachedStateVar; // variable in MoveNext that caches the stateField.
|
|
|
|
TryCatch mainTryCatch; |
|
|
|
TryCatch? mainTryCatch; |
|
|
|
Block setResultReturnBlock; // block that is jumped to for return statements
|
|
|
|
Block? setResultReturnBlock; // block that is jumped to for return statements
|
|
|
|
// Note: for async enumerators, a jump to setResultReturnBlock is a 'yield break;'
|
|
|
|
// Note: for async enumerators, a jump to setResultReturnBlock is a 'yield break;'
|
|
|
|
int finalState; // final state after the setResultAndExitBlock
|
|
|
|
int finalState; // final state after the setResultAndExitBlock
|
|
|
|
bool finalStateKnown; |
|
|
|
bool finalStateKnown; |
|
|
|
ILVariable resultVar; // the variable that gets returned by the setResultAndExitBlock
|
|
|
|
ILVariable? resultVar; // the variable that gets returned by the setResultAndExitBlock
|
|
|
|
Block setResultYieldBlock; // block that is jumped to for 'yield return' statements
|
|
|
|
Block? setResultYieldBlock; // block that is jumped to for 'yield return' statements
|
|
|
|
ILVariable doFinallyBodies; |
|
|
|
ILVariable? doFinallyBodies; |
|
|
|
|
|
|
|
|
|
|
|
// These fields are set by AnalyzeStateMachine():
|
|
|
|
// These fields are set by AnalyzeStateMachine():
|
|
|
|
int smallestAwaiterVarIndex; |
|
|
|
int smallestAwaiterVarIndex; |
|
|
@ -295,15 +295,15 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow |
|
|
|
} |
|
|
|
} |
|
|
|
if (startCall.Arguments.Count != 2) |
|
|
|
if (startCall.Arguments.Count != 2) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
ILInstruction loadBuilderExpr = startCall.Arguments[0]; |
|
|
|
ILInstruction? loadBuilderExpr = startCall.Arguments[0]; |
|
|
|
if (!startCall.Arguments[1].MatchLdLoca(out ILVariable stateMachineVar)) |
|
|
|
if (!startCall.Arguments[1].MatchLdLoca(out ILVariable? stateMachineVar)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
stateMachineType = stateMachineVar.Type.GetDefinition(); |
|
|
|
stateMachineType = stateMachineVar.Type.GetDefinition(); |
|
|
|
if (stateMachineType == null) |
|
|
|
if (stateMachineType == null) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
pos--; |
|
|
|
pos--; |
|
|
|
|
|
|
|
|
|
|
|
if (loadBuilderExpr.MatchLdLocRef(out ILVariable builderVar)) |
|
|
|
if (loadBuilderExpr.MatchLdLocRef(out ILVariable? builderVar)) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// Check third-to-last instruction (copy of builder)
|
|
|
|
// Check third-to-last instruction (copy of builder)
|
|
|
|
// stloc builder(ldfld StateMachine::<>t__builder(ldloc stateMachine))
|
|
|
|
// stloc builder(ldfld StateMachine::<>t__builder(ldloc stateMachine))
|
|
|
@ -340,8 +340,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (!MatchCall(returnValue, "get_Task", out var getTaskArgs) || getTaskArgs.Count != 1) |
|
|
|
if (!MatchCall(returnValue, "get_Task", out var getTaskArgs) || getTaskArgs.Count != 1) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
ILInstruction target; |
|
|
|
ILInstruction? target; |
|
|
|
IField builderField2; |
|
|
|
IField? builderField2; |
|
|
|
if (builderType.IsReferenceType == true) |
|
|
|
if (builderType.IsReferenceType == true) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (!getTaskArgs[0].MatchLdFld(out target, out builderField2)) |
|
|
|
if (!getTaskArgs[0].MatchLdFld(out target, out builderField2)) |
|
|
@ -804,7 +804,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow |
|
|
|
return block.Instructions[1].MatchLeave(blockContainer); |
|
|
|
return block.Instructions[1].MatchLeave(blockContainer); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private Block CheckSetResultReturnBlock(BlockContainer blockContainer, int setResultReturnBlockIndex, bool[] blocksAnalyzed) |
|
|
|
private Block? CheckSetResultReturnBlock(BlockContainer blockContainer, int setResultReturnBlockIndex, bool[] blocksAnalyzed) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (setResultReturnBlockIndex >= blockContainer.Blocks.Count) |
|
|
|
if (setResultReturnBlockIndex >= blockContainer.Blocks.Count) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1931,7 +1931,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow |
|
|
|
context.StepEndGroup(keepIfEmpty: true); |
|
|
|
context.StepEndGroup(keepIfEmpty: true); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
internal static Block GetBodyEntryPoint(BlockContainer body) |
|
|
|
internal static Block? GetBodyEntryPoint(BlockContainer? body) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (body == null) |
|
|
|
if (body == null) |
|
|
|
return null; |
|
|
|
return null; |
|
|
|