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

Suppress linker warnings properly #84272

Merged
merged 7 commits into from
Apr 4, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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 @@ -6,7 +6,7 @@

namespace System.Reflection.Emit
{
// This static helper class adds common entities to a Metadata Builder.
// This static helper class adds common entities to a MetadataBuilder.
internal static class MetadataHelper
{
internal static AssemblyReferenceHandle AddAssemblyReference(Assembly assembly, MetadataBuilder metadata)
Expand Down Expand Up @@ -34,7 +34,7 @@ internal static TypeDefinitionHandle AddTypeDefinition(MetadataBuilder metadata,
// Add type metadata
return metadata.AddTypeDefinition(
attributes: typeBuilder.Attributes,
(typeBuilder.Namespace == null) ? default : metadata.GetOrAddString(typeBuilder.Namespace),
@namespace: (typeBuilder.Namespace == null) ? default : metadata.GetOrAddString(typeBuilder.Namespace),
name: metadata.GetOrAddString(typeBuilder.Name),
baseType: baseType,
fieldList: MetadataTokens.FieldDefinitionHandle(fieldToken),
Expand All @@ -49,28 +49,30 @@ internal static TypeReferenceHandle AddTypeReference(MetadataBuilder metadata, T
internal static TypeReferenceHandle AddTypeReference(MetadataBuilder metadata, AssemblyReferenceHandle parent, string name, string? nameSpace)
{
return metadata.AddTypeReference(
parent,
(nameSpace == null) ? default : metadata.GetOrAddString(nameSpace),
metadata.GetOrAddString(name)
resolutionScope: parent,
@namespace: (nameSpace == null) ? default : metadata.GetOrAddString(nameSpace),
name: metadata.GetOrAddString(name)
);
}

internal static MethodDefinitionHandle AddMethodDefinition(MetadataBuilder metadata, MethodBuilderImpl methodBuilder, BlobBuilder methodSignatureBlob)
{
return metadata.AddMethodDefinition(
methodBuilder.Attributes,
MethodImplAttributes.IL,
metadata.GetOrAddString(methodBuilder.Name),
metadata.GetOrAddBlob(methodSignatureBlob),
-1, // No body supported yet
attributes: methodBuilder.Attributes,
implAttributes: MethodImplAttributes.IL,
name: metadata.GetOrAddString(methodBuilder.Name),
signature: metadata.GetOrAddBlob(methodSignatureBlob),
bodyOffset: -1, // No body supported yet
parameterList: MetadataTokens.ParameterHandle(1)
);
}

internal static FieldDefinitionHandle AddFieldDefinition(MetadataBuilder metadata, FieldInfo field)
internal static FieldDefinitionHandle AddFieldDefinition(MetadataBuilder metadata, FieldInfo field, BlobBuilder fieldSignatureBlob)
{
return metadata.AddFieldDefinition(field.Attributes, metadata.GetOrAddString(field.Name),
metadata.GetOrAddBlob(MetadataSignatureHelper.FieldSignatureEncoder(field.FieldType)));
return metadata.AddFieldDefinition(
attributes: field.Attributes,
name: metadata.GetOrAddString(field.Name),
signature: metadata.GetOrAddBlob(fieldSignatureBlob));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;

namespace System.Reflection.Emit
{
Expand All @@ -22,7 +21,7 @@ internal MethodBuilderImpl(string name, MethodAttributes attributes, CallingConv
Type[]? parameterTypes, ModuleBuilderImpl module, TypeBuilderImpl declaringType)
{
_module = module;
_returnType = returnType ?? _module.GetTypeFromCoreAssembly("System.Void"); ;
_returnType = returnType ?? _module.GetTypeFromCoreAssembly(CoreTypeId.Void)!;
_name = name;
_attributes = attributes;
_callingConventions = callingConventions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,29 @@ internal sealed class ModuleBuilderImpl : ModuleBuilder
{
private readonly Assembly _coreAssembly;
private readonly string _name;
private readonly Dictionary<string, Type> _coreTypes = new();
private Type?[]? _coreTypes;
private readonly Dictionary<Assembly, AssemblyReferenceHandle> _assemblyRefStore = new();
private readonly Dictionary<Type, TypeReferenceHandle> _typeRefStore = new();
private readonly List<TypeBuilderImpl> _typeDefStore = new();
private int _nextMethodDefRowId = 1;
private int _nextFieldDefRowId = 1;

private static readonly Type[] s_coreTypes = { typeof(void), typeof(object), typeof(bool), typeof(char), typeof(sbyte), typeof(byte), typeof(short),
typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double),
typeof(decimal), typeof(DateTime), typeof(string), typeof(nint), typeof(nuint) };
internal ModuleBuilderImpl(string name, Assembly coreAssembly)
{
_coreAssembly = coreAssembly;
_name = name;
}

internal Type GetTypeFromCoreAssembly(string name)
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Types are preserved via s_coreTypes")]
internal Type? GetTypeFromCoreAssembly(CoreTypeId typeId)
{
Type? type;

// TODO: Use Enum as the key for perf
if (!_coreTypes.TryGetValue(name, out type))
{
#pragma warning disable IL2026 // Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code
type = _coreAssembly.GetType(name, throwOnError: true)!;
#pragma warning restore IL2026
_coreTypes.Add(name, type);
}
int index = (int)typeId;
// Use s_coreTypes directly for runtime reflection
_coreTypes ??= (_coreAssembly == typeof(object).Assembly) ? s_coreTypes : new Type[s_coreTypes.Length];

return type;
return _coreTypes[index] ?? (_coreTypes[index] = _coreAssembly.GetType(s_coreTypes[index].FullName!, throwOnError: true));
}

internal void AppendMetadata(MetadataBuilder metadata)
Expand Down Expand Up @@ -82,7 +78,7 @@ internal void AppendMetadata(MetadataBuilder metadata)

foreach (FieldBuilderImpl field in typeBuilder._fieldDefStore)
{
MetadataHelper.AddFieldDefinition(metadata, field);
MetadataHelper.AddFieldDefinition(metadata, field, MetadataSignatureHelper.FieldSignatureEncoder(field.FieldType, this));
_nextFieldDefRowId++;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics.CodeAnalysis;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;

Expand All @@ -9,16 +10,16 @@ namespace System.Reflection.Emit
// TODO: Only support simple signatures. More complex signatures will be added.
internal static class MetadataSignatureHelper
{
internal static BlobBuilder FieldSignatureEncoder(Type fieldType)
internal static BlobBuilder FieldSignatureEncoder(Type fieldType, ModuleBuilderImpl module)
{
BlobBuilder fieldSignature = new();

WriteSignatureTypeForReflectionType(new BlobEncoder(fieldSignature).FieldSignature(), fieldType);
WriteSignatureTypeForReflectionType(new BlobEncoder(fieldSignature).FieldSignature(), fieldType, module);

return fieldSignature;
}

internal static BlobBuilder MethodSignatureEncoder(ModuleBuilderImpl _module, Type[]? parameters, Type? returnType, bool isInstance)
internal static BlobBuilder MethodSignatureEncoder(ModuleBuilderImpl module, Type[]? parameters, Type? returnType, bool isInstance)
{
// Encoding return type and parameters.
BlobBuilder methodSignature = new();
Expand All @@ -30,9 +31,9 @@ internal static BlobBuilder MethodSignatureEncoder(ModuleBuilderImpl _module, Ty
MethodSignature(isInstanceMethod: isInstance).
Parameters((parameters == null) ? 0 : parameters.Length, out retEncoder, out parEncoder);

if (returnType != null && returnType != _module.GetTypeFromCoreAssembly("System.Void"))
if (returnType != null && returnType != module.GetTypeFromCoreAssembly(CoreTypeId.Void))
{
WriteSignatureTypeForReflectionType(retEncoder.Type(), returnType);
WriteSignatureTypeForReflectionType(retEncoder.Type(), returnType, module);
}
else // If null mark ReturnTypeEncoder as void
{
Expand All @@ -43,46 +44,95 @@ internal static BlobBuilder MethodSignatureEncoder(ModuleBuilderImpl _module, Ty
{
foreach (Type parameter in parameters)
{
WriteSignatureTypeForReflectionType(parEncoder.AddParameter().Type(), parameter);
WriteSignatureTypeForReflectionType(parEncoder.AddParameter().Type(), parameter, module);
}
}

return methodSignature;
}

private static void WriteSignatureTypeForReflectionType(SignatureTypeEncoder signature, Type type)
private static void WriteSignatureTypeForReflectionType(SignatureTypeEncoder signature, Type type, ModuleBuilderImpl module)
{
// We need to translate from Reflection.Type to SignatureTypeEncoder. Most common types for proof of concept. More types will be added.
// TODO: This switch should be done by comparing Type objects, without fetching FullName.
switch (type.FullName)
// We need to translate from Reflection.Type to SignatureTypeEncoder.
if (Enum.TryParse(type.Name, out CoreTypeId typeId) && type.Equals(module.GetTypeFromCoreAssembly(typeId)))
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
{
case "System.Boolean":
signature.Boolean();
break;
case "System.Byte":
signature.Byte();
break;
case "System.Char":
signature.Char();
break;
case "System.Double":
signature.Double();
break;
case "System.Int32":
signature.Int32();
break;
case "System.Int64":
signature.Int64();
break;
case "System.Object":
signature.Object();
break;
case "System.String":
signature.String();
break;

default: throw new NotSupportedException(SR.Format(SR.NotSupported_Signature, type.FullName));
switch (typeId)
{
case CoreTypeId.Boolean:
signature.Boolean();
return;
case CoreTypeId.Byte:
signature.Byte();
return;
case CoreTypeId.SByte:
signature.SByte();
return;
case CoreTypeId.Char:
signature.Char();
return;
case CoreTypeId.Int16:
signature.Int16();
break;
case CoreTypeId.UInt16:
signature.UInt16();
return;
case CoreTypeId.Int32:
signature.Int32();
return;
case CoreTypeId.UInt32:
signature.UInt32();
return;
case CoreTypeId.Int64:
signature.Int64();
return;
case CoreTypeId.UInt64:
signature.UInt64();
return;
case CoreTypeId.Single:
signature.Single();
return;
case CoreTypeId.Double:
signature.Double();
return;
case CoreTypeId.IntPtr:
signature.IntPtr();
return;
case CoreTypeId.UIntPtr:
signature.UIntPtr();
return;
case CoreTypeId.Object:
signature.Object();
return;
case CoreTypeId.String:
signature.String();
return;
}
}

jkotas marked this conversation as resolved.
Show resolved Hide resolved
throw new NotSupportedException(SR.Format(SR.NotSupported_Signature, type.FullName));
jkotas marked this conversation as resolved.
Show resolved Hide resolved
}
}

internal enum CoreTypeId
{
Void = 0,
Object = 1,
Boolean = 2,
Char = 3,
SByte = 4,
Byte = 5,
Int16 = 6,
UInt16 = 7,
Int32 = 8,
UInt32 = 9,
Int64 = 10,
UInt64 = 11,
Single = 12,
Double = 13,
Decimal = 14,
DateTime = 15,
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
String = 16,
IntPtr = 17,
UIntPtr = 18,
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ protected override MethodBuilder DefineMethodCore(string name, MethodAttributes
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute) => throw new NotImplementedException();
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder) => throw new NotImplementedException();

protected override void SetParentCore([DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes)(-1))] Type? parent)
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2074:DynamicallyAccessedMembers",
Justification = "No need to propogate the attribute to the called method")]
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
protected override void SetParentCore([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent)
{
if (parent != null)
{
Expand All @@ -86,9 +88,7 @@ protected override void SetParentCore([DynamicallyAccessedMembers((DynamicallyAc
{
if ((_attributes & TypeAttributes.Interface) != TypeAttributes.Interface)
{
#pragma warning disable IL2074 // Value stored in field does not satisfy 'DynamicallyAccessedMembersAttribute' requirements. The return value of the source method does not have matching annotations.
_typeParent = _module.GetTypeFromCoreAssembly("System.Object");
#pragma warning restore IL2074
_typeParent = _module.GetTypeFromCoreAssembly(CoreTypeId.Object);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public static IEnumerable<object[]> VariousInterfacesStructsTestData()
yield return new object[] { new Type[] { typeof(EmptyStruct) } };
yield return new object[] { new Type[] { typeof(StructWithField) } };
yield return new object[] { new Type[] { typeof(StructWithField), typeof(EmptyStruct) } };
yield return new object[] { new Type[] { typeof(IMultipleMethod), typeof(EmptyStruct) , typeof(INoMethod2), typeof(StructWithField) } };
yield return new object[] { new Type[] { typeof(IMultipleMethod), typeof(EmptyStruct), typeof(INoMethod2), typeof(StructWithField) } };
}

[Theory]
Expand Down