Support custom modifier for method signature (dotnet/coreclr#27676)
authorAndrew Au <andrewau@microsoft.com>
Thu, 7 Nov 2019 05:07:33 +0000 (21:07 -0800)
committerGitHub <noreply@github.com>
Thu, 7 Nov 2019 05:07:33 +0000 (21:07 -0800)
Commit migrated from https://github.com/dotnet/coreclr/commit/6d56c7a1b64070b7f302c6083d6cf189692f7240

src/coreclr/src/tools/crossgen2/Common/TypeSystem/Common/MethodDesc.cs
src/coreclr/src/tools/crossgen2/Common/TypeSystem/Ecma/EcmaSignatureParser.cs

index 7103433..3e204f8 100644 (file)
@@ -24,6 +24,19 @@ namespace Internal.TypeSystem
         Static = 0x0010,
     }
 
+    public enum EmbeddedSignatureDataKind
+    {
+        RequiredCustomModifier = 0,
+        OptionalCustomModifier = 1
+    }
+
+    public struct EmbeddedSignatureData
+    {
+        public string index;
+        public EmbeddedSignatureDataKind kind;
+        public TypeDesc type;
+    }
+
     /// <summary>
     /// Represents the parameter types, the return type, and flags of a method.
     /// </summary>
@@ -33,13 +46,15 @@ namespace Internal.TypeSystem
         internal int _genericParameterCount;
         internal TypeDesc _returnType;
         internal TypeDesc[] _parameters;
+        internal EmbeddedSignatureData[] _embeddedSignatureData;
 
-        public MethodSignature(MethodSignatureFlags flags, int genericParameterCount, TypeDesc returnType, TypeDesc[] parameters)
+        public MethodSignature(MethodSignatureFlags flags, int genericParameterCount, TypeDesc returnType, TypeDesc[] parameters, EmbeddedSignatureData[] embeddedSignatureData = null)
         {
             _flags = flags;
             _genericParameterCount = genericParameterCount;
             _returnType = returnType;
             _parameters = parameters;
+            _embeddedSignatureData = embeddedSignatureData;
 
             Debug.Assert(parameters != null, "Parameters must not be null");
         }
@@ -120,7 +135,32 @@ namespace Internal.TypeSystem
                     return false;
             }
 
-            return true;
+            if (this._embeddedSignatureData == null && otherSignature._embeddedSignatureData == null)
+            {
+                return true;
+            }
+
+            if (this._embeddedSignatureData != null && otherSignature._embeddedSignatureData != null)
+            {
+                if (this._embeddedSignatureData.Length != otherSignature._embeddedSignatureData.Length)
+                {
+                    return false;
+                }
+
+                for (int i = 0; i < this._embeddedSignatureData.Length; i++)
+                {
+                    if (this._embeddedSignatureData[i].index != otherSignature._embeddedSignatureData[i].index)
+                        return false;
+                    if (this._embeddedSignatureData[i].kind != otherSignature._embeddedSignatureData[i].kind)
+                        return false;
+                    if (this._embeddedSignatureData[i].type != otherSignature._embeddedSignatureData[i].type)
+                        return false;
+                }
+
+                return true;
+            }
+
+            return false;
         }
 
         public override bool Equals(object obj)
@@ -174,6 +214,7 @@ namespace Internal.TypeSystem
         private int _genericParameterCount;
         private TypeDesc _returnType;
         private TypeDesc[] _parameters;
+        private EmbeddedSignatureData[] _customModifiers;
 
         public MethodSignatureBuilder(MethodSignature template)
         {
@@ -183,6 +224,7 @@ namespace Internal.TypeSystem
             _genericParameterCount = template._genericParameterCount;
             _returnType = template._returnType;
             _parameters = template._parameters;
+            _customModifiers = template._embeddedSignatureData;
         }
 
         public MethodSignatureFlags Flags
@@ -237,7 +279,7 @@ namespace Internal.TypeSystem
                 _returnType != _template._returnType ||
                 _parameters != _template._parameters)
             {
-                _template = new MethodSignature(_flags, _genericParameterCount, _returnType, _parameters);
+                _template = new MethodSignature(_flags, _genericParameterCount, _returnType, _parameters, _customModifiers);
             }
 
             return _template;
index 7c89642..aa691a2 100644 (file)
@@ -6,8 +6,10 @@ using System;
 using System.Reflection.Metadata;
 using System.Runtime.InteropServices;
 using System.Diagnostics;
+using System.Linq;
 
 using Internal.TypeSystem;
+using System.Collections.Generic;
 
 namespace Internal.TypeSystem.Ecma
 {
@@ -16,13 +18,16 @@ namespace Internal.TypeSystem.Ecma
         private EcmaModule _module;
         private BlobReader _reader;
 
-        // TODO
-        // bool _hasModifiers;
+        private Stack<int> _indexStack;
+        private List<EmbeddedSignatureData> _embeddedSignatureDataList;
+
 
         public EcmaSignatureParser(EcmaModule module, BlobReader reader)
         {
             _module = module;
             _reader = reader;
+            _indexStack = null;
+            _embeddedSignatureDataList = null;
         }
 
         private TypeDesc GetWellKnownType(WellKnownType wellKnownType)
@@ -32,6 +37,23 @@ namespace Internal.TypeSystem.Ecma
 
         private TypeDesc ParseType(SignatureTypeCode typeCode)
         {
+
+            if (_indexStack != null)
+            {
+                int was = _indexStack.Pop();
+                _indexStack.Push(was + 1);
+                _indexStack.Push(0);
+            }
+            TypeDesc result = ParseTypeImpl(typeCode);
+            if (_indexStack != null)
+            {
+                _indexStack.Pop();
+            }
+            return result;
+        }
+
+        private TypeDesc ParseTypeImpl(SignatureTypeCode typeCode)
+        {
             // Switch on the type.
             switch (typeCode)
             {
@@ -111,7 +133,7 @@ namespace Internal.TypeSystem.Ecma
                 case SignatureTypeCode.TypedReference:
                     return GetWellKnownType(WellKnownType.TypedReference);
                 case SignatureTypeCode.FunctionPointer:
-                    return _module.Context.GetFunctionPointerType(ParseMethodSignature());
+                    return _module.Context.GetFunctionPointerType(ParseMethodSignatureInternal(skipEmbeddedSignatureData: true));
                 default:
                     throw new BadImageFormatException();
             }
@@ -119,15 +141,43 @@ namespace Internal.TypeSystem.Ecma
 
         private SignatureTypeCode ParseTypeCode(bool skipPinned = true)
         {
-            for (;;)
+            if (_indexStack != null)
+            {
+                int was = _indexStack.Pop();
+                _indexStack.Push(was + 1);
+                _indexStack.Push(0);
+            }
+            SignatureTypeCode result = ParseTypeCodeImpl(skipPinned);
+            if (_indexStack != null)
+            {
+                _indexStack.Pop();
+            }
+            return result;
+        }
+
+        private SignatureTypeCode ParseTypeCodeImpl(bool skipPinned = true)
+        {
+            for (; ; )
             {
                 SignatureTypeCode typeCode = _reader.ReadSignatureTypeCode();
 
-                // TODO: actually consume modopts
-                if (typeCode == SignatureTypeCode.RequiredModifier ||
-                    typeCode == SignatureTypeCode.OptionalModifier)
+                if (typeCode == SignatureTypeCode.RequiredModifier)
+                {
+                    EntityHandle typeHandle = _reader.ReadTypeHandle();
+                    if (_embeddedSignatureDataList != null)
+                    {
+                        _embeddedSignatureDataList.Add(new EmbeddedSignatureData { index = string.Join(".", _indexStack), kind = EmbeddedSignatureDataKind.RequiredCustomModifier, type = _module.GetType(typeHandle) });
+                    }
+                    continue;
+                }
+
+                if (typeCode == SignatureTypeCode.OptionalModifier)
                 {
-                    _reader.ReadTypeHandle();
+                    EntityHandle typeHandle = _reader.ReadTypeHandle();
+                    if (_embeddedSignatureDataList != null)
+                    {
+                        _embeddedSignatureDataList.Add(new EmbeddedSignatureData { index = string.Join(".", _indexStack), kind = EmbeddedSignatureDataKind.OptionalCustomModifier, type = _module.GetType(typeHandle) });
+                    }
                     continue;
                 }
 
@@ -144,6 +194,22 @@ namespace Internal.TypeSystem.Ecma
 
         public TypeDesc ParseType()
         {
+            if (_indexStack != null)
+            {
+                int was = _indexStack.Pop();
+                _indexStack.Push(was + 1);
+                _indexStack.Push(0);
+            }
+            TypeDesc result = ParseTypeImpl();
+            if (_indexStack != null)
+            {
+                _indexStack.Pop();
+            }
+            return result;
+        }
+
+        private TypeDesc ParseTypeImpl()
+        {
             return ParseType(ParseTypeCode());
         }
 
@@ -158,6 +224,39 @@ namespace Internal.TypeSystem.Ecma
 
         public MethodSignature ParseMethodSignature()
         {
+            try
+            {
+                _indexStack = new Stack<int>();
+                _indexStack.Push(0);
+                _embeddedSignatureDataList = new List<EmbeddedSignatureData>();
+                return ParseMethodSignatureInternal(skipEmbeddedSignatureData: false);
+            }
+            finally
+            {
+                _indexStack = null;
+                _embeddedSignatureDataList = null;
+            }
+
+        }
+
+        private MethodSignature ParseMethodSignatureInternal(bool skipEmbeddedSignatureData)
+        {
+            if (_indexStack != null)
+            {
+                int was = _indexStack.Pop();
+                _indexStack.Push(was + 1);
+                _indexStack.Push(0);
+            }
+            MethodSignature result = ParseMethodSignatureImpl(skipEmbeddedSignatureData);
+            if (_indexStack != null)
+            {
+                _indexStack.Pop();
+            }
+            return result;
+        }
+
+        private MethodSignature ParseMethodSignatureImpl(bool skipEmbeddedSignatureData)
+        {
             SignatureHeader header = _reader.ReadSignatureHeader();
 
             MethodSignatureFlags flags = 0;
@@ -198,7 +297,10 @@ namespace Internal.TypeSystem.Ecma
                 parameters = TypeDesc.EmptyTypes;
             }
 
-            return new MethodSignature(flags, arity, returnType, parameters);
+            EmbeddedSignatureData[] embeddedSignatureDataArray = (_embeddedSignatureDataList == null || _embeddedSignatureDataList.Count == 0 || skipEmbeddedSignatureData) ? null : _embeddedSignatureDataList.ToArray();
+
+            return new MethodSignature(flags, arity, returnType, parameters, embeddedSignatureDataArray);
+
         }
 
         public PropertySignature ParsePropertySignature()