Add generic encoding support to metasig
authorJan Kotas <jkotas@microsoft.com>
Fri, 28 Jul 2017 15:53:01 +0000 (11:53 -0400)
committerStephen Toub <stoub@microsoft.com>
Fri, 28 Jul 2017 15:53:01 +0000 (11:53 -0400)
src/vm/binder.cpp
src/vm/binder.h
src/vm/metasig.h

index 9ce1584..6a60712 100644 (file)
@@ -311,6 +311,58 @@ Signature MscorlibBinder::GetSignatureLocal(LPHARDCODEDMETASIG pHardcodedSig)
 
 #ifndef DACCESS_COMPILE
 
+bool MscorlibBinder::ConvertType(const BYTE*& pSig, SigBuilder * pSigBuilder)
+{
+    bool bSomethingResolved = false;
+
+    CorElementType type = (CorElementType)*pSig++;
+
+    switch (type)
+    {
+    case ELEMENT_TYPE_GENERICINST:
+        {
+            pSigBuilder->AppendElementType(type);
+            if (ConvertType(pSig, pSigBuilder))
+                bSomethingResolved = true;
+            int arity = *pSig++;
+            pSigBuilder->AppendData(arity);
+            for (int i = 0; i < arity; i++)
+            {
+                if (ConvertType(pSig, pSigBuilder))
+                    bSomethingResolved = true;
+            }
+        }
+        break;
+
+    case ELEMENT_TYPE_BYREF:
+    case ELEMENT_TYPE_PTR:
+    case ELEMENT_TYPE_SZARRAY:
+        pSigBuilder->AppendElementType(type);
+        if (ConvertType(pSig, pSigBuilder))
+            bSomethingResolved = true;
+        break;
+
+    case ELEMENT_TYPE_CLASS:
+    case ELEMENT_TYPE_VALUETYPE:
+        {
+            // The binder class id may overflow 1 byte. Use 2 bytes to encode it.
+            BinderClassID id = (BinderClassID)(*pSig + 0x100 * *(pSig + 1));
+            pSig += 2;
+
+            pSigBuilder->AppendElementType(type);
+            pSigBuilder->AppendToken(GetClassLocal(id)->GetCl());
+            bSomethingResolved = true;
+        }
+        break;
+
+    default:
+        pSigBuilder->AppendElementType(type);
+        break;
+    }
+
+    return bSomethingResolved;
+}
+
 //------------------------------------------------------------------
 // Resolve type references in the hardcoded metasig.
 // Returns a new signature with type refences resolved.
@@ -327,7 +379,7 @@ void MscorlibBinder::BuildConvertedSignature(const BYTE* pSig, SigBuilder * pSig
 
     unsigned argCount;
     unsigned callConv;
-    INDEBUG(bool bSomethingResolved = false;)
+    bool bSomethingResolved = false;
 
     // calling convention
     callConv = *pSig++;
@@ -346,51 +398,8 @@ void MscorlibBinder::BuildConvertedSignature(const BYTE* pSig, SigBuilder * pSig
 
     // <= because we want to include the return value or the field
     for (unsigned i = 0; i <= argCount; i++) {
-
-        for (;;) {
-            BinderClassID id = CLASS__NIL;
-            bool again = false;
-
-            CorElementType type = (CorElementType)*pSig++;
-
-            switch (type)
-            {
-            case ELEMENT_TYPE_BYREF:
-            case ELEMENT_TYPE_PTR:
-            case ELEMENT_TYPE_SZARRAY:
-                again = true;
-                break;
-
-            case ELEMENT_TYPE_CLASS:
-            case ELEMENT_TYPE_VALUETYPE:
-                // The binder class id may overflow 1 byte. Use 2 bytes to encode it.
-                id = (BinderClassID) (*pSig + 0x100 * *(pSig + 1));
-                pSig += 2;
-                break;
-
-            case ELEMENT_TYPE_VOID:
-                if (i != 0) {
-                    if (pSig[-2] != ELEMENT_TYPE_PTR)
-                        THROW_BAD_FORMAT(BFA_ONLY_VOID_PTR_IN_ARGS, (Module*)NULL); // only pointer to void allowed in arguments
-                }
-                break;
-
-            default:
-                break;
-            }
-
-            pSigBuilder->AppendElementType(type);
-
-            if (id != CLASS__NIL)
-            {
-                pSigBuilder->AppendToken(GetClassLocal(id)->GetCl());
-
-                INDEBUG(bSomethingResolved = true;)
-            }
-
-            if (!again)
-                break;
-        }
+        if (ConvertType(pSig, pSigBuilder))
+            bSomethingResolved = true;
     }
 
     _ASSERTE(bSomethingResolved);
index 8e26bdd..ad80292 100644 (file)
@@ -277,6 +277,7 @@ private:
 
     Signature GetSignatureLocal(LPHARDCODEDMETASIG pHardcodedSig);
 
+    bool ConvertType(const BYTE*& pSig, SigBuilder * pSigBuilder);
     void BuildConvertedSignature(const BYTE* pSig, SigBuilder * pSigBuilder);
     const BYTE* ConvertSignature(LPHARDCODEDMETASIG pHardcodedSig, const BYTE* pSig);
 
index c2dc42f..f8d9cfe 100644 (file)
@@ -56,6 +56,7 @@
 //   T  -- TypedReference -- TypedReference 
 //   G  --      -- Generic type variable
 //   M  --      -- Generic method variable
+//   GI --      -- Generic type instantiation
 //
 
 //#DEFINE_METASIG
 #define G(n) METASIG_ATOM(ELEMENT_TYPE_VAR) METASIG_ATOM(n)
 #define M(n) METASIG_ATOM(ELEMENT_TYPE_MVAR) METASIG_ATOM(n)
 
+#define GI(type, n, x) METASIG_ATOM(ELEMENT_TYPE_GENERICINST) type METASIG_ATOM(n) x
+
 // The references to other types have special definition in some cases
 #ifndef C
 #define C(x) METASIG_ATOM(ELEMENT_TYPE_CLASS) METASIG_ATOM(CLASS__ ## x % 0x100) METASIG_ATOM(CLASS__ ## x / 0x100)
 #define G(n) METASIG_ATOM(ELEMENT_TYPE_VAR)
 #define M(n) METASIG_ATOM(ELEMENT_TYPE_MVAR)
 
+#define GI(type, n, x) METASIG_ATOM(ELEMENT_TYPE_GENERICINST)
+
 // The references to other types have special definition in some cases
 #ifndef C
 #define C(x) METASIG_ATOM(ELEMENT_TYPE_CLASS)
@@ -608,6 +613,7 @@ DEFINE_METASIG_T(IM(IAsyncResult_RetVoid, C(IASYNCRESULT), v))
 #undef T
 #undef G
 #undef M
+#undef GI
 
 #undef _