Add method array args support for eval.
authorMikhail Kurinnoi <m.kurinnoi@samsung.com>
Fri, 22 Jul 2022 10:52:30 +0000 (13:52 +0300)
committerAlexander Soldatov/Platform Lab /SRR/Staff Engineer/Samsung Electronics <soldatov.a@samsung.com>
Thu, 28 Jul 2022 12:12:36 +0000 (15:12 +0300)
src/debugger/evalstackmachine.cpp
src/debugger/evaluator.cpp
test-suite/MITestEvaluate/Program.cs
test-suite/VSCodeTestEvaluate/Program.cs

index 2dcd0a8e0ea969662505c736702d632e44ad81fb..4db7abd2da07444789d280794a9946dffde52da5 100644 (file)
@@ -1151,6 +1151,8 @@ namespace
 
             if (funcArgs[i].corType == ELEMENT_TYPE_VALUETYPE || funcArgs[i].corType == ELEMENT_TYPE_CLASS)
                 IfFailRet(TypePrinter::NameForTypeByValue(iCorValueArg, funcArgs[i].typeName));
+            else if (funcArgs[i].corType == ELEMENT_TYPE_SZARRAY || funcArgs[i].corType == ELEMENT_TYPE_ARRAY)
+                IfFailRet(TypePrinter::GetTypeOfValue(iCorValueArg, funcArgs[i].typeName));
         }
 
         ToRelease<ICorDebugFunction> iCorFunc;
index 237c7eec859743c3e530f56508c4fbb75dbc8f97..1fe5eadaff43d85ba8600a30fa0275c2ec6ad02f 100644 (file)
@@ -462,7 +462,62 @@ static HRESULT ForEachProperties(IMetaDataImport *pMD, mdTypeDef currentTypeDef,
 // LoBounds ::= 29-bit-encoded-integer
 // Number ::= 29-bit-encoded-integer
 
-static HRESULT ParseElementType(IMetaDataImport *pMD, PCCOR_SIGNATURE *ppSig, Evaluator::ArgElementType &argElementType)
+static void GetCorTypeName(ULONG corType, std::string &typeName)
+{
+    switch (corType)
+    {
+        case ELEMENT_TYPE_VOID:
+            typeName = "void";
+            break;
+        case ELEMENT_TYPE_BOOLEAN:
+            typeName = "bool";
+            break;
+        case ELEMENT_TYPE_CHAR:
+            typeName = "char";
+            break;
+        case ELEMENT_TYPE_I1:
+            typeName = "sbyte";
+            break;
+        case ELEMENT_TYPE_U1:
+            typeName = "byte";
+            break;
+        case ELEMENT_TYPE_I2:
+            typeName = "short";
+            break;
+        case ELEMENT_TYPE_U2:
+            typeName = "ushort";
+            break;
+        case ELEMENT_TYPE_I4:
+            typeName = "int";
+            break;
+        case ELEMENT_TYPE_U4:
+            typeName = "uint";
+            break;
+        case ELEMENT_TYPE_I8:
+            typeName = "long";
+            break;
+        case ELEMENT_TYPE_U8:
+            typeName = "ulong";
+            break;
+        case ELEMENT_TYPE_R4:
+            typeName = "float";
+            break;
+        case ELEMENT_TYPE_R8:
+            typeName = "double";
+            break;
+        case ELEMENT_TYPE_STRING:
+            typeName = "string";
+            break;
+        case ELEMENT_TYPE_OBJECT:
+            typeName = "object";
+            break;
+        default:
+            typeName = "";
+            break;
+    }
+}
+
+static HRESULT ParseElementType(IMetaDataImport *pMD, PCCOR_SIGNATURE *ppSig, Evaluator::ArgElementType &argElementType, bool addCorTypeName = false)
 {
     HRESULT Status;
     ULONG corType;
@@ -487,6 +542,8 @@ static HRESULT ParseElementType(IMetaDataImport *pMD, PCCOR_SIGNATURE *ppSig, Ev
         case ELEMENT_TYPE_R8:
         case ELEMENT_TYPE_STRING:
         case ELEMENT_TYPE_OBJECT:
+            if (addCorTypeName)
+                GetCorTypeName(argElementType.corType, argElementType.typeName);
             break;
 
         case ELEMENT_TYPE_VALUETYPE:
@@ -495,14 +552,49 @@ static HRESULT ParseElementType(IMetaDataImport *pMD, PCCOR_SIGNATURE *ppSig, Ev
             IfFailRet(TypePrinter::NameForTypeByToken(tk, pMD, argElementType.typeName, nullptr));
             break;
 
+        case ELEMENT_TYPE_SZARRAY:
+            if (FAILED(Status = ParseElementType(pMD, ppSig, argElementType, true)) || Status == S_FALSE)
+                return Status;
+            argElementType.corType = (CorElementType)corType;
+            argElementType.typeName += "[]";
+            break;
+        case ELEMENT_TYPE_ARRAY:
+        {
+            if (FAILED(Status = ParseElementType(pMD, ppSig, argElementType, true)) || Status == S_FALSE)
+                return Status;
+            argElementType.corType = (CorElementType)corType;
+            // Parse for the rank
+            ULONG rank = 0;
+            *ppSig += CorSigUncompressData(*ppSig, &rank);
+            // if rank == 0, we are done
+            if (rank == 0)
+                break;
+            // any size of dimension specified?
+            ULONG sizeDim;
+            ULONG ulTemp;
+            *ppSig += CorSigUncompressData(*ppSig, &sizeDim);
+            while (sizeDim--)
+            {
+                *ppSig += CorSigUncompressData(*ppSig, &ulTemp);
+            }
+            // any lower bound specified?
+            ULONG lowerBound;
+            int iTemp;
+            *ppSig += CorSigUncompressData(*ppSig, &lowerBound);
+            while (lowerBound--)
+            {
+                *ppSig += CorSigUncompressSignedInt(*ppSig, &iTemp);
+            }
+            argElementType.typeName += "[" + std::string(rank - 1, ',') + "]";
+            break;
+        }
+
 // TODO
         case ELEMENT_TYPE_U: // "nuint" - error CS8652: The feature 'native-sized integers' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
         case ELEMENT_TYPE_I: // "nint" - error CS8652: The feature 'native-sized integers' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
         case ELEMENT_TYPE_TYPEDBYREF:
-        case ELEMENT_TYPE_ARRAY:
         case ELEMENT_TYPE_PTR: // int* ptr (unsafe code only)
         case ELEMENT_TYPE_BYREF: // ref, in, out
-        case ELEMENT_TYPE_SZARRAY:
         case ELEMENT_TYPE_VAR: // Generic parameter in a generic type definition, represented as number
         case ELEMENT_TYPE_MVAR: // Generic parameter in a generic method definition, represented as number
         case ELEMENT_TYPE_GENERICINST: // A type modifier for generic types - List<>, Dictionary<>, ...
index 1b5354ae578338c272627973674b0ace007ff11e..dee834c20a89b521c6bc8128688bfdfc39b364e1 100644 (file)
@@ -685,6 +685,31 @@ namespace MITestEvaluate
             return 5;
         }
 
+        static int TestArrayArg(int[] arrayArg, int i)
+        {
+            return arrayArg[0] + i;
+        }
+
+        static int TestArrayArg(test_array[] arrayT, int i)
+        {
+            return i;
+        }
+
+        static int TestArrayArg2(short[] arrayArg, int i)
+        {
+            return arrayArg[0] + i;
+        }
+
+        static int TestArray2Arg(int[,] multiArray2, int i)
+        {
+            return multiArray2[0,0] + i;
+        }
+
+        static int TestArray2Arg2(short[,] multiArray2, int i)
+        {
+            return multiArray2[0,0] + i;
+        }
+
         static void Main(string[] args)
         {
             Label.Checkpoint("init", "values_test", (Object context) => {
@@ -742,6 +767,9 @@ namespace MITestEvaluate
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", "10", "int", "array1[ 0]"); // check spaces
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", "30", "int", "array1[2 ]"); // check spaces
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", "50", "int", "array1 [ 4 ]"); // check spaces
+                Context.GetAndCheckValue(@"__FILE__:__LINE__", "15", "int", "TestArrayArg(array1, 5)");
+                Context.GetAndCheckValue(@"__FILE__:__LINE__", "11", "int", "TestArrayArg(array2, 11)");
+                Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "TestArrayArg2(array1, 5)", "Error:");
 
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", "{int[2, 3]}", "int[,]", "multi_array2");
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", "101", "int", "multi_array2[0,0]");
@@ -752,6 +780,8 @@ namespace MITestEvaluate
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", "102", "int", "multi_array2[i1,i4]");
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", "101", "int", "multi_array2[ 0 , 0 ]"); // check spaces
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", "105", "int", "multi_array2  [ 1,1 ]"); // check spaces
+                Context.GetAndCheckValue(@"__FILE__:__LINE__", "106", "int", "TestArray2Arg(multi_array2, 5)");
+                Context.CheckErrorAtRequest(@"__FILE__:__LINE__", "TestArray2Arg2(multi_array2, 5)", "Error:");
 
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", "{MITestEvaluate.test_array[4]}", "MITestEvaluate.test_array[]", "array2");
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", "{MITestEvaluate.test_array}", "MITestEvaluate.test_array", "array2[0]");
index 9e751c9954245fc8ad6d444f5811814d68500874..6eb8377f9e2fc2c4996635c7ec2663a592348d6f 100644 (file)
@@ -802,6 +802,31 @@ namespace VSCodeTestEvaluate
             return 5;
         }
 
+        static int TestArrayArg(int[] arrayArg, int i)
+        {
+            return arrayArg[0] + i;
+        }
+
+        static int TestArrayArg(test_array[] arrayT, int i)
+        {
+            return i;
+        }
+
+        static int TestArrayArg2(short[] arrayArg, int i)
+        {
+            return arrayArg[0] + i;
+        }
+
+        static int TestArray2Arg(int[,] multiArray2, int i)
+        {
+            return multiArray2[0,0] + i;
+        }
+
+        static int TestArray2Arg2(short[,] multiArray2, int i)
+        {
+            return multiArray2[0,0] + i;
+        }
+
         static void Main(string[] args)
         {
             Label.Checkpoint("init", "values_test", (Object context) => {
@@ -862,6 +887,9 @@ namespace VSCodeTestEvaluate
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "10", "int", "array1[ 0]"); // check spaces
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "30", "int", "array1[2 ]"); // check spaces
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "50", "int", "array1 [ 4 ]"); // check spaces
+                Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "15", "int", "TestArrayArg(array1, 5)");
+                Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "11", "int", "TestArrayArg(array2, 11)");
+                Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "TestArrayArg2(array1, 5)", "error:");
 
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "{int[2, 3]}", "int[,]", "multi_array2");
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "101", "int", "multi_array2[0,0]");
@@ -872,6 +900,8 @@ namespace VSCodeTestEvaluate
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "102", "int", "multi_array2[i1,i4]");
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "101", "int", "multi_array2[ 0 , 0 ]"); // check spaces
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "105", "int", "multi_array2  [ 1,1 ]"); // check spaces
+                Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "106", "int", "TestArray2Arg(multi_array2, 5)");
+                Context.CheckErrorAtRequest(@"__FILE__:__LINE__", frameId, "TestArray2Arg2(multi_array2, 5)", "error:");
 
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "{VSCodeTestEvaluate.test_array[4]}", "VSCodeTestEvaluate.test_array[]", "array2");
                 Context.GetAndCheckValue(@"__FILE__:__LINE__", frameId, "{VSCodeTestEvaluate.test_array}", "VSCodeTestEvaluate.test_array", "array2[0]");