Skip to content

Commit 35cbe11

Browse files
buyaa-njkotas
andauthored
Write generic method, write complex signatures like array/pointer/generics (#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]>
1 parent a8947cc commit 35cbe11

File tree

11 files changed

+541
-135
lines changed

11 files changed

+541
-135
lines changed

src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -519,17 +519,18 @@ protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(par
519519
if (m_inst != null)
520520
throw new InvalidOperationException(SR.InvalidOperation_GenericParametersAlreadySet);
521521

522-
for (int i = 0; i < names.Length; i++)
523-
ArgumentNullException.ThrowIfNull(names[i], nameof(names));
524-
525522
if (m_token != 0)
526523
throw new InvalidOperationException(SR.InvalidOperation_MethodBuilderBaked);
527524

528-
m_bIsGenMethDef = true;
529525
m_inst = new RuntimeGenericTypeParameterBuilder[names.Length];
530526
for (int i = 0; i < names.Length; i++)
531-
m_inst[i] = new RuntimeGenericTypeParameterBuilder(new RuntimeTypeBuilder(names[i], i, this));
527+
{
528+
string name = names[i];
529+
ArgumentNullException.ThrowIfNull(name, nameof(names));
530+
m_inst[i] = new RuntimeGenericTypeParameterBuilder(new RuntimeTypeBuilder(name, i, this));
531+
}
532532

533+
m_bIsGenMethDef = true;
533534
return m_inst;
534535
}
535536

src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.cs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,29 +1061,6 @@ public override Type UnderlyingSystemType
10611061
}
10621062
}
10631063

1064-
public override Type MakePointerType()
1065-
{
1066-
return SymbolType.FormCompoundType("*", this, 0)!;
1067-
}
1068-
1069-
public override Type MakeByRefType()
1070-
{
1071-
return SymbolType.FormCompoundType("&", this, 0)!;
1072-
}
1073-
1074-
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
1075-
public override Type MakeArrayType()
1076-
{
1077-
return SymbolType.FormCompoundType("[]", this, 0)!;
1078-
}
1079-
1080-
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
1081-
public override Type MakeArrayType(int rank)
1082-
{
1083-
string s = GetRankString(rank);
1084-
return SymbolType.FormCompoundType(s, this, 0)!;
1085-
}
1086-
10871064
#endregion
10881065

10891066
#region ICustomAttributeProvider Implementation
@@ -1157,13 +1134,6 @@ protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(par
11571134
return m_inst;
11581135
}
11591136

1160-
[RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")]
1161-
[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.")]
1162-
public override Type MakeGenericType(params Type[] typeArguments)
1163-
{
1164-
return TypeBuilderInstantiation.MakeGenericType(this, typeArguments);
1165-
}
1166-
11671137
public override Type[] GetGenericArguments() => m_inst ?? Type.EmptyTypes;
11681138

11691139
// If a TypeBuilder is generic, it must be a generic type definition

src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,5 +290,35 @@ public void SetParent([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes
290290
=> SetParentCore(parent);
291291

292292
protected abstract void SetParentCore([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent);
293+
294+
public override Type MakePointerType()
295+
{
296+
return SymbolType.FormCompoundType("*", this, 0)!;
297+
}
298+
299+
public override Type MakeByRefType()
300+
{
301+
return SymbolType.FormCompoundType("&", this, 0)!;
302+
}
303+
304+
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
305+
public override Type MakeArrayType()
306+
{
307+
return SymbolType.FormCompoundType("[]", this, 0)!;
308+
}
309+
310+
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
311+
public override Type MakeArrayType(int rank)
312+
{
313+
string s = GetRankString(rank);
314+
return SymbolType.FormCompoundType(s, this, 0)!;
315+
}
316+
317+
[RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")]
318+
[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.")]
319+
public override Type MakeGenericType(params Type[] typeArguments)
320+
{
321+
return TypeBuilderInstantiation.MakeGenericType(this, typeArguments);
322+
}
293323
}
294324
}

src/libraries/System.Reflection.Emit/src/Resources/Strings.resx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,7 @@
168168
<data name="Argument_SizeConstMustBeSpecified" xml:space="preserve">
169169
<value>SizeConst parameter must be specified for UnmanagedType.ByValTStr type.</value>
170170
</data>
171-
</root>
171+
<data name="InvalidOperation_GenericParametersAlreadySet" xml:space="preserve">
172+
<value>The generic parameters are already defined on this MethodBuilder.</value>
173+
</data>
174+
</root>

src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/GenericTypeParameterBuilderImpl.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,38 @@
44
using System.Collections.Generic;
55
using System.Diagnostics.CodeAnalysis;
66
using System.Globalization;
7+
using System.Reflection.Metadata;
78

89
namespace System.Reflection.Emit
910
{
1011
internal sealed class GenericTypeParameterBuilderImpl : GenericTypeParameterBuilder
1112
{
1213
private readonly string _name;
13-
private readonly TypeBuilderImpl _type;
14+
private readonly TypeBuilder _type;
1415
private readonly int _genParamPosition;
1516
private GenericParameterAttributes _genParamAttributes;
16-
private bool _isGenericMethodParameter;
1717
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
1818
private Type? _parent;
1919

2020
internal List<CustomAttributeWrapper>? _customAttributes;
2121
internal List<Type>? _interfaces;
22+
private MethodBuilderImpl? _methodBuilder;
23+
internal EntityHandle _parentHandle;
2224

23-
internal GenericTypeParameterBuilderImpl(string name, int genParamPosition, TypeBuilderImpl typeBuilder)
25+
internal GenericTypeParameterBuilderImpl(string name, int genParamPosition, TypeBuilderImpl typeBuilder, EntityHandle parentHandle)
2426
{
2527
_name = name;
2628
_genParamPosition = genParamPosition;
2729
_type = typeBuilder;
28-
_isGenericMethodParameter = false;
30+
_parentHandle = parentHandle;
31+
}
32+
33+
public GenericTypeParameterBuilderImpl(string name, int genParamPosition, MethodBuilderImpl methodBuilder)
34+
{
35+
_name = name;
36+
_genParamPosition = genParamPosition;
37+
_methodBuilder = methodBuilder;
38+
_type = methodBuilder.DeclaringType;
2939
}
3040

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

6070
public override Type[] GetGenericParameterConstraints() =>
6171
_interfaces == null ? EmptyTypes : _interfaces.ToArray();
62-
public override bool IsGenericTypeParameter => !_isGenericMethodParameter;
63-
public override bool IsGenericMethodParameter => _isGenericMethodParameter;
72+
public override bool IsGenericTypeParameter => _methodBuilder is null;
73+
public override bool IsGenericMethodParameter => _methodBuilder is not null;
6474
public override int GenericParameterPosition => _genParamPosition;
6575
public override GenericParameterAttributes GenericParameterAttributes => _genParamAttributes;
6676
public override string Name => _name;

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

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,23 @@
33

44
using System.Buffers.Binary;
55
using System.Collections.Generic;
6-
using System.Diagnostics;
76
using System.Diagnostics.CodeAnalysis;
87
using System.Globalization;
98
using System.Reflection.Metadata;
10-
using System.Runtime.InteropServices;
119

1210
namespace System.Reflection.Emit
1311
{
1412
internal sealed class MethodBuilderImpl : MethodBuilder
1513
{
16-
private readonly Type _returnType;
17-
private readonly Type[]? _parameterTypes;
14+
private Type _returnType;
15+
private Type[]? _parameterTypes;
1816
private readonly ModuleBuilderImpl _module;
1917
private readonly string _name;
2018
private readonly CallingConventions _callingConventions;
2119
private readonly TypeBuilderImpl _declaringType;
2220
private MethodAttributes _attributes;
2321
private MethodImplAttributes _methodImplFlags;
22+
private GenericTypeParameterBuilderImpl[]? _typeParameters;
2423

2524
internal DllImportData? _dllImportData;
2625
internal List<CustomAttributeWrapper>? _customAttributes;
@@ -49,11 +48,43 @@ internal MethodBuilderImpl(string name, MethodAttributes attributes, CallingConv
4948
_methodImplFlags = MethodImplAttributes.IL;
5049
}
5150

52-
internal BlobBuilder GetMethodSignatureBlob() =>
53-
MetadataSignatureHelper.MethodSignatureEncoder(_module, _parameterTypes, ReturnType, !IsStatic);
51+
internal BlobBuilder GetMethodSignatureBlob() => MetadataSignatureHelper.MethodSignatureEncoder(_module,
52+
_parameterTypes, ReturnType, GetSignatureConvention(_callingConventions), GetGenericArguments().Length, !IsStatic);
5453

54+
internal static SignatureCallingConvention GetSignatureConvention(CallingConventions callingConventions)
55+
{
56+
// TODO: find out and handle other SignatureCallingConvention scenarios
57+
SignatureCallingConvention convention = SignatureCallingConvention.Default;
58+
if ((callingConventions & CallingConventions.HasThis) != 0 ||
59+
(callingConventions & CallingConventions.ExplicitThis) != 0)
60+
{
61+
convention |= SignatureCallingConvention.ThisCall;
62+
}
63+
64+
if ((callingConventions & CallingConventions.VarArgs) != 0)
65+
{
66+
convention |= SignatureCallingConvention.VarArgs;
67+
}
68+
69+
return convention;
70+
}
5571
protected override bool InitLocalsCore { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
56-
protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(params string[] names) => throw new NotImplementedException();
72+
protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(params string[] names)
73+
{
74+
if (_typeParameters != null)
75+
throw new InvalidOperationException(SR.InvalidOperation_GenericParametersAlreadySet);
76+
77+
var typeParameters = new GenericTypeParameterBuilderImpl[names.Length];
78+
for (int i = 0; i < names.Length; i++)
79+
{
80+
string name = names[i];
81+
ArgumentNullException.ThrowIfNull(names, nameof(names));
82+
typeParameters[i] = new GenericTypeParameterBuilderImpl(name, i, this);
83+
}
84+
85+
return _typeParameters = typeParameters;
86+
}
87+
5788
protected override ParameterBuilder DefineParameterCore(int position, ParameterAttributes attributes, string? strParamName)
5889
{
5990
if (position > 0 && (_parameterTypes == null || position > _parameterTypes.Length))
@@ -66,6 +97,7 @@ protected override ParameterBuilder DefineParameterCore(int position, ParameterA
6697
_parameters[position] = parameter;
6798
return parameter;
6899
}
100+
69101
protected override ILGenerator GetILGeneratorCore(int size) => throw new NotImplementedException();
70102
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
71103
{
@@ -106,15 +138,32 @@ protected override void SetImplementationFlagsCore(MethodImplAttributes attribut
106138
_methodImplFlags = attributes;
107139
}
108140
protected override void SetSignatureCore(Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes,
109-
Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers) => throw new NotImplementedException();
141+
Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers)
142+
{
143+
if (returnType != null)
144+
{
145+
_returnType = returnType;
146+
}
147+
148+
if (parameterTypes != null)
149+
{
150+
_parameterTypes = new Type[parameterTypes.Length];
151+
_parameters = new ParameterBuilderImpl[parameterTypes.Length + 1]; // parameter 0 reserved for return type
152+
for (int i = 0; i < parameterTypes.Length; i++)
153+
{
154+
ArgumentNullException.ThrowIfNull(_parameterTypes[i] = parameterTypes[i], nameof(parameterTypes));
155+
}
156+
}
157+
// TODO: Add support for other parameters: returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypeRequiredCustomModifiers and parameterTypeOptionalCustomModifiers
158+
}
110159
public override string Name => _name;
111160
public override MethodAttributes Attributes => _attributes;
112161
public override CallingConventions CallingConvention => _callingConventions;
113162
public override TypeBuilder DeclaringType => _declaringType;
114163
public override Module Module => _module;
115-
public override bool ContainsGenericParameters { get => throw new NotSupportedException(SR.NotSupported_DynamicModule); }
116-
public override bool IsGenericMethod { get => throw new NotImplementedException(); }
117-
public override bool IsGenericMethodDefinition { get => throw new NotImplementedException(); }
164+
public override bool ContainsGenericParameters => throw new NotSupportedException();
165+
public override bool IsGenericMethod => _typeParameters != null;
166+
public override bool IsGenericMethodDefinition => _typeParameters != null;
118167
public override bool IsSecurityCritical => true;
119168
public override bool IsSecuritySafeCritical => false;
120169
public override bool IsSecurityTransparent => false;
@@ -131,11 +180,9 @@ protected override void SetSignatureCore(Type? returnType, Type[]? returnTypeReq
131180

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

134-
public override Type[] GetGenericArguments()
135-
=> throw new NotImplementedException();
183+
public override Type[] GetGenericArguments() => _typeParameters ?? Type.EmptyTypes;
136184

137-
public override MethodInfo GetGenericMethodDefinition()
138-
=> throw new NotImplementedException();
185+
public override MethodInfo GetGenericMethodDefinition() => !IsGenericMethod ? throw new InvalidOperationException() : this;
139186

140187
public override int GetHashCode()
141188
=> throw new NotImplementedException();

0 commit comments

Comments
 (0)