diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs index dfcc66d6dcb699..f87435ffc783c3 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs @@ -40,7 +40,7 @@ internal static T[] EnlargeArray(T[] incoming, int requiredSize) private int m_length; private byte[] m_ILStream; - private int[]? m_labelList; + private __LabelInfo[]? m_labelList; private int m_labelCount; private __FixupData[]? m_fixupData; @@ -61,10 +61,13 @@ internal static T[] EnlargeArray(T[] incoming, int requiredSize) internal int m_localCount; internal SignatureHelper m_localSignature; - private int m_maxStackSize; // Maximum stack size not counting the exceptions. + private int m_curDepth; // Current stack depth, with -1 meaning unknown. + private int m_targetDepth; // Stack depth at a target of the previous instruction (when it is branching). + private int m_maxDepth; // Running max of the stack depth. - private int m_maxMidStack; // Maximum stack size for a given basic block. - private int m_maxMidStackCur; // Running count of the maximum stack size for the current basic block. + // Adjustment to add to m_maxDepth for incorrect/invalid IL. For example, when branch instructions + // with different stack depths target the same label. + private long m_depthAdjustment; internal int CurrExcStackCount => m_currExcStackCount; @@ -131,28 +134,32 @@ internal void UpdateStackSize(OpCode opcode, int stackchange) // requirements for the function. stackchange specifies the amount // by which the stacksize needs to be updated. - // Special case for the Return. Returns pops 1 if there is a - // non-void return value. - - // Update the running stacksize. m_maxMidStack specifies the maximum - // amount of stack required for the current basic block irrespective of - // where you enter the block. - m_maxMidStackCur += stackchange; - if (m_maxMidStackCur > m_maxMidStack) - m_maxMidStack = m_maxMidStackCur; - else if (m_maxMidStackCur < 0) - m_maxMidStackCur = 0; - - // If the current instruction signifies end of a basic, which basically - // means an unconditional branch, add m_maxMidStack to m_maxStackSize. - // m_maxStackSize will eventually be the sum of the stack requirements for - // each basic block. - if (opcode.EndsUncondJmpBlk()) + if (m_curDepth < 0) + { + // Current depth is "unknown". We get here when: + // * this is unreachable code. + // * the client uses explicit numeric offsets rather than Labels. + m_curDepth = 0; + } + + m_curDepth += stackchange; + if (m_curDepth < 0) { - m_maxStackSize += m_maxMidStack; - m_maxMidStack = 0; - m_maxMidStackCur = 0; + // Stack underflow. Assume our previous depth computation was flawed. + m_depthAdjustment -= m_curDepth; + m_curDepth = 0; } + else if (m_maxDepth < m_curDepth) + m_maxDepth = m_curDepth; + Debug.Assert(m_depthAdjustment >= 0); + Debug.Assert(m_curDepth >= 0); + + // Record the stack depth at a "target" of this instruction. + m_targetDepth = m_curDepth; + + // If the current instruction can't fall through, set the depth to unknown. + if (opcode.EndsUncondJmpBlk()) + m_curDepth = -1; } private int GetMethodToken(MethodBase method, Type[]? optionalParameterTypes, bool useMethodDef) @@ -280,10 +287,11 @@ private int GetLabelPos(Label lbl) if (index < 0 || index >= m_labelCount || m_labelList is null) throw new ArgumentException(SR.Argument_BadLabel); - if (m_labelList[index] < 0) + int pos = m_labelList[index].m_pos; + if (pos < 0) throw new ArgumentException(SR.Argument_BadLabelContent); - return m_labelList[index]; + return pos; } private void AddFixup(Label lbl, int pos, int instSize) @@ -306,11 +314,30 @@ private void AddFixup(Label lbl, int pos, int instSize) m_fixupLabel = lbl, m_fixupInstSize = instSize }; + + int labelIndex = lbl.GetLabelValue(); + if (labelIndex < 0 || labelIndex >= m_labelCount || m_labelList is null) + throw new ArgumentException(SR.Argument_BadLabel); + + int depth = m_labelList[labelIndex].m_depth; + int targetDepth = m_targetDepth; + Debug.Assert(depth >= -1); + Debug.Assert(targetDepth >= -1); + if (depth < targetDepth) + { + // Either unknown depth for this label or this branch location has a larger depth than previously recorded. + // In the latter case, the IL is (likely) invalid, but we just compensate for it. + if (depth >= 0) + m_depthAdjustment += targetDepth - depth; + m_labelList[labelIndex].m_depth = targetDepth; + } } internal int GetMaxStackSize() { - return m_maxStackSize; + // Limit the computed max stack to 2^16 - 1, since the value is mod`ed by 2^16 by other code. + Debug.Assert(m_depthAdjustment >= 0); + return (int)Math.Min(ushort.MaxValue, m_maxDepth + m_depthAdjustment); } private static void SortExceptions(__ExceptionInfo[] exceptions) @@ -926,7 +953,7 @@ public virtual Label BeginExceptionBlock() m_currExcStack = EnlargeArray(m_currExcStack); } - Label endLabel = DefineLabel(); + Label endLabel = DefineLabel(0); __ExceptionInfo exceptionInfo = new __ExceptionInfo(m_length, endLabel); // add the exception to the tracking list @@ -934,6 +961,10 @@ public virtual Label BeginExceptionBlock() // Make this exception the current active exception m_currExcStack[m_currExcStackCount++] = exceptionInfo; + + // Stack depth for "try" starts at zero. + m_curDepth = 0; + return endLabel; } @@ -969,7 +1000,7 @@ public virtual void EndExceptionBlock() // Check if we've already set this label. // The only reason why we might have set this is if we have a finally block. - Label label = m_labelList![endLabel.GetLabelValue()] != -1 + Label label = m_labelList![endLabel.GetLabelValue()].m_pos != -1 ? current.m_finallyEndLabel : endLabel; @@ -990,6 +1021,9 @@ public virtual void BeginExceptFilterBlock() Emit(OpCodes.Leave, current.GetEndLabel()); current.MarkFilterAddr(m_length); + + // Stack depth for "filter" starts at one. + m_curDepth = 1; } public virtual void BeginCatchBlock(Type? exceptionType) @@ -1020,6 +1054,9 @@ public virtual void BeginCatchBlock(Type? exceptionType) } current.MarkCatchAddr(m_length, exceptionType); + + // Stack depth for "catch" starts at one. + m_curDepth = 1; } public virtual void BeginFaultBlock() @@ -1034,6 +1071,9 @@ public virtual void BeginFaultBlock() Emit(OpCodes.Leave, current.GetEndLabel()); current.MarkFaultAddr(m_length); + + // Stack depth for "fault" starts at zero. + m_curDepth = 0; } public virtual void BeginFinallyBlock() @@ -1055,7 +1095,7 @@ public virtual void BeginFinallyBlock() MarkLabel(endLabel); - Label finallyEndLabel = DefineLabel(); + Label finallyEndLabel = DefineLabel(0); current.SetFinallyEndLabel(finallyEndLabel); // generate leave for try clause @@ -1063,25 +1103,36 @@ public virtual void BeginFinallyBlock() if (catchEndAddr == 0) catchEndAddr = m_length; current.MarkFinallyAddr(m_length, catchEndAddr); + + // Stack depth for "finally" starts at zero. + m_curDepth = 0; } #endregion #region Labels public virtual Label DefineLabel() + { + // We don't know the stack depth at the label yet, so set it to -1. + return DefineLabel(-1); + } + + private Label DefineLabel(int depth) { // Declares a new Label. This is just a token and does not yet represent any particular location // within the stream. In order to set the position of the label within the stream, you must call // Mark Label. + Debug.Assert(depth >= -1); - // Delay init the lable array in case we dont use it - m_labelList ??= new int[DefaultLabelArraySize]; + // Delay init the label array in case we dont use it + m_labelList ??= new __LabelInfo[DefaultLabelArraySize]; if (m_labelCount >= m_labelList.Length) { m_labelList = EnlargeArray(m_labelList); } - m_labelList[m_labelCount] = -1; + m_labelList[m_labelCount].m_pos = -1; + m_labelList[m_labelCount].m_depth = depth; return new Label(m_labelCount++); } @@ -1098,12 +1149,39 @@ public virtual void MarkLabel(Label loc) throw new ArgumentException(SR.Argument_InvalidLabel); } - if (m_labelList[labelIndex] != -1) + if (m_labelList[labelIndex].m_pos != -1) { throw new ArgumentException(SR.Argument_RedefinedLabel); } - m_labelList[labelIndex] = m_length; + m_labelList[labelIndex].m_pos = m_length; + + int depth = m_labelList[labelIndex].m_depth; + if (depth < 0) + { + // Unknown depth for this label, indicating that it hasn't been used yet. + // If m_curDepth is unknown, we're in the Backward branch constraint case. See ECMA-335 III.1.7.5. + // The m_depthAdjustment field will compensate for violations of this constraint, as we + // discover them. That is, here we assume a depth of zero. If a (later) branch to this label + // has a positive stack depth, we'll record that as the new depth and add the delta into + // m_depthAdjustment. + if (m_curDepth < 0) + m_curDepth = 0; + m_labelList[labelIndex].m_depth = m_curDepth; + } + else if (depth < m_curDepth) + { + // A branch location with smaller stack targets this label. In this case, the IL is + // invalid, but we just compensate for it. + m_depthAdjustment += m_curDepth - depth; + m_labelList[labelIndex].m_depth = m_curDepth; + } + else if (depth > m_curDepth) + { + // Either the current depth is unknown, or a branch location with larger stack targets + // this label, so the IL is invalid. In either case, just adjust the current depth. + m_curDepth = depth; + } } #endregion @@ -1287,6 +1365,12 @@ public virtual void EndScope() #endregion } + internal struct __LabelInfo + { + internal int m_pos; // Position in the il stream, with -1 meaning unknown. + internal int m_depth; // Stack depth, with -1 meaning unknown. + } + internal struct __FixupData { internal Label m_fixupLabel; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs index 10da169b3e33ff..a5f4fdd8ba7d50 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs @@ -309,7 +309,7 @@ internal int GetMaxStack() { if (m_ilGenerator != null) { - return m_ilGenerator.GetMaxStackSize() + ExceptionHandlerCount; + return m_ilGenerator.GetMaxStackSize(); } else { @@ -323,8 +323,6 @@ internal int GetMaxStack() return m_exceptions; } - internal int ExceptionHandlerCount => m_exceptions != null ? m_exceptions.Length : 0; - internal static int CalculateNumberOfExceptions(__ExceptionInfo[]? excp) { int num = 0; diff --git a/src/libraries/System.Linq.Expressions/tests/BinaryOperators/Coalesce/BinaryCoalesceTests.cs b/src/libraries/System.Linq.Expressions/tests/BinaryOperators/Coalesce/BinaryCoalesceTests.cs index 50131d51cbc25b..793c26f85332fd 100644 --- a/src/libraries/System.Linq.Expressions/tests/BinaryOperators/Coalesce/BinaryCoalesceTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/BinaryOperators/Coalesce/BinaryCoalesceTests.cs @@ -506,7 +506,7 @@ public static void VerifyIL_NullableIntCoalesceToNullableInt() f.VerifyIL( @".method valuetype [System.Private.CoreLib]System.Nullable`1 ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure,valuetype [System.Private.CoreLib]System.Nullable`1,valuetype [System.Private.CoreLib]System.Nullable`1) { - .maxstack 2 + .maxstack 1 .locals init ( [0] valuetype [System.Private.CoreLib]System.Nullable`1 ) diff --git a/src/libraries/System.Linq.Expressions/tests/CompilerTests.cs b/src/libraries/System.Linq.Expressions/tests/CompilerTests.cs index 1093a8235fc441..069d72e6abcef0 100644 --- a/src/libraries/System.Linq.Expressions/tests/CompilerTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/CompilerTests.cs @@ -184,7 +184,7 @@ public static void VerifyIL_Exceptions() f.VerifyIL( @".method int32 ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure,int32) { - .maxstack 4 + .maxstack 2 .locals init ( [0] int32 ) diff --git a/src/libraries/System.Linq.Expressions/tests/StackSpillerTests.cs b/src/libraries/System.Linq.Expressions/tests/StackSpillerTests.cs index 480b85028db88d..d931126b4ef2be 100644 --- a/src/libraries/System.Linq.Expressions/tests/StackSpillerTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/StackSpillerTests.cs @@ -413,7 +413,7 @@ public static void Spill_RefInstance_IndexAssignment_CodeGen() il: @" .method int32 ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure) { - .maxstack 4 + .maxstack 3 .locals init ( [0] valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueVector&, [1] int32, @@ -516,7 +516,7 @@ public static void Spill_RefInstance_Index_CodeGen() il: @" .method int32 ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure) { - .maxstack 3 + .maxstack 2 .locals init ( [0] valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueBar&, [1] int32, @@ -611,7 +611,7 @@ public static void Spill_RefInstance_MemberAssignment_CodeGen() il: @" .method int32 ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure) { - .maxstack 3 + .maxstack 2 .locals init ( [0] valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueBar&, [1] int32, @@ -716,7 +716,7 @@ public static void Spill_RefInstance_Call_CodeGen() il: @" .method int32 ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure) { - .maxstack 3 + .maxstack 2 .locals init ( [0] valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueBar&, [1] int32, @@ -810,7 +810,7 @@ public static void Spill_RefArgs_Call_CodeGen() il: @" .method int32 ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure) { - .maxstack 3 + .maxstack 2 .locals init ( [0] int32&, [1] int32, @@ -902,7 +902,7 @@ public static void Spill_RefArgs_New_CodeGen() il: @" .method int32 ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure) { - .maxstack 5 + .maxstack 4 .locals init ( [0] int32&, [1] int32, @@ -985,7 +985,7 @@ public static void Spill_RefArgs_Invoke_CodeGen() il: @" .method int32 ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure) { - .maxstack 4 + .maxstack 3 .locals init ( [0] int32&, [1] int32, @@ -1096,7 +1096,7 @@ public static void Spill_RefArgs_Invoke_Inline_CodeGen() il: @" .method int32 ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure) { - .maxstack 3 + .maxstack 2 .locals init ( [0] int32&, [1] int32, @@ -1202,7 +1202,7 @@ public static void Spill_RefInstance_ListInit_CodeGen() il: @" .method valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueList ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure) { - .maxstack 3 + .maxstack 2 .locals init ( [0] valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueList, [1] valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueList&, @@ -1309,7 +1309,7 @@ public static void Spill_RefInstance_MemberInit_Assign_Field_CodeGen() il: @" .method valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueBar ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure) { - .maxstack 3 + .maxstack 2 .locals init ( [0] valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueBar, [1] valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueBar&, @@ -1416,7 +1416,7 @@ public static void Spill_RefInstance_MemberInit_Assign_Property_CodeGen() il: @" .method valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueBar ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure) { - .maxstack 3 + .maxstack 2 .locals init ( [0] valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueBar, [1] valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueBar&, @@ -1513,7 +1513,7 @@ public static void Spill_RefInstance_MemberInit_MemberBind_CodeGen() il: @" .method valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueBar ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure) { - .maxstack 6 + .maxstack 4 .locals init ( [0] valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueBar, [1] valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueBar&, @@ -1605,7 +1605,7 @@ public static void Spill_RefInstance_MemberInit_ListBind_CodeGen() il: @" .method valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueBar ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure) { - .maxstack 3 + .maxstack 2 .locals init ( [0] valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueBar, [1] valuetype [System.Linq.Expressions.Tests]System.Linq.Expressions.Tests.StackSpillerTests+ValueBar&, @@ -1692,7 +1692,7 @@ public static void Spill_Optimizations_Constant() e.VerifyIL(@" .method void ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure,int32[]) { - .maxstack 4 + .maxstack 3 .locals init ( [0] int32[], [1] int32, @@ -1750,7 +1750,7 @@ public static void Spill_Optimizations_Default() e.VerifyIL(@" .method void ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure,int32[]) { - .maxstack 4 + .maxstack 3 .locals init ( [0] int32[], [1] int32, @@ -1806,7 +1806,7 @@ public static void Spill_Optimizations_LiteralField_NotNetFramework() e.VerifyIL(@" .method float64 ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure) { - .maxstack 3 + .maxstack 2 .locals init ( [0] float64, [1] float64 @@ -1855,7 +1855,7 @@ public static void Spill_Optimizations_StaticReadOnlyField() e.VerifyIL(@" .method string ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure) { - .maxstack 3 + .maxstack 2 .locals init ( [0] string, [1] string @@ -1906,7 +1906,7 @@ public static void Spill_Optimizations_RuntimeVariables1() e.VerifyIL(@" .method void ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure,class [System.Private.CoreLib]System.Action`2) { - .maxstack 4 + .maxstack 3 .locals init ( [0] class [System.Private.CoreLib]System.Action`2, [1] int32, @@ -1967,7 +1967,7 @@ public static void Spill_Optimizations_RuntimeVariables2() e.VerifyIL(@" .method void ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure,class [System.Private.CoreLib]System.Action`2,int32) { - .maxstack 10 + .maxstack 6 .locals init ( [0] object[], [1] class [System.Private.CoreLib]System.Action`2, @@ -2057,7 +2057,7 @@ public static void Spill_Optimizations_NoSpillBeyondSpillSite1() e.VerifyIL(@" .method int32 ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure,class [System.Private.CoreLib]System.Func`4,int32,int32,int32) { - .maxstack 5 + .maxstack 4 .locals init ( [0] class [System.Private.CoreLib]System.Func`4, [1] int32, @@ -2135,7 +2135,7 @@ public static void Spill_Optimizations_NoSpillBeyondSpillSite2() e.VerifyIL(@" .method int32 ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure,int32,int32,int32,int32) { - .maxstack 3 + .maxstack 2 .locals init ( [0] int32, [1] int32, diff --git a/src/libraries/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedNullableTests.cs b/src/libraries/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedNullableTests.cs index 9811cd7b632d3e..f67ee3ab6f81a7 100644 --- a/src/libraries/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedNullableTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedNullableTests.cs @@ -212,7 +212,7 @@ public static void VerifyIL_NullableShortNegateChecked() f.VerifyIL( @".method valuetype [System.Private.CoreLib]System.Nullable`1 ::lambda_method(class [System.Linq.Expressions]System.Runtime.CompilerServices.Closure,valuetype [System.Private.CoreLib]System.Nullable`1) { - .maxstack 4 + .maxstack 3 .locals init ( [0] valuetype [System.Private.CoreLib]System.Nullable`1 ) diff --git a/src/libraries/System.Reflection.Emit.ILGeneration/System.Reflection.Emit.ILGeneration.sln b/src/libraries/System.Reflection.Emit.ILGeneration/System.Reflection.Emit.ILGeneration.sln index 225e615fd3208f..43dc12f65a668c 100644 --- a/src/libraries/System.Reflection.Emit.ILGeneration/System.Reflection.Emit.ILGeneration.sln +++ b/src/libraries/System.Reflection.Emit.ILGeneration/System.Reflection.Emit.ILGeneration.sln @@ -1,4 +1,8 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32505.173 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{B1053D24-237E-4E55-9413-20B34ED79F23}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{05696F45-ACF1-4C02-B8D9-E8C1F5E28717}" @@ -33,17 +37,23 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{155A2103-05C EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Checked|Any CPU = Checked|Any CPU + Checked|x64 = Checked|x64 + Checked|x86 = Checked|x86 Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 - Checked|Any CPU = Checked|Any CPU - Checked|x64 = Checked|x64 - Checked|x86 = Checked|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B1053D24-237E-4E55-9413-20B34ED79F23}.Checked|Any CPU.ActiveCfg = Checked|x64 + {B1053D24-237E-4E55-9413-20B34ED79F23}.Checked|Any CPU.Build.0 = Checked|x64 + {B1053D24-237E-4E55-9413-20B34ED79F23}.Checked|x64.ActiveCfg = Checked|x64 + {B1053D24-237E-4E55-9413-20B34ED79F23}.Checked|x64.Build.0 = Checked|x64 + {B1053D24-237E-4E55-9413-20B34ED79F23}.Checked|x86.ActiveCfg = Checked|x86 + {B1053D24-237E-4E55-9413-20B34ED79F23}.Checked|x86.Build.0 = Checked|x86 {B1053D24-237E-4E55-9413-20B34ED79F23}.Debug|Any CPU.ActiveCfg = Debug|x64 {B1053D24-237E-4E55-9413-20B34ED79F23}.Debug|Any CPU.Build.0 = Debug|x64 {B1053D24-237E-4E55-9413-20B34ED79F23}.Debug|x64.ActiveCfg = Debug|x64 @@ -56,12 +66,12 @@ Global {B1053D24-237E-4E55-9413-20B34ED79F23}.Release|x64.Build.0 = Release|x64 {B1053D24-237E-4E55-9413-20B34ED79F23}.Release|x86.ActiveCfg = Release|x86 {B1053D24-237E-4E55-9413-20B34ED79F23}.Release|x86.Build.0 = Release|x86 - {B1053D24-237E-4E55-9413-20B34ED79F23}.Checked|Any CPU.ActiveCfg = Checked|x64 - {B1053D24-237E-4E55-9413-20B34ED79F23}.Checked|Any CPU.Build.0 = Checked|x64 - {B1053D24-237E-4E55-9413-20B34ED79F23}.Checked|x64.ActiveCfg = Checked|x64 - {B1053D24-237E-4E55-9413-20B34ED79F23}.Checked|x64.Build.0 = Checked|x64 - {B1053D24-237E-4E55-9413-20B34ED79F23}.Checked|x86.ActiveCfg = Checked|x86 - {B1053D24-237E-4E55-9413-20B34ED79F23}.Checked|x86.Build.0 = Checked|x86 + {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Checked|Any CPU.Build.0 = Debug|Any CPU + {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Checked|x64.ActiveCfg = Debug|Any CPU + {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Checked|x64.Build.0 = Debug|Any CPU + {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Checked|x86.ActiveCfg = Debug|Any CPU + {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Checked|x86.Build.0 = Debug|Any CPU {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Debug|Any CPU.Build.0 = Debug|Any CPU {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -74,12 +84,12 @@ Global {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Release|x64.Build.0 = Release|Any CPU {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Release|x86.ActiveCfg = Release|Any CPU {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Release|x86.Build.0 = Release|Any CPU - {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Checked|Any CPU.Build.0 = Debug|Any CPU - {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Checked|x64.ActiveCfg = Debug|Any CPU - {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Checked|x64.Build.0 = Debug|Any CPU - {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Checked|x86.ActiveCfg = Debug|Any CPU - {05696F45-ACF1-4C02-B8D9-E8C1F5E28717}.Checked|x86.Build.0 = Debug|Any CPU + {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Checked|Any CPU.Build.0 = Debug|Any CPU + {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Checked|x64.ActiveCfg = Debug|Any CPU + {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Checked|x64.Build.0 = Debug|Any CPU + {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Checked|x86.ActiveCfg = Debug|Any CPU + {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Checked|x86.Build.0 = Debug|Any CPU {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Debug|Any CPU.Build.0 = Debug|Any CPU {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -92,12 +102,12 @@ Global {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Release|x64.Build.0 = Release|Any CPU {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Release|x86.ActiveCfg = Release|Any CPU {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Release|x86.Build.0 = Release|Any CPU - {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Checked|Any CPU.Build.0 = Debug|Any CPU - {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Checked|x64.ActiveCfg = Debug|Any CPU - {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Checked|x64.Build.0 = Debug|Any CPU - {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Checked|x86.ActiveCfg = Debug|Any CPU - {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1}.Checked|x86.Build.0 = Debug|Any CPU + {8843EA69-AD8F-4C73-8436-1641470199DC}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {8843EA69-AD8F-4C73-8436-1641470199DC}.Checked|Any CPU.Build.0 = Debug|Any CPU + {8843EA69-AD8F-4C73-8436-1641470199DC}.Checked|x64.ActiveCfg = Debug|Any CPU + {8843EA69-AD8F-4C73-8436-1641470199DC}.Checked|x64.Build.0 = Debug|Any CPU + {8843EA69-AD8F-4C73-8436-1641470199DC}.Checked|x86.ActiveCfg = Debug|Any CPU + {8843EA69-AD8F-4C73-8436-1641470199DC}.Checked|x86.Build.0 = Debug|Any CPU {8843EA69-AD8F-4C73-8436-1641470199DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8843EA69-AD8F-4C73-8436-1641470199DC}.Debug|Any CPU.Build.0 = Debug|Any CPU {8843EA69-AD8F-4C73-8436-1641470199DC}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -110,12 +120,12 @@ Global {8843EA69-AD8F-4C73-8436-1641470199DC}.Release|x64.Build.0 = Release|Any CPU {8843EA69-AD8F-4C73-8436-1641470199DC}.Release|x86.ActiveCfg = Release|Any CPU {8843EA69-AD8F-4C73-8436-1641470199DC}.Release|x86.Build.0 = Release|Any CPU - {8843EA69-AD8F-4C73-8436-1641470199DC}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {8843EA69-AD8F-4C73-8436-1641470199DC}.Checked|Any CPU.Build.0 = Debug|Any CPU - {8843EA69-AD8F-4C73-8436-1641470199DC}.Checked|x64.ActiveCfg = Debug|Any CPU - {8843EA69-AD8F-4C73-8436-1641470199DC}.Checked|x64.Build.0 = Debug|Any CPU - {8843EA69-AD8F-4C73-8436-1641470199DC}.Checked|x86.ActiveCfg = Debug|Any CPU - {8843EA69-AD8F-4C73-8436-1641470199DC}.Checked|x86.Build.0 = Debug|Any CPU + {64BBA40A-8DB5-4829-815A-3D612A12222D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {64BBA40A-8DB5-4829-815A-3D612A12222D}.Checked|Any CPU.Build.0 = Debug|Any CPU + {64BBA40A-8DB5-4829-815A-3D612A12222D}.Checked|x64.ActiveCfg = Debug|Any CPU + {64BBA40A-8DB5-4829-815A-3D612A12222D}.Checked|x64.Build.0 = Debug|Any CPU + {64BBA40A-8DB5-4829-815A-3D612A12222D}.Checked|x86.ActiveCfg = Debug|Any CPU + {64BBA40A-8DB5-4829-815A-3D612A12222D}.Checked|x86.Build.0 = Debug|Any CPU {64BBA40A-8DB5-4829-815A-3D612A12222D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {64BBA40A-8DB5-4829-815A-3D612A12222D}.Debug|Any CPU.Build.0 = Debug|Any CPU {64BBA40A-8DB5-4829-815A-3D612A12222D}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -128,12 +138,12 @@ Global {64BBA40A-8DB5-4829-815A-3D612A12222D}.Release|x64.Build.0 = Release|Any CPU {64BBA40A-8DB5-4829-815A-3D612A12222D}.Release|x86.ActiveCfg = Release|Any CPU {64BBA40A-8DB5-4829-815A-3D612A12222D}.Release|x86.Build.0 = Release|Any CPU - {64BBA40A-8DB5-4829-815A-3D612A12222D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {64BBA40A-8DB5-4829-815A-3D612A12222D}.Checked|Any CPU.Build.0 = Debug|Any CPU - {64BBA40A-8DB5-4829-815A-3D612A12222D}.Checked|x64.ActiveCfg = Debug|Any CPU - {64BBA40A-8DB5-4829-815A-3D612A12222D}.Checked|x64.Build.0 = Debug|Any CPU - {64BBA40A-8DB5-4829-815A-3D612A12222D}.Checked|x86.ActiveCfg = Debug|Any CPU - {64BBA40A-8DB5-4829-815A-3D612A12222D}.Checked|x86.Build.0 = Debug|Any CPU + {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Checked|Any CPU.Build.0 = Debug|Any CPU + {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Checked|x64.ActiveCfg = Debug|Any CPU + {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Checked|x64.Build.0 = Debug|Any CPU + {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Checked|x86.ActiveCfg = Debug|Any CPU + {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Checked|x86.Build.0 = Debug|Any CPU {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Debug|Any CPU.Build.0 = Debug|Any CPU {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -146,12 +156,12 @@ Global {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Release|x64.Build.0 = Release|Any CPU {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Release|x86.ActiveCfg = Release|Any CPU {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Release|x86.Build.0 = Release|Any CPU - {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Checked|Any CPU.Build.0 = Debug|Any CPU - {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Checked|x64.ActiveCfg = Debug|Any CPU - {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Checked|x64.Build.0 = Debug|Any CPU - {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Checked|x86.ActiveCfg = Debug|Any CPU - {A18E814C-13D6-4859-B6FA-3CAB8673B31F}.Checked|x86.Build.0 = Debug|Any CPU + {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Checked|Any CPU.Build.0 = Debug|Any CPU + {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Checked|x64.ActiveCfg = Debug|Any CPU + {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Checked|x64.Build.0 = Debug|Any CPU + {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Checked|x86.ActiveCfg = Debug|Any CPU + {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Checked|x86.Build.0 = Debug|Any CPU {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Debug|Any CPU.Build.0 = Debug|Any CPU {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -164,12 +174,12 @@ Global {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Release|x64.Build.0 = Release|Any CPU {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Release|x86.ActiveCfg = Release|Any CPU {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Release|x86.Build.0 = Release|Any CPU - {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Checked|Any CPU.Build.0 = Debug|Any CPU - {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Checked|x64.ActiveCfg = Debug|Any CPU - {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Checked|x64.Build.0 = Debug|Any CPU - {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Checked|x86.ActiveCfg = Debug|Any CPU - {EA6F01DF-1F63-49FF-A6E8-CA9104296196}.Checked|x86.Build.0 = Debug|Any CPU + {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Checked|Any CPU.Build.0 = Debug|Any CPU + {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Checked|x64.ActiveCfg = Debug|Any CPU + {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Checked|x64.Build.0 = Debug|Any CPU + {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Checked|x86.ActiveCfg = Debug|Any CPU + {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Checked|x86.Build.0 = Debug|Any CPU {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Debug|Any CPU.Build.0 = Debug|Any CPU {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -182,12 +192,12 @@ Global {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Release|x64.Build.0 = Release|Any CPU {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Release|x86.ActiveCfg = Release|Any CPU {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Release|x86.Build.0 = Release|Any CPU - {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Checked|Any CPU.Build.0 = Debug|Any CPU - {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Checked|x64.ActiveCfg = Debug|Any CPU - {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Checked|x64.Build.0 = Debug|Any CPU - {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Checked|x86.ActiveCfg = Debug|Any CPU - {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1}.Checked|x86.Build.0 = Debug|Any CPU + {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Checked|Any CPU.Build.0 = Debug|Any CPU + {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Checked|x64.ActiveCfg = Debug|Any CPU + {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Checked|x64.Build.0 = Debug|Any CPU + {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Checked|x86.ActiveCfg = Debug|Any CPU + {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Checked|x86.Build.0 = Debug|Any CPU {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Debug|Any CPU.Build.0 = Debug|Any CPU {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -200,12 +210,12 @@ Global {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Release|x64.Build.0 = Release|Any CPU {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Release|x86.ActiveCfg = Release|Any CPU {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Release|x86.Build.0 = Release|Any CPU - {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Checked|Any CPU.Build.0 = Debug|Any CPU - {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Checked|x64.ActiveCfg = Debug|Any CPU - {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Checked|x64.Build.0 = Debug|Any CPU - {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Checked|x86.ActiveCfg = Debug|Any CPU - {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D}.Checked|x86.Build.0 = Debug|Any CPU + {3461E542-7F19-4B98-B206-BDF932529A5B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {3461E542-7F19-4B98-B206-BDF932529A5B}.Checked|Any CPU.Build.0 = Debug|Any CPU + {3461E542-7F19-4B98-B206-BDF932529A5B}.Checked|x64.ActiveCfg = Debug|Any CPU + {3461E542-7F19-4B98-B206-BDF932529A5B}.Checked|x64.Build.0 = Debug|Any CPU + {3461E542-7F19-4B98-B206-BDF932529A5B}.Checked|x86.ActiveCfg = Debug|Any CPU + {3461E542-7F19-4B98-B206-BDF932529A5B}.Checked|x86.Build.0 = Debug|Any CPU {3461E542-7F19-4B98-B206-BDF932529A5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3461E542-7F19-4B98-B206-BDF932529A5B}.Debug|Any CPU.Build.0 = Debug|Any CPU {3461E542-7F19-4B98-B206-BDF932529A5B}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -218,12 +228,12 @@ Global {3461E542-7F19-4B98-B206-BDF932529A5B}.Release|x64.Build.0 = Release|Any CPU {3461E542-7F19-4B98-B206-BDF932529A5B}.Release|x86.ActiveCfg = Release|Any CPU {3461E542-7F19-4B98-B206-BDF932529A5B}.Release|x86.Build.0 = Release|Any CPU - {3461E542-7F19-4B98-B206-BDF932529A5B}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {3461E542-7F19-4B98-B206-BDF932529A5B}.Checked|Any CPU.Build.0 = Debug|Any CPU - {3461E542-7F19-4B98-B206-BDF932529A5B}.Checked|x64.ActiveCfg = Debug|Any CPU - {3461E542-7F19-4B98-B206-BDF932529A5B}.Checked|x64.Build.0 = Debug|Any CPU - {3461E542-7F19-4B98-B206-BDF932529A5B}.Checked|x86.ActiveCfg = Debug|Any CPU - {3461E542-7F19-4B98-B206-BDF932529A5B}.Checked|x86.Build.0 = Debug|Any CPU + {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Checked|Any CPU.Build.0 = Debug|Any CPU + {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Checked|x64.ActiveCfg = Debug|Any CPU + {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Checked|x64.Build.0 = Debug|Any CPU + {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Checked|x86.ActiveCfg = Debug|Any CPU + {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Checked|x86.Build.0 = Debug|Any CPU {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Debug|Any CPU.Build.0 = Debug|Any CPU {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -236,12 +246,12 @@ Global {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Release|x64.Build.0 = Release|Any CPU {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Release|x86.ActiveCfg = Release|Any CPU {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Release|x86.Build.0 = Release|Any CPU - {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Checked|Any CPU.Build.0 = Debug|Any CPU - {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Checked|x64.ActiveCfg = Debug|Any CPU - {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Checked|x64.Build.0 = Debug|Any CPU - {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Checked|x86.ActiveCfg = Debug|Any CPU - {D2A00A5C-148B-43D2-BD72-4B70D8E990EB}.Checked|x86.Build.0 = Debug|Any CPU + {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Checked|Any CPU.Build.0 = Debug|Any CPU + {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Checked|x64.ActiveCfg = Debug|Any CPU + {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Checked|x64.Build.0 = Debug|Any CPU + {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Checked|x86.ActiveCfg = Debug|Any CPU + {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Checked|x86.Build.0 = Debug|Any CPU {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Debug|Any CPU.Build.0 = Debug|Any CPU {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -254,31 +264,28 @@ Global {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Release|x64.Build.0 = Release|Any CPU {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Release|x86.ActiveCfg = Release|Any CPU {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Release|x86.Build.0 = Release|Any CPU - {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Checked|Any CPU.Build.0 = Debug|Any CPU - {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Checked|x64.ActiveCfg = Debug|Any CPU - {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Checked|x64.Build.0 = Debug|Any CPU - {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Checked|x86.ActiveCfg = Debug|Any CPU - {81204A19-8DF3-461B-A5FE-7B85149F5CCD}.Checked|x86.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {B1053D24-237E-4E55-9413-20B34ED79F23} = {C723F596-B189-428C-A090-F4965F87A73D} - {A18E814C-13D6-4859-B6FA-3CAB8673B31F} = {C723F596-B189-428C-A090-F4965F87A73D} {05696F45-ACF1-4C02-B8D9-E8C1F5E28717} = {61C529DF-66C4-42E9-AE70-3427838FAFE3} - {EA6F01DF-1F63-49FF-A6E8-CA9104296196} = {61C529DF-66C4-42E9-AE70-3427838FAFE3} {5EC8FDE3-DD46-4D89-80AC-AEF571C405B1} = {A20A0878-5647-4145-B224-C390446B7676} + {8843EA69-AD8F-4C73-8436-1641470199DC} = {155A2103-05C1-4020-8922-4F6275F6AE7E} {64BBA40A-8DB5-4829-815A-3D612A12222D} = {A20A0878-5647-4145-B224-C390446B7676} + {A18E814C-13D6-4859-B6FA-3CAB8673B31F} = {C723F596-B189-428C-A090-F4965F87A73D} + {EA6F01DF-1F63-49FF-A6E8-CA9104296196} = {61C529DF-66C4-42E9-AE70-3427838FAFE3} {1F1F9925-48BB-4384-9C46-ADBDCC7E72D1} = {A20A0878-5647-4145-B224-C390446B7676} - {D2A00A5C-148B-43D2-BD72-4B70D8E990EB} = {A20A0878-5647-4145-B224-C390446B7676} - {81204A19-8DF3-461B-A5FE-7B85149F5CCD} = {A20A0878-5647-4145-B224-C390446B7676} - {8843EA69-AD8F-4C73-8436-1641470199DC} = {155A2103-05C1-4020-8922-4F6275F6AE7E} {FFA71ACB-EAD8-4242-A5D6-FBB3F704949D} = {155A2103-05C1-4020-8922-4F6275F6AE7E} {3461E542-7F19-4B98-B206-BDF932529A5B} = {155A2103-05C1-4020-8922-4F6275F6AE7E} + {D2A00A5C-148B-43D2-BD72-4B70D8E990EB} = {A20A0878-5647-4145-B224-C390446B7676} + {81204A19-8DF3-461B-A5FE-7B85149F5CCD} = {A20A0878-5647-4145-B224-C390446B7676} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {248E0825-3C88-4854-B192-C50C9FDDBBC3} EndGlobalSection + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems*{b1053d24-237e-4e55-9413-20b34ed79f23}*SharedItemsImports = 5 + EndGlobalSection EndGlobal diff --git a/src/libraries/System.Reflection.Emit.ILGeneration/tests/ILGenerator/Emit5Tests.cs b/src/libraries/System.Reflection.Emit.ILGeneration/tests/ILGenerator/Emit5Tests.cs new file mode 100644 index 00000000000000..7a11fd4cb4c63e --- /dev/null +++ b/src/libraries/System.Reflection.Emit.ILGeneration/tests/ILGenerator/Emit5Tests.cs @@ -0,0 +1,305 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using Xunit; + +namespace System.Reflection.Emit.Tests +{ + public class ILGeneratorEmit5 + { + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/63805", TestRuntimes.Mono)] + public void MaxStackOverflowTest() + { + Run(1 << 5); + Run(1 << 10); + + // Previously this threw because the computed stack depth was 2^16 + 1, which is 1 mod 2^16 + // and 1 is too small. + Run(1 << 14); + + static void Run(int num) + { + var meth = GetCode(num); + Assert.NotNull(meth); + Assert.Equal(typeof(int), meth.ReturnType); + + var body = meth.GetMethodBody(); + Assert.Equal(4, body.MaxStackSize); // Previously the depth was computed as 4 * num + 1. + + var val = (int)meth.Invoke(null, null); + Assert.Equal(4 * num, val); + } + + /// + /// The parameter is the number of basic blocks. Each has a max stack + /// depth of four. There is one final basic block with max stack of one. The ILGenerator + /// erroneously adds these, so the final value can overflow 2^16. When that result mod 2^16 + /// is less than required, the CLR throws an . + /// + static MethodInfo GetCode(int num) + { + TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); + MethodBuilder method = type.DefineMethod("meth1", MethodAttributes.Public | MethodAttributes.Static, typeof(int), Type.EmptyTypes); + var ilg = method.GetILGenerator(); + + var loc = ilg.DeclareLocal(typeof(int)); + ilg.Emit(OpCodes.Ldc_I4_0); + ilg.Emit(OpCodes.Stloc, loc); + + for (int i = 0; i < num; i++) + { + ilg.Emit(OpCodes.Ldloc, loc); + ilg.Emit(OpCodes.Ldc_I4_1); + ilg.Emit(OpCodes.Ldc_I4_1); + ilg.Emit(OpCodes.Ldc_I4_2); + ilg.Emit(OpCodes.Add); + ilg.Emit(OpCodes.Add); + ilg.Emit(OpCodes.Add); + ilg.Emit(OpCodes.Stloc, loc); + + // Unconditional jump to next block. + var labNext = ilg.DefineLabel(); + ilg.Emit(OpCodes.Br, labNext); + ilg.MarkLabel(labNext); + } + + ilg.Emit(OpCodes.Ldloc, loc); + ilg.Emit(OpCodes.Ret); + + // Create the type where this method is in + Type createdType = type.CreateTypeInfo().AsType(); + MethodInfo createdMethod = createdType.GetMethod("meth1"); + + return createdMethod; + } + } + + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/63805", TestRuntimes.Mono)] + public void MaxStackNonEmptyForward() + { + // This test uses forward branches to "new" basic blocks where the stack depth + // at the branch location is non-empty. + + Run(1 << 0); + Run(1 << 1); + Run(1 << 5); + + // This one seems to overwhelm the jit or something. + // Run(1 << 10); + + void Run(int num) + { + var meth = GetCode(num); + Assert.NotNull(meth); + Assert.Equal(typeof(int), meth.ReturnType); + + var body = meth.GetMethodBody(); + Assert.Equal(2 * num + 3, body.MaxStackSize); // Previously the depth was computed as 4 * num + 1. + + var val = (int)meth.Invoke(null, null); + Assert.Equal(4 * num, val); + } + + static MethodInfo GetCode(int num) + { + TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); + MethodBuilder method = type.DefineMethod("meth1", MethodAttributes.Public | MethodAttributes.Static, typeof(int), Type.EmptyTypes); + var ilg = method.GetILGenerator(); + + ilg.Emit(OpCodes.Ldc_I4_0); + for (int i = 0; i < num; i++) + { + ilg.Emit(OpCodes.Ldc_I4_1); + ilg.Emit(OpCodes.Ldc_I4_1); + ilg.Emit(OpCodes.Ldc_I4_1); + ilg.Emit(OpCodes.Ldc_I4_1); + ilg.Emit(OpCodes.Add); + ilg.Emit(OpCodes.Add); + + // Unconditional jump to next block. + var labNext = ilg.DefineLabel(); + ilg.Emit(OpCodes.Br, labNext); + ilg.MarkLabel(labNext); + } + + // Each block leaves two values on the stack. Add them into the previous value. + for (int i = 0; i < num; i++) + { + ilg.Emit(OpCodes.Add); + ilg.Emit(OpCodes.Add); + } + + ilg.Emit(OpCodes.Ret); + + // Create the type where this method is in + Type createdType = type.CreateTypeInfo().AsType(); + return createdType.GetMethod("meth1"); + } + } + + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/63805", TestRuntimes.Mono)] + public void MaxStackNonEmptyBackward() + { + // This test uses backward branches to "new" basic blocks where the stack depth + // at the branch location is non-empty. + + Run(1 << 1); + Run(1 << 2); + Run(1 << 3); + Run(1 << 4); + Run(1 << 5); + + // This one seems to overwhelm the jit or something. + // Run(1 << 10); + + void Run(int num) + { + var meth = GetCode(num); + Assert.NotNull(meth); + Assert.Equal(typeof(int), meth.ReturnType); + + var body = meth.GetMethodBody(); + Assert.Equal(4 * num + 2, body.MaxStackSize); + + var val = (int)meth.Invoke(null, null); + Assert.Equal(4 * num, val); + } + + static MethodInfo GetCode(int num) + { + TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); + MethodBuilder method = type.DefineMethod("meth1", MethodAttributes.Public | MethodAttributes.Static, typeof(int), Type.EmptyTypes); + var ilg = method.GetILGenerator(); + + var labels = new Label[num + 1]; + for (int i = 0; i <= num; i++) + labels[i] = ilg.DefineLabel(); + + ilg.Emit(OpCodes.Ldc_I4_0); + ilg.Emit(OpCodes.Br, labels[0]); + + for (int i = num; --i >= 0;) + { + ilg.MarkLabel(labels[i]); + + ilg.Emit(OpCodes.Ldc_I4_1); + ilg.Emit(OpCodes.Ldc_I4_1); + ilg.Emit(OpCodes.Ldc_I4_1); + ilg.Emit(OpCodes.Ldc_I4_1); + ilg.Emit(OpCodes.Add); + ilg.Emit(OpCodes.Add); + + // Unconditional jump to "next" block (which is really before this code). + ilg.Emit(OpCodes.Br, labels[i + 1]); + } + + ilg.MarkLabel(labels[num]); + + // Each block leaves two values on the stack. Add them into the previous value. + for (int i = 0; i < num; i++) + { + ilg.Emit(OpCodes.Add); + ilg.Emit(OpCodes.Add); + } + + ilg.Emit(OpCodes.Ret); + + // Create the type where this method is in + Type createdType = type.CreateTypeInfo().AsType(); + return createdType.GetMethod("meth1"); + } + } + + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/63805", TestRuntimes.Mono)] + public void AmbiguousDepth() + { + var meth = GetCode(); + Assert.NotNull(meth); + Assert.Equal(typeof(int), meth.ReturnType); + + var body = meth.GetMethodBody(); + // Observed depth of 2, with "adjustment" of 1. + Assert.Equal(2 + 1, body.MaxStackSize); + + try + { + meth.Invoke(null, new object[] { false }); + Assert.True(false); + } + catch (TargetInvocationException ex) + { + Assert.IsType(ex.InnerException); + } + + static MethodInfo GetCode() + { + TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); + MethodBuilder method = type.DefineMethod("meth1", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new[] { typeof(bool) }); + var ilg = method.GetILGenerator(); + + // The label is targeted with stack depth zero. + var lab = ilg.DefineLabel(); + ilg.Emit(OpCodes.Ldarg_0); + ilg.Emit(OpCodes.Brfalse, lab); + + // The label is marked with a larger stack depth, one. This IL is invalid. + ilg.Emit(OpCodes.Ldc_I4_1); + ilg.MarkLabel(lab); + + ilg.Emit(OpCodes.Ldc_I4_1); + ilg.Emit(OpCodes.Add); + ilg.Emit(OpCodes.Ret); + + // Create the type where this method is in + Type createdType = type.CreateTypeInfo().AsType(); + return createdType.GetMethod("meth1"); + } + } + + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/63805", TestRuntimes.Mono)] + public void UnreachableDepth() + { + var meth = GetCode(); + Assert.NotNull(meth); + Assert.Equal(typeof(int), meth.ReturnType); + + var body = meth.GetMethodBody(); + // Observed depth of 2, with no "adjustment". + Assert.Equal(2, body.MaxStackSize); + + var val = (int)meth.Invoke(null, null); + Assert.Equal(2, val); + + static MethodInfo GetCode() + { + TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public); + MethodBuilder method = type.DefineMethod("meth1", MethodAttributes.Public | MethodAttributes.Static, typeof(int), Type.EmptyTypes); + var ilg = method.GetILGenerator(); + + var lab = ilg.DefineLabel(); + + ilg.Emit(OpCodes.Ldc_I4_1); + ilg.Emit(OpCodes.Ldc_I4_1); + ilg.Emit(OpCodes.Br, lab); + + // Unreachable. + ilg.Emit(OpCodes.Ldarg_0); + + // Depth + ilg.MarkLabel(lab); + ilg.Emit(OpCodes.Add); + ilg.Emit(OpCodes.Ret); + + // Create the type where this method is in + Type createdType = type.CreateTypeInfo().AsType(); + return createdType.GetMethod("meth1"); + } + } + } +} diff --git a/src/libraries/System.Reflection.Emit.ILGeneration/tests/System.Reflection.Emit.ILGeneration.Tests.csproj b/src/libraries/System.Reflection.Emit.ILGeneration/tests/System.Reflection.Emit.ILGeneration.Tests.csproj index fb6a8ef9b6fd00..9c672251db0af0 100644 --- a/src/libraries/System.Reflection.Emit.ILGeneration/tests/System.Reflection.Emit.ILGeneration.Tests.csproj +++ b/src/libraries/System.Reflection.Emit.ILGeneration/tests/System.Reflection.Emit.ILGeneration.Tests.csproj @@ -10,6 +10,7 @@ +