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

Implement more APIs in new TypeBuilder, fix bugs found during testing #95753

Merged
merged 16 commits into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from 5 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 @@ -145,9 +145,9 @@ internal static bool IsTypeEqual(Type? t1, Type? t2)
Type? runtimeType2;

// set up the runtimeType and TypeBuilder type corresponding to t1 and t2
if (t1 is RuntimeTypeBuilder)
if (t1 is RuntimeTypeBuilder rtb1)
{
tb1 = (RuntimeTypeBuilder)t1;
tb1 = rtb1;
// This will be null if it is not baked.
runtimeType1 = tb1.m_bakedRuntimeType;
}
Expand All @@ -156,9 +156,9 @@ internal static bool IsTypeEqual(Type? t1, Type? t2)
runtimeType1 = t1;
}

if (t2 is RuntimeTypeBuilder)
if (t2 is RuntimeTypeBuilder rtb2)
{
tb2 = (RuntimeTypeBuilder)t2;
tb2 = rtb2;
// This will be null if it is not baked.
runtimeType2 = tb2.m_bakedRuntimeType;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{772C93D4-FC45-46AA-B09F-26F01B672EDC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{E5543842-139D-43BD-B604-E65EBB91649E}"
Expand Down Expand Up @@ -727,4 +727,4 @@ Global
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {739AA767-154B-4C69-8C9B-C3D332833D92}
EndGlobalSection
EndGlobal
EndGlobal
23 changes: 22 additions & 1 deletion src/libraries/System.Reflection.Emit/src/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@
<value>The invoked member is not supported in a dynamic module.</value>
</data>
<data name="Argument_InvalidTypeCodeForTypeArgument" xml:space="preserve">
<value>The type code may not be used as a type argument of a custom attribute .</value>
<value>The type code may not be used as a type argument of a custom attribute.</value>
</data>
<data name="NotSupported_UnmanagedTypeOnlyForFields" xml:space="preserve">
<value> 'UnmanagedType.{0}' named parameter is only valid for fields.</value>
Expand Down Expand Up @@ -228,4 +228,25 @@
<data name="Arg_NotGenericMethodDefinition" xml:space="preserve">
<value>{0} is not a GenericMethodDefinition. MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true.</value>
</data>
<data name="ArgumentException_BadMethodImplBody" xml:space="preserve">
<value>MethodOverride's body must be from this type.</value>
</data>
<data name="Argument_GenericParameter" xml:space="preserve">
<value>Method must be called on a Type for which Type.IsGenericParameter is false.</value>
</data>
<data name="Argument_InvalidMethodOverride" xml:space="preserve">
<value>Type '{0}' tried to override method '{1}' but does not implement or inherit that method.</value>
</data>
<data name="Argument_ArrayGetInterfaceMap" xml:space="preserve">
<value>Interface maps for generic interfaces on arrays cannot be retrieved.</value>
</data>
<data name="Argument_InterfaceNotFound" xml:space="preserve">
<value>Interface not found.</value>
</data>
<data name="Argument_MethodOverriden" xml:space="preserve">
<value>Method '{0}' on type '{1}' is overriding a method that has been overridden.</value>
</data>
<data name="Argument_MustBeInterface" xml:space="preserve">
<value>Type passed must be an interface.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -133,5 +133,7 @@ protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan
_customAttributes ??= new List<CustomAttributeWrapper>();
_customAttributes.Add(new CustomAttributeWrapper(con, binaryAttribute));
}

public override string? FullName => _assemblyName.FullName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Buffers.Binary;
using System.Diagnostics;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.InteropServices;

namespace System.Reflection.Emit
{
Expand Down Expand Up @@ -83,7 +80,7 @@ internal static CustomAttributeInfo DecodeCustomAttribute(ConstructorInfo ctor,
if (namedType == Field)
{
// For known pseudo custom attributes underlying Enum type is int
Type fieldType = dataType == EnumType ? typeof(int) : ElementTypeToType((PrimitiveSerializationTypeCode)dataType);
Type fieldType = dataType == EnumType ? typeof(int) : ElementTypeToType((SerializationTypeCode)dataType);
info._namedParamValues[i] = DecodeCustomAttributeValue(fieldType, binaryAttribute, pos, out pos); ;
}
else
Expand Down Expand Up @@ -149,30 +146,31 @@ private static int DecodeLen(ReadOnlySpan<byte> data, int pos, out int rpos)

if (subtype >= 0x02 && subtype <= 0x0e)
{
return DecodeCustomAttributeValue(ElementTypeToType((PrimitiveSerializationTypeCode)subtype), data, pos, out rpos);
return DecodeCustomAttributeValue(ElementTypeToType((SerializationTypeCode)subtype), data, pos, out rpos);
}
break;
}

throw new NotImplementedException(SR.Format(SR.NotImplemented_TypeForValue, t));
}

private static Type ElementTypeToType(PrimitiveSerializationTypeCode elementType) =>
private static Type ElementTypeToType(SerializationTypeCode elementType) =>
elementType switch
{
PrimitiveSerializationTypeCode.Boolean => typeof(bool),
PrimitiveSerializationTypeCode.Char => typeof(char),
PrimitiveSerializationTypeCode.SByte => typeof(sbyte),
PrimitiveSerializationTypeCode.Byte => typeof(byte),
PrimitiveSerializationTypeCode.Int16 => typeof(short),
PrimitiveSerializationTypeCode.UInt16 => typeof(ushort),
PrimitiveSerializationTypeCode.Int32 => typeof(int),
PrimitiveSerializationTypeCode.UInt32 => typeof(uint),
PrimitiveSerializationTypeCode.Int64 => typeof(long),
PrimitiveSerializationTypeCode.UInt64 => typeof(ulong),
PrimitiveSerializationTypeCode.Single => typeof(float),
PrimitiveSerializationTypeCode.Double => typeof(double),
PrimitiveSerializationTypeCode.String => typeof(string),
SerializationTypeCode.Boolean => typeof(bool),
SerializationTypeCode.Char => typeof(char),
SerializationTypeCode.SByte => typeof(sbyte),
SerializationTypeCode.Byte => typeof(byte),
SerializationTypeCode.Int16 => typeof(short),
SerializationTypeCode.UInt16 => typeof(ushort),
SerializationTypeCode.Int32 => typeof(int),
SerializationTypeCode.UInt32 => typeof(uint),
SerializationTypeCode.Int64 => typeof(long),
SerializationTypeCode.UInt64 => typeof(ulong),
SerializationTypeCode.Single => typeof(float),
SerializationTypeCode.Double => typeof(double),
SerializationTypeCode.String => typeof(string),
SerializationTypeCode.Type => typeof(string), // the type name written in string format
_ => throw new ArgumentException(SR.Argument_InvalidTypeCodeForTypeArgument, "binaryAttribute"),
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,6 @@ internal static SignatureCallingConvention GetSignatureConvention(CallingConvent
return convention;
}

internal BindingFlags GetBindingFlags()
{
BindingFlags bindingFlags = (_attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public ?
BindingFlags.Public : BindingFlags.NonPublic;
bindingFlags |= (_attributes & MethodAttributes.Static) != 0 ? BindingFlags.Static : BindingFlags.Instance;

return bindingFlags;
}

protected override bool InitLocalsCore
{
get { ThrowIfGeneric(); return _initLocals; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,20 +155,12 @@ internal void AppendMetadata(MethodBodyStreamEncoder methodBodyEncoder)
_metadataBuilder.AddTypeLayout(typeHandle, (ushort)typeBuilder.PackingSize, (uint)typeBuilder.Size);
}

if (typeBuilder._interfaces != null)
{
foreach (Type iface in typeBuilder._interfaces)
{
_metadataBuilder.AddInterfaceImplementation(typeHandle, GetTypeHandle(iface));
// TODO: need to add interface mapping between interface method and implemented method
}
}

if (typeBuilder.DeclaringType != null)
{
_metadataBuilder.AddNestedType(typeHandle, (TypeDefinitionHandle)GetTypeHandle(typeBuilder.DeclaringType));
}

WriteInterfaceImplementations(typeBuilder, typeHandle);
WriteCustomAttributes(typeBuilder._customAttributes, typeHandle);
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
WriteProperties(typeBuilder);
WriteFields(typeBuilder);
Expand All @@ -190,6 +182,29 @@ internal void AppendMetadata(MethodBodyStreamEncoder methodBodyEncoder)
}
}

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072:DynamicallyAccessedMembers", Justification = "Members are retrieved from internal cache")]
private void WriteInterfaceImplementations(TypeBuilderImpl typeBuilder, TypeDefinitionHandle typeHandle)
{
if (typeBuilder._interfaces != null)
{
foreach (Type iface in typeBuilder._interfaces)
{
_metadataBuilder.AddInterfaceImplementation(typeHandle, GetTypeHandle(iface));
}
}

if (typeBuilder._interfaceMappings != null)
{
foreach (InterfaceMap map in typeBuilder._interfaceMappings.Values)
{
for (int i = 0; i < map._interfaceMethods.Count; i++)
{
_metadataBuilder.AddMethodImplementation(typeHandle, GetMemberHandle(map._targetMethods[i]), GetMemberHandle(map._interfaceMethods[i]));
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}

private void WriteProperties(TypeBuilderImpl typeBuilder)
{
if (typeBuilder._propertyDefinitions.Count == 0)
Expand Down Expand Up @@ -411,7 +426,7 @@ private EntityHandle GetTypeReferenceOrSpecificationHandle(Type type)
}
else
{
typeHandle = AddTypeReference(type, GetAssemblyReference(type.Assembly));
typeHandle = AddTypeReference(type, GetResolutionScopeHandle(type));
}

_typeReferences.Add(type, typeHandle);
Expand All @@ -420,6 +435,16 @@ private EntityHandle GetTypeReferenceOrSpecificationHandle(Type type)
return typeHandle;
}

private EntityHandle GetResolutionScopeHandle(Type type)
{
if (type.IsNested)
{
return GetTypeReferenceOrSpecificationHandle(type.DeclaringType!);
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
}

return GetAssemblyReference(type.Assembly);
}

private TypeSpecificationHandle AddTypeSpecification(Type type) =>
_metadataBuilder.AddTypeSpecification(
signature: _metadataBuilder.GetOrAddBlob(MetadataSignatureHelper.GetTypeSpecificationSignature(type, this)));
Expand Down Expand Up @@ -557,9 +582,9 @@ private MethodDefinitionHandle AddMethodDefinition(MethodBuilderImpl method, Blo
bodyOffset: offset,
parameterList: MetadataTokens.ParameterHandle(parameterToken));

private TypeReferenceHandle AddTypeReference(Type type, AssemblyReferenceHandle parent) =>
private TypeReferenceHandle AddTypeReference(Type type, EntityHandle resolutionScope) =>
_metadataBuilder.AddTypeReference(
resolutionScope: parent,
resolutionScope: resolutionScope,
@namespace: (type.Namespace == null) ? default : _metadataBuilder.GetOrAddString(type.Namespace),
name: _metadataBuilder.GetOrAddString(type.Name));

Expand Down Expand Up @@ -679,7 +704,7 @@ public override int GetMethodMetadataToken(MethodInfo method)
return MetadataTokens.GetToken(mb._handle);
}

return 0;
return method.MetadataToken;
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
}

public override int GetStringMetadataToken(string stringConstant) => MetadataTokens.GetToken(_metadataBuilder.GetOrAddUserString(stringConstant));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ internal sealed class MarshallingData
private int _marshalArrayElementType; // safe array: VarEnum; array: UnmanagedType
private int _marshalArrayElementCount; // number of elements in an array, length of a string, or Unspecified
private int _marshalParameterIndex; // index of parameter that specifies array size (short) or IID (int), or Unspecified
private object? _marshalTypeNameOrSymbol; // custom marshaller: string or Type; safe array: element type
private string? _marshalTypeName; // custom marshaller: string or type name; safe array: element type name
private string? _marshalCookie;

internal const int Invalid = -1;
Expand All @@ -139,17 +139,14 @@ internal BlobBuilder SerializeMarshallingData()
case UnmanagedType.CustomMarshaler:
writer.WriteUInt16(0); // padding

switch (_marshalTypeNameOrSymbol)
if (_marshalTypeName != null)
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
{
case Type type:
writer.WriteSerializedString(type.FullName); // or AssemblyQualifiedName?
break;
case null:
writer.WriteByte(0);
break;
default:
writer.WriteSerializedString((string)_marshalTypeNameOrSymbol);
break;
writer.WriteSerializedString(_marshalTypeName);
}
else
{
writer.WriteByte(0);

}

if (_marshalCookie != null)
Expand Down Expand Up @@ -186,9 +183,9 @@ internal BlobBuilder SerializeMarshallingData()
{
writer.WriteCompressedInteger((int)safeArrayElementSubtype);

if (_marshalTypeNameOrSymbol is Type elementType)
if (_marshalTypeName is string)
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
{
writer.WriteSerializedString(elementType.FullName);
writer.WriteSerializedString(_marshalTypeName);
}
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
}
break;
Expand All @@ -209,10 +206,10 @@ internal BlobBuilder SerializeMarshallingData()
return writer;
}

internal void SetMarshalAsCustom(object typeSymbolOrName, string? cookie)
internal void SetMarshalAsCustom(string? name, string? cookie)
{
_marshalType = UnmanagedType.CustomMarshaler;
_marshalTypeNameOrSymbol = typeSymbolOrName;
_marshalTypeName = name;
_marshalCookie = cookie;
}

Expand Down Expand Up @@ -245,13 +242,13 @@ internal void SetMarshalAsFixedArray(UnmanagedType? elementType, int? elementCou
_marshalArrayElementCount = elementCount ?? Invalid;
}

internal void SetMarshalAsSafeArray(VarEnum? elementType, Type? type)
internal void SetMarshalAsSafeArray(VarEnum? elementType, string? type)
{
Debug.Assert(elementType == null || elementType >= 0 && (int)elementType <= MaxMarshalInteger);

_marshalType = UnmanagedType.SafeArray;
_marshalArrayElementType = (int)(elementType ?? InvalidVariantType);
_marshalTypeNameOrSymbol = type;
_marshalTypeName = type;
}

internal void SetMarshalAsFixedString(int elementCount)
Expand Down Expand Up @@ -366,7 +363,7 @@ private static void DecodeMarshalAsFixedString(string[] paramNames, object?[] va
private static void DecodeMarshalAsSafeArray(string[] paramNames, object?[] values, MarshallingData info)
{
VarEnum? elementTypeVariant = null;
Type? elementType = null;
string? elementType = null;
int symbolIndex = -1;

for (int i = 0; i < paramNames.Length; i++)
Expand All @@ -377,7 +374,7 @@ private static void DecodeMarshalAsSafeArray(string[] paramNames, object?[] valu
elementTypeVariant = (VarEnum)values[i]!;
break;
case "SafeArrayUserDefinedSubType":
elementType = (Type?)values[i];
elementType = (string?)values[i];
symbolIndex = i;
break;
case "ArraySubType":
Expand Down Expand Up @@ -470,17 +467,14 @@ private static void DecodeMarshalAsComInterface(string[] paramNames, object?[] v
private static void DecodeMarshalAsCustom(string[] paramNames, object?[] values, MarshallingData info)
{
string? cookie = null;
Type? type = null;
string? name = null;
for (int i = 0; i < paramNames.Length; i++)
{
switch (paramNames[i])
{
case "MarshalType":
name = (string?)values[i];
break;
case "MarshalTypeRef":
type = (Type?)values[i];
name = (string?)values[i];
break;
case "MarshalCookie":
cookie = (string?)values[i];
Expand All @@ -489,7 +483,7 @@ private static void DecodeMarshalAsCustom(string[] paramNames, object?[] values,
}
}

info.SetMarshalAsCustom((object?)name ?? type!, cookie);
info.SetMarshalAsCustom(name, cookie);
}
}
}
Loading
Loading