Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Abstract out LocalBuilder, emit Locals with new ILGenerator #93809

Merged
merged 16 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -162,14 +162,14 @@
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\CustomAttributeBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\DynamicILGenerator.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\DynamicMethod.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\LocalBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\RuntimeAssemblyBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\RuntimeConstructorBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\RuntimeEnumBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\RuntimeEventBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\RuntimeFieldBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\RuntimeGenericTypeParameterBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\RuntimeILGenerator.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\RuntimeLocalBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\RuntimeMethodBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\RuntimeModuleBuilder.cs" />
<Compile Include="$(BclSourcesRoot)\System\Reflection\Emit\RuntimeParameterBuilder.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ public override LocalBuilder DeclareLocal(Type localType, bool pinned)
{
ArgumentNullException.ThrowIfNull(localType);

LocalBuilder localBuilder;
RuntimeLocalBuilder localBuilder;

RuntimeType? rtType = localType as RuntimeType;

if (rtType == null)
throw new ArgumentException(SR.Argument_MustBeRuntimeType);

localBuilder = new LocalBuilder(m_localCount, localType, m_methodBuilder, pinned);
localBuilder = new RuntimeLocalBuilder(m_localCount, localType, m_methodBuilder, pinned);
// add the localType to local signature
m_localSignature.AddArgument(localType, pinned);
m_localCount++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -819,8 +819,8 @@ public override void Emit(OpCode opcode, LocalBuilder local)
ArgumentNullException.ThrowIfNull(local);

// Puts the opcode onto the IL stream followed by the information for local variable local.
int tempVal = local.GetLocalIndex();
if (local.GetMethodBuilder() != m_methodBuilder)
int tempVal = local.LocalIndex;
if (local is not RuntimeLocalBuilder localBuilder || localBuilder.GetMethodBuilder() != m_methodBuilder)
{
throw new ArgumentException(SR.Argument_UnmatchedMethodForLocal, nameof(local));
}
Expand Down Expand Up @@ -1185,7 +1185,7 @@ public override LocalBuilder DeclareLocal(Type localType, bool pinned)
// add the localType to local signature
m_localSignature.AddArgument(localType, pinned);

return new LocalBuilder(m_localCount++, localType, methodBuilder, pinned);
return new RuntimeLocalBuilder(m_localCount++, localType, methodBuilder, pinned);
}

public override void UsingNamespace(string usingNamespace)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace System.Reflection.Emit
{
public sealed class LocalBuilder : LocalVariableInfo
internal sealed class RuntimeLocalBuilder : LocalBuilder
{
#region Private Data Members
private readonly int m_localIndex;
Expand All @@ -13,9 +13,9 @@ public sealed class LocalBuilder : LocalVariableInfo
#endregion

#region Constructor
internal LocalBuilder(int localIndex, Type localType, MethodInfo methodBuilder)
internal RuntimeLocalBuilder(int localIndex, Type localType, MethodInfo methodBuilder)
: this(localIndex, localType, methodBuilder, false) { }
internal LocalBuilder(int localIndex, Type localType, MethodInfo methodBuilder, bool isPinned)
internal RuntimeLocalBuilder(int localIndex, Type localType, MethodInfo methodBuilder, bool isPinned)
{
m_isPinned = isPinned;
m_localIndex = localIndex;
Expand All @@ -25,14 +25,7 @@ internal LocalBuilder(int localIndex, Type localType, MethodInfo methodBuilder,
#endregion

#region Internal Members
internal int GetLocalIndex()
{
return m_localIndex;
}
internal MethodInfo GetMethodBuilder()
{
return m_methodBuilder;
}
internal MethodInfo GetMethodBuilder() => m_methodBuilder;
#endregion

#region LocalVariableInfo Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@
<Compile Include="System\Reflection\Emit\CustomAttributeBuilder.cs" />
<Compile Include="System\Reflection\Emit\DynamicILInfo.cs" />
<Compile Include="System\Reflection\Emit\DynamicMethod.cs" />
<Compile Include="System\Reflection\Emit\LocalBuilder.cs" />
<Compile Include="System\Reflection\Emit\ReflectionEmitThrower.cs" />
<Compile Include="System\Reflection\Emit\SignatureHelper.cs" />
<Compile Include="System\Reflection\EnumInfo.cs" />
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,6 @@
<Compile Include="$(MSBuildThisFileDirectory)System\IFormatProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IFormattable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Index.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\ILGenerator.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\BitVector256.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\ProbabilisticWithAsciiCharSearchValues.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\SingleCharSearchValues.cs" />
Expand Down Expand Up @@ -674,7 +673,9 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\FieldOnTypeBuilderInstantiation.cs" Condition="'$(FeatureNativeAot)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\FlowControl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\GenericTypeParameterBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\ILGenerator.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\Label.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\LocalBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\MethodBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\MethodBuilderInstantiation.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\MethodOnTypeBuilderInstantiation.cs" Condition="'$(FeatureNativeAot)' != 'true'" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Reflection.Emit
{
public abstract class LocalBuilder : LocalVariableInfo
{
/// <summary>
/// Initializes a new instance of the <see cref="LocalBuilder"/> class.
/// </summary>
/// <remarks>
/// This constructor is invoked by derived classes.
/// </remarks>
protected LocalBuilder() { }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ public virtual void ThrowException([System.Diagnostics.CodeAnalysis.DynamicallyA
public static bool operator ==(System.Reflection.Emit.Label a, System.Reflection.Emit.Label b) { throw null; }
public static bool operator !=(System.Reflection.Emit.Label a, System.Reflection.Emit.Label b) { throw null; }
}
public sealed partial class LocalBuilder : System.Reflection.LocalVariableInfo
public abstract class LocalBuilder : System.Reflection.LocalVariableInfo
{
internal LocalBuilder() { }
protected LocalBuilder() { }
public override bool IsPinned { get { throw null; } }
public override int LocalIndex { get { throw null; } }
public override System.Type LocalType { get { throw null; } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@
<data name="InvalidOperation_ShouldNotHaveMethodBody" xml:space="preserve">
<value>Method body should not exist.</value>
</data>
<data name="Argument_UnmatchedMethodForLocal" xml:space="preserve">
<value>Local passed in does not belong to this ILGenerator.</value>
</data>
<data name="Argument_InvalidLabel" xml:space="preserve">
<value>Invalid Label.</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<Compile Include="System\Reflection\Emit\FieldBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\GenericTypeParameterBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\ILGeneratorImpl.cs" />
<Compile Include="System\Reflection\Emit\LocalBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\MethodBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\ModuleBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\ParameterBuilderImpl.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ internal sealed class ILGeneratorImpl : ILGenerator
private bool _hasDynamicStackAllocation;
private int _maxStackSize;
private int _currentStack;
private List<LocalBuilder> _locals = new();
private Dictionary<Label, LabelHandle> _labelTable = new(2);

internal ILGeneratorImpl(MethodBuilder methodBuilder, int size)
Expand All @@ -28,9 +29,9 @@ internal ILGeneratorImpl(MethodBuilder methodBuilder, int size)
}

internal int GetMaxStackSize() => _maxStackSize;

internal InstructionEncoder Instructions => _il;
internal bool HasDynamicStackAllocation => _hasDynamicStackAllocation;
internal List<LocalBuilder> Locals => _locals;

public override int ILOffset => _il.Offset;

Expand All @@ -40,7 +41,19 @@ internal ILGeneratorImpl(MethodBuilder methodBuilder, int size)
public override void BeginFaultBlock() => throw new NotImplementedException();
public override void BeginFinallyBlock() => throw new NotImplementedException();
public override void BeginScope() => throw new NotImplementedException();
public override LocalBuilder DeclareLocal(Type localType, bool pinned) => throw new NotImplementedException();

public override LocalBuilder DeclareLocal(Type localType, bool pinned)
{
if (_methodBuilder is not MethodBuilderImpl methodBuilder)
throw new NotSupportedException();

ArgumentNullException.ThrowIfNull(localType);

LocalBuilder local = new LocalBuilderImpl(_locals.Count, localType, methodBuilder, pinned);
_locals.Add(local);

return local;
}

public override Label DefineLabel()
{
Expand Down Expand Up @@ -228,7 +241,34 @@ public override void Emit(OpCode opcode, Label[] labels)
}
}

public override void Emit(OpCode opcode, LocalBuilder local) => throw new NotImplementedException();
public override void Emit(OpCode opcode, LocalBuilder local)
{
ArgumentNullException.ThrowIfNull(local);

if (local is not LocalBuilderImpl localBuilder || localBuilder.GetMethodBuilder() != _methodBuilder)
{
throw new ArgumentException(SR.Argument_UnmatchedMethodForLocal, nameof(local));
}

int tempVal = local.LocalIndex;
string name = opcode.Name!;

if (name.StartsWith("ldloca"))
{
_il.LoadLocalAddress(tempVal);
}
else if (name.StartsWith("ldloc"))
{
_il.LoadLocal(tempVal);
}
else if (name.StartsWith("stloc"))
{
_il.StoreLocal(tempVal);
}

UpdateStackSize(opcode);
}

public override void Emit(OpCode opcode, SignatureHelper signature) => throw new NotImplementedException();
public override void Emit(OpCode opcode, FieldInfo field) => throw new NotImplementedException();
public override void Emit(OpCode opcode, MethodInfo meth) => throw new NotImplementedException();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Reflection.Emit
{
internal sealed class LocalBuilderImpl : LocalBuilder
{
#region Private Data Members
private readonly int _localIndex;
private readonly Type _localType;
private readonly MethodInfo _method;
private readonly bool _isPinned;
#endregion

#region Constructor
internal LocalBuilderImpl(int index, Type type, MethodInfo method, bool isPinned)
{
_isPinned = isPinned;
_localIndex = index;
_localType = type;
_method = method;
}
#endregion

#region Internal Members
internal MethodInfo GetMethodBuilder() => _method;
#endregion

#region LocalVariableInfo Override
public override bool IsPinned => _isPinned;
public override Type LocalType => _localType;
public override int LocalIndex => _localIndex;
#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,9 @@ private void WriteMethods(TypeBuilderImpl typeBuilder, List<GenericTypeParameter
ILGeneratorImpl? il = method.ILGeneratorImpl;
if (il != null)
{
offset = AddMethodBody(method, il, methodBodyEncoder);
StandaloneSignatureHandle signature = il.Locals.Count == 0 ? default :
_metadataBuilder.AddStandaloneSignature(_metadataBuilder.GetOrAddBlob(MetadataSignatureHelper.LocalSignatureEncoder(il.Locals, this)));
offset = AddMethodBody(method, il, signature, methodBodyEncoder);
}

MethodDefinitionHandle methodHandle = AddMethodDefinition(method, method.GetMethodSignatureBlob(), offset, _nextParameterRowId);
Expand Down Expand Up @@ -237,11 +239,11 @@ private void WriteMethods(TypeBuilderImpl typeBuilder, List<GenericTypeParameter
}
}

private static int AddMethodBody(MethodBuilderImpl method, ILGeneratorImpl il, MethodBodyStreamEncoder methodBodyEncoder) =>
methodBodyEncoder.AddMethodBody(
private static int AddMethodBody(MethodBuilderImpl method, ILGeneratorImpl il, StandaloneSignatureHandle signature, MethodBodyStreamEncoder bodyEncoder) =>
bodyEncoder.AddMethodBody(
instructionEncoder: il.Instructions,
maxStack: il.GetMaxStackSize(),
localVariablesSignature: default, // TODO
localVariablesSignature: signature,
attributes: method.InitLocals ? MethodBodyAttributes.InitLocals : MethodBodyAttributes.None,
hasDynamicStackAllocation: il.HasDynamicStackAllocation);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
Expand All @@ -10,6 +11,20 @@ namespace System.Reflection.Emit
// TODO: Only support simple signatures. More complex signatures (generics, array, byref, pointers etc) will be added.
internal static class MetadataSignatureHelper
{
internal static BlobBuilder LocalSignatureEncoder(List<LocalBuilder> locals, ModuleBuilderImpl module)
{
BlobBuilder localSignature = new();
LocalVariablesEncoder encoder = new BlobEncoder(localSignature).LocalVariableSignature(locals.Count);

foreach(LocalBuilder local in locals)
{
WriteSignatureForType(encoder.AddVariable().Type(local.LocalType.IsByRef, local.IsPinned),
local.LocalType.IsByRef ? local.LocalType.GetElementType()! : local.LocalType, module);
}

return localSignature;
}

internal static BlobBuilder FieldSignatureEncoder(Type fieldType, ModuleBuilderImpl module)
{
BlobBuilder fieldSignature = new();
Expand Down
Loading