From 6f97718bc344ef347c7a8b2e90ccff9dacdc5ed5 Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Mon, 22 May 2023 19:36:40 -0700 Subject: [PATCH] Abstract out System.Reflection.Emit.ILGenerator (#86594) * Abstract out ILGenerator * Finish up abstracting * Remove protected abstract methods, use more public abstract instead * Use RuntimeILGenerator for Linq test --- .../System.Private.CoreLib.csproj | 2 +- .../System/Reflection/Emit/DynamicILGenerator.cs | 4 +- .../Emit/{ILGenerator.cs => RuntimeILGenerator.cs} | 215 ++++----------------- .../System/Reflection/Emit/RuntimeMethodBuilder.cs | 6 +- .../System/Reflection/Emit/RuntimeTypeBuilder.cs | 2 +- .../src/System.Private.CoreLib.csproj | 1 - .../src/System/Reflection/Emit/ILGenerator.cs | 177 ----------------- .../tests/ILReader/DynamicMethodILProvider.cs | 15 +- .../src/System.Private.CoreLib.Shared.projitems | 1 + .../src/System/Reflection/Emit/ILGenerator.cs | 200 +++++++++++++++++++ .../ref/System.Reflection.Emit.ILGeneration.cs | 68 +++---- .../System.Private.CoreLib.csproj | 2 +- .../src/System/Reflection/Emit/DynamicILInfo.cs | 14 +- .../System/Reflection/Emit/DynamicMethod.Mono.cs | 10 +- .../Emit/RuntimeConstructorBuilder.Mono.cs | 4 +- ...enerator.Mono.cs => RuntimeILGenerator.Mono.cs} | 133 ++++--------- .../Reflection/Emit/RuntimeMethodBuilder.Mono.cs | 4 +- 17 files changed, 344 insertions(+), 514 deletions(-) rename src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/{ILGenerator.cs => RuntimeILGenerator.cs} (86%) delete mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs rename src/mono/System.Private.CoreLib/src/System/Reflection/Emit/{ILGenerator.Mono.cs => RuntimeILGenerator.Mono.cs} (85%) diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index 3b82e34..2632a68 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -161,7 +161,6 @@ - @@ -169,6 +168,7 @@ + diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs index 88dbeff..ee72bab 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs @@ -8,7 +8,7 @@ using System.Diagnostics; namespace System.Reflection.Emit { - internal sealed class DynamicILGenerator : ILGenerator + internal sealed class DynamicILGenerator : RuntimeILGenerator { internal DynamicScope m_scope; private readonly int m_methodSigToken; @@ -105,7 +105,6 @@ namespace System.Reflection.Emit } UpdateStackSize(opcode, stackchange); - PutInteger4(token); } @@ -131,7 +130,6 @@ namespace System.Reflection.Emit // need to sort out the stack size story UpdateStackSize(opcode, 1); - PutInteger4(token); } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeILGenerator.cs similarity index 86% rename from src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs rename to src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeILGenerator.cs index 727fc5f..6cf211e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeILGenerator.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; namespace System.Reflection.Emit { - public class ILGenerator + internal class RuntimeILGenerator : ILGenerator { #region Const Members private const int DefaultSize = 16; @@ -78,11 +78,11 @@ namespace System.Reflection.Emit #region Constructor // package private constructor. This code path is used when client create // ILGenerator through MethodBuilder. - internal ILGenerator(MethodInfo methodBuilder) : this(methodBuilder, 64) + internal RuntimeILGenerator(MethodInfo methodBuilder) : this(methodBuilder, 64) { } - internal ILGenerator(MethodInfo methodBuilder, int size) + internal RuntimeILGenerator(MethodInfo methodBuilder, int size) { Debug.Assert(methodBuilder != null); Debug.Assert(methodBuilder is MethodBuilder || methodBuilder is DynamicMethod); @@ -177,18 +177,7 @@ namespace System.Reflection.Emit Type[]? parameterTypes, Type[]? optionalParameterTypes) { - return GetMemberRefSignature(call, returnType, parameterTypes, null, null, optionalParameterTypes); - } - internal virtual SignatureHelper GetMemberRefSignature(CallingConventions call, Type? returnType, - Type[]? parameterTypes, Type[][]? requiredCustomModifiers, Type[][]? optionalCustomModifiers, Type[]? optionalParameterTypes) - { - return GetMemberRefSignature(call, returnType, parameterTypes, requiredCustomModifiers, optionalCustomModifiers, optionalParameterTypes, 0); - } - - private SignatureHelper GetMemberRefSignature(CallingConventions call, Type? returnType, - Type[]? parameterTypes, Type[][]? requiredCustomModifiers, Type[][]? optionalCustomModifiers, Type[]? optionalParameterTypes, int cGenericParameters) - { - return ((RuntimeModuleBuilder)m_methodBuilder.Module).GetMemberRefSignature(call, returnType, parameterTypes, requiredCustomModifiers, optionalCustomModifiers, optionalParameterTypes, cGenericParameters); + return ((RuntimeModuleBuilder)m_methodBuilder.Module).GetMemberRefSignature(call, returnType, parameterTypes, null, null, optionalParameterTypes, 0); } internal byte[]? BakeByteArray() @@ -383,29 +372,20 @@ namespace System.Reflection.Emit #region Public Members #region Emit - public virtual void Emit(OpCode opcode) + public override void Emit(OpCode opcode) { EnsureCapacity(3); InternalEmit(opcode); } - public virtual void Emit(OpCode opcode, byte arg) + public override void Emit(OpCode opcode, byte arg) { EnsureCapacity(4); InternalEmit(opcode); m_ILStream[m_length++] = arg; } - [CLSCompliant(false)] - public void Emit(OpCode opcode, sbyte arg) - { - // Puts opcode onto the stream of instructions followed by arg - EnsureCapacity(4); - InternalEmit(opcode); - m_ILStream[m_length++] = (byte)arg; - } - - public virtual void Emit(OpCode opcode, short arg) + public override void Emit(OpCode opcode, short arg) { // Puts opcode onto the stream of instructions followed by arg EnsureCapacity(5); @@ -414,7 +394,7 @@ namespace System.Reflection.Emit m_length += 2; } - public virtual void Emit(OpCode opcode, int arg) + public override void Emit(OpCode opcode, int arg) { // Special-case several opcodes that have shorter variants for common values. if (opcode.Equals(OpCodes.Ldc_I4)) @@ -505,7 +485,7 @@ namespace System.Reflection.Emit PutInteger4(arg); } - public virtual void Emit(OpCode opcode, MethodInfo meth) + public override void Emit(OpCode opcode, MethodInfo meth) { ArgumentNullException.ThrowIfNull(meth); @@ -531,7 +511,7 @@ namespace System.Reflection.Emit } } - public virtual void EmitCalli(OpCode opcode, CallingConventions callingConvention, + public override void EmitCalli(OpCode opcode, CallingConventions callingConvention, Type? returnType, Type[]? parameterTypes, Type[]? optionalParameterTypes) { int stackchange = 0; @@ -573,7 +553,7 @@ namespace System.Reflection.Emit PutInteger4(modBuilder.GetSignatureMetadataToken(sig)); } - public virtual void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type? returnType, Type[]? parameterTypes) + public override void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type? returnType, Type[]? parameterTypes) { int stackchange = 0; int cParams = 0; @@ -616,7 +596,7 @@ namespace System.Reflection.Emit PutInteger4(modBuilder.GetSignatureMetadataToken(sig)); } - public virtual void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[]? optionalParameterTypes) + public override void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[]? optionalParameterTypes) { ArgumentNullException.ThrowIfNull(methodInfo); @@ -650,7 +630,7 @@ namespace System.Reflection.Emit PutInteger4(tk); } - public virtual void Emit(OpCode opcode, SignatureHelper signature) + public override void Emit(OpCode opcode, SignatureHelper signature) { ArgumentNullException.ThrowIfNull(signature); @@ -683,7 +663,7 @@ namespace System.Reflection.Emit PutInteger4(tempVal); } - public virtual void Emit(OpCode opcode, ConstructorInfo con) + public override void Emit(OpCode opcode, ConstructorInfo con) { ArgumentNullException.ThrowIfNull(con); @@ -723,7 +703,7 @@ namespace System.Reflection.Emit PutInteger4(tk); } - public virtual void Emit(OpCode opcode, Type cls) + public override void Emit(OpCode opcode, Type cls) { // Puts opcode onto the stream and then the metadata token represented // by cls. The location of cls is recorded so that the token can be @@ -739,7 +719,7 @@ namespace System.Reflection.Emit PutInteger4(tempVal); } - public virtual void Emit(OpCode opcode, long arg) + public override void Emit(OpCode opcode, long arg) { EnsureCapacity(11); InternalEmit(opcode); @@ -747,7 +727,7 @@ namespace System.Reflection.Emit m_length += 8; } - public virtual void Emit(OpCode opcode, float arg) + public override void Emit(OpCode opcode, float arg) { EnsureCapacity(7); InternalEmit(opcode); @@ -755,7 +735,7 @@ namespace System.Reflection.Emit m_length += 4; } - public virtual void Emit(OpCode opcode, double arg) + public override void Emit(OpCode opcode, double arg) { EnsureCapacity(11); InternalEmit(opcode); @@ -763,7 +743,7 @@ namespace System.Reflection.Emit m_length += 8; } - public virtual void Emit(OpCode opcode, Label label) + public override void Emit(OpCode opcode, Label label) { // Puts opcode onto the stream and leaves space to include label // when fixups are done. Labels are created using ILGenerator.DefineLabel and @@ -789,7 +769,7 @@ namespace System.Reflection.Emit } } - public virtual void Emit(OpCode opcode, Label[] labels) + public override void Emit(OpCode opcode, Label[] labels) { ArgumentNullException.ThrowIfNull(labels); @@ -811,7 +791,7 @@ namespace System.Reflection.Emit } } - public virtual void Emit(OpCode opcode, FieldInfo field) + public override void Emit(OpCode opcode, FieldInfo field) { ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module; int tempVal = modBuilder.GetFieldMetadataToken(field); @@ -821,7 +801,7 @@ namespace System.Reflection.Emit PutInteger4(tempVal); } - public virtual void Emit(OpCode opcode, string str) + public override void Emit(OpCode opcode, string str) { // Puts the opcode onto the IL stream followed by the metadata token // represented by str. The location of str is recorded for future @@ -834,7 +814,7 @@ namespace System.Reflection.Emit PutInteger4(tempVal); } - public virtual void Emit(OpCode opcode, LocalBuilder local) + public override void Emit(OpCode opcode, LocalBuilder local) { ArgumentNullException.ThrowIfNull(local); @@ -919,7 +899,7 @@ namespace System.Reflection.Emit #endregion #region Exceptions - public virtual Label BeginExceptionBlock() + public override Label BeginExceptionBlock() { // Begin an Exception block. Creating an Exception block records some information, // but does not actually emit any IL onto the stream. Exceptions should be created and @@ -962,7 +942,7 @@ namespace System.Reflection.Emit return endLabel; } - public virtual void EndExceptionBlock() + public override void EndExceptionBlock() { if (m_currExcStackCount == 0) { @@ -1003,7 +983,7 @@ namespace System.Reflection.Emit current.Done(m_length); } - public virtual void BeginExceptFilterBlock() + public override void BeginExceptFilterBlock() { // Begins an exception filter block. Emits a branch instruction to the end of the current exception block. @@ -1020,7 +1000,7 @@ namespace System.Reflection.Emit m_curDepth = 1; } - public virtual void BeginCatchBlock(Type? exceptionType) + public override void BeginCatchBlock(Type? exceptionType) { // Begins a catch block. Emits a branch instruction to the end of the current exception block. @@ -1053,7 +1033,7 @@ namespace System.Reflection.Emit m_curDepth = 1; } - public virtual void BeginFaultBlock() + public override void BeginFaultBlock() { if (m_currExcStackCount == 0) { @@ -1070,7 +1050,7 @@ namespace System.Reflection.Emit m_curDepth = 0; } - public virtual void BeginFinallyBlock() + public override void BeginFinallyBlock() { if (m_currExcStackCount == 0) { @@ -1105,7 +1085,7 @@ namespace System.Reflection.Emit #endregion #region Labels - public virtual Label DefineLabel() + public override Label DefineLabel() { // We don't know the stack depth at the label yet, so set it to -1. return DefineLabel(-1); @@ -1130,7 +1110,7 @@ namespace System.Reflection.Emit return new Label(m_labelCount++); } - public virtual void MarkLabel(Label loc) + public override void MarkLabel(Label loc) { // Defines a label by setting the position where that label is found within the stream. // Does not allow a label to be defined more than once. @@ -1180,119 +1160,8 @@ namespace System.Reflection.Emit #endregion - #region IL Macros - public virtual void ThrowException([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type excType) - { - // Emits the il to throw an exception - - ArgumentNullException.ThrowIfNull(excType); - - if (!excType.IsSubclassOf(typeof(Exception)) && excType != typeof(Exception)) - { - throw new ArgumentException(SR.Argument_NotExceptionType, nameof(excType)); - } - ConstructorInfo? con = excType.GetConstructor(Type.EmptyTypes); - if (con == null) - { - throw new ArgumentException(SR.Arg_NoDefCTorWithoutTypeName, nameof(excType)); - } - Emit(OpCodes.Newobj, con); - Emit(OpCodes.Throw); - } - - private const string ConsoleTypeFullName = "System.Console, System.Console"; - - public virtual void EmitWriteLine(string value) - { - // Emits the IL to call Console.WriteLine with a string. - - Emit(OpCodes.Ldstr, value); - Type[] parameterTypes = new Type[1]; - parameterTypes[0] = typeof(string); - Type consoleType = Type.GetType(ConsoleTypeFullName, throwOnError: true)!; - MethodInfo mi = consoleType.GetMethod("WriteLine", parameterTypes)!; - Emit(OpCodes.Call, mi); - } - - public virtual void EmitWriteLine(LocalBuilder localBuilder) - { - // Emits the IL necessary to call WriteLine with lcl. It is - // an error to call EmitWriteLine with a lcl which is not of - // one of the types for which Console.WriteLine implements overloads. (e.g. - // we do *not* call ToString on the locals. - - if (m_methodBuilder == null) - { - throw new ArgumentException(SR.InvalidOperation_BadILGeneratorUsage); - } - - Type consoleType = Type.GetType(ConsoleTypeFullName, throwOnError: true)!; - MethodInfo prop = consoleType.GetMethod("get_Out")!; - Emit(OpCodes.Call, prop); - Emit(OpCodes.Ldloc, localBuilder); - Type[] parameterTypes = new Type[1]; - Type cls = localBuilder.LocalType; - if (cls is TypeBuilder || cls is EnumBuilder) - { - throw new ArgumentException(SR.NotSupported_OutputStreamUsingTypeBuilder); - } - parameterTypes[0] = cls; - MethodInfo? mi = typeof(System.IO.TextWriter).GetMethod("WriteLine", parameterTypes); - if (mi == null) - { - throw new ArgumentException(SR.Argument_EmitWriteLineType, nameof(localBuilder)); - } - - Emit(OpCodes.Callvirt, mi); - } - - public virtual void EmitWriteLine(FieldInfo fld) - { - ArgumentNullException.ThrowIfNull(fld); - - // Emits the IL necessary to call WriteLine with fld. It is - // an error to call EmitWriteLine with a fld which is not of - // one of the types for which Console.WriteLine implements overloads. (e.g. - // we do *not* call ToString on the fields. - - Type consoleType = Type.GetType(ConsoleTypeFullName, throwOnError: true)!; - MethodInfo prop = consoleType.GetMethod("get_Out")!; - Emit(OpCodes.Call, prop); - - if ((fld.Attributes & FieldAttributes.Static) != 0) - { - Emit(OpCodes.Ldsfld, fld); - } - else - { - Emit(OpCodes.Ldarg_0); // Load the this ref. - Emit(OpCodes.Ldfld, fld); - } - Type[] parameterTypes = new Type[1]; - Type cls = fld.FieldType; - if (cls is TypeBuilder || cls is EnumBuilder) - { - throw new NotSupportedException(SR.NotSupported_OutputStreamUsingTypeBuilder); - } - parameterTypes[0] = cls; - MethodInfo? mi = typeof(System.IO.TextWriter).GetMethod("WriteLine", parameterTypes); - if (mi == null) - { - throw new ArgumentException(SR.Argument_EmitWriteLineType, nameof(fld)); - } - - Emit(OpCodes.Callvirt, mi); - } - - #endregion - #region Debug API - public virtual LocalBuilder DeclareLocal(Type localType) - { - return DeclareLocal(localType, false); - } - - public virtual LocalBuilder DeclareLocal(Type localType, bool pinned) + public override LocalBuilder DeclareLocal(Type localType, bool pinned) { // Declare a local of type "local". The current active lexical scope // will be the scope that local will live. @@ -1319,7 +1188,7 @@ namespace System.Reflection.Emit return new LocalBuilder(m_localCount++, localType, methodBuilder, pinned); } - public virtual void UsingNamespace(string usingNamespace) + public override void UsingNamespace(string usingNamespace) { // Specifying the namespace to be used in evaluating locals and watches // for the current active lexical scope. @@ -1329,7 +1198,7 @@ namespace System.Reflection.Emit if (m_methodBuilder is not RuntimeMethodBuilder methodBuilder) throw new NotSupportedException(); - int index = methodBuilder.GetILGenerator().m_ScopeTree.GetCurrentActiveScopeIndex(); + int index = ((RuntimeILGenerator)methodBuilder.GetILGenerator()).m_ScopeTree.GetCurrentActiveScopeIndex(); if (index == -1) { methodBuilder.m_localSymInfo!.AddUsingNamespace(usingNamespace); @@ -1340,17 +1209,17 @@ namespace System.Reflection.Emit } } - public virtual void BeginScope() + public override void BeginScope() { m_ScopeTree.AddScopeInfo(ScopeAction.Open, m_length); } - public virtual void EndScope() + public override void EndScope() { m_ScopeTree.AddScopeInfo(ScopeAction.Close, m_length); } - public virtual int ILOffset => m_length; + public override int ILOffset => m_length; #endregion @@ -1424,11 +1293,11 @@ namespace System.Reflection.Emit int currentCatch = m_currentCatch; if (currentCatch >= m_catchAddr.Length) { - m_filterAddr = ILGenerator.EnlargeArray(m_filterAddr); - m_catchAddr = ILGenerator.EnlargeArray(m_catchAddr); - m_catchEndAddr = ILGenerator.EnlargeArray(m_catchEndAddr); - m_catchClass = ILGenerator.EnlargeArray(m_catchClass); - m_type = ILGenerator.EnlargeArray(m_type); + m_filterAddr = RuntimeILGenerator.EnlargeArray(m_filterAddr); + m_catchAddr = RuntimeILGenerator.EnlargeArray(m_catchAddr); + m_catchEndAddr = RuntimeILGenerator.EnlargeArray(m_catchEndAddr); + m_catchClass = RuntimeILGenerator.EnlargeArray(m_catchClass); + m_type = RuntimeILGenerator.EnlargeArray(m_type); } if (type == Filter) { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs index ecf34b5..f0cf9e6 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs @@ -26,7 +26,7 @@ namespace System.Reflection.Emit private int[]? m_mdMethodFixups; // The location of all of the token fixups. Null means no fixups. private byte[]? m_localSignature; // Local signature if set explicitly via DefineBody. Null otherwise. internal LocalSymInfo? m_localSymInfo; // keep track debugging local information - internal ILGenerator? m_ilGenerator; // Null if not used. + internal RuntimeILGenerator? m_ilGenerator; // Null if not used. private byte[]? m_ubBody; // The IL for the method private ExceptionHandler[]? m_exceptions; // Exception handlers or null if there are none. private const int DefaultMaxStack = 16; @@ -130,7 +130,7 @@ namespace System.Reflection.Emit #region Internal Members - internal void CreateMethodBodyHelper(ILGenerator il) + internal void CreateMethodBodyHelper(RuntimeILGenerator il) { ArgumentNullException.ThrowIfNull(il); @@ -668,7 +668,7 @@ namespace System.Reflection.Emit ThrowIfGeneric(); ThrowIfShouldNotHaveBody(); - return m_ilGenerator ??= new ILGenerator(this, size); + return m_ilGenerator ??= new RuntimeILGenerator(this, size); } private void ThrowIfShouldNotHaveBody() diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.cs index 47b7191..79aaaeb 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.cs @@ -1709,7 +1709,7 @@ namespace System.Reflection.Emit if (meth.m_ilGenerator != null) { // we need to bake the method here. - meth.CreateMethodBodyHelper(meth.GetILGenerator()); + meth.CreateMethodBodyHelper(((RuntimeILGenerator)meth.GetILGenerator())); } body = meth.GetBody(); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index 4c728e8..945077f 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -143,7 +143,6 @@ - diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs deleted file mode 100644 index 49190e8..0000000 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs +++ /dev/null @@ -1,177 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; - -namespace System.Reflection.Emit -{ - public partial class ILGenerator - { - internal ILGenerator() - { - // Prevent generating a default constructor - } - - public virtual int ILOffset - { - get - { - return default; - } - } - - public virtual void BeginCatchBlock(Type? exceptionType) - { - } - - public virtual void BeginExceptFilterBlock() - { - } - - public virtual Label BeginExceptionBlock() - { - return default; - } - - public virtual void BeginFaultBlock() - { - } - - public virtual void BeginFinallyBlock() - { - } - - public virtual void BeginScope() - { - } - - public virtual LocalBuilder DeclareLocal(Type localType) - { - return default; - } - - public virtual LocalBuilder DeclareLocal(Type localType, bool pinned) - { - return default; - } - - public virtual Label DefineLabel() - { - return default; - } - - public virtual void Emit(OpCode opcode) - { - } - - public virtual void Emit(OpCode opcode, byte arg) - { - } - - public virtual void Emit(OpCode opcode, double arg) - { - } - - public virtual void Emit(OpCode opcode, short arg) - { - } - - public virtual void Emit(OpCode opcode, int arg) - { - } - - public virtual void Emit(OpCode opcode, long arg) - { - } - - public virtual void Emit(OpCode opcode, ConstructorInfo con) - { - } - - public virtual void Emit(OpCode opcode, Label label) - { - } - - public virtual void Emit(OpCode opcode, Label[] labels) - { - } - - public virtual void Emit(OpCode opcode, LocalBuilder local) - { - } - - public virtual void Emit(OpCode opcode, SignatureHelper signature) - { - } - - public virtual void Emit(OpCode opcode, FieldInfo field) - { - } - - public virtual void Emit(OpCode opcode, MethodInfo meth) - { - } - - [CLSCompliantAttribute(false)] - public void Emit(OpCode opcode, sbyte arg) - { - } - - public virtual void Emit(OpCode opcode, float arg) - { - } - - public virtual void Emit(OpCode opcode, string str) - { - } - - public virtual void Emit(OpCode opcode, Type cls) - { - } - - public virtual void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes) - { - } - - public virtual void EmitCalli(OpCode opcode, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes) - { - } - - public virtual void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type returnType, Type[] parameterTypes) - { - } - - public virtual void EmitWriteLine(LocalBuilder localBuilder) - { - } - - public virtual void EmitWriteLine(FieldInfo fld) - { - } - - public virtual void EmitWriteLine(string value) - { - } - - public virtual void EndExceptionBlock() - { - } - - public virtual void EndScope() - { - } - - public virtual void MarkLabel(Label loc) - { - } - - public virtual void ThrowException([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type excType) - { - } - - public virtual void UsingNamespace(string usingNamespace) - { - } - } -} diff --git a/src/libraries/System.Linq.Expressions/tests/ILReader/DynamicMethodILProvider.cs b/src/libraries/System.Linq.Expressions/tests/ILReader/DynamicMethodILProvider.cs index 04bb2bb..8ecd1a2 100644 --- a/src/libraries/System.Linq.Expressions/tests/ILReader/DynamicMethodILProvider.cs +++ b/src/libraries/System.Linq.Expressions/tests/ILReader/DynamicMethodILProvider.cs @@ -10,13 +10,14 @@ namespace System.Linq.Expressions.Tests { public sealed class DynamicMethodILProvider : IILProvider { - private static readonly FieldInfo s_fiLen = typeof(ILGenerator).GetFieldAssert("m_length"); - private static readonly FieldInfo s_fiStream = typeof(ILGenerator).GetFieldAssert("m_ILStream"); - private static readonly FieldInfo s_fiExceptions = typeof(ILGenerator).GetFieldAssert("m_exceptions"); - private static readonly FieldInfo s_fiExceptionCount = typeof(ILGenerator).GetFieldAssert("m_exceptionCount"); - private static readonly FieldInfo s_fiLocalSignature = typeof(ILGenerator).GetFieldAssert("m_localSignature"); - private static readonly MethodInfo s_miBakeByteArray = typeof(ILGenerator).GetMethodAssert("BakeByteArray"); - private static readonly MethodInfo s_miMaxStackSize = typeof(ILGenerator).GetMethodAssert("GetMaxStackSize"); + private static readonly Type s_runtimeILGenerator = Type.GetType("System.Reflection.Emit.RuntimeILGenerator"); + private static readonly FieldInfo s_fiLen = s_runtimeILGenerator.GetFieldAssert("m_length"); + private static readonly FieldInfo s_fiStream = s_runtimeILGenerator.GetFieldAssert("m_ILStream"); + private static readonly FieldInfo s_fiExceptions = s_runtimeILGenerator.GetFieldAssert("m_exceptions"); + private static readonly FieldInfo s_fiExceptionCount = s_runtimeILGenerator.GetFieldAssert("m_exceptionCount"); + private static readonly FieldInfo s_fiLocalSignature = s_runtimeILGenerator.GetFieldAssert("m_localSignature"); + private static readonly MethodInfo s_miBakeByteArray = s_runtimeILGenerator.GetMethodAssert("BakeByteArray"); + private static readonly MethodInfo s_miMaxStackSize = s_runtimeILGenerator.GetMethodAssert("GetMaxStackSize"); private readonly DynamicMethod _method; private byte[] _byteArray; diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 10b27e3..63fbe77 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -408,6 +408,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs new file mode 100644 index 0000000..84ae8bb --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs @@ -0,0 +1,200 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +namespace System.Reflection.Emit +{ + public abstract class ILGenerator + { + protected ILGenerator() + { + } + + #region Public Members + + #region Emit + public abstract void Emit(OpCode opcode); + + public abstract void Emit(OpCode opcode, byte arg); + + public abstract void Emit(OpCode opcode, short arg); + + public abstract void Emit(OpCode opcode, long arg); + + public abstract void Emit(OpCode opcode, float arg); + + public abstract void Emit(OpCode opcode, double arg); + + public abstract void Emit(OpCode opcode, int arg); + + public abstract void Emit(OpCode opcode, MethodInfo meth); + + public abstract void EmitCalli(OpCode opcode, CallingConventions callingConvention, + Type? returnType, Type[]? parameterTypes, Type[]? optionalParameterTypes); + + public abstract void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type? returnType, Type[]? parameterTypes); + + public abstract void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[]? optionalParameterTypes); + + public abstract void Emit(OpCode opcode, SignatureHelper signature); + + public abstract void Emit(OpCode opcode, ConstructorInfo con); + + public abstract void Emit(OpCode opcode, Type cls); + + public abstract void Emit(OpCode opcode, Label label); + + public abstract void Emit(OpCode opcode, Label[] labels); + + public abstract void Emit(OpCode opcode, FieldInfo field); + + public abstract void Emit(OpCode opcode, string str); + + public abstract void Emit(OpCode opcode, LocalBuilder local); + #endregion + + #region Exceptions + public abstract Label BeginExceptionBlock(); + + public abstract void EndExceptionBlock(); + + public abstract void BeginExceptFilterBlock(); + + public abstract void BeginCatchBlock(Type? exceptionType); + + public abstract void BeginFaultBlock(); + + public abstract void BeginFinallyBlock(); + + #endregion + + #region Labels + public abstract Label DefineLabel(); + + public abstract void MarkLabel(Label loc); + + #endregion + + #region IL Macros + public virtual void ThrowException([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type excType) + { + // Emits the il to throw an exception + ArgumentNullException.ThrowIfNull(excType); + + if (!excType.IsSubclassOf(typeof(Exception)) && excType != typeof(Exception)) + { + throw new ArgumentException(SR.Argument_NotExceptionType, nameof(excType)); + } + ConstructorInfo? con = excType.GetConstructor(Type.EmptyTypes); + if (con == null) + { + throw new ArgumentException(SR.Arg_NoDefCTorWithoutTypeName, nameof(excType)); + } + Emit(OpCodes.Newobj, con); + Emit(OpCodes.Throw); + } + + private const string ConsoleTypeFullName = "System.Console, System.Console"; + private static readonly Type[] s_parameterTypes = new Type[] { typeof(string) }; + + public virtual void EmitWriteLine(string value) + { + // Emits the IL to call Console.WriteLine with a string. + Emit(OpCodes.Ldstr, value); + Type consoleType = Type.GetType(ConsoleTypeFullName, throwOnError: true)!; + MethodInfo mi = consoleType.GetMethod("WriteLine", s_parameterTypes)!; + Emit(OpCodes.Call, mi); + } + + public virtual void EmitWriteLine(LocalBuilder localBuilder) + { + // Emits the IL necessary to call WriteLine with lcl. It is + // an error to call EmitWriteLine with a lcl which is not of + // one of the types for which Console.WriteLine implements overloads. (e.g. + // we do *not* call ToString on the locals. + + Type consoleType = Type.GetType(ConsoleTypeFullName, throwOnError: true)!; + MethodInfo prop = consoleType.GetMethod("get_Out")!; + Emit(OpCodes.Call, prop); + Emit(OpCodes.Ldloc, localBuilder); + Type[] parameterTypes = new Type[1]; + Type cls = localBuilder.LocalType; + if (cls is TypeBuilder || cls is EnumBuilder) + { + throw new ArgumentException(SR.NotSupported_OutputStreamUsingTypeBuilder); + } + parameterTypes[0] = cls; + MethodInfo? mi = typeof(System.IO.TextWriter).GetMethod("WriteLine", parameterTypes); + if (mi == null) + { + throw new ArgumentException(SR.Argument_EmitWriteLineType, nameof(localBuilder)); + } + + Emit(OpCodes.Callvirt, mi); + } + + public virtual void EmitWriteLine(FieldInfo fld) + { + ArgumentNullException.ThrowIfNull(fld); + + // Emits the IL necessary to call WriteLine with fld. It is + // an error to call EmitWriteLine with a fld which is not of + // one of the types for which Console.WriteLine implements overloads. (e.g. + // we do *not* call ToString on the fields. + Type consoleType = Type.GetType(ConsoleTypeFullName, throwOnError: true)!; + MethodInfo prop = consoleType.GetMethod("get_Out")!; + Emit(OpCodes.Call, prop); + + if ((fld.Attributes & FieldAttributes.Static) != 0) + { + Emit(OpCodes.Ldsfld, fld); + } + else + { + Emit(OpCodes.Ldarg_0); // Load the this ref. + Emit(OpCodes.Ldfld, fld); + } + Type[] parameterTypes = new Type[1]; + Type cls = fld.FieldType; + if (cls is TypeBuilder || cls is EnumBuilder) + { + throw new NotSupportedException(SR.NotSupported_OutputStreamUsingTypeBuilder); + } + parameterTypes[0] = cls; + MethodInfo? mi = typeof(System.IO.TextWriter).GetMethod("WriteLine", parameterTypes); + if (mi == null) + { + throw new ArgumentException(SR.Argument_EmitWriteLineType, nameof(fld)); + } + + Emit(OpCodes.Callvirt, mi); + } + + #endregion + + #region Debug API + public virtual LocalBuilder DeclareLocal(Type localType) + { + return DeclareLocal(localType, false); + } + + public abstract LocalBuilder DeclareLocal(Type localType, bool pinned); + + public abstract void UsingNamespace(string usingNamespace); + + public abstract void BeginScope(); + + public abstract void EndScope(); + + public abstract int ILOffset { get; } + + [CLSCompliant(false)] + public void Emit(OpCode opcode, sbyte arg) => Emit(opcode, (byte)arg); + + #endregion + + #endregion + } +} diff --git a/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.cs b/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.cs index 1a200d8..93f7313 100644 --- a/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.cs +++ b/src/libraries/System.Reflection.Emit.ILGeneration/ref/System.Reflection.Emit.ILGeneration.cs @@ -13,48 +13,48 @@ namespace System.Reflection.Emit public CustomAttributeBuilder(System.Reflection.ConstructorInfo con, object?[] constructorArgs, System.Reflection.PropertyInfo[] namedProperties, object?[] propertyValues) { } public CustomAttributeBuilder(System.Reflection.ConstructorInfo con, object?[] constructorArgs, System.Reflection.PropertyInfo[] namedProperties, object?[] propertyValues, System.Reflection.FieldInfo[] namedFields, object?[] fieldValues) { } } - public partial class ILGenerator + public abstract class ILGenerator { - internal ILGenerator() { } - public virtual int ILOffset { get { throw null; } } - public virtual void BeginCatchBlock(System.Type? exceptionType) { } - public virtual void BeginExceptFilterBlock() { } - public virtual System.Reflection.Emit.Label BeginExceptionBlock() { throw null; } - public virtual void BeginFaultBlock() { } - public virtual void BeginFinallyBlock() { } - public virtual void BeginScope() { } + protected ILGenerator() { } + public abstract int ILOffset { get; } + public abstract void BeginCatchBlock(System.Type? exceptionType); + public abstract void BeginExceptFilterBlock(); + public abstract System.Reflection.Emit.Label BeginExceptionBlock(); + public abstract void BeginFaultBlock(); + public abstract void BeginFinallyBlock(); + public abstract void BeginScope(); public virtual System.Reflection.Emit.LocalBuilder DeclareLocal(System.Type localType) { throw null; } - public virtual System.Reflection.Emit.LocalBuilder DeclareLocal(System.Type localType, bool pinned) { throw null; } - public virtual System.Reflection.Emit.Label DefineLabel() { throw null; } - public virtual void Emit(System.Reflection.Emit.OpCode opcode) { } - public virtual void Emit(System.Reflection.Emit.OpCode opcode, byte arg) { } - public virtual void Emit(System.Reflection.Emit.OpCode opcode, double arg) { } - public virtual void Emit(System.Reflection.Emit.OpCode opcode, short arg) { } - public virtual void Emit(System.Reflection.Emit.OpCode opcode, int arg) { } - public virtual void Emit(System.Reflection.Emit.OpCode opcode, long arg) { } - public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con) { } - public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label label) { } - public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label[] labels) { } - public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.LocalBuilder local) { } - public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.SignatureHelper signature) { } - public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.FieldInfo field) { } - public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo meth) { } + public abstract System.Reflection.Emit.LocalBuilder DeclareLocal(System.Type localType, bool pinned); + public abstract System.Reflection.Emit.Label DefineLabel(); + public abstract void Emit(System.Reflection.Emit.OpCode opcode); + public abstract void Emit(System.Reflection.Emit.OpCode opcode, byte arg); + public abstract void Emit(System.Reflection.Emit.OpCode opcode, double arg); + public abstract void Emit(System.Reflection.Emit.OpCode opcode, short arg); + public abstract void Emit(System.Reflection.Emit.OpCode opcode, int arg); + public abstract void Emit(System.Reflection.Emit.OpCode opcode, long arg); + public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con); + public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label label); + public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label[] labels); + public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.LocalBuilder local); + public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.SignatureHelper signature); + public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.FieldInfo field); + public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo meth); [System.CLSCompliantAttribute(false)] public void Emit(System.Reflection.Emit.OpCode opcode, sbyte arg) { } - public virtual void Emit(System.Reflection.Emit.OpCode opcode, float arg) { } - public virtual void Emit(System.Reflection.Emit.OpCode opcode, string str) { } - public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Type cls) { } - public virtual void EmitCall(System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo methodInfo, System.Type[]? optionalParameterTypes) { } - public virtual void EmitCalli(System.Reflection.Emit.OpCode opcode, System.Reflection.CallingConventions callingConvention, System.Type? returnType, System.Type[]? parameterTypes, System.Type[]? optionalParameterTypes) { } - public virtual void EmitCalli(System.Reflection.Emit.OpCode opcode, System.Runtime.InteropServices.CallingConvention unmanagedCallConv, System.Type? returnType, System.Type[]? parameterTypes) { } + public abstract void Emit(System.Reflection.Emit.OpCode opcode, float arg); + public abstract void Emit(System.Reflection.Emit.OpCode opcode, string str); + public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Type cls); + public abstract void EmitCall(System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo methodInfo, System.Type[]? optionalParameterTypes); + public abstract void EmitCalli(System.Reflection.Emit.OpCode opcode, System.Reflection.CallingConventions callingConvention, System.Type? returnType, System.Type[]? parameterTypes, System.Type[]? optionalParameterTypes); + public abstract void EmitCalli(System.Reflection.Emit.OpCode opcode, System.Runtime.InteropServices.CallingConvention unmanagedCallConv, System.Type? returnType, System.Type[]? parameterTypes); public virtual void EmitWriteLine(System.Reflection.Emit.LocalBuilder localBuilder) { } public virtual void EmitWriteLine(System.Reflection.FieldInfo fld) { } public virtual void EmitWriteLine(string value) { } - public virtual void EndExceptionBlock() { } - public virtual void EndScope() { } - public virtual void MarkLabel(System.Reflection.Emit.Label loc) { } + public abstract void EndExceptionBlock(); + public abstract void EndScope(); + public abstract void MarkLabel(System.Reflection.Emit.Label loc); public virtual void ThrowException([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] System.Type excType) { } - public virtual void UsingNamespace(string usingNamespace) { } + public abstract void UsingNamespace(string usingNamespace); } public readonly partial struct Label : System.IEquatable { diff --git a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj index b8e53f4..a469865 100644 --- a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -223,7 +223,6 @@ - @@ -233,6 +232,7 @@ + diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILInfo.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILInfo.cs index ca10cc9..c96c0cb 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILInfo.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILInfo.cs @@ -66,29 +66,29 @@ namespace System.Reflection.Emit public int GetTokenFor(DynamicMethod method) { - return this.method.GetILGenerator().TokenGenerator.GetToken(method, false); + return this.method.GetRuntimeILGenerator().TokenGenerator.GetToken(method, false); } public int GetTokenFor(RuntimeFieldHandle field) { - return this.method.GetILGenerator().TokenGenerator.GetToken(FieldInfo.GetFieldFromHandle(field), false); + return this.method.GetRuntimeILGenerator().TokenGenerator.GetToken(FieldInfo.GetFieldFromHandle(field), false); } public int GetTokenFor(RuntimeMethodHandle method) { MethodBase mi = MethodBase.GetMethodFromHandle(method)!; - return this.method.GetILGenerator().TokenGenerator.GetToken(mi, false); + return this.method.GetRuntimeILGenerator().TokenGenerator.GetToken(mi, false); } public int GetTokenFor(RuntimeTypeHandle type) { Type t = Type.GetTypeFromHandle(type)!; - return this.method.GetILGenerator().TokenGenerator.GetToken(t, false); + return this.method.GetRuntimeILGenerator().TokenGenerator.GetToken(t, false); } public int GetTokenFor(string literal) { - return method.GetILGenerator().TokenGenerator.GetToken(literal); + return method.GetRuntimeILGenerator().TokenGenerator.GetToken(literal); } // FIXME: @@ -105,7 +105,7 @@ namespace System.Reflection.Emit public void SetCode(byte[]? code, int maxStackSize) { - method.GetILGenerator().SetCode(code, maxStackSize); + method.GetRuntimeILGenerator().SetCode(code, maxStackSize); } [CLSCompliantAttribute(false)] @@ -115,7 +115,7 @@ namespace System.Reflection.Emit if (codeSize > 0) ArgumentNullException.ThrowIfNull(code); - method.GetILGenerator().SetCode(code, codeSize, maxStackSize); + method.GetRuntimeILGenerator().SetCode(code, codeSize, maxStackSize); } // FIXME: diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.Mono.cs index 834f648..d0f8984 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.Mono.cs @@ -18,7 +18,7 @@ namespace System.Reflection.Emit private bool _skipVisibility; private bool _restrictedSkipVisibility; private bool _initLocals; - private ILGenerator? _ilGenerator; + private RuntimeILGenerator? _ilGenerator; private int _nrefs; private object?[]? _refs; private IntPtr _referencedBy; @@ -59,8 +59,12 @@ namespace System.Reflection.Emit public DynamicILInfo GetDynamicILInfo() => _dynamicILInfo ??= new DynamicILInfo(this); - public ILGenerator GetILGenerator(int streamSize) => - _ilGenerator ??= new ILGenerator(Module, new DynamicMethodTokenGenerator(this), streamSize); + public ILGenerator GetILGenerator(int streamSize) => GetILGeneratorInternal(streamSize); + + internal RuntimeILGenerator GetRuntimeILGenerator() => GetILGeneratorInternal(64); + + private RuntimeILGenerator GetILGeneratorInternal(int streamSize) => + _ilGenerator ??= new RuntimeILGenerator(Module, new DynamicMethodTokenGenerator(this), streamSize); public override object? Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) { diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeConstructorBuilder.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeConstructorBuilder.Mono.cs index ecfae6b..f6127e1 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeConstructorBuilder.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeConstructorBuilder.Mono.cs @@ -46,7 +46,7 @@ namespace System.Reflection.Emit { #region Sync with MonoReflectionCtorBuilder in object-internals.h private RuntimeMethodHandle mhandle; - private ILGenerator? ilgen; + private RuntimeILGenerator? ilgen; internal Type[]? parameters; private MethodAttributes attrs; private MethodImplAttributes iattrs; @@ -251,7 +251,7 @@ namespace System.Reflection.Emit return ilgen; if (!(((attrs & (MethodAttributes.Abstract | MethodAttributes.PinvokeImpl)) == 0) && ((iattrs & (MethodImplAttributes.Runtime | MethodImplAttributes.InternalCall)) == 0))) throw new InvalidOperationException(); - ilgen = new ILGenerator(type.Module, ((RuntimeModuleBuilder)type.Module).GetTokenGenerator(), streamSize); + ilgen = new RuntimeILGenerator(type.Module, ((RuntimeModuleBuilder)type.Module).GetTokenGenerator(), streamSize); return ilgen; } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeILGenerator.Mono.cs similarity index 85% rename from src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.Mono.cs rename to src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeILGenerator.Mono.cs index 97236de..755c552 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeILGenerator.Mono.cs @@ -180,7 +180,7 @@ namespace System.Reflection.Emit } [StructLayout(LayoutKind.Sequential)] - public partial class ILGenerator + internal sealed class RuntimeILGenerator : ILGenerator { private struct LabelFixup { @@ -227,7 +227,7 @@ namespace System.Reflection.Emit private const int defaultExceptionStackSize = 2; [DynamicDependency(nameof(token_fixups))] // Automatically keeps all previous fields too due to StructLayout - internal ILGenerator(Module m, ITokenGenerator token_gen, int size) + internal RuntimeILGenerator(Module m, ITokenGenerator token_gen, int size) { if (size < 0) size = 128; @@ -343,7 +343,7 @@ namespace System.Reflection.Emit } } - public virtual void BeginCatchBlock(Type? exceptionType) + public override void BeginCatchBlock(Type? exceptionType) { if (!InExceptionBlock) throw new NotSupportedException(SR.Argument_NotInExceptionBlock); @@ -369,7 +369,7 @@ namespace System.Reflection.Emit //System.Console.WriteLine ("Begin catch Block: {0} {1}",exceptionType.ToString(), max_stack); } - public virtual void BeginExceptFilterBlock() + public override void BeginExceptFilterBlock() { if (!InExceptionBlock) throw new NotSupportedException(SR.Argument_NotInExceptionBlock); @@ -378,7 +378,7 @@ namespace System.Reflection.Emit ex_handlers![cur_block].AddFilter(code_len); } - public virtual Label BeginExceptionBlock() + public override Label BeginExceptionBlock() { //System.Console.WriteLine ("Begin Block"); Int32Stack open_blocks = this.open_blocks ??= new Int32Stack(defaultExceptionStackSize); @@ -400,7 +400,7 @@ namespace System.Reflection.Emit return ex_handlers[cur_block].end = DefineLabel(); } - public virtual void BeginFaultBlock() + public override void BeginFaultBlock() { if (!InExceptionBlock) throw new NotSupportedException(SR.Argument_NotInExceptionBlock); @@ -416,7 +416,7 @@ namespace System.Reflection.Emit ex_handlers[cur_block].AddFault(code_len); } - public virtual void BeginFinallyBlock() + public override void BeginFinallyBlock() { if (!InExceptionBlock) throw new NotSupportedException(SR.Argument_NotInExceptionBlock); @@ -433,16 +433,10 @@ namespace System.Reflection.Emit ex_handlers[cur_block].AddFinally(code_len); } - public virtual void BeginScope() + public override void BeginScope() { } - public virtual LocalBuilder DeclareLocal(Type localType) - { - return DeclareLocal(localType, false); - } - - - public virtual LocalBuilder DeclareLocal(Type localType, bool pinned) + public override LocalBuilder DeclareLocal(Type localType, bool pinned) { ArgumentNullException.ThrowIfNull(localType); if (localType.IsUserType) @@ -466,7 +460,7 @@ namespace System.Reflection.Emit return res; } - public virtual Label DefineLabel() + public override Label DefineLabel() { if (labels == null) { @@ -484,20 +478,20 @@ namespace System.Reflection.Emit return new Label(num_labels++); } - public virtual void Emit(OpCode opcode) + public override void Emit(OpCode opcode) { make_room(2); ll_emit(opcode); } - public virtual void Emit(OpCode opcode, byte arg) + public override void Emit(OpCode opcode, byte arg) { make_room(3); ll_emit(opcode); code[code_len++] = arg; } - public virtual void Emit(OpCode opcode, ConstructorInfo con) + public override void Emit(OpCode opcode, ConstructorInfo con) { int token = token_gen.GetToken(con, true); make_room(6); @@ -508,7 +502,7 @@ namespace System.Reflection.Emit cur_stack -= con.GetParametersCount(); } - public virtual void Emit(OpCode opcode, double arg) + public override void Emit(OpCode opcode, double arg) { make_room(10); ll_emit(opcode); @@ -516,7 +510,7 @@ namespace System.Reflection.Emit code_len += 8; } - public virtual void Emit(OpCode opcode, FieldInfo field) + public override void Emit(OpCode opcode, FieldInfo field) { int token = token_gen.GetToken(field, true); make_room(6); @@ -524,7 +518,7 @@ namespace System.Reflection.Emit emit_int(token); } - public virtual void Emit(OpCode opcode, short arg) + public override void Emit(OpCode opcode, short arg) { make_room(4); ll_emit(opcode); @@ -532,14 +526,14 @@ namespace System.Reflection.Emit code_len += 2; } - public virtual void Emit(OpCode opcode, int arg) + public override void Emit(OpCode opcode, int arg) { make_room(6); ll_emit(opcode); emit_int(arg); } - public virtual void Emit(OpCode opcode, long arg) + public override void Emit(OpCode opcode, long arg) { make_room(10); ll_emit(opcode); @@ -547,7 +541,7 @@ namespace System.Reflection.Emit code_len += 8; } - public virtual void Emit(OpCode opcode, Label label) + public override void Emit(OpCode opcode, Label label) { int tlen = target_len(opcode); make_room(6); @@ -573,7 +567,7 @@ namespace System.Reflection.Emit } - public virtual void Emit(OpCode opcode, Label[] labels) + public override void Emit(OpCode opcode, Label[] labels) { ArgumentNullException.ThrowIfNull(labels); @@ -622,7 +616,7 @@ namespace System.Reflection.Emit } } - public virtual void Emit(OpCode opcode, LocalBuilder local) + public override void Emit(OpCode opcode, LocalBuilder local) { ArgumentNullException.ThrowIfNull(local); if (local.ilgen != this) @@ -713,7 +707,7 @@ namespace System.Reflection.Emit } } - public virtual void Emit(OpCode opcode, MethodInfo meth) + public override void Emit(OpCode opcode, MethodInfo meth) { ArgumentNullException.ThrowIfNull(meth); @@ -744,15 +738,7 @@ namespace System.Reflection.Emit cur_stack -= method.GetParametersCount(); } - [CLSCompliant(false)] - public void Emit(OpCode opcode, sbyte arg) - { - make_room(3); - ll_emit(opcode); - code[code_len++] = (byte)arg; - } - - public virtual void Emit(OpCode opcode, SignatureHelper signature) + public override void Emit(OpCode opcode, SignatureHelper signature) { int token = token_gen.GetToken(signature); make_room(6); @@ -760,7 +746,7 @@ namespace System.Reflection.Emit emit_int(token); } - public virtual void Emit(OpCode opcode, float arg) + public override void Emit(OpCode opcode, float arg) { make_room(6); ll_emit(opcode); @@ -768,7 +754,7 @@ namespace System.Reflection.Emit code_len += 4; } - public virtual void Emit(OpCode opcode, string str) + public override void Emit(OpCode opcode, string str) { int token = token_gen.GetToken(str); make_room(6); @@ -776,7 +762,7 @@ namespace System.Reflection.Emit emit_int(token); } - public virtual void Emit(OpCode opcode, Type cls) + public override void Emit(OpCode opcode, Type cls) { make_room(6); ll_emit(opcode); @@ -785,7 +771,7 @@ namespace System.Reflection.Emit } // FIXME: vararg methods are not supported - public virtual void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[]? optionalParameterTypes) + public override void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[]? optionalParameterTypes) { ArgumentNullException.ThrowIfNull(methodInfo); short value = opcode.Value; @@ -807,7 +793,7 @@ namespace System.Reflection.Emit Emit(opcode, methodInfo); } - public virtual void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type? returnType, Type[]? parameterTypes) + public override void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type? returnType, Type[]? parameterTypes) { // GetMethodSigHelper expects a ModuleBuilder or null, and module might be // a normal module when using dynamic methods. @@ -815,7 +801,7 @@ namespace System.Reflection.Emit Emit(opcode, helper); } - public virtual void EmitCalli(OpCode opcode, CallingConventions callingConvention, Type returnType, Type[]? parameterTypes, Type[]? optionalParameterTypes) + public override void EmitCalli(OpCode opcode, CallingConventions callingConvention, Type? returnType, Type[]? parameterTypes, Type[]? optionalParameterTypes) { if (optionalParameterTypes != null) throw new NotImplementedException(); @@ -824,46 +810,7 @@ namespace System.Reflection.Emit Emit(opcode, helper); } - private const string ConsoleTypeFullName = "System.Console, System.Console"; - - public virtual void EmitWriteLine(FieldInfo fld) - { - ArgumentNullException.ThrowIfNull(fld); - - // The MS implementation does not check for valuetypes here but it - // should. Also, it should check that if the field is not static, - // then it is a member of this type. - if (fld.IsStatic) - Emit(OpCodes.Ldsfld, fld); - else - { - Emit(OpCodes.Ldarg_0); - Emit(OpCodes.Ldfld, fld); - } - Type consoleType = Type.GetType(ConsoleTypeFullName, throwOnError: true)!; - Emit(OpCodes.Call, consoleType.GetMethod("WriteLine", new Type[1] { fld.FieldType })!); - } - - public virtual void EmitWriteLine(LocalBuilder localBuilder) - { - ArgumentNullException.ThrowIfNull(localBuilder); - if (localBuilder.LocalType is TypeBuilder) - throw new NotSupportedException(SR.NotSupported_OutputStreamUsingTypeBuilder); - // The MS implementation does not check for valuetypes here but it - // should. - Emit(OpCodes.Ldloc, localBuilder); - Type consoleType = Type.GetType(ConsoleTypeFullName, throwOnError: true)!; - Emit(OpCodes.Call, consoleType.GetMethod("WriteLine", new Type[1] { localBuilder.LocalType })!); - } - - public virtual void EmitWriteLine(string value) - { - Emit(OpCodes.Ldstr, value); - Type consoleType = Type.GetType(ConsoleTypeFullName, throwOnError: true)!; - Emit(OpCodes.Call, consoleType.GetMethod("WriteLine", new Type[1] { typeof(string) })!); - } - - public virtual void EndExceptionBlock() + public override void EndExceptionBlock() { if (!InExceptionBlock) throw new NotSupportedException(SR.Argument_NotInExceptionBlock); @@ -879,10 +826,10 @@ namespace System.Reflection.Emit cur_block = open_blocks.Peek()!; } - public virtual void EndScope() + public override void EndScope() { } - public virtual void MarkLabel(Label loc) + public override void MarkLabel(Label loc) { if (loc.m_label < 0 || loc.m_label >= num_labels) throw new System.ArgumentException(SR.Argument_InvalidLabel); @@ -893,21 +840,9 @@ namespace System.Reflection.Emit cur_stack = labels[loc.m_label].maxStack; } - public virtual void ThrowException([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type excType) - { - ArgumentNullException.ThrowIfNull(excType); - if (!((excType == typeof(Exception)) || - excType.IsSubclassOf(typeof(Exception)))) - throw new ArgumentException(SR.Argument_NotExceptionType, nameof(excType)); - ConstructorInfo? ctor = excType.GetConstructor(Type.EmptyTypes); - if (ctor == null) - throw new ArgumentException(SR.Arg_NoDefCTorWithoutTypeName, nameof(excType)); - Emit(OpCodes.Newobj, ctor); - Emit(OpCodes.Throw); - } // FIXME: "Not implemented" - public virtual void UsingNamespace(string usingNamespace) + public override void UsingNamespace(string usingNamespace) { throw new NotImplementedException(); } @@ -955,7 +890,7 @@ namespace System.Reflection.Emit internal ITokenGenerator TokenGenerator => token_gen; - public virtual int ILOffset => code_len; + public override int ILOffset => code_len; } internal struct SequencePoint diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.Mono.cs index 88996e0..8e4503c 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.Mono.cs @@ -53,7 +53,7 @@ namespace System.Reflection.Emit private string name; private int table_idx; private byte[]? code; - private ILGenerator? ilgen; + private RuntimeILGenerator? ilgen; private RuntimeTypeBuilder type; internal ParameterBuilder[]? pinfo; private CustomAttributeBuilder[]? cattrs; @@ -321,7 +321,7 @@ namespace System.Reflection.Emit throw new InvalidOperationException(SR.InvalidOperation_ShouldNotHaveMethodBody); if (ilgen != null) return ilgen; - ilgen = new ILGenerator(type.Module, ((RuntimeModuleBuilder)type.Module).GetTokenGenerator(), size); + ilgen = new RuntimeILGenerator(type.Module, ((RuntimeModuleBuilder)type.Module).GetTokenGenerator(), size); return ilgen; } -- 2.7.4