-
Notifications
You must be signed in to change notification settings - Fork 4.5k
/
MethodBuilderImpl.cs
299 lines (248 loc) · 14 KB
/
MethodBuilderImpl.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
namespace System.Reflection.Emit
{
internal sealed class MethodBuilderImpl : MethodBuilder
{
private Type _returnType;
internal 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;
private ILGeneratorImpl? _ilGenerator;
private bool _initLocals;
internal DllImportData? _dllImportData;
internal List<CustomAttributeWrapper>? _customAttributes;
internal ParameterBuilderImpl[]? _parameterBuilders;
internal MethodDefinitionHandle _handle;
internal MethodBuilderImpl(string name, MethodAttributes attributes, CallingConventions callingConventions, Type? returnType,
Type[]? parameterTypes, ModuleBuilderImpl module, TypeBuilderImpl declaringType)
{
_module = module;
_returnType = returnType ?? _module.GetTypeFromCoreAssembly(CoreTypeId.Void);
_name = name;
_attributes = attributes;
if ((attributes & MethodAttributes.Static) == 0)
{
// turn on the has this calling convention
callingConventions |= CallingConventions.HasThis;
}
else if ((attributes & MethodAttributes.Virtual) != 0 && (attributes & MethodAttributes.Abstract) == 0)
{
throw new ArgumentException(SR.Argument_NoStaticVirtual);
}
_callingConventions = callingConventions;
_declaringType = declaringType;
if (parameterTypes != null)
{
_parameterTypes = new Type[parameterTypes.Length];
_parameterBuilders = 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));
}
}
_methodImplFlags = MethodImplAttributes.IL;
_initLocals = true;
}
internal int ParameterCount => _parameterTypes == null ? 0 : _parameterTypes.Length;
internal Type[]? ParameterTypes => _parameterTypes;
internal ILGeneratorImpl? ILGeneratorImpl => _ilGenerator;
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;
}
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; }
set { ThrowIfGeneric(); _initLocals = value; }
}
private void ThrowIfGeneric() { if (IsGenericMethod && !IsGenericMethodDefinition) throw new InvalidOperationException(); }
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)
{
_declaringType.ThrowIfCreated();
if (position > 0 && (_parameterTypes == null || position > _parameterTypes.Length))
{
throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_ParamSequence);
}
_parameterBuilders ??= new ParameterBuilderImpl[1];
attributes &= ~ParameterAttributes.ReservedMask;
ParameterBuilderImpl parameter = new ParameterBuilderImpl(this, position, attributes, strParamName);
_parameterBuilders[position] = parameter;
return parameter;
}
protected override ILGenerator GetILGeneratorCore(int size)
{
if (IsGenericMethod && !IsGenericMethodDefinition)
{
throw new InvalidOperationException();
}
if ((_methodImplFlags & MethodImplAttributes.CodeTypeMask) != MethodImplAttributes.IL ||
(_methodImplFlags & MethodImplAttributes.Unmanaged) != 0 ||
(_attributes & MethodAttributes.PinvokeImpl) != 0)
{
throw new InvalidOperationException(SR.InvalidOperation_ShouldNotHaveMethodBody);
}
if ((_attributes & MethodAttributes.Abstract) != 0)
{
throw new InvalidOperationException(SR.InvalidOperation_ShouldNotHaveMethodBody);
}
return _ilGenerator ??= new ILGeneratorImpl(this, size);
}
internal void SetCustomAttribute(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute) =>
SetCustomAttributeCore(con, binaryAttribute);
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
// Handle pseudo custom attributes
switch (con.ReflectedType!.FullName)
{
case "System.Runtime.CompilerServices.MethodImplAttribute":
int implValue = BinaryPrimitives.ReadUInt16LittleEndian(binaryAttribute.Slice(2));
_methodImplFlags |= (MethodImplAttributes)implValue;
return;
case "System.Runtime.InteropServices.DllImportAttribute":
{
_dllImportData = DllImportData.CreateDllImportData(CustomAttributeInfo.DecodeCustomAttribute(con, binaryAttribute), out var preserveSig);
_attributes |= MethodAttributes.PinvokeImpl;
if (preserveSig)
{
_methodImplFlags |= MethodImplAttributes.PreserveSig;
}
}
return;
case "System.Runtime.InteropServices.PreserveSigAttribute":
_methodImplFlags |= MethodImplAttributes.PreserveSig;
return;
case "System.Runtime.CompilerServices.SpecialNameAttribute":
_attributes |= MethodAttributes.SpecialName;
return;
case "System.Security.SuppressUnmanagedCodeSecurityAttribute":
_attributes |= MethodAttributes.HasSecurity;
break;
}
_customAttributes ??= new List<CustomAttributeWrapper>();
_customAttributes.Add(new CustomAttributeWrapper(con, binaryAttribute));
}
protected override void SetImplementationFlagsCore(MethodImplAttributes attributes)
{
_declaringType.ThrowIfCreated();
_methodImplFlags = attributes;
}
protected override void SetSignatureCore(Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes,
Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers)
{
if (returnType != null)
{
_returnType = returnType;
}
if (parameterTypes != null)
{
_parameterTypes = new Type[parameterTypes.Length];
_parameterBuilders = 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 => 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;
public override int MetadataToken => _handle == default ? 0 : MetadataTokens.GetToken(_handle);
public override RuntimeMethodHandle MethodHandle => throw new NotSupportedException(SR.NotSupported_DynamicModule);
public override Type? ReflectedType => _declaringType;
public override ParameterInfo ReturnParameter { get => throw new NotImplementedException(); }
public override Type ReturnType => _returnType;
public override ICustomAttributeProvider ReturnTypeCustomAttributes { get => throw new NotImplementedException(); }
public override MethodInfo GetBaseDefinition() => this;
public override object[] GetCustomAttributes(bool inherit) => throw new NotSupportedException(SR.NotSupported_DynamicModule);
public override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new NotSupportedException(SR.NotSupported_DynamicModule);
public override Type[] GetGenericArguments() => _typeParameters ?? Type.EmptyTypes;
public override MethodInfo GetGenericMethodDefinition() => !IsGenericMethod ? throw new InvalidOperationException() : this;
public override MethodImplAttributes GetMethodImplementationFlags()
=> _methodImplFlags;
public override ParameterInfo[] GetParameters()
{
// This is called from ILGenerator when Emit(OpCode, ConstructorInfo) when the ctor is
// instance of 'ConstructorOnTypeBuilderInstantiation', so we could not throw here even
// the type was not baked. Runtime implementation throws when the type is not baked.
if (_parameterTypes == null)
{
return Array.Empty<ParameterInfo>();
}
_parameterBuilders ??= new ParameterBuilderImpl[_parameterTypes.Length + 1]; // parameter 0 reserved for return type
ParameterInfo[] parameters = new ParameterInfo[_parameterTypes.Length];
for (int i = 0; i < _parameterTypes.Length; i++)
{
if (_parameterBuilders[i + 1] == null)
{
parameters[i] = new ParameterInfoWrapper(new ParameterBuilderImpl(this, i, ParameterAttributes.None, null), _parameterTypes[i]);
}
else
{
parameters[i] = new ParameterInfoWrapper(_parameterBuilders[i + 1], _parameterTypes[i]);
}
}
return parameters;
}
public override object Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture)
=> throw new NotSupportedException(SR.NotSupported_DynamicModule);
public override bool IsDefined(Type attributeType, bool inherit) => throw new NotSupportedException(SR.NotSupported_DynamicModule);
[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 MethodInfo MakeGenericMethod(params Type[] typeArguments) =>
MethodBuilderInstantiation.MakeGenericMethod(this, typeArguments);
}
}