IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
MethodBuilder.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2008-2012 Jeroen Frijters
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19
20 Jeroen Frijters
21 jeroen@frijters.net
22
23*/
24using System;
25using System.Buffers.Binary;
26using System.Collections.Generic;
27using System.Diagnostics;
28using System.Diagnostics.SymbolStore;
29using System.Linq;
30using System.Reflection.Metadata;
31using System.Reflection.Metadata.Ecma335;
33using System.Runtime.InteropServices;
34
37
39{
40
41 internal sealed class MethodBuilder : MethodInfo
42 {
43
44 readonly TypeBuilder type;
45 readonly string name;
46 readonly int pseudoToken;
47
48 // user configurable values
49 Type returnType;
50 Type[] parameterTypes = Array.Empty<Type>();
51 PackedCustomModifiers customModifiers;
52 MethodAttributes attributes;
53 MethodImplAttributes implFlags;
54
55 List<ParameterBuilder> parameters;
56 ILGenerator m_ilGenerator;
57 GenericTypeParameterBuilder[] gtpb;
58 List<CustomAttributeBuilder> declarativeSecurity;
59 MethodSignature methodSignature;
60 CallingConventions callingConvention;
61 bool initLocals = true;
62
63 StringHandle nameIndex;
64 BlobHandle signature;
65 int rva = -1;
66
67 byte[] m_ubBody; // The IL for the method
68 int m_maxStack; // Maximum stack size calculated
69 byte[] m_localSignature; // Local signature if set explicitly via DefineBody. Null otherwise.
70 ExceptionHandler[] m_exceptions; // Exception handlers or null if there are none.
71 int[] m_mdMethodFixups; // The location of all of the token fixups. Null means no fixups.
72 internal LocalSymInfo m_localSymInfo; // keep track debugging local information
73
81 internal MethodBuilder(TypeBuilder typeBuilder, string name, MethodAttributes attributes, CallingConventions callingConvention)
82 {
83 this.type = typeBuilder;
84 this.name = name;
85 this.pseudoToken = typeBuilder.ModuleBuilder.AllocPseudoToken();
86 this.attributes = attributes;
87 if ((attributes & MethodAttributes.Static) == 0)
88 callingConvention |= CallingConventions.HasThis;
89 this.callingConvention = callingConvention;
90 this.returnType = Module.Universe.System_Void;
91 }
92
93 public ILGenerator GetILGenerator()
94 {
95 return GetILGenerator(16);
96 }
97
98 public ILGenerator GetILGenerator(int streamSize)
99 {
100 if (rva != -1)
101 throw new InvalidOperationException();
102
103 return m_ilGenerator ??= new ILGenerator(this, streamSize);
104 }
105
106 public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
107 {
108 SetCustomAttribute(new CustomAttributeBuilder(con, binaryAttribute));
109 }
110
111 private void SetDllImportPseudoCustomAttribute(CustomAttributeBuilder customBuilder)
112 {
113 var callingConvention = customBuilder.GetFieldValue<CallingConvention>("CallingConvention");
114 var charSet = customBuilder.GetFieldValue<CharSet>("CharSet");
115 SetDllImportPseudoCustomAttribute((string)customBuilder.GetConstructorArgument(0),
116 (string)customBuilder.GetFieldValue("EntryPoint"),
117 callingConvention,
118 charSet,
119 (bool?)customBuilder.GetFieldValue("BestFitMapping"),
120 (bool?)customBuilder.GetFieldValue("ThrowOnUnmappableChar"),
121 (bool?)customBuilder.GetFieldValue("SetLastError"),
122 (bool?)customBuilder.GetFieldValue("PreserveSig"),
123 (bool?)customBuilder.GetFieldValue("ExactSpelling"));
124 }
125
126 internal void SetDllImportPseudoCustomAttribute(string dllName, string entryName, CallingConvention? nativeCallConv, CharSet? nativeCharSet, bool? bestFitMapping, bool? throwOnUnmappableChar, bool? setLastError, bool? preserveSig, bool? exactSpelling)
127 {
128 const short NoMangle = 0x0001;
129 const short CharSetMask = 0x0006;
130 const short CharSetNotSpec = 0x0000;
131 const short CharSetAnsi = 0x0002;
132 const short CharSetUnicode = 0x0004;
133 const short CharSetAuto = 0x0006;
134 const short SupportsLastError = 0x0040;
135 const short CallConvMask = 0x0700;
136 const short CallConvWinapi = 0x0100;
137 const short CallConvCdecl = 0x0200;
138 const short CallConvStdcall = 0x0300;
139 const short CallConvThiscall = 0x0400;
140 const short CallConvFastcall = 0x0500;
141 // non-standard flags
142 const short BestFitOn = 0x0010;
143 const short BestFitOff = 0x0020;
144 const short CharMapErrorOn = 0x1000;
145 const short CharMapErrorOff = 0x2000;
146 short flags = CharSetNotSpec | CallConvWinapi;
147
148 if (bestFitMapping.HasValue)
149 flags |= bestFitMapping.Value ? BestFitOn : BestFitOff;
150
151 if (throwOnUnmappableChar.HasValue)
152 flags |= throwOnUnmappableChar.Value ? CharMapErrorOn : CharMapErrorOff;
153
154 if (nativeCallConv.HasValue)
155 {
156 flags &= ~CallConvMask;
157 switch (nativeCallConv.Value)
158 {
159 case System.Runtime.InteropServices.CallingConvention.Cdecl:
160 flags |= CallConvCdecl;
161 break;
162 case System.Runtime.InteropServices.CallingConvention.FastCall:
163 flags |= CallConvFastcall;
164 break;
165 case System.Runtime.InteropServices.CallingConvention.StdCall:
166 flags |= CallConvStdcall;
167 break;
168 case System.Runtime.InteropServices.CallingConvention.ThisCall:
169 flags |= CallConvThiscall;
170 break;
171 case System.Runtime.InteropServices.CallingConvention.Winapi:
172 flags |= CallConvWinapi;
173 break;
174 }
175 }
176
177 if (nativeCharSet.HasValue)
178 {
179 flags &= ~CharSetMask;
180 switch (nativeCharSet.Value)
181 {
182 case CharSet.Ansi:
183 case CharSet.None:
184 flags |= CharSetAnsi;
185 break;
186 case CharSet.Auto:
187 flags |= CharSetAuto;
188 break;
189 case CharSet.Unicode:
190 flags |= CharSetUnicode;
191 break;
192 }
193 }
194
195 if (exactSpelling.HasValue && exactSpelling.Value)
196 flags |= NoMangle;
197
198 if (!preserveSig.HasValue || preserveSig.Value)
199 implFlags |= MethodImplAttributes.PreserveSig;
200
201 if (setLastError.HasValue && setLastError.Value)
202 flags |= SupportsLastError;
203
204 var rec = new ImplMapTable.Record();
205 rec.MappingFlags = flags;
206 rec.MemberForwarded = pseudoToken;
207 rec.ImportName = ModuleBuilder.GetOrAddString(entryName ?? name);
208 rec.ImportScope = MetadataTokens.GetToken(MetadataTokens.ModuleReferenceHandle(ModuleBuilder.ModuleRefTable.FindOrAddRecord(dllName == null ? default : ModuleBuilder.GetOrAddString(dllName))));
209 ModuleBuilder.ImplMapTable.AddRecord(rec);
210 }
211
212 void SetMethodImplAttribute(CustomAttributeBuilder customBuilder)
213 {
214 MethodImplOptions opt;
215 switch (customBuilder.Constructor.ParameterCount)
216 {
217 case 0:
218 opt = 0;
219 break;
220 case 1:
221 {
222 var val = customBuilder.GetConstructorArgument(0);
223 if (val is short s)
224 opt = (MethodImplOptions)s;
225 else if (val is int)
226 opt = (MethodImplOptions)(int)val;
227 else
228 opt = (MethodImplOptions)val;
229 break;
230 }
231 default:
232 throw new NotSupportedException();
233 }
234 implFlags = (MethodImplAttributes)opt;
235 var type = customBuilder.GetFieldValue<MethodCodeType>("MethodCodeType");
236 if (type.HasValue)
237 implFlags |= (MethodImplAttributes)type;
238 }
239
240 public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
241 {
242 switch (customBuilder.KnownCA)
243 {
244 case KnownCA.DllImportAttribute:
245 SetDllImportPseudoCustomAttribute(customBuilder.DecodeBlob(this.Module.Assembly));
246 attributes |= MethodAttributes.PinvokeImpl;
247 break;
248 case KnownCA.MethodImplAttribute:
249 SetMethodImplAttribute(customBuilder.DecodeBlob(this.Module.Assembly));
250 break;
251 case KnownCA.PreserveSigAttribute:
252 implFlags |= MethodImplAttributes.PreserveSig;
253 break;
254 case KnownCA.SpecialNameAttribute:
255 attributes |= MethodAttributes.SpecialName;
256 break;
257 case KnownCA.SuppressUnmanagedCodeSecurityAttribute:
258 attributes |= MethodAttributes.HasSecurity;
259 goto default;
260 default:
261 ModuleBuilder.SetCustomAttribute(pseudoToken, customBuilder);
262 break;
263 }
264 }
265
266 public void __AddDeclarativeSecurity(CustomAttributeBuilder customBuilder)
267 {
268 attributes |= MethodAttributes.HasSecurity;
269 declarativeSecurity ??= new List<CustomAttributeBuilder>();
270 declarativeSecurity.Add(customBuilder);
271 }
272
273 public void AddDeclarativeSecurity(System.Security.Permissions.SecurityAction securityAction, System.Security.PermissionSet permissionSet)
274 {
275 this.ModuleBuilder.AddDeclarativeSecurity(pseudoToken, securityAction, permissionSet);
276 this.attributes |= MethodAttributes.HasSecurity;
277 }
278
279 public void SetImplementationFlags(MethodImplAttributes attributes)
280 {
281 implFlags = attributes;
282 }
283
284 public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, string strParamName)
285 {
286 parameters ??= new List<ParameterBuilder>();
287
288 ModuleBuilder.ParamTable.AddVirtualRecord();
289 var pb = new ParameterBuilder(this, position, attributes, strParamName);
290 if (parameters.Count == 0 || position >= parameters[parameters.Count - 1].Position)
291 {
292 parameters.Add(pb);
293 }
294 else
295 {
296 for (var i = 0; i < parameters.Count; i++)
297 {
298 if (parameters[i].Position > position)
299 {
300 parameters.Insert(i, pb);
301 break;
302 }
303 }
304 }
305
306 return pb;
307 }
308
309 void CheckSig()
310 {
311 if (methodSignature != null)
312 throw new InvalidOperationException("The method signature can not be modified after it has been used.");
313 }
314
315 public void SetParameters(params Type[] parameterTypes)
316 {
317 CheckSig();
318 this.parameterTypes = Util.Copy(parameterTypes);
319 }
320
321 public void SetReturnType(Type returnType)
322 {
323 CheckSig();
324 this.returnType = returnType ?? this.Module.Universe.System_Void;
325 }
326
327 public void SetSignature(Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
328 {
329 SetSignature(returnType, parameterTypes, PackedCustomModifiers.CreateFromExternal(returnTypeOptionalCustomModifiers, returnTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers, parameterTypeRequiredCustomModifiers, Util.NullSafeLength(parameterTypes)));
330 }
331
332 public void __SetSignature(Type returnType, CustomModifiers returnTypeCustomModifiers, Type[] parameterTypes, CustomModifiers[] parameterTypeCustomModifiers)
333 {
334 SetSignature(returnType, parameterTypes, PackedCustomModifiers.CreateFromExternal(returnTypeCustomModifiers, parameterTypeCustomModifiers, Util.NullSafeLength(parameterTypes)));
335 }
336
337 private void SetSignature(Type returnType, Type[] parameterTypes, PackedCustomModifiers customModifiers)
338 {
339 CheckSig();
340 this.returnType = returnType ?? this.Module.Universe.System_Void;
341 this.parameterTypes = Util.Copy(parameterTypes);
342 this.customModifiers = customModifiers;
343 }
344
345 public GenericTypeParameterBuilder[] DefineGenericParameters(params string[] names)
346 {
347 CheckSig();
348 if (gtpb != null)
349 throw new InvalidOperationException("Generic parameters already defined.");
350
351 gtpb = new GenericTypeParameterBuilder[names.Length];
352 for (int i = 0; i < names.Length; i++)
353 gtpb[i] = new GenericTypeParameterBuilder(names[i], this, i);
354
355 return (GenericTypeParameterBuilder[])gtpb.Clone();
356 }
357
358 public override MethodInfo MakeGenericMethod(params Type[] typeArguments)
359 {
360 return new GenericMethodInstance(type, this, typeArguments);
361 }
362
363 public override MethodInfo GetGenericMethodDefinition()
364 {
365 if (gtpb == null)
366 throw new InvalidOperationException();
367
368 return this;
369 }
370
371 public override Type[] GetGenericArguments()
372 {
373 return Util.Copy(gtpb);
374 }
375
376 internal override Type GetGenericMethodArgument(int index)
377 {
378 return gtpb[index];
379 }
380
381 internal override int GetGenericMethodArgumentCount()
382 {
383 return gtpb == null ? 0 : gtpb.Length;
384 }
385
386 public override Type ReturnType
387 {
388 get { return returnType; }
389 }
390
391 public override ParameterInfo ReturnParameter
392 {
393 get { return new ParameterInfoImpl(this, -1); }
394 }
395
396 public override MethodAttributes Attributes
397 {
398 get { return attributes; }
399 }
400
401 public void __SetAttributes(MethodAttributes attributes)
402 {
403 this.attributes = attributes;
404 }
405
406 public void __SetCallingConvention(CallingConventions callingConvention)
407 {
408 this.callingConvention = callingConvention;
409 this.methodSignature = null;
410 }
411
412 public override MethodImplAttributes GetMethodImplementationFlags()
413 {
414 return implFlags;
415 }
416
417 sealed class ParameterInfoImpl : ParameterInfo
418 {
419
420 readonly MethodBuilder method;
421 readonly int parameter;
422
428 internal ParameterInfoImpl(MethodBuilder method, int parameter)
429 {
430 this.method = method;
431 this.parameter = parameter;
432 }
433
434 ParameterBuilder ParameterBuilder
435 {
436 get
437 {
438 if (method.parameters != null)
439 foreach (var pb in method.parameters)
440 if (pb.Position - 1 == parameter)
441 return pb;
442
443 return null;
444 }
445 }
446
447 public override string Name
448 {
449 get
450 {
451 var pb = ParameterBuilder;
452 return pb != null ? pb.Name : null;
453 }
454 }
455
456 public override Type ParameterType
457 {
458 get { return parameter == -1 ? method.returnType : method.parameterTypes[parameter]; }
459 }
460
461 public override ParameterAttributes Attributes
462 {
463 get
464 {
465 var pb = ParameterBuilder;
466 return pb != null ? (ParameterAttributes)pb.Attributes : ParameterAttributes.None;
467 }
468 }
469
470 public override int Position
471 {
472 get { return parameter; }
473 }
474
475 public override object RawDefaultValue
476 {
477 get
478 {
479 var pb = ParameterBuilder;
480 if (pb != null && (pb.Attributes & (int)ParameterAttributes.HasDefault) != 0)
481 return method.ModuleBuilder.ConstantTable.GetRawConstantValue(method.ModuleBuilder, pb.PseudoToken);
482 if (pb != null && (pb.Attributes & (int)ParameterAttributes.Optional) != 0)
483 return Missing.Value;
484
485 return null;
486 }
487 }
488
489 public override CustomModifiers __GetCustomModifiers()
490 {
491 return method.customModifiers.GetParameterCustomModifiers(parameter);
492 }
493
494 public override bool __TryGetFieldMarshal(out FieldMarshal fieldMarshal)
495 {
496 fieldMarshal = new FieldMarshal();
497 return false;
498 }
499
500 public override MemberInfo Member
501 {
502 get { return method; }
503 }
504
505 public override int MetadataToken
506 {
507 get
508 {
509 var pb = ParameterBuilder;
510 return pb != null ? pb.PseudoToken : 0x08000000;
511 }
512 }
513
514 public override Module Module
515 {
516 get { return method.Module; }
517 }
518
519 }
520
521 public override ParameterInfo[] GetParameters()
522 {
523 var parameters = new ParameterInfo[parameterTypes.Length];
524 for (int i = 0; i < parameters.Length; i++)
525 parameters[i] = new ParameterInfoImpl(this, i);
526
527 return parameters;
528 }
529
530 internal override Type[] GetParameterTypes()
531 {
532 return parameterTypes;
533 }
534
535 internal override int ParameterCount
536 {
537 get { return parameterTypes.Length; }
538 }
539
540 public override Type DeclaringType
541 {
542 get { return type.IsModulePseudoType ? null : type; }
543 }
544
545 public override string Name
546 {
547 get { return name; }
548 }
549
550 public override CallingConventions CallingConvention
551 {
552 get { return callingConvention; }
553 }
554
555 public override int MetadataToken
556 {
557 get { return pseudoToken; }
558 }
559
560 public override bool IsGenericMethod
561 {
562 get { return gtpb != null; }
563 }
564
565 public override bool IsGenericMethodDefinition
566 {
567 get { return gtpb != null; }
568 }
569
570 public override Module Module
571 {
572 get { return type.Module; }
573 }
574
575 public Module GetModule()
576 {
577 return type.Module;
578 }
579
580 public MethodToken GetToken()
581 {
582 return new MethodToken(pseudoToken);
583 }
584
585 public override MethodBody GetMethodBody()
586 {
587 throw new NotSupportedException();
588 }
589
590 public override int __MethodRVA
591 {
592 get { throw new NotImplementedException(); }
593 }
594
595 public bool InitLocals
596 {
597 get { return initLocals; }
598 set { initLocals = value; }
599 }
600
601 public void CreateMethodBody(byte[] il, int count)
602 {
603 if (il == null)
604 throw new NotSupportedException();
605 if (il.Length != count)
606 Array.Resize(ref il, count);
607
608 SetMethodBody(il, 16, null, null, null);
609 }
610
615 void ThrowIfShouldNotHaveBody()
616 {
617 if ((implFlags & MethodImplAttributes.CodeTypeMask) != MethodImplAttributes.IL ||
618 (implFlags & MethodImplAttributes.Unmanaged) != 0 ||
619 (attributes & MethodAttributes.PinvokeImpl) != 0 ||
620 /*m_isDllImport*/ false)
621 throw new InvalidOperationException("Method body should not exist.");
622 }
623
632 public void SetMethodBody(byte[] il, int maxStack, byte[] localSignature, IEnumerable<ExceptionHandler> exceptionHandlers, IEnumerable<int> tokenFixups)
633 {
634 if (IsBaked)
635 throw new InvalidOperationException("Method already has a body.");
636
637 ThrowIfShouldNotHaveBody();
638 SetMethodBody(il, maxStack, localSignature, exceptionHandlers?.ToArray(), tokenFixups?.ToArray());
639 }
640
649 void SetMethodBody(byte[] il, int maxStack, byte[] localSignature, ExceptionHandler[] exceptionHandlers, int[] tokenFixups)
650 {
651 this.m_ubBody = il;
652 this.m_maxStack = maxStack;
653 this.m_localSignature = localSignature;
654 this.m_exceptions = exceptionHandlers;
655 this.m_mdMethodFixups = tokenFixups;
656 }
657
658 internal void Bake()
659 {
660 nameIndex = ModuleBuilder.GetOrAddString(name);
661 signature = ModuleBuilder.GetSignatureBlobIndex(MethodSignature);
662
663 // extract method body information from IL generator
664 if (m_ilGenerator != null)
665 {
666 if (m_ilGenerator.m_ScopeTree.m_iOpenScopeCount != 0)
667 throw new InvalidOperationException("Local variable scope was not properly closed.");
668
669 // save information from the ILGenerator
670 SetMethodBody(m_ilGenerator.BakeByteArray(), m_ilGenerator.GetMaxStackSize(), m_ilGenerator.m_localSignature.GetSignature(), GetExceptions(m_ilGenerator.GetExceptions()), m_ilGenerator.GetTokenFixups());
671 }
672
673 if (declarativeSecurity != null)
674 ModuleBuilder.AddDeclarativeSecurity(pseudoToken, declarativeSecurity);
675 }
676
682 ExceptionHandler[] GetExceptions(__ExceptionInfo[] excp)
683 {
684 // no exceptions required
685 if (excp == null)
686 return null;
687
688 int numExceptions = CalculateNumberOfExceptions(excp);
689 if (numExceptions > 0)
690 {
691 var counter = 0;
692 var m_exceptions = new ExceptionHandler[numExceptions];
693
694 for (int i = 0; i < excp.Length; i++)
695 {
696 var numCatch = excp[i].GetNumberOfCatches();
697 var start = excp[i].GetStartAddress();
698 var end = excp[i].GetEndAddress();
699 var type = excp[i].GetExceptionTypes();
700
701 var filterAddrs = excp[i].GetFilterAddresses();
702 var catchAddrs = excp[i].GetCatchAddresses();
703 var catchEndAddrs = excp[i].GetCatchEndAddresses();
704 var catchClass = excp[i].GetCatchClass();
705
706 // for each
707 for (int j = 0; j < numCatch; j++)
708 {
709 int tkExceptionClass = 0;
710 if (catchClass[j] != null)
711 {
712 tkExceptionClass = ModuleBuilder.GetTypeTokenForMemberRef(catchClass[j]);
713 Debug.Assert(ModuleBuilder.IsPseudoToken(tkExceptionClass) == false);
714 }
715
716 switch (type[j])
717 {
718 case __ExceptionInfo.None:
719 case __ExceptionInfo.Fault:
720 case __ExceptionInfo.Filter:
721 m_exceptions[counter++] = new ExceptionHandler(start, end, filterAddrs[j], catchAddrs[j], catchEndAddrs[j], type[j], tkExceptionClass);
722 break;
723
724 case __ExceptionInfo.Finally:
725 m_exceptions[counter++] = new ExceptionHandler(start, excp[i].GetFinallyEndAddress(), filterAddrs[j], catchAddrs[j], catchEndAddrs[j], type[j], tkExceptionClass);
726 break;
727 }
728 }
729 }
730
731 return m_exceptions;
732 }
733
734 return Array.Empty<ExceptionHandler>();
735 }
736
745 static int CalculateNumberOfExceptions(__ExceptionInfo[] excp)
746 {
747 var num = 0;
748
749 if (excp != null)
750 for (int i = 0; i < excp.Length; i++)
751 num += excp[i].GetNumberOfCatches();
752
753 return num;
754 }
755
756 internal ModuleBuilder ModuleBuilder => type.ModuleBuilder;
757
763 internal void WriteMetadata(ref int paramList)
764 {
765 Debug.Assert(IsBaked);
766
767 // encode local signature into metadata
768 var localSignatureHandle = default(StandaloneSignatureHandle);
769 if (m_localSignature != null)
770 {
771 var buf = new BlobBuilder();
772 buf.WriteBytes(m_localSignature);
773 localSignatureHandle = MetadataTokens.StandaloneSignatureHandle(ModuleBuilder.StandAloneSigTable.FindOrAddRecord(ModuleBuilder.GetOrAddBlob(buf)));
774 }
775
776 // write the body to the metadata
777 WriteBody(localSignatureHandle);
778
779 // handle we expect to be allocated
780 var t = (MethodDefinitionHandle)MetadataTokens.EntityHandle(ModuleBuilder.ResolvePseudoToken(pseudoToken));
781
782 // write metadata, allocating real handle
783 var h = ModuleBuilder.Metadata.AddMethodDefinition(
784 (System.Reflection.MethodAttributes)attributes,
785 (System.Reflection.MethodImplAttributes)implFlags,
786 nameIndex,
787 signature,
788 rva,
789 MetadataTokens.ParameterHandle(paramList));
790 Debug.Assert(h == t);
791
792 // ilgen code was already written, but now we can fill in the debug tables
793 WriteSymbols(h, localSignatureHandle);
794
795 if (parameters != null)
796 paramList += parameters.Count;
797
798 // release IL information
799 m_ilGenerator = null;
800 m_ubBody = null;
801 m_exceptions = null;
802 m_localSymInfo = null;
803 }
804
809 void WriteBody(StandaloneSignatureHandle localSignatureHandle)
810 {
811 // might not have a body
812 if (m_ubBody == null)
813 return;
814
815 // calculate whether any large exception regions exist
816 var hasSmallExceptions = HasSmallExceptionRegions(m_exceptions);
817 var methodBody = ModuleBuilder.MethodBodyEncoder.AddMethodBody(m_ubBody.Length, m_maxStack, m_exceptions != null ? m_exceptions.Length : 0, hasSmallExceptions, localSignatureHandle, initLocals ? MethodBodyAttributes.InitLocals : MethodBodyAttributes.None, false);
818 var ilBytes = methodBody.Instructions.GetBytes();
819
820 // if we've been provided with any token fixups, let's patch up the method body directly before copying to IL stream
821 if (m_mdMethodFixups != null && m_mdMethodFixups.Length > 0)
822 {
823 var span = m_ubBody.AsSpan();
824 foreach (int offset in m_mdMethodFixups)
825 {
826 var ilp = span.Slice(offset, sizeof(int));
827 BinaryPrimitives.WriteInt32LittleEndian(ilp, ModuleBuilder.ResolvePseudoToken(BinaryPrimitives.ReadInt32LittleEndian(ilp)));
828 }
829 }
830
831 // copy il stream to instruction space
832 m_ubBody.CopyTo(ilBytes.AsSpan());
833
834 // add exception regions
835 if (m_exceptions != null)
836 foreach (var e in m_exceptions)
837 methodBody.ExceptionRegions.Add((ExceptionRegionKind)(int)e.Kind, e.TryOffset, e.TryLength, e.HandlerOffset, e.HandlerLength, MetadataTokens.EntityHandle(e.ExceptionTypeToken), e.FilterOffset);
838
839 // capture offset as RVA of method
840 rva = methodBody.Offset;
841 }
842
848 bool HasSmallExceptionRegions(ExceptionHandler[] exceptions)
849 {
850 if (exceptions == null)
851 return true;
852
853 if (ExceptionRegionEncoder.IsSmallRegionCount(exceptions.Length) == false)
854 return false;
855
856 foreach (var e in exceptions)
857 if (ExceptionRegionEncoder.IsSmallExceptionRegion(e.TryOffset, e.TryLength) == false || ExceptionRegionEncoder.IsSmallExceptionRegion(e.HandlerOffset, e.HandlerLength) == false)
858 return false;
859
860 return true;
861 }
862
868 void WriteSymbols(MethodDefinitionHandle methodHandle, StandaloneSignatureHandle localSignatureHandle)
869 {
870 if (ModuleBuilder.GetSymWriter() != null)
871 {
872 // set the debugging information such as scope and line number
873 // if it is in a debug module
874 //
875 SymbolToken tk = new SymbolToken(MetadataTokens.GetToken(methodHandle));
876 ISymbolWriter symWriter = ModuleBuilder.GetSymWriter();
877
878 // call OpenMethod to make this method the current method
879 if (symWriter is IMetadataSymbolWriter metadataSymWriter)
880 metadataSymWriter.OpenMethod(tk, localSignatureHandle);
881 else
882 symWriter.OpenMethod(tk);
883
884 // we do write method (since the method exists), but not the contents
885 if (m_ilGenerator != null)
886 {
887 // call OpenScope because OpenMethod no longer implicitly creating
888 // the top-level method scope
889 symWriter.OpenScope(0);
890
891 // emit debug information for method
892 m_localSymInfo?.EmitLocalSymInfo(symWriter);
893 m_ilGenerator.m_ScopeTree.EmitScopeTree(symWriter);
894 m_ilGenerator.m_LineNumberInfo.EmitLineNumberInfo(symWriter);
895
896 symWriter.CloseScope(m_ilGenerator.ILOffset);
897 }
898
899 // exit the method
900 symWriter.CloseMethod();
901 }
902 }
903
904 internal void WriteParamRecords()
905 {
906 if (parameters != null)
907 foreach (var pb in parameters)
908 pb.WriteMetadata();
909 }
910
911 internal void FixupToken(int token, ref int parameterToken)
912 {
913 type.ModuleBuilder.RegisterTokenFixup(pseudoToken, token);
914 if (parameters != null)
915 foreach (var pb in parameters)
916 pb.FixupToken(parameterToken++);
917 }
918
919 internal override MethodSignature MethodSignature => methodSignature ??= MethodSignature.MakeFromBuilder(returnType ?? type.Universe.System_Void, parameterTypes ?? Type.EmptyTypes, customModifiers, callingConvention, gtpb == null ? 0 : gtpb.Length);
920
921 internal override int ImportTo(ModuleBuilder other)
922 {
923 return other.ImportMethodOrField(type, name, this.MethodSignature);
924 }
925
926 internal void CheckBaked()
927 {
928 type.CheckBaked();
929 }
930
931 internal override int GetCurrentToken()
932 {
933 if (type.ModuleBuilder.IsSaved)
934 return type.ModuleBuilder.ResolvePseudoToken(pseudoToken);
935 else
936 return pseudoToken;
937 }
938
939 internal bool IsTypeCreated()
940 {
941 return type.IsCreated();
942 }
943
944 internal override bool IsBaked => type.IsBaked;
945
946 }
947
948}
IKVM.Reflection.Module Module
IKVM.Reflection.Type Type
IKVM.Reflection.ConstructorInfo ConstructorInfo
IKVM.Reflection.MemberInfo MemberInfo
IKVM.Reflection.MethodInfo MethodInfo
IKVM.Reflection.ParameterInfo ParameterInfo
global::java.lang.invoke.LambdaForm.Name Name
System.Runtime.InteropServices.CallingConvention CallingConvention
Definition Signature.cs:35
Represents a method signature from IL metadadata.
KnownCA
These are the pseudo-custom attributes that are recognized by name by the runtime (i....
Definition KnownCA.cs:35