Skip to content

Commit

Permalink
Implement remaining ILGenertorImpl methods, excluding scope. Add max …
Browse files Browse the repository at this point in the history
…stack calculation for branching. (dotnet#96362)

* Fix/refactor ModuleBuilder.Get***MetadatToken, add ILGenerator.EmitCalli implementation

* Fix Assembly.LoadFrom(...) issue, add more tests

* Calculate max stack correctly when branching, add more tests

* Apply feedback, fix test failure, disable some tests on mono
  • Loading branch information
buyaa-n authored Jan 2, 2024
1 parent a8d3c5a commit 93caf8d
Show file tree
Hide file tree
Showing 9 changed files with 1,248 additions and 226 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1523,7 +1523,7 @@
<value>Recursive fallback not allowed for bytes {0}.</value>
</data>
<data name="Argument_RedefinedLabel" xml:space="preserve">
<value>Label multiply defined.</value>
<value>Label defined multiple times.</value>
</data>
<data name="Argument_ResolveField" xml:space="preserve">
<value>Token {0:x} is not a valid FieldInfo token in the scope of module {1}.</value>
Expand Down Expand Up @@ -4283,4 +4283,4 @@
<data name="Reflection_Disabled" xml:space="preserve">
<value>This operation is not available because the reflection support was disabled at compile time.</value>
</data>
</root>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@
<data name="Arg_NotGenericMethodDefinition" xml:space="preserve">
<value>{0} is not a GenericMethodDefinition. MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true.</value>
</data>
<data name="InvalidOperation_NotAVarArgCallingConvention" xml:space="preserve">
<value>Calling convention must be VarArgs.</value>
</data>
<data name="ArgumentException_BadMethodImplBody" xml:space="preserve">
<value>MethodOverride's body must be from this type.</value>
</data>
Expand Down Expand Up @@ -261,4 +264,7 @@
<data name="InvalidOperation_BadEmptyMethodBody" xml:space="preserve">
<value>Method '{0}' does not have a method body.</value>
</data>
<data name="Argument_RedefinedLabel" xml:space="preserve">
<value>Label defined multiple times.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,22 @@ internal AssemblyBuilderImpl(AssemblyName name, Assembly coreAssembly, IEnumerab
}
}

internal static AssemblyBuilderImpl DefinePersistedAssembly(AssemblyName name, Assembly coreAssembly, IEnumerable<CustomAttributeBuilder>? assemblyAttributes)
internal static AssemblyBuilderImpl DefinePersistedAssembly(AssemblyName name, Assembly coreAssembly,
IEnumerable<CustomAttributeBuilder>? assemblyAttributes)
=> new AssemblyBuilderImpl(name, coreAssembly, assemblyAttributes);

private void WritePEImage(Stream peStream, BlobBuilder ilBuilder)
{
// Create executable with the managed metadata from the specified MetadataBuilder.
var peHeaderBuilder = new PEHeaderBuilder(
imageCharacteristics: Characteristics.Dll // Start off with a simple DLL
);
// For now only support DLL, DLL files are considered executable files
// for almost all purposes, although they cannot be directly run.
imageCharacteristics: Characteristics.ExecutableImage | Characteristics.Dll);

var peBuilder = new ManagedPEBuilder(
peHeaderBuilder,
new MetadataRootBuilder(_metadataBuilder),
ilBuilder);
header: peHeaderBuilder,
metadataRootBuilder: new MetadataRootBuilder(_metadataBuilder),
ilStream: ilBuilder,
strongNameSignatureSize: 0);

// Write executable into the specified stream.
var peBlob = new BlobBuilder();
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ internal MethodBuilderImpl(string name, MethodAttributes attributes, CallingConv
}
}

internal BlobBuilder GetMethodSignatureBlob() => MetadataSignatureHelper.MethodSignatureEncoder(_module,
_parameterTypes, ReturnType, GetSignatureConvention(_callingConventions, _dllImportData), GetGenericArguments().Length, !IsStatic);
internal BlobBuilder GetMethodSignatureBlob() => MetadataSignatureHelper.GetMethodSignature(_module, _parameterTypes,
_returnType, GetSignatureConvention(_callingConventions, _dllImportData), GetGenericArguments().Length, !IsStatic);

internal static SignatureCallingConvention GetSignatureConvention(CallingConventions callingConvention, DllImportData? dllImportData = null)
{
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@

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)
internal static BlobBuilder GetLocalSignature(List<LocalBuilder> locals, ModuleBuilderImpl module)
{
BlobBuilder localSignature = new();
LocalVariablesEncoder encoder = new BlobEncoder(localSignature).LocalVariableSignature(locals.Count);
Expand All @@ -25,15 +24,15 @@ internal static BlobBuilder LocalSignatureEncoder(List<LocalBuilder> locals, Mod
return localSignature;
}

internal static BlobBuilder FieldSignatureEncoder(Type fieldType, ModuleBuilderImpl module)
internal static BlobBuilder GetFieldSignature(Type fieldType, ModuleBuilderImpl module)
{
BlobBuilder fieldSignature = new();
WriteSignatureForType(new BlobEncoder(fieldSignature).Field().Type(), fieldType, module);

return fieldSignature;
}

internal static BlobBuilder ConstructorSignatureEncoder(ParameterInfo[]? parameters, ModuleBuilderImpl module)
internal static BlobBuilder GetConstructorSignature(ParameterInfo[]? parameters, ModuleBuilderImpl module)
{
BlobBuilder constructorSignature = new();

Expand Down Expand Up @@ -71,27 +70,32 @@ internal static BlobBuilder GetMethodSpecificationSignature(Type[] genericArgume
return methodSpecSignature;
}

internal static BlobBuilder MethodSignatureEncoder(ModuleBuilderImpl module, Type[]? parameters,
Type? returnType, SignatureCallingConvention convention, int genParamCount, bool isInstance)
internal static BlobBuilder GetMethodSignature(ModuleBuilderImpl module, Type[]? parameters, Type? returnType,
SignatureCallingConvention convention, int genParamCount = 0, bool isInstance = false, Type[]? optionalParameterTypes = null)
{
// Encoding return type and parameters.
BlobBuilder methodSignature = new();

new BlobEncoder(methodSignature).
MethodSignature(convention: convention, genericParameterCount: genParamCount, isInstanceMethod: isInstance).
Parameters((parameters == null) ? 0 : parameters.Length, out ReturnTypeEncoder retEncoder, out ParametersEncoder parEncoder);
int paramsLength = ((parameters == null) ? 0 : parameters.Length) + ((optionalParameterTypes == null) ? 0 : optionalParameterTypes.Length);

new BlobEncoder(methodSignature).MethodSignature(convention, genParamCount, isInstance).
Parameters(paramsLength, out ReturnTypeEncoder retEncoder, out ParametersEncoder parEncoder);

if (returnType != null && returnType != module.GetTypeFromCoreAssembly(CoreTypeId.Void))
{
WriteSignatureForType(retEncoder.Type(), returnType, module);
}
else // If null mark ReturnTypeEncoder as void
else
{
retEncoder.Void();
}

WriteParametersSignature(module, parameters, parEncoder);

if (optionalParameterTypes != null && optionalParameterTypes.Length != 0)
{
WriteParametersSignature(module, optionalParameterTypes, parEncoder.StartVarArgs());
}

return methodSignature;
}

Expand All @@ -106,7 +110,7 @@ private static void WriteParametersSignature(ModuleBuilderImpl module, Type[]? p
}
}

internal static BlobBuilder PropertySignatureEncoder(PropertyBuilderImpl property, ModuleBuilderImpl module)
internal static BlobBuilder GetPropertySignature(PropertyBuilderImpl property, ModuleBuilderImpl module)
{
BlobBuilder propertySignature = new();

Expand Down
Loading

0 comments on commit 93caf8d

Please sign in to comment.