Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emission and reading of custom modifiers #85504

Merged
merged 4 commits into from
May 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1742,7 +1742,7 @@ public MethodTable* this[int index]
if (((nint)_pFirst & IsRelative) != 0)
return (((RelativePointer<MethodTable>*)((nint)_pFirst - IsRelative)) + index)->Value;

return *(MethodTable**)_pFirst + index;
return *((MethodTable**)_pFirst + index);
}
#if TYPE_LOADER_IMPLEMENTATION
set
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,123 @@
// 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 System.Reflection.Runtime.General;

using Internal.Metadata.NativeFormat;

using Debug = System.Diagnostics.Debug;

namespace System.Reflection
{
internal partial class ModifiedType
{
internal struct TypeSignature
internal readonly struct TypeSignature
{
internal readonly MetadataReader Reader;
internal readonly Handle Handle;
public TypeSignature(MetadataReader reader, Handle handle)
=> (Reader, Handle) = (reader, handle);
}

internal Type GetTypeParameter(Type unmodifiedType, int index)
{
MetadataReader reader = _typeSignature.Reader;
Handle handle = _typeSignature.Handle;

while (handle.HandleType == HandleType.ModifiedType)
handle = reader.GetModifiedType(handle.ToModifiedTypeHandle(reader)).Type;

if (handle.HandleType == HandleType.TypeSpecification)
handle = reader.GetTypeSpecification(handle.ToTypeSpecificationHandle(reader)).Signature;

switch (handle.HandleType)
{
case HandleType.SZArraySignature:
Debug.Assert(index == 0);
return Create(unmodifiedType, new TypeSignature(reader, reader.GetSZArraySignature(handle.ToSZArraySignatureHandle(reader)).ElementType));
case HandleType.ArraySignature:
Debug.Assert(index == 0);
return Create(unmodifiedType, new TypeSignature(reader, reader.GetArraySignature(handle.ToArraySignatureHandle(reader)).ElementType));
case HandleType.PointerSignature:
Debug.Assert(index == 0);
return Create(unmodifiedType, new TypeSignature(reader, reader.GetPointerSignature(handle.ToPointerSignatureHandle(reader)).Type));
case HandleType.ByReferenceSignature:
Debug.Assert(index == 0);
return Create(unmodifiedType, new TypeSignature(reader, reader.GetByReferenceSignature(handle.ToByReferenceSignatureHandle(reader)).Type));
case HandleType.FunctionPointerSignature:
{
MethodSignature functionSig = reader.GetMethodSignature(
reader.GetFunctionPointerSignature(handle.ToFunctionPointerSignatureHandle(reader)).Signature);
if (index-- == 0)
return Create(unmodifiedType, new TypeSignature(reader, functionSig.ReturnType));

Debug.Assert(index <= functionSig.Parameters.Count);
foreach (Handle paramHandle in functionSig.Parameters)
if (index-- == 0)
return Create(unmodifiedType, new TypeSignature(reader, paramHandle));
}
break;
case HandleType.TypeInstantiationSignature:
{
TypeInstantiationSignature typeInst =
reader.GetTypeInstantiationSignature(handle.ToTypeInstantiationSignatureHandle(reader));
Debug.Assert(index < typeInst.GenericTypeArguments.Count);
foreach (Handle paramHandle in typeInst.GenericTypeArguments)
if (index-- == 0)
return Create(unmodifiedType, new TypeSignature(reader, paramHandle));
}
break;
}

Debug.Fail(handle.HandleType.ToString());
return null;
}

internal SignatureCallingConvention GetCallingConventionFromFunctionPointer()
{
MetadataReader reader = _typeSignature.Reader;
Handle fnPtrTypeSigHandle = reader.GetTypeSpecification(
_typeSignature.Handle.ToTypeSpecificationHandle(reader)).Signature;
MethodSignatureHandle methodSigHandle = reader.GetFunctionPointerSignature(
fnPtrTypeSigHandle.ToFunctionPointerSignatureHandle(reader)).Signature;

Debug.Assert((int)Internal.Metadata.NativeFormat.SignatureCallingConvention.StdCall == (int)SignatureCallingConvention.StdCall);
Debug.Assert((int)Internal.Metadata.NativeFormat.SignatureCallingConvention.Unmanaged == (int)SignatureCallingConvention.Unmanaged);
return (SignatureCallingConvention)(reader.GetMethodSignature(methodSigHandle).CallingConvention
& Internal.Metadata.NativeFormat.SignatureCallingConvention.UnmanagedCallingConventionMask);
}

#pragma warning disable IDE0060
internal Type GetTypeParameter(Type unmodifiedType, int index) => throw new NotSupportedException();
private Type[] GetCustomModifiers(bool required)
{
ArrayBuilder<Type> builder = default;

MetadataReader reader = _typeSignature.Reader;
Handle handle = _typeSignature.Handle;

while (handle.HandleType == HandleType.ModifiedType)
{
var modifiedType = reader.GetModifiedType(handle.ToModifiedTypeHandle(reader));

internal SignatureCallingConvention GetCallingConventionFromFunctionPointer() => throw new NotSupportedException();
handle = modifiedType.Type;

if (modifiedType.IsOptional == required)
continue;

builder.Add(modifiedType.ModifierType.Resolve(reader, new TypeContext(null, null)));
}

Type[] result = builder.ToArray();

// We call Reverse for compat with CoreCLR that also reverses these.
// ILDasm also reverses these but don't be fooled: you can go to
// View -> MetaInfo -> Show to see the file format order in ILDasm.
Array.Reverse(result);
Comment on lines +112 to +115
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is weird.


return result;
}

private Type[] GetCustomModifiers(bool required) => throw new NotSupportedException();
#pragma warning restore IDE0060
public static Type Create(Type unmodifiedType, MetadataReader reader, Handle typeSignature)
=> ModifiedType.Create(unmodifiedType, new TypeSignature(reader, typeSignature));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ protected sealed override RuntimeTypeInfo FieldRuntimeType

protected sealed override int ExplicitLayoutFieldOffsetData => (int)(_field.Offset);

public sealed override Type GetModifiedFieldType() => ModifiedType.Create(FieldRuntimeType, _reader, FieldTypeHandle);

private Handle FieldTypeHandle => _field.Signature.GetFieldSignature(_reader).Type;

private readonly NativeFormatRuntimeNamedTypeInfo _definingTypeInfo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,10 @@ internal Type[] GetCustomModifiers(TypeContext typeContext, bool optional)
return _handle.GetCustomModifiers((global::Internal.Metadata.NativeFormat.MetadataReader)Reader, typeContext, optional);
#endif
}

internal Type GetModifiedType(TypeContext typeContext)
{
return ModifiedType.Create(Resolve(typeContext), (global::Internal.Metadata.NativeFormat.MetadataReader)Reader, _handle);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public sealed override Type ParameterType
}
}

public sealed override Type GetModifiedParameterType() => QualifiedParameterTypeHandle.GetModifiedType(_typeContext);

protected readonly QSignatureTypeHandle QualifiedParameterTypeHandle;
private readonly TypeContext _typeContext;
private volatile Type _lazyParameterType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ public sealed override IEnumerable<CustomAttributeData> CustomAttributes
}
}

public override Type GetModifiedPropertyType()
{
return ModifiedType.Create(PropertyType, _reader, _reader.GetPropertySignature(_property.Signature).Type);

}

public sealed override bool HasSameMetadataDefinitionAs(MemberInfo other)
{
ArgumentNullException.ThrowIfNull(other);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,24 @@ private static unsafe int CreateGCDesc(LowLevelList<bool> bitfield, int size, bo
return numSeries;
}

public static RuntimeTypeHandle CreateFunctionPointerEEType(uint hashCodeOfNewType, RuntimeTypeHandle returnTypeHandle, RuntimeTypeHandle[] parameterHandles, FunctionPointerType functionPointerType)
{
TypeBuilderState state = new TypeBuilderState(functionPointerType);

CreateEETypeWorker(typeof(delegate*<void>).TypeHandle.ToEETypePtr(), hashCodeOfNewType, 0, state);
Debug.Assert(!state.HalfBakedRuntimeTypeHandle.IsNull());

TypeLoaderLogger.WriteLine("Allocated new FUNCTION POINTER type " + functionPointerType.ToString() + " with hashcode value = 0x" + hashCodeOfNewType.LowLevelToString() + " with MethodTable = " + state.HalfBakedRuntimeTypeHandle.ToIntPtr().LowLevelToString());

state.HalfBakedRuntimeTypeHandle.ToEETypePtr()->FunctionPointerReturnType = returnTypeHandle.ToEETypePtr();
Debug.Assert(state.HalfBakedRuntimeTypeHandle.ToEETypePtr()->NumFunctionPointerParameters == parameterHandles.Length);
MethodTableList paramList = state.HalfBakedRuntimeTypeHandle.ToEETypePtr()->FunctionPointerParameters;
for (int i = 0; i < parameterHandles.Length; i++)
paramList[i] = parameterHandles[i].ToEETypePtr();

return state.HalfBakedRuntimeTypeHandle;
}

public static RuntimeTypeHandle CreatePointerEEType(uint hashCodeOfNewType, RuntimeTypeHandle pointeeTypeHandle, TypeDesc pointerType)
{
TypeBuilderState state = new TypeBuilderState(pointerType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,30 @@ public static bool TryBuildByRefType(RuntimeTypeHandle pointeeTypeHandle, out Ru
return true;
}

public static bool TryBuildFunctionPointerType(RuntimeTypeHandle returnTypeHandle, RuntimeTypeHandle[] parameterHandles, bool isUnmanaged, out RuntimeTypeHandle runtimeTypeHandle)
{
var key = new TypeSystemContext.FunctionPointerTypeKey(returnTypeHandle, parameterHandles, isUnmanaged);
if (!TypeSystemContext.FunctionPointerTypesCache.TryGetValue(key, out runtimeTypeHandle))
{
TypeSystemContext context = TypeSystemContextFactory.Create();
FunctionPointerType functionPointerType = context.GetFunctionPointerType(new MethodSignature(
isUnmanaged ? MethodSignatureFlags.UnmanagedCallingConvention : 0,
genericParameterCount: 0,
context.ResolveRuntimeTypeHandle(returnTypeHandle),
context.ResolveRuntimeTypeHandlesInternal(parameterHandles)));
runtimeTypeHandle = EETypeCreator.CreateFunctionPointerEEType((uint)functionPointerType.GetHashCode(), returnTypeHandle, parameterHandles, functionPointerType);
unsafe
{
Debug.Assert(runtimeTypeHandle.ToEETypePtr()->IsFunctionPointerType);
}
TypeSystemContext.FunctionPointerTypesCache.AddOrGetExisting(runtimeTypeHandle);

// Recycle the context only if we successfully built the type. The state may be partially initialized otherwise.
TypeSystemContextFactory.Recycle(context);
}
return true;
}

internal static bool TryBuildGenericMethod(InstantiatedMethod methodBeingLoaded, out IntPtr methodDictionary)
{
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,15 +349,33 @@ public bool TryGetFunctionPointerTypeForComponents(RuntimeTypeHandle returnTypeH

using (LockHolder.Hold(_typeLoaderLock))
{
throw new NotImplementedException();
return TypeBuilder.TryBuildFunctionPointerType(returnTypeHandle, parameterHandles, isUnmanaged, out runtimeTypeHandle);
}
}

public bool TryLookupFunctionPointerTypeForComponents(RuntimeTypeHandle returnTypeHandle, RuntimeTypeHandle[] parameterHandles, bool isUnmanaged, out RuntimeTypeHandle runtimeTypeHandle)
{
// TODO: cache same as for arrays
// TODO: lookup dynamically built ones
return TryGetStaticFunctionPointerTypeForComponents(returnTypeHandle, parameterHandles, isUnmanaged, out runtimeTypeHandle);
var key = new TypeSystemContext.FunctionPointerTypeKey(returnTypeHandle, parameterHandles, isUnmanaged);
if (TypeSystemContext.FunctionPointerTypesCache.TryGetValue(key, out runtimeTypeHandle))
return true;

if (!RuntimeAugments.IsDynamicType(returnTypeHandle)
&& AllNonDynamicTypes(parameterHandles)
&& TryGetStaticFunctionPointerTypeForComponents(returnTypeHandle, parameterHandles, isUnmanaged, out runtimeTypeHandle))
{
TypeSystemContext.FunctionPointerTypesCache.AddOrGetExisting(runtimeTypeHandle);
return true;
}

return false;

static bool AllNonDynamicTypes(RuntimeTypeHandle[] handles)
{
foreach (RuntimeTypeHandle h in handles)
if (RuntimeAugments.IsDynamicType(h))
return false;
return true;
}
}

// Get an array RuntimeTypeHandle given an element's RuntimeTypeHandle and rank. Pass false for isMdArray, and rank == -1 for SzArrays
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ internal static RuntimeTypeHandleToParameterTypeRuntimeTypeHandleHashtable GetAr
internal static FunctionPointerRuntimeTypeHandleHashtable FunctionPointerTypesCache { get; }
= new FunctionPointerRuntimeTypeHandleHashtable();

private TypeDesc[] ResolveRuntimeTypeHandlesInternal(RuntimeTypeHandle[] runtimeTypeHandles)
public TypeDesc[] ResolveRuntimeTypeHandlesInternal(RuntimeTypeHandle[] runtimeTypeHandles)
{
TypeDesc[] TypeDescs = new TypeDesc[runtimeTypeHandles.Length];
for (int i = 0; i < runtimeTypeHandles.Length; i++)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ from primitiveType in PrimitiveTypes select
name: "MethodInstantiation",
members: new MemberDef[] {
new MemberDef("Method", MethodDefOrRef, MemberDefFlags.RecordRef),
new MemberDef("GenericTypeArguments", TypeDefOrRefOrSpec, MemberDefFlags.List | MemberDefFlags.RecordRef),
new MemberDef("GenericTypeArguments", TypeDefOrRefOrSpecOrMod, MemberDefFlags.List | MemberDefFlags.RecordRef),
// COMPLETENESS: new MemberDef("CustomAttributes", "CustomAttribute", MemberDefFlags.List | MemberDefFlags.RecordRef | MemberDefFlags.Child),
}
),
Expand Down Expand Up @@ -674,7 +674,7 @@ from primitiveType in PrimitiveTypes select
name: "TypeInstantiationSignature",
members: new MemberDef[] {
new MemberDef("GenericType", TypeDefOrRefOrSpec, MemberDefFlags.RecordRef),
new MemberDef("GenericTypeArguments", TypeDefOrRefOrSpec, MemberDefFlags.List | MemberDefFlags.RecordRef),
new MemberDef("GenericTypeArguments", TypeDefOrRefOrSpecOrMod, MemberDefFlags.List | MemberDefFlags.RecordRef),
MichalStrehovsky marked this conversation as resolved.
Show resolved Hide resolved
}
),
new RecordDef(
Expand All @@ -686,7 +686,7 @@ from primitiveType in PrimitiveTypes select
new RecordDef(
name: "ArraySignature",
members: new MemberDef[] {
new MemberDef("ElementType", TypeDefOrRefOrSpec, MemberDefFlags.RecordRef),
new MemberDef("ElementType", TypeDefOrRefOrSpecOrMod, MemberDefFlags.RecordRef),
new MemberDef("Rank", "int"),
new MemberDef("Sizes", "Int32", MemberDefFlags.Array),
new MemberDef("LowerBounds", "Int32", MemberDefFlags.Array),
Expand All @@ -695,7 +695,7 @@ from primitiveType in PrimitiveTypes select
new RecordDef(
name: "ByReferenceSignature",
members: new MemberDef[] {
new MemberDef("Type", TypeDefOrRefOrSpec, MemberDefFlags.RecordRef),
new MemberDef("Type", TypeDefOrRefOrSpecOrMod, MemberDefFlags.RecordRef),
}
),
new RecordDef(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public ArraySignatureHandle Handle
return _handle;
}
} // Handle
/// One of: TypeDefinition, TypeReference, TypeSpecification
/// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType

public Handle ElementType
{
Expand Down Expand Up @@ -182,7 +182,7 @@ public ByReferenceSignatureHandle Handle
return _handle;
}
} // Handle
/// One of: TypeDefinition, TypeReference, TypeSpecification
/// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType

public Handle Type
{
Expand Down Expand Up @@ -4901,7 +4901,7 @@ public Handle Method
} // Method

internal Handle _method;
/// One of: TypeDefinition, TypeReference, TypeSpecification
/// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType

public HandleCollection GenericTypeArguments
{
Expand Down Expand Up @@ -7756,7 +7756,7 @@ public Handle GenericType
} // GenericType

internal Handle _genericType;
/// One of: TypeDefinition, TypeReference, TypeSpecification
/// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType

public HandleCollection GenericTypeArguments
{
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/tools/Common/TypeSystem/Common/FieldDesc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public abstract TypeDesc FieldType
// Get the embedded signature data used to hold custom modifiers and such within a field signature
public abstract EmbeddedSignatureData[] GetEmbeddedSignatureData();

public abstract bool HasEmbeddedSignatureData { get; }

public abstract bool IsStatic
{
get;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ public override EmbeddedSignatureData[] GetEmbeddedSignatureData()
return _fieldDef.GetEmbeddedSignatureData();
}

public override bool HasEmbeddedSignatureData
{
get
{
return _fieldDef.HasEmbeddedSignatureData;
}
}

public override bool IsStatic
{
get
Expand Down
Loading