internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); int firstArgument = (OpCode != OpCode.NewObj && !Method.IsStatic) ? 1 : 0; Debug.Assert(Method.Parameters.Count + firstArgument == Arguments.Count); Debug.Assert(Method.Parameters.Count + firstArgument == ArgumentToParameterMap.Length); if (firstArgument == 1) { Debug.Assert(Arguments[0].ResultType == ExpectedTypeForThisPointer(ConstrainedTo ?? Method.DeclaringType), $"Stack type mismatch in 'this' argument in call to {Method.Name}()"); Debug.Assert(ArgumentToParameterMap[0] == -1, "'this' argument must always be mapped at position 0"); } int paramCount = Method.Parameters.Count; if (paramCount > 0) { BitSet bitSet = new BitSet(paramCount); for (int i = 0; i < paramCount; ++i) { int mappedTo = ArgumentToParameterMap[firstArgument + i]; Debug.Assert(mappedTo >= 0 && mappedTo < paramCount, $"mapping out of [0..{paramCount}[, was: {mappedTo}"); Debug.Assert(!bitSet[mappedTo], $"argument {mappedTo} is already mapped to a different parameter"); bitSet.Set(mappedTo); Debug.Assert(Arguments[firstArgument + i].ResultType == Method.Parameters[mappedTo].Type.GetStackType(), $"Stack type mismatch in parameter {mappedTo} (argument {firstArgument + i}) in call to {Method.Name}()"); } Debug.Assert(bitSet.All(0, paramCount - 1), "Not all arguments are mapped to a parameter"); } }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); Debug.Assert(Kind != ConversionKind.Invalid); Debug.Assert(Argument.ResultType == (IsLifted ? StackType.O : InputType)); Debug.Assert(!(IsLifted && Kind == ConversionKind.StopGCTracking)); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); 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); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); 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); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); // 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)); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); Debug.Assert(Parent is TryCatch); Debug.Assert(filter.ResultType == StackType.I4); Debug.Assert(this.IsDescendantOf(variable.Function)); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); var patternVariables = new HashSet <ILVariable>(); var conversionVariables = new HashSet <ILVariable>(); foreach (StLoc init in this.Init) { Debug.Assert(init.Variable.IsSingleDefinition && init.Variable.LoadCount == 1); Debug.Assert(init.Variable.LoadInstructions[0].IsDescendantOf(assignments)); } ValidatePattern(pattern); foreach (var inst in this.conversions.Instructions) { if (!IsConversionStLoc(inst, out var variable, out var inputVariable)) { Debug.Fail("inst is not a conversion stloc!"); } Debug.Assert(variable.IsSingleDefinition && variable.LoadCount == 1); Debug.Assert(variable.LoadInstructions[0].IsDescendantOf(assignments)); Debug.Assert(patternVariables.Contains(inputVariable)); conversionVariables.Add(variable); } Debug.Assert(this.conversions.FinalInstruction is Nop); foreach (var inst in assignments.Instructions) { if (!(IsAssignment(inst, typeSystem: null, 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)); } Debug.Assert(this.assignments.FinalInstruction is Nop); void ValidatePattern(MatchInstruction inst) { Debug.Assert(inst.IsDeconstructCall || inst.IsDeconstructTuple); Debug.Assert(!inst.CheckNotNull && !inst.CheckType); Debug.Assert(!inst.HasDesignator); foreach (var subPattern in inst.SubPatterns.Cast <MatchInstruction>()) { if (subPattern.IsVar) { Debug.Assert(subPattern.Variable.IsSingleDefinition && subPattern.Variable.LoadCount <= 1); if (subPattern.Variable.LoadCount == 1) { Debug.Assert(subPattern.Variable.LoadInstructions[0].IsDescendantOf(this)); } patternVariables.Add(subPattern.Variable); } else { ValidatePattern(subPattern); } } } }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); Debug.Assert(EntryPoint == Blocks[0]); Debug.Assert(!IsConnected || EntryPoint.IncomingEdgeCount >= 1); Debug.Assert(Blocks.All(b => b.HasFlag(InstructionFlags.EndPointUnreachable))); Debug.Assert(Blocks.All(b => b.FinalInstruction.OpCode == OpCode.Nop)); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); Debug.Assert(condition.ResultType == StackType.I4); Debug.Assert(trueInst.ResultType == falseInst.ResultType || trueInst.HasDirectFlag(InstructionFlags.EndPointUnreachable) || falseInst.HasDirectFlag(InstructionFlags.EndPointUnreachable)); }
internal override void CheckInvariant(ILPhase phase) { for (int i = 0; i < Variables.Count; i++) { Debug.Assert(Variables[i].Function == this); Debug.Assert(Variables[i].IndexInFunction == i); } base.CheckInvariant(phase); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); for (int i = 0; i < Instructions.Count - 1; i++) { // only the last instruction may have an unreachable endpoint Debug.Assert(!Instructions[i].HasFlag(InstructionFlags.EndPointUnreachable)); } }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); if (phase > ILPhase.InILReader) { Debug.Assert(targetBlock.Parent is BlockContainer); Debug.Assert(this.IsDescendantOf(targetBlock.Parent)); Debug.Assert(targetBlock.Parent.Children[targetBlock.ChildIndex] == targetBlock); } }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); LongSet sets = LongSet.Empty; foreach (var section in Sections) { Debug.Assert(!section.Labels.IsEmpty); Debug.Assert(!section.Labels.Overlaps(sets)); sets = sets.UnionWith(section.Labels); } }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); for (int i = 0; i < Instructions.Count - 1; i++) { // only the last instruction may have an unreachable endpoint Debug.Assert(!Instructions[i].HasFlag(InstructionFlags.EndPointUnreachable)); } if (this.Type == BlockType.ControlFlow) { Debug.Assert(finalInstruction.OpCode == OpCode.Nop); } }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); if (LiftingKind == ComparisonLiftingKind.None) { Debug.Assert(Left.ResultType == InputType); Debug.Assert(Right.ResultType == InputType); } else { Debug.Assert(Left.ResultType == InputType || Left.ResultType == StackType.O); Debug.Assert(Right.ResultType == InputType || Right.ResultType == StackType.O); } }
internal virtual void CheckInvariant(ILPhase phase) { foreach (var child in Children) { Debug.Assert(child.Parent == this); Debug.Assert(this.GetChild(child.ChildIndex) == child); // if child flags are invalid, parent flags must be too // exception: nested ILFunctions (lambdas) Debug.Assert(this is ILFunction || child.flags != invalidFlags || this.flags == invalidFlags); Debug.Assert(child.IsConnected == this.IsConnected); child.CheckInvariant(phase); } Debug.Assert((this.DirectFlags & ~this.Flags) == 0, "All DirectFlags must also appear in this.Flags"); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); int firstArgument = (OpCode != OpCode.NewObj && !Method.IsStatic) ? 1 : 0; Debug.Assert(Method.Parameters.Count + firstArgument == Arguments.Count); if (firstArgument == 1) { Debug.Assert(Arguments[0].ResultType == ExpectedTypeForThisPointer(ConstrainedTo ?? Method.DeclaringType), $"Stack type mismatch in 'this' argument in call to {Method.Name}()"); } for (int i = 0; i < Method.Parameters.Count; ++i) { Debug.Assert(Arguments[firstArgument + i].ResultType == Method.Parameters[i].Type.GetStackType(), $"Stack type mismatch in parameter {i} in call to {Method.Name}()"); } }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); for (int i = 0; i < Instructions.Count - 1; i++) { // only the last instruction may have an unreachable endpoint Debug.Assert(!Instructions[i].HasFlag(InstructionFlags.EndPointUnreachable)); } switch (this.Kind) { case BlockKind.ControlFlow: Debug.Assert(finalInstruction.OpCode == OpCode.Nop); break; case BlockKind.CallInlineAssign: Debug.Assert(MatchInlineAssignBlock(out _, out _)); break; } }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); bool expectNullSection = this.IsLifted; LongSet sets = LongSet.Empty; foreach (var section in Sections) { if (section.HasNullLabel) { Debug.Assert(expectNullSection, "Duplicate 'case null' or 'case null' in non-lifted switch."); expectNullSection = false; } Debug.Assert(!section.Labels.IsEmpty || section.HasNullLabel); Debug.Assert(!section.Labels.Overlaps(sets)); sets = sets.UnionWith(section.Labels); } Debug.Assert(sets.SetEquals(LongSet.Universe), "switch does not handle all possible cases"); Debug.Assert(!expectNullSection, "Lifted switch is missing 'case null'"); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); switch (field.DeclaringType.IsReferenceType) { case true: Debug.Assert(target.ResultType == StackType.O, "Class fields can only be accessed with an object on the stack"); break; case false: Debug.Assert(target.ResultType == StackType.I || target.ResultType == StackType.Ref, "Struct fields can only be accessed with a pointer on the stack"); break; case null: // field of unresolved type Debug.Assert(target.ResultType == StackType.O || target.ResultType == StackType.I || target.ResultType == StackType.Ref); break; } }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); for (int i = 0; i < Instructions.Count - 1; i++) { // only the last instruction may have an unreachable endpoint Debug.Assert(!Instructions[i].HasFlag(InstructionFlags.EndPointUnreachable)); } switch (this.Kind) { case BlockKind.ControlFlow: Debug.Assert(finalInstruction.OpCode == OpCode.Nop); break; case BlockKind.CallInlineAssign: Debug.Assert(MatchInlineAssignBlock(out _, out _)); break; case BlockKind.CallWithNamedArgs: Debug.Assert(finalInstruction is CallInstruction); foreach (var inst in Instructions) { var stloc = inst as StLoc; Debug.Assert(stloc != null, "Instructions in CallWithNamedArgs must be assignments"); Debug.Assert(stloc.Variable.Kind == VariableKind.NamedArgument); Debug.Assert(stloc.Variable.IsSingleDefinition && stloc.Variable.LoadCount == 1); Debug.Assert(stloc.Variable.LoadInstructions.Single().Parent == finalInstruction); } var call = (CallInstruction)finalInstruction; if (call.IsInstanceCall) { // special case: with instance calls, Instructions[0] must be for the this parameter ILVariable v = ((StLoc)Instructions[0]).Variable; Debug.Assert(call.Arguments[0].MatchLdLoc(v)); } break; } }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); Debug.Assert(IsLifted == (ResultType == StackType.O)); Debug.Assert(IsLifted || ResultType == UnderlyingResultType); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); Debug.Assert(condition.ResultType == StackType.I4); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); Debug.Assert(Left.ResultType == StackType.I4 || Left.ResultType == StackType.O); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(targetContainer)); Debug.Assert(phase <= ILPhase.InILReader || phase == ILPhase.InAsyncAwait || value.ResultType == targetContainer.ResultType); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); Debug.Assert(Arguments.Count == ParameterTypes.Length + (IsInstance ? 1 : 0)); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(targetContainer)); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); Debug.Assert(valueInst.ResultType == StackType.O || valueInst.ResultType == fallbackInst.ResultType); }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); for (int i = 0; i < Instructions.Count - 1; i++) { // only the last instruction may have an unreachable endpoint Debug.Assert(!Instructions[i].HasFlag(InstructionFlags.EndPointUnreachable)); } switch (this.Kind) { case BlockKind.ControlFlow: Debug.Assert(finalInstruction.OpCode == OpCode.Nop); break; case BlockKind.CallInlineAssign: Debug.Assert(MatchInlineAssignBlock(out _, out _)); break; case BlockKind.CallWithNamedArgs: Debug.Assert(finalInstruction is CallInstruction); foreach (var inst in Instructions) { var stloc = inst as StLoc; DebugAssert(stloc != null, "Instructions in CallWithNamedArgs must be assignments"); DebugAssert(stloc.Variable.Kind == VariableKind.NamedArgument); DebugAssert(stloc.Variable.IsSingleDefinition && stloc.Variable.LoadCount == 1); DebugAssert(stloc.Variable.LoadInstructions.Single().Parent == finalInstruction); } var call = (CallInstruction)finalInstruction; if (call.IsInstanceCall) { // special case: with instance calls, Instructions[0] must be for the this parameter ILVariable v = ((StLoc)Instructions[0]).Variable; Debug.Assert(call.Arguments[0].MatchLdLoc(v)); } break; case BlockKind.ArrayInitializer: var final = finalInstruction as LdLoc; Debug.Assert(final != null && final.Variable.IsSingleDefinition && final.Variable.Kind == VariableKind.InitializerTarget); IType?type = null; Debug.Assert(Instructions[0].MatchStLoc(final !.Variable, out var init) && init.MatchNewArr(out type)); for (int i = 1; i < Instructions.Count; i++) { DebugAssert(Instructions[i].MatchStObj(out ILInstruction? target, out _, out var t) && type != null && type.Equals(t)); DebugAssert(target.MatchLdElema(out t, out ILInstruction? array) && type.Equals(t)); DebugAssert(array.MatchLdLoc(out ILVariable? v) && v == final.Variable); } break; case BlockKind.CollectionInitializer: case BlockKind.ObjectInitializer: var final2 = finalInstruction as LdLoc; Debug.Assert(final2 != null); var initVar2 = final2 !.Variable; Debug.Assert(initVar2.StoreCount == 1 && initVar2.Kind == VariableKind.InitializerTarget); IType?type2 = null; bool condition = Instructions[0].MatchStLoc(final2.Variable, out var init2); Debug.Assert(condition); Debug.Assert(init2 is NewObj || init2 is DefaultValue || (init2 is CallInstruction c && c.Method.FullNameIs("System.Activator", "CreateInstance") && c.Method.TypeArguments.Count == 1) || (init2 is Block named && named.Kind == BlockKind.CallWithNamedArgs)); switch (init2) { case NewObj newObj: type2 = newObj.Method.DeclaringType; break; case DefaultValue defaultValue: type2 = defaultValue.Type; break; case Block callWithNamedArgs when callWithNamedArgs.Kind == BlockKind.CallWithNamedArgs: type2 = ((CallInstruction)callWithNamedArgs.FinalInstruction).Method.ReturnType; break; case CallInstruction ci2 when TransformCollectionAndObjectInitializers.IsRecordCloneMethodCall(ci2): type2 = ci2.Method.DeclaringType; break; case Call c2 when c2.Method.FullNameIs("System.Activator", "CreateInstance") && c2.Method.TypeArguments.Count == 1: type2 = c2.Method.TypeArguments[0]; break; default: Debug.Assert(false); break; } for (int i = 1; i < Instructions.Count; i++) { Debug.Assert(Instructions[i] is StLoc || AccessPathElement.GetAccessPath(Instructions[i], type2).Kind != AccessPathKind.Invalid); } break; case BlockKind.DeconstructionConversions: Debug.Assert(this.SlotInfo == DeconstructInstruction.ConversionsSlot); break; case BlockKind.DeconstructionAssignments: Debug.Assert(this.SlotInfo == DeconstructInstruction.AssignmentsSlot); break; } }
internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); CheckValidTarget(); }