Skip to content

Commit

Permalink
Write generic method, write complex signatures like array/pointer/gen…
Browse files Browse the repository at this point in the history
…erics (#86026)

* Write generic method, write complex signatures like array/pointer/generics

* Update src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/MethodBuilderImpl.cs

Co-authored-by: Jan Kotas <[email protected]>

* Update src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/MethodBuilderImpl.cs

---------

Co-authored-by: Jan Kotas <[email protected]>
  • Loading branch information
buyaa-n and jkotas authored May 12, 2023
1 parent a8947cc commit 35cbe11
Show file tree
Hide file tree
Showing 11 changed files with 541 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -519,17 +519,18 @@ protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(par
if (m_inst != null)
throw new InvalidOperationException(SR.InvalidOperation_GenericParametersAlreadySet);

for (int i = 0; i < names.Length; i++)
ArgumentNullException.ThrowIfNull(names[i], nameof(names));

if (m_token != 0)
throw new InvalidOperationException(SR.InvalidOperation_MethodBuilderBaked);

m_bIsGenMethDef = true;
m_inst = new RuntimeGenericTypeParameterBuilder[names.Length];
for (int i = 0; i < names.Length; i++)
m_inst[i] = new RuntimeGenericTypeParameterBuilder(new RuntimeTypeBuilder(names[i], i, this));
{
string name = names[i];
ArgumentNullException.ThrowIfNull(name, nameof(names));
m_inst[i] = new RuntimeGenericTypeParameterBuilder(new RuntimeTypeBuilder(name, i, this));
}

m_bIsGenMethDef = true;
return m_inst;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1061,29 +1061,6 @@ public override Type UnderlyingSystemType
}
}

public override Type MakePointerType()
{
return SymbolType.FormCompoundType("*", this, 0)!;
}

public override Type MakeByRefType()
{
return SymbolType.FormCompoundType("&", this, 0)!;
}

[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
public override Type MakeArrayType()
{
return SymbolType.FormCompoundType("[]", this, 0)!;
}

[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
public override Type MakeArrayType(int rank)
{
string s = GetRankString(rank);
return SymbolType.FormCompoundType(s, this, 0)!;
}

#endregion

#region ICustomAttributeProvider Implementation
Expand Down Expand Up @@ -1157,13 +1134,6 @@ protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(par
return m_inst;
}

[RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")]
[RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")]
public override Type MakeGenericType(params Type[] typeArguments)
{
return TypeBuilderInstantiation.MakeGenericType(this, typeArguments);
}

public override Type[] GetGenericArguments() => m_inst ?? Type.EmptyTypes;

// If a TypeBuilder is generic, it must be a generic type definition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,5 +290,35 @@ public void SetParent([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes
=> SetParentCore(parent);

protected abstract void SetParentCore([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent);

public override Type MakePointerType()
{
return SymbolType.FormCompoundType("*", this, 0)!;
}

public override Type MakeByRefType()
{
return SymbolType.FormCompoundType("&", this, 0)!;
}

[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
public override Type MakeArrayType()
{
return SymbolType.FormCompoundType("[]", this, 0)!;
}

[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
public override Type MakeArrayType(int rank)
{
string s = GetRankString(rank);
return SymbolType.FormCompoundType(s, this, 0)!;
}

[RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")]
[RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")]
public override Type MakeGenericType(params Type[] typeArguments)
{
return TypeBuilderInstantiation.MakeGenericType(this, typeArguments);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,7 @@
<data name="Argument_SizeConstMustBeSpecified" xml:space="preserve">
<value>SizeConst parameter must be specified for UnmanagedType.ByValTStr type.</value>
</data>
</root>
<data name="InvalidOperation_GenericParametersAlreadySet" xml:space="preserve">
<value>The generic parameters are already defined on this MethodBuilder.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,38 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection.Metadata;

namespace System.Reflection.Emit
{
internal sealed class GenericTypeParameterBuilderImpl : GenericTypeParameterBuilder
{
private readonly string _name;
private readonly TypeBuilderImpl _type;
private readonly TypeBuilder _type;
private readonly int _genParamPosition;
private GenericParameterAttributes _genParamAttributes;
private bool _isGenericMethodParameter;
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
private Type? _parent;

internal List<CustomAttributeWrapper>? _customAttributes;
internal List<Type>? _interfaces;
private MethodBuilderImpl? _methodBuilder;
internal EntityHandle _parentHandle;

internal GenericTypeParameterBuilderImpl(string name, int genParamPosition, TypeBuilderImpl typeBuilder)
internal GenericTypeParameterBuilderImpl(string name, int genParamPosition, TypeBuilderImpl typeBuilder, EntityHandle parentHandle)
{
_name = name;
_genParamPosition = genParamPosition;
_type = typeBuilder;
_isGenericMethodParameter = false;
_parentHandle = parentHandle;
}

public GenericTypeParameterBuilderImpl(string name, int genParamPosition, MethodBuilderImpl methodBuilder)
{
_name = name;
_genParamPosition = genParamPosition;
_methodBuilder = methodBuilder;
_type = methodBuilder.DeclaringType;
}

protected override void SetBaseTypeConstraintCore([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? baseTypeConstraint)
Expand Down Expand Up @@ -59,8 +69,8 @@ protected override void SetInterfaceConstraintsCore(params Type[]? interfaceCons

public override Type[] GetGenericParameterConstraints() =>
_interfaces == null ? EmptyTypes : _interfaces.ToArray();
public override bool IsGenericTypeParameter => !_isGenericMethodParameter;
public override bool IsGenericMethodParameter => _isGenericMethodParameter;
public override bool IsGenericTypeParameter => _methodBuilder is null;
public override bool IsGenericMethodParameter => _methodBuilder is not null;
public override int GenericParameterPosition => _genParamPosition;
public override GenericParameterAttributes GenericParameterAttributes => _genParamAttributes;
public override string Name => _name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,23 @@

using System.Buffers.Binary;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection.Metadata;
using System.Runtime.InteropServices;

namespace System.Reflection.Emit
{
internal sealed class MethodBuilderImpl : MethodBuilder
{
private readonly Type _returnType;
private readonly Type[]? _parameterTypes;
private Type _returnType;
private Type[]? _parameterTypes;
private readonly ModuleBuilderImpl _module;
private readonly string _name;
private readonly CallingConventions _callingConventions;
private readonly TypeBuilderImpl _declaringType;
private MethodAttributes _attributes;
private MethodImplAttributes _methodImplFlags;
private GenericTypeParameterBuilderImpl[]? _typeParameters;

internal DllImportData? _dllImportData;
internal List<CustomAttributeWrapper>? _customAttributes;
Expand Down Expand Up @@ -49,11 +48,43 @@ internal MethodBuilderImpl(string name, MethodAttributes attributes, CallingConv
_methodImplFlags = MethodImplAttributes.IL;
}

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

internal static SignatureCallingConvention GetSignatureConvention(CallingConventions callingConventions)
{
// TODO: find out and handle other SignatureCallingConvention scenarios
SignatureCallingConvention convention = SignatureCallingConvention.Default;
if ((callingConventions & CallingConventions.HasThis) != 0 ||
(callingConventions & CallingConventions.ExplicitThis) != 0)
{
convention |= SignatureCallingConvention.ThisCall;
}

if ((callingConventions & CallingConventions.VarArgs) != 0)
{
convention |= SignatureCallingConvention.VarArgs;
}

return convention;
}
protected override bool InitLocalsCore { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(params string[] names) => throw new NotImplementedException();
protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(params string[] names)
{
if (_typeParameters != null)
throw new InvalidOperationException(SR.InvalidOperation_GenericParametersAlreadySet);

var typeParameters = new GenericTypeParameterBuilderImpl[names.Length];
for (int i = 0; i < names.Length; i++)
{
string name = names[i];
ArgumentNullException.ThrowIfNull(names, nameof(names));
typeParameters[i] = new GenericTypeParameterBuilderImpl(name, i, this);
}

return _typeParameters = typeParameters;
}

protected override ParameterBuilder DefineParameterCore(int position, ParameterAttributes attributes, string? strParamName)
{
if (position > 0 && (_parameterTypes == null || position > _parameterTypes.Length))
Expand All @@ -66,6 +97,7 @@ protected override ParameterBuilder DefineParameterCore(int position, ParameterA
_parameters[position] = parameter;
return parameter;
}

protected override ILGenerator GetILGeneratorCore(int size) => throw new NotImplementedException();
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
Expand Down Expand Up @@ -106,15 +138,32 @@ protected override void SetImplementationFlagsCore(MethodImplAttributes attribut
_methodImplFlags = attributes;
}
protected override void SetSignatureCore(Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes,
Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers) => throw new NotImplementedException();
Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers)
{
if (returnType != null)
{
_returnType = returnType;
}

if (parameterTypes != null)
{
_parameterTypes = new Type[parameterTypes.Length];
_parameters = new ParameterBuilderImpl[parameterTypes.Length + 1]; // parameter 0 reserved for return type
for (int i = 0; i < parameterTypes.Length; i++)
{
ArgumentNullException.ThrowIfNull(_parameterTypes[i] = parameterTypes[i], nameof(parameterTypes));
}
}
// TODO: Add support for other parameters: returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypeRequiredCustomModifiers and parameterTypeOptionalCustomModifiers
}
public override string Name => _name;
public override MethodAttributes Attributes => _attributes;
public override CallingConventions CallingConvention => _callingConventions;
public override TypeBuilder DeclaringType => _declaringType;
public override Module Module => _module;
public override bool ContainsGenericParameters { get => throw new NotSupportedException(SR.NotSupported_DynamicModule); }
public override bool IsGenericMethod { get => throw new NotImplementedException(); }
public override bool IsGenericMethodDefinition { get => throw new NotImplementedException(); }
public override bool ContainsGenericParameters => throw new NotSupportedException();
public override bool IsGenericMethod => _typeParameters != null;
public override bool IsGenericMethodDefinition => _typeParameters != null;
public override bool IsSecurityCritical => true;
public override bool IsSecuritySafeCritical => false;
public override bool IsSecurityTransparent => false;
Expand All @@ -131,11 +180,9 @@ protected override void SetSignatureCore(Type? returnType, Type[]? returnTypeReq

public override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new NotSupportedException(SR.NotSupported_DynamicModule);

public override Type[] GetGenericArguments()
=> throw new NotImplementedException();
public override Type[] GetGenericArguments() => _typeParameters ?? Type.EmptyTypes;

public override MethodInfo GetGenericMethodDefinition()
=> throw new NotImplementedException();
public override MethodInfo GetGenericMethodDefinition() => !IsGenericMethod ? throw new InvalidOperationException() : this;

public override int GetHashCode()
=> throw new NotImplementedException();
Expand Down
Loading

0 comments on commit 35cbe11

Please sign in to comment.