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 1 commit
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 @@ -258,4 +258,10 @@
<data name="InvalidOperation_BadTypeAttributesNotAbstract" xml:space="preserve">
<value>Type must be declared abstract if any of its methods are abstract.</value>
</data>
<data name="AmbiguousMatch_MemberInfo" xml:space="preserve">
<value>Ambiguous match found for '{0} {1}'</value>
</data>
<data name="InvalidOperation_BadEmptyMethodBody" xml:space="preserve">
<value>Method '{0}' does not have a method body.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ internal sealed class MethodBuilderImpl : MethodBuilder
private ILGeneratorImpl? _ilGenerator;
private bool _initLocals;

internal bool _canBeRuntimeImpl;
internal DllImportData? _dllImportData;
internal List<CustomAttributeWrapper>? _customAttributes;
internal ParameterBuilderImpl[]? _parameterBuilders;
Expand Down Expand Up @@ -70,6 +71,19 @@ internal MethodBuilderImpl(string name, MethodAttributes attributes, CallingConv

internal ILGeneratorImpl? ILGeneratorImpl => _ilGenerator;

public new bool IsConstructor
{
get
{
if ((_attributes & (MethodAttributes.RTSpecialName | MethodAttributes.SpecialName)) != (MethodAttributes.RTSpecialName | MethodAttributes.SpecialName))
{
return false;
}

return _name.Equals(ConstructorInfo.ConstructorName) || _name.Equals(ConstructorInfo.TypeConstructorName);
}
}

internal BlobBuilder GetMethodSignatureBlob() => MetadataSignatureHelper.MethodSignatureEncoder(_module,
_parameterTypes, ReturnType, GetSignatureConvention(_callingConventions, _dllImportData), GetGenericArguments().Length, !IsStatic);

Expand Down Expand Up @@ -172,11 +186,13 @@ protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan
case "System.Runtime.CompilerServices.MethodImplAttribute":
int implValue = BinaryPrimitives.ReadUInt16LittleEndian(binaryAttribute.Slice(2));
_methodImplFlags |= (MethodImplAttributes)implValue;
_canBeRuntimeImpl = true;
return;
case "System.Runtime.InteropServices.DllImportAttribute":
{
_dllImportData = DllImportData.CreateDllImportData(CustomAttributeInfo.DecodeCustomAttribute(con, binaryAttribute), out var preserveSig);
_attributes |= MethodAttributes.PinvokeImpl;
_canBeRuntimeImpl = true;
if (preserveSig)
{
_methodImplFlags |= MethodImplAttributes.PreserveSig;
Expand All @@ -201,6 +217,8 @@ protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan
protected override void SetImplementationFlagsCore(MethodImplAttributes attributes)
{
_declaringType.ThrowIfCreated();

_canBeRuntimeImpl = true;
_methodImplFlags = attributes;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ internal sealed class ModuleBuilderImpl : ModuleBuilder
private readonly Dictionary<MemberInfo, EntityHandle> _memberReferences = new();
private readonly List<TypeBuilderImpl> _typeDefinitions = new();
private readonly Dictionary<ConstructorInfo, MemberReferenceHandle> _ctorReferences = new();
private readonly Guid _moduleVersionId;
private Dictionary<string, ModuleReferenceHandle>? _moduleReferences;
private List<CustomAttributeWrapper>? _customAttributes;
private int _nextTypeDefRowId = 1;
Expand All @@ -40,6 +41,7 @@ internal ModuleBuilderImpl(string name, Assembly coreAssembly, MetadataBuilder b
_name = name;
_metadataBuilder = builder;
_assemblyBuilder = assemblyBuilder;
_moduleVersionId = Guid.NewGuid();
}

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Types are preserved via s_coreTypes")]
Expand Down Expand Up @@ -109,7 +111,7 @@ internal void AppendMetadata(MethodBodyStreamEncoder methodBodyEncoder)
ModuleDefinitionHandle moduleHandle = _metadataBuilder.AddModule(
generation: 0,
moduleName: _metadataBuilder.GetOrAddString(_name),
mvid: _metadataBuilder.GetOrAddGuid(Guid.NewGuid()),
mvid: _metadataBuilder.GetOrAddGuid(_moduleVersionId),
encId: default,
encBaseId: default);

Expand Down Expand Up @@ -195,9 +197,10 @@ private void WriteInterfaceImplementations(TypeBuilderImpl typeBuilder, TypeDefi
}
}

if (typeBuilder._interfaceMappings != null)
// Even there were no interfaces implemented it could have an override for base type abstract method
if (typeBuilder._methodOverrides != null)
{
foreach (List<(MethodInfo ifaceMethod, MethodInfo targetMethod)> mapList in typeBuilder._interfaceMappings.Values)
foreach (List<(MethodInfo ifaceMethod, MethodInfo targetMethod)> mapList in typeBuilder._methodOverrides.Values)
{
foreach ((MethodInfo ifaceMethod, MethodInfo targetMethod) pair in mapList)
{
Expand Down Expand Up @@ -566,7 +569,7 @@ private AssemblyReferenceHandle GetAssemblyReference(Assembly assembly)
if (!_assemblyReferences.TryGetValue(assembly, out var handle))
{
AssemblyName aName = assembly.GetName();
handle = AddAssemblyReference(aName.Name!, aName.Version, aName.CultureName, aName.GetPublicKeyToken(), aName.Flags, aName.ContentType);
handle = AddAssemblyReference(aName.Name, aName.Version, aName.CultureName, aName.GetPublicKeyToken(), aName.Flags, aName.ContentType);
_assemblyReferences.Add(assembly, handle);
}

Expand Down Expand Up @@ -687,10 +690,10 @@ private ParameterHandle AddParameter(ParameterBuilderImpl parameter) =>
name: parameter.Name != null ? _metadataBuilder.GetOrAddString(parameter.Name) : default,
sequenceNumber: parameter.Position);

private AssemblyReferenceHandle AddAssemblyReference(string name, Version? version, string? culture,
private AssemblyReferenceHandle AddAssemblyReference(string? name, Version? version, string? culture,
byte[]? publicKeyToken, AssemblyNameFlags flags, AssemblyContentType contentType) =>
_metadataBuilder.AddAssemblyReference(
name: _metadataBuilder.GetOrAddString(name),
name: name == null ? default : _metadataBuilder.GetOrAddString(name),
version: version ?? new Version(0, 0, 0, 0),
culture: (culture == null) ? default : _metadataBuilder.GetOrAddString(value: culture),
publicKeyOrToken: (publicKeyToken == null) ? default : _metadataBuilder.GetOrAddBlob(publicKeyToken), // reference has token, not full public key
Expand Down Expand Up @@ -744,28 +747,29 @@ internal TypeBuilder DefineNestedType(string name, TypeAttributes attr, [Dynamic
public override string Name => "<In Memory Module>";
public override string ScopeName => _name;
public override Assembly Assembly => _assemblyBuilder;
public override Guid ModuleVersionId => _moduleVersionId;
public override bool IsDefined(Type attributeType, bool inherit) => throw new NotImplementedException();

public override int GetFieldMetadataToken(FieldInfo field)
{
if (field is FieldBuilderImpl fb)
if (field is FieldBuilderImpl fb && fb._handle != default)
{
return MetadataTokens.GetToken(fb._handle);
}

return field.MetadataToken;
return 0;
}

public override int GetMethodMetadataToken(ConstructorInfo constructor) => throw new NotImplementedException();

public override int GetMethodMetadataToken(MethodInfo method)
{
if (method is MethodBuilderImpl mb)
if (method is MethodBuilderImpl mb && mb._handle != default)
{
return MetadataTokens.GetToken(mb._handle);
}

return method.MetadataToken;
return 0;
}

public override int GetStringMetadataToken(string stringConstant) => MetadataTokens.GetToken(_metadataBuilder.GetOrAddUserString(stringConstant));
Expand Down
Loading