Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

Commit

Permalink
Support custom modifier for method signature
Browse files Browse the repository at this point in the history
  • Loading branch information
cshung authored Nov 12, 2019
1 parent b47a67d commit 5575cc0
Show file tree
Hide file tree
Showing 8 changed files with 322 additions and 13 deletions.
3 changes: 3 additions & 0 deletions src/Common/src/System/Collections/Generic/LowLevelStack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ namespace System.Collections.Generic
/// Data size is smaller because there will be minimal virtual function table.
/// Code size is smaller because only functions called will be in the binary.
/// </summary>
#if TYPE_LOADER_IMPLEMENTATION
[System.Runtime.CompilerServices.ForceDictionaryLookups]
#endif
internal class LowLevelStack<T>
{
protected T[] _items;
Expand Down
48 changes: 45 additions & 3 deletions src/Common/src/TypeSystem/Common/MethodDesc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,19 @@ public enum MethodSignatureFlags
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>
Expand All @@ -33,13 +46,15 @@ public sealed partial class MethodSignature : TypeSystemEntity
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");
}
Expand Down Expand Up @@ -120,7 +135,32 @@ public bool Equals(MethodSignature otherSignature)
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)
Expand Down Expand Up @@ -174,6 +214,7 @@ public struct MethodSignatureBuilder
private int _genericParameterCount;
private TypeDesc _returnType;
private TypeDesc[] _parameters;
private EmbeddedSignatureData[] _customModifiers;

public MethodSignatureBuilder(MethodSignature template)
{
Expand All @@ -183,6 +224,7 @@ public MethodSignatureBuilder(MethodSignature template)
_genericParameterCount = template._genericParameterCount;
_returnType = template._returnType;
_parameters = template._parameters;
_customModifiers = template._embeddedSignatureData;
}

public MethodSignatureFlags Flags
Expand Down Expand Up @@ -237,7 +279,7 @@ public MethodSignature ToSignature()
_returnType != _template._returnType ||
_parameters != _template._parameters)
{
_template = new MethodSignature(_flags, _genericParameterCount, _returnType, _parameters);
_template = new MethodSignature(_flags, _genericParameterCount, _returnType, _parameters, _customModifiers);
}

return _template;
Expand Down
128 changes: 119 additions & 9 deletions src/Common/src/TypeSystem/Ecma/EcmaSignatureParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
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
{
Expand All @@ -16,13 +18,20 @@ public struct EcmaSignatureParser
private EcmaModule _module;
private BlobReader _reader;

// TODO
// bool _hasModifiers;
#if TYPE_LOADER_IMPLEMENTATION
private LowLevelStack<int> _indexStack;
#else
private Stack<int> _indexStack;
#endif
private List<EmbeddedSignatureData> _embeddedSignatureDataList;


public EcmaSignatureParser(EcmaModule module, BlobReader reader)
{
_module = module;
_reader = reader;
_indexStack = null;
_embeddedSignatureDataList = null;
}

private TypeDesc GetWellKnownType(WellKnownType wellKnownType)
Expand All @@ -31,6 +40,23 @@ private TypeDesc GetWellKnownType(WellKnownType wellKnownType)
}

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)
Expand Down Expand Up @@ -111,23 +137,51 @@ private TypeDesc ParseType(SignatureTypeCode typeCode)
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();
}
}

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;
}

Expand All @@ -143,6 +197,22 @@ private SignatureTypeCode ParseTypeCode(bool skipPinned = true)
}

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());
}
Expand All @@ -157,6 +227,43 @@ public bool IsFieldSignature
}

public MethodSignature ParseMethodSignature()
{
try
{
#if TYPE_LOADER_IMPLEMENTATION
_indexStack = new LowLevelStack<int>();
#else
_indexStack = new Stack<int>();
#endif
_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();

Expand Down Expand Up @@ -198,7 +305,10 @@ public MethodSignature ParseMethodSignature()
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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<Compile Include="InstanceFieldLayout.il" />
<Compile Include="StaticFieldLayout.il" />
<Compile Include="VirtualFunctionOverride.il" />
<Compile Include="Signature.il" />
</ItemGroup>

<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
Expand Down
Loading

0 comments on commit 5575cc0

Please sign in to comment.