diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 27fc23442..4e4b4fb60 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -2389,7 +2389,7 @@ namespace ICSharpCode.Decompiler.CSharp return; } function = ilReader.ReadIL((MethodDefinitionHandle)method.MetadataToken, methodBody, cancellationToken: CancellationToken); - function.CheckInvariant(ILPhase.Normal); + function.CheckInvariant(ILPhase.Normal, typeSystem); AddAnnotationsToDeclaration(method, entityDecl, function, parameterOffset); diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs index 45b50af8f..471dfa67b 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs @@ -143,9 +143,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow } InlineBodyOfMoveNext(function); - function.CheckInvariant(ILPhase.InAsyncAwait); + function.CheckInvariant(ILPhase.InAsyncAwait, context.TypeSystem); CleanUpBodyOfMoveNext(function); - function.CheckInvariant(ILPhase.InAsyncAwait); + function.CheckInvariant(ILPhase.InAsyncAwait, context.TypeSystem); AnalyzeStateMachine(function); DetectAwaitPattern(function); diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs index f23e7507f..fad7fb9b2 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs @@ -189,7 +189,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow // Note: because this only deletes blocks outright, the 'stateChanges' entries remain valid // (though some may point to now-deleted blocks) newBody.SortBlocks(deleteUnreachableBlocks: true); - function.CheckInvariant(ILPhase.Normal); + function.CheckInvariant(ILPhase.Normal, context.TypeSystem); try { diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs index b95fd182e..8db321ba5 100644 --- a/ICSharpCode.Decompiler/IL/ILReader.cs +++ b/ICSharpCode.Decompiler/IL/ILReader.cs @@ -543,7 +543,7 @@ namespace ICSharpCode.Decompiler.IL var inst = decodedInstruction.Instruction; if (inst.ResultType == StackType.Unknown && inst.OpCode != OpCode.InvalidBranch && inst.OpCode != OpCode.InvalidExpression) Warn("Unknown result type (might be due to invalid IL or missing references)"); - inst.CheckInvariant(ILPhase.InILReader); + inst.CheckInvariant(ILPhase.InILReader, compilation); int end = reader.Offset; inst.AddILRange(new Interval(start, end)); if (!decodedInstruction.PushedOnExpressionStack) diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs index 314f6f198..308ba2a73 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions.cs @@ -1038,9 +1038,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as PinnedRegion; return o != null && variable == o.variable && this.init.PerformMatch(o.init, ref match) && this.body.PerformMatch(o.body, ref match); } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function!)); DebugAssert(phase <= ILPhase.InILReader || variable.Function!.Variables[variable.IndexInFunction] == variable); DebugAssert(Variable.Kind == VariableKind.PinnedRegionLocal); @@ -1940,9 +1940,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as LockInstruction; return o != null && this.onExpression.PerformMatch(o.onExpression, ref match) && this.body.PerformMatch(o.body, ref match); } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(onExpression.ResultType == StackType.O); } } @@ -2084,9 +2084,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as UsingInstruction; return o != null && variable == o.variable && this.resourceExpression.PerformMatch(o.resourceExpression, ref match) && this.body.PerformMatch(o.body, ref match); } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function!)); DebugAssert(phase <= ILPhase.InILReader || variable.Function!.Variables[variable.IndexInFunction] == variable); DebugAssert(resourceExpression.ResultType == StackType.O); @@ -2363,9 +2363,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as LdLoc; return o != null && variable == o.variable; } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function!)); DebugAssert(phase <= ILPhase.InILReader || variable.Function!.Variables[variable.IndexInFunction] == variable); } @@ -2437,9 +2437,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as LdLoca; return o != null && variable == o.variable; } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function!)); DebugAssert(phase <= ILPhase.InILReader || variable.Function!.Variables[variable.IndexInFunction] == variable); } @@ -3567,9 +3567,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as Cpblk; return o != null && this.destAddress.PerformMatch(o.destAddress, ref match) && this.sourceAddress.PerformMatch(o.sourceAddress, ref match) && this.size.PerformMatch(o.size, ref match) && IsVolatile == o.IsVolatile && UnalignedPrefix == o.UnalignedPrefix; } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(destAddress.ResultType == StackType.I || destAddress.ResultType == StackType.Ref); DebugAssert(sourceAddress.ResultType == StackType.I || sourceAddress.ResultType == StackType.Ref); DebugAssert(size.ResultType == StackType.I4); @@ -3718,9 +3718,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as Initblk; return o != null && this.address.PerformMatch(o.address, ref match) && this.value.PerformMatch(o.value, ref match) && this.size.PerformMatch(o.size, ref match) && IsVolatile == o.IsVolatile && UnalignedPrefix == o.UnalignedPrefix; } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(address.ResultType == StackType.I || address.ResultType == StackType.Ref); DebugAssert(value.ResultType == StackType.I4); DebugAssert(size.ResultType == StackType.I4); @@ -4081,9 +4081,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as LdObj; return o != null && this.target.PerformMatch(o.target, ref match) && type.Equals(o.type) && IsVolatile == o.IsVolatile && UnalignedPrefix == o.UnalignedPrefix; } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(target.ResultType == StackType.Ref || target.ResultType == StackType.I); } } @@ -4191,9 +4191,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as LdObjIfRef; return o != null && this.target.PerformMatch(o.target, ref match) && type.Equals(o.type); } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(target.ResultType == StackType.Ref || target.ResultType == StackType.I); } } @@ -4330,9 +4330,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as StObj; return o != null && this.target.PerformMatch(o.target, ref match) && this.value.PerformMatch(o.value, ref match) && type.Equals(o.type) && IsVolatile == o.IsVolatile && UnalignedPrefix == o.UnalignedPrefix; } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(target.ResultType == StackType.Ref || target.ResultType == StackType.I); DebugAssert(value.ResultType == type.GetStackType()); CheckTargetSlot(); @@ -4856,9 +4856,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as LdLen; return o != null && this.array.PerformMatch(o.array, ref match); } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(array.ResultType == StackType.O); } } @@ -5218,9 +5218,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as GetPinnableReference; return o != null && this.argument.PerformMatch(o.argument, ref match) && object.Equals(method, o.method); } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(argument.ResultType == StackType.O); } } @@ -5307,9 +5307,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as StringToInt; return o != null && this.argument.PerformMatch(o.argument, ref match); } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(argument.ResultType == StackType.O); } } @@ -5831,9 +5831,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as DynamicConvertInstruction; return o != null && type.Equals(o.type) && this.argument.PerformMatch(o.argument, ref match); } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(argument.ResultType == StackType.O); } } @@ -5919,9 +5919,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as DynamicGetMemberInstruction; return o != null && this.target.PerformMatch(o.target, ref match); } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(target.ResultType == StackType.O); } } @@ -6024,9 +6024,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as DynamicSetMemberInstruction; return o != null && this.target.PerformMatch(o.target, ref match) && this.value.PerformMatch(o.value, ref match); } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(target.ResultType == StackType.O); } } @@ -6467,9 +6467,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as DynamicIsEventInstruction; return o != null && this.argument.PerformMatch(o.argument, ref match); } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(argument.ResultType == StackType.O); } } @@ -6608,9 +6608,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as MatchInstruction; return o != null && variable == o.variable && object.Equals(method, o.method) && this.IsDeconstructCall == o.IsDeconstructCall && this.IsDeconstructTuple == o.IsDeconstructTuple && this.CheckType == o.CheckType && this.CheckNotNull == o.CheckNotNull && this.testedOperand.PerformMatch(o.testedOperand, ref match) && Patterns.ListMatch.DoMatch(this.SubPatterns, o.SubPatterns, ref match); } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); DebugAssert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function!)); DebugAssert(phase <= ILPhase.InILReader || variable.Function!.Variables[variable.IndexInFunction] == variable); AdditionalInvariants(); @@ -6984,9 +6984,9 @@ namespace ICSharpCode.Decompiler.IL var o = other as DeconstructResultInstruction; return o != null && this.Argument.PerformMatch(o.Argument, ref match); } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); AdditionalInvariants(); } } diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt index 96fcb35ef..2311fb5af 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.tt +++ b/ICSharpCode.Decompiler/IL/Instructions.tt @@ -455,9 +455,9 @@ namespace <#=opCode.Namespace#> } <# } #> <# if (opCode.Invariants.Count > 0) { #> - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); <# foreach (var invariant in opCode.Invariants) {#> <#=invariant#> <# } #> diff --git a/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs index b3499fb9a..5100e6894 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs @@ -129,9 +129,9 @@ namespace ICSharpCode.Decompiler.IL get => IsLifted ? StackType.O : resultType; } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); if (!IsLifted) { Debug.Assert(LeftInputType == Left.ResultType); diff --git a/ICSharpCode.Decompiler/IL/Instructions/Block.cs b/ICSharpCode.Decompiler/IL/Instructions/Block.cs index 6c8206c46..43b76c78c 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Block.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Block.cs @@ -103,9 +103,9 @@ namespace ICSharpCode.Decompiler.IL return clone; } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); for (int i = 0; i < Instructions.Count - 1; i++) { // only the last instruction may have an unreachable endpoint @@ -358,14 +358,14 @@ namespace ICSharpCode.Decompiler.IL /// public void RunTransforms(IEnumerable transforms, BlockTransformContext context) { - this.CheckInvariant(ILPhase.Normal); + this.CheckInvariant(ILPhase.Normal, context.TypeSystem); foreach (var transform in transforms) { context.CancellationToken.ThrowIfCancellationRequested(); Debug.Assert(context.IndexOfFirstAlreadyTransformedInstruction <= this.Instructions.Count); context.StepStartGroup(transform.GetType().Name); transform.Run(this, context); - this.CheckInvariant(ILPhase.Normal); + this.CheckInvariant(ILPhase.Normal, context.TypeSystem); context.StepEndGroup(); } } diff --git a/ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs b/ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs index 9c212982d..6a929d93c 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs @@ -24,6 +24,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using ICSharpCode.Decompiler.IL.Transforms; +using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.IL { @@ -191,9 +192,9 @@ namespace ICSharpCode.Decompiler.IL return BlockSlot; } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); Debug.Assert(Blocks.Count > 0 && EntryPoint == Blocks[0]); Debug.Assert(!IsConnected || EntryPoint.IncomingEdgeCount >= 1); Debug.Assert(Parent is ILFunction || !ILRangeIsEmpty); diff --git a/ICSharpCode.Decompiler/IL/Instructions/Branch.cs b/ICSharpCode.Decompiler/IL/Instructions/Branch.cs index 1cb7b206b..dac44c186 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Branch.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Branch.cs @@ -20,6 +20,8 @@ using System; using System.Diagnostics; +using ICSharpCode.Decompiler.TypeSystem; + namespace ICSharpCode.Decompiler.IL { /// @@ -108,9 +110,9 @@ namespace ICSharpCode.Decompiler.IL return false; } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); if (phase > ILPhase.InILReader) { Debug.Assert(targetBlock?.Parent is BlockContainer); diff --git a/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs b/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs index 54a2b8880..a3781c8e6 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs @@ -68,9 +68,9 @@ namespace ICSharpCode.Decompiler.IL public override StackType ResultType => FunctionPointerType.ReturnType.GetStackType(); - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); Debug.Assert(Arguments.Count == FunctionPointerType.ParameterTypes.Length + (IsInstance ? 1 : 0)); } diff --git a/ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs index 3aa46e16e..47558a743 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs @@ -121,9 +121,9 @@ namespace ICSharpCode.Decompiler.IL } } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); int firstArgument = (OpCode != OpCode.NewObj && !Method.IsStatic) ? 1 : 0; Debug.Assert(Method.Parameters.Count + firstArgument == Arguments.Count); if (firstArgument == 1) diff --git a/ICSharpCode.Decompiler/IL/Instructions/Comp.cs b/ICSharpCode.Decompiler/IL/Instructions/Comp.cs index 2a6756644..ea320301e 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Comp.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Comp.cs @@ -164,9 +164,9 @@ namespace ICSharpCode.Decompiler.IL public bool IsLifted => LiftingKind != ComparisonLiftingKind.None; public StackType UnderlyingResultType => StackType.I4; - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); if (LiftingKind == ComparisonLiftingKind.None) { Debug.Assert(Left.ResultType == InputType); diff --git a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs index 85f49aad6..b456173ed 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs @@ -79,9 +79,9 @@ namespace ICSharpCode.Decompiler.IL CheckValidTarget(); } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); CheckValidTarget(); } diff --git a/ICSharpCode.Decompiler/IL/Instructions/Conv.cs b/ICSharpCode.Decompiler/IL/Instructions/Conv.cs index e029b1894..52f968f1a 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Conv.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Conv.cs @@ -169,9 +169,9 @@ namespace ICSharpCode.Decompiler.IL this.IsLifted = isLifted; } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); // Debug.Assert(Kind != ConversionKind.Invalid); // invalid conversion can happen with invalid IL/missing references Debug.Assert(Argument.ResultType == (IsLifted ? StackType.O : InputType)); Debug.Assert(!(IsLifted && Kind == ConversionKind.StopGCTracking)); diff --git a/ICSharpCode.Decompiler/IL/Instructions/DeconstructInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/DeconstructInstruction.cs index 3d13f228d..5382d07db 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/DeconstructInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/DeconstructInstruction.cs @@ -296,9 +296,9 @@ namespace ICSharpCode.Decompiler.IL return null; } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); var patternVariables = new HashSet(); var conversionVariables = new HashSet(); @@ -323,7 +323,7 @@ namespace ICSharpCode.Decompiler.IL foreach (var inst in assignments.Instructions) { - if (!(IsAssignment(inst, typeSystem: null, out _, out var value) && value.MatchLdLoc(out var inputVariable))) + if (!(IsAssignment(inst, compilation, out _, out var value) && value.MatchLdLoc(out var inputVariable))) throw new InvalidOperationException("inst is not an assignment!"); Debug.Assert(patternVariables.Contains(inputVariable) || conversionVariables.Contains(inputVariable)); } diff --git a/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs b/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs index c0718070c..fa4c98c16 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs @@ -230,7 +230,7 @@ namespace ICSharpCode.Decompiler.IL this.kind = kind; } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { switch (kind) { @@ -263,7 +263,7 @@ namespace ICSharpCode.Decompiler.IL Debug.Assert(Variables[i].IndexInFunction == i); Variables[i].CheckInvariant(); } - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); } void CloneVariables() @@ -401,7 +401,7 @@ namespace ICSharpCode.Decompiler.IL /// public void RunTransforms(IEnumerable transforms, ILTransformContext context) { - this.CheckInvariant(ILPhase.Normal); + this.CheckInvariant(ILPhase.Normal, context.TypeSystem); bool traceTransforms = DecompilerEventSource.Log.IsTransformTracingEnabled(); foreach (var transform in transforms) { @@ -421,7 +421,7 @@ namespace ICSharpCode.Decompiler.IL transform.Run(this, context); if (traceTransforms) DecompilerEventSource.Log.ILTransformExecuted(transform, this, traceStart); - this.CheckInvariant(ILPhase.Normal); + this.CheckInvariant(ILPhase.Normal, context.TypeSystem); context.StepEndGroup(keepIfEmpty: true); } } diff --git a/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs index e362d8a29..1b4d135f7 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs @@ -81,9 +81,16 @@ namespace ICSharpCode.Decompiler.IL Debug.Assert(b, msg); } + /// + /// Verifies the invariants of this instruction and its descendants. Only active in debug builds. + /// + /// Which set of invariants applies; they tighten as the pipeline progresses. + /// The compilation the instruction tree was decoded against, so that + /// invariants involving types can be resolved against the same type system the decompiler uses. [Conditional("DEBUG")] - internal virtual void CheckInvariant(ILPhase phase) + internal virtual void CheckInvariant(ILPhase phase, ICompilation compilation) { + Debug.Assert(compilation != null); foreach (var child in Children) { Debug.Assert(child.Parent == this); @@ -92,7 +99,7 @@ namespace ICSharpCode.Decompiler.IL // exception: nested ILFunctions (lambdas) Debug.Assert(this is ILFunction || child.flags != invalidFlags || this.flags == invalidFlags); Debug.Assert(child.IsConnected == this.IsConnected); - child.CheckInvariant(phase); + child.CheckInvariant(phase, compilation); } Debug.Assert((this.DirectFlags & ~this.Flags) == 0, "All DirectFlags must also appear in this.Flags"); } diff --git a/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs index f61e8b510..985317cc4 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs @@ -19,6 +19,8 @@ using System.Diagnostics; +using ICSharpCode.Decompiler.TypeSystem; + namespace ICSharpCode.Decompiler.IL { /// If statement / conditional expression. if (condition) trueExpr else falseExpr @@ -53,9 +55,9 @@ namespace ICSharpCode.Decompiler.IL return new IfInstruction(lhs, new LdcI4(1), rhs); } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); Debug.Assert(condition.ResultType == StackType.I4); Debug.Assert(trueInst.ResultType == falseInst.ResultType || trueInst.HasDirectFlag(InstructionFlags.EndPointUnreachable) diff --git a/ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs b/ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs index a8f064b96..d79170201 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs @@ -19,13 +19,15 @@ using System.Diagnostics; +using ICSharpCode.Decompiler.TypeSystem; + namespace ICSharpCode.Decompiler.IL { public sealed partial class LdFlda { - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); switch (field.DeclaringType.IsReferenceType) { case true: diff --git a/ICSharpCode.Decompiler/IL/Instructions/Leave.cs b/ICSharpCode.Decompiler/IL/Instructions/Leave.cs index 2b44e210d..1251d2d2f 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/Leave.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/Leave.cs @@ -19,6 +19,8 @@ using System.Diagnostics; +using ICSharpCode.Decompiler.TypeSystem; + namespace ICSharpCode.Decompiler.IL { /// @@ -106,9 +108,9 @@ namespace ICSharpCode.Decompiler.IL } } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(targetContainer!)); Debug.Assert(phase <= ILPhase.InILReader || phase == ILPhase.InAsyncAwait || value.ResultType == targetContainer!.ResultType); } diff --git a/ICSharpCode.Decompiler/IL/Instructions/LogicInstructions.cs b/ICSharpCode.Decompiler/IL/Instructions/LogicInstructions.cs index af6c74694..822309767 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/LogicInstructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/LogicInstructions.cs @@ -19,6 +19,8 @@ using System.Diagnostics; +using ICSharpCode.Decompiler.TypeSystem; + namespace ICSharpCode.Decompiler.IL { // Note: The comp instruction also supports three-valued logic via ComparisonLiftingKind.ThreeValuedLogic. @@ -29,9 +31,9 @@ namespace ICSharpCode.Decompiler.IL bool ILiftableInstruction.IsLifted => true; StackType ILiftableInstruction.UnderlyingResultType => StackType.I4; - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); Debug.Assert(Left.ResultType == StackType.I4 || Left.ResultType == StackType.O); } } @@ -41,9 +43,9 @@ namespace ICSharpCode.Decompiler.IL bool ILiftableInstruction.IsLifted => true; StackType ILiftableInstruction.UnderlyingResultType => StackType.I4; - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); Debug.Assert(Left.ResultType == StackType.I4 || Left.ResultType == StackType.O); } } diff --git a/ICSharpCode.Decompiler/IL/Instructions/NullCoalescingInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/NullCoalescingInstruction.cs index 67085e040..9820a0f7d 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/NullCoalescingInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/NullCoalescingInstruction.cs @@ -19,6 +19,8 @@ using System.Diagnostics; +using ICSharpCode.Decompiler.TypeSystem; + namespace ICSharpCode.Decompiler.IL { /// @@ -63,9 +65,9 @@ namespace ICSharpCode.Decompiler.IL this.FallbackInst = fallbackInst; } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); Debug.Assert(valueInst.ResultType == StackType.O); // lhs is reference type or nullable type Debug.Assert(fallbackInst.ResultType == StackType.O || Kind == NullCoalescingKind.NullableWithValueFallback); Debug.Assert(ResultType == UnderlyingResultType || Kind == NullCoalescingKind.Nullable); diff --git a/ICSharpCode.Decompiler/IL/Instructions/NullableInstructions.cs b/ICSharpCode.Decompiler/IL/Instructions/NullableInstructions.cs index 8fc20f6a3..6e828ce22 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/NullableInstructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/NullableInstructions.cs @@ -21,6 +21,7 @@ using System.Diagnostics; using System.Linq; using ICSharpCode.Decompiler.IL.Transforms; +using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.Decompiler.IL { @@ -76,9 +77,9 @@ namespace ICSharpCode.Decompiler.IL } } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); if (this.RefInput) { Debug.Assert(Argument.ResultType == StackType.Ref, "nullable.unwrap expects reference to nullable type as input"); @@ -108,9 +109,9 @@ namespace ICSharpCode.Decompiler.IL partial class NullableRewrap { - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); Debug.Assert(Argument.HasFlag(InstructionFlags.MayUnwrapNull)); } diff --git a/ICSharpCode.Decompiler/IL/Instructions/StLoc.cs b/ICSharpCode.Decompiler/IL/Instructions/StLoc.cs index aadecf101..1fb599c83 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/StLoc.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/StLoc.cs @@ -19,6 +19,8 @@ using System.Diagnostics; +using ICSharpCode.Decompiler.TypeSystem; + namespace ICSharpCode.Decompiler.IL { partial class StLoc @@ -36,9 +38,9 @@ namespace ICSharpCode.Decompiler.IL /// internal bool ILStackWasEmpty; - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function!)); Debug.Assert(phase <= ILPhase.InILReader || variable.Function!.Variables[variable.IndexInFunction] == variable); Debug.Assert(value.ResultType == variable.StackType); diff --git a/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs index 7f4874a7d..2ea684a36 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs @@ -152,9 +152,9 @@ namespace ICSharpCode.Decompiler.IL this.resultType = resultType; } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); bool expectNullSection = this.IsLifted; LongSet sets = LongSet.Empty; foreach (var section in Sections) diff --git a/ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs index 048a178f0..be55739ba 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs @@ -21,6 +21,7 @@ using System; using System.Diagnostics; using System.Linq; +using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.IL @@ -140,9 +141,9 @@ namespace ICSharpCode.Decompiler.IL /// partial class TryCatchHandler { - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); Debug.Assert(Parent is TryCatch); Debug.Assert(filter.ResultType == StackType.I4); Debug.Assert(this.IsDescendantOf(variable.Function!)); diff --git a/ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs index b4bf7bdc6..8aa96a380 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs @@ -19,6 +19,8 @@ using System.Diagnostics; +using ICSharpCode.Decompiler.TypeSystem; + namespace ICSharpCode.Decompiler.IL { partial class BitNot : ILiftableInstruction @@ -43,9 +45,9 @@ namespace ICSharpCode.Decompiler.IL } } - internal override void CheckInvariant(ILPhase phase) + internal override void CheckInvariant(ILPhase phase, ICompilation compilation) { - base.CheckInvariant(phase); + base.CheckInvariant(phase, compilation); Debug.Assert(IsLifted == (ResultType == StackType.O)); Debug.Assert(IsLifted || ResultType == UnderlyingResultType); } diff --git a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs index c27f34408..7971c68e6 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs @@ -199,7 +199,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms // Embed the lambda into the parent function's ILAst, so that "Show steps" can show // how the lambda body is being transformed. value.ReplaceWith(function); - function.CheckInvariant(ILPhase.Normal); + function.CheckInvariant(ILPhase.Normal, context.TypeSystem); var contextPrefix = targetMethod.Name; foreach (ILVariable v in function.Variables.Where(v => v.Kind != VariableKind.Parameter)) diff --git a/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs index 83000fe10..47c156ded 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs @@ -28,7 +28,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms { /// /// If possible, transforms plain ILAst loops into while (condition), do-while and for-loops. - /// For the invariants of the transforms . + /// For the invariants of the transforms . /// public class HighLevelLoopTransform : IILTransform { diff --git a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs index aeb82eff8..1a54a88ab 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/LocalFunctionDecompiler.cs @@ -487,7 +487,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms if (hasBody) { function.DeclarationScope = (BlockContainer)rootFunction.Body; - function.CheckInvariant(ILPhase.Normal); + function.CheckInvariant(ILPhase.Normal, context.TypeSystem); var nestedContext = new ILTransformContext(context, function); function.RunTransforms(CSharpDecompiler.GetILTransforms().TakeWhile(t => !(t is LocalFunctionDecompiler)), nestedContext); function.DeclarationScope = null; diff --git a/ICSharpCode.Decompiler/IL/Transforms/StatementTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/StatementTransform.cs index 549bd16f6..9095b480a 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/StatementTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/StatementTransform.cs @@ -139,7 +139,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms { transform.Run(block, pos, ctx); #if DEBUG - block.Instructions[pos].CheckInvariant(ILPhase.Normal); + block.Instructions[pos].CheckInvariant(ILPhase.Normal, context.TypeSystem); for (int i = Math.Max(0, pos - 100); i < pos; ++i) { if (block.Instructions[i].IsDirty) diff --git a/doc/DecompilerArchitecture.html b/doc/DecompilerArchitecture.html index 56937fb8f..37d21b2b7 100644 --- a/doc/DecompilerArchitecture.html +++ b/doc/DecompilerArchitecture.html @@ -751,7 +751,7 @@ matching is cheap. (See also doc/ILAst Pattern Matching.m

5.6 Invariants

-

CheckInvariant(ILPhase) verifies parent/child consistency, flag correctness, and +

CheckInvariant(ILPhase, ICompilation) verifies parent/child consistency, flag correctness, and connectedness. The phase parameter exists because invariants tighten over time: in ILPhase.InILReader, branches may still point at offsets; from ILPhase.Normal on, the full rules apply. ILFunction.RunTransforms checks the