Skip to content
Closed
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 @@ -159,10 +159,16 @@ public AssemblyReferenceHandle FindOrAddAssemblyRef (string assemblyName)
/// Adds a member reference using the reusable signature blob builder.
/// </summary>
public MemberReferenceHandle AddMemberRef (EntityHandle parent, string name, Action<BlobEncoder> encodeSig)
=> AddMemberRef (parent, name, GetOrAddSignature (encodeSig));

public MemberReferenceHandle AddMemberRef (EntityHandle parent, string name, BlobHandle signature)
=> Metadata.AddMemberReference (parent, Metadata.GetOrAddString (name), signature);

public BlobHandle GetOrAddSignature (Action<BlobEncoder> encodeSig)
{
_sigBlob.Clear ();
encodeSig (new BlobEncoder (_sigBlob));
return Metadata.AddMemberReference (parent, Metadata.GetOrAddString (name), Metadata.GetOrAddBlob (_sigBlob));
return Metadata.GetOrAddBlob (_sigBlob);
}

/// <summary>
Expand Down Expand Up @@ -382,6 +388,15 @@ public MethodDefinitionHandle EmitBody (string name, MethodAttributes attrs,
Action<BlobEncoder> encodeSig, Action<TrackedInstructionEncoder> emitIL)
=> EmitBody (name, attrs, encodeSig, emitIL, encodeLocals: null, useBranches: false);

public MethodDefinitionHandle EmitBody (string name, MethodAttributes attrs,
BlobHandle signature, Action<TrackedInstructionEncoder> emitIL)
=> EmitBody (name, attrs, signature, emitIL, encodeLocals: null, useBranches: false);

public MethodDefinitionHandle EmitBody (string name, MethodAttributes attrs,
BlobHandle signature, Action<TrackedInstructionEncoder> emitIL,
Action<BlobBuilder>? encodeLocals)
=> EmitBody (name, attrs, signature, emitIL, encodeLocals, useBranches: false);

/// <summary>
/// Emits a method body and definition with optional local variable declarations.
/// </summary>
Expand All @@ -404,11 +419,15 @@ public MethodDefinitionHandle EmitBody (string name, MethodAttributes attrs,
Action<BlobEncoder> encodeSig, Action<TrackedInstructionEncoder> emitIL,
Action<BlobBuilder>? encodeLocals, bool useBranches)
{
_sigBlob.Clear ();
encodeSig (new BlobEncoder (_sigBlob));
// Capture the sig blob handle before emitIL, because emitIL callbacks
// may call AddMemberRef which clears and repopulates _sigBlob.
var sigBlobHandle = Metadata.GetOrAddBlob (_sigBlob);
return EmitBody (name, attrs, GetOrAddSignature (encodeSig), emitIL, encodeLocals, useBranches);
}

MethodDefinitionHandle EmitBody (string name, MethodAttributes attrs,
BlobHandle signature, Action<TrackedInstructionEncoder> emitIL,
Action<BlobBuilder>? encodeLocals, bool useBranches)
{

StandaloneSignatureHandle localSigHandle = default;
if (encodeLocals != null) {
Expand All @@ -433,7 +452,7 @@ public MethodDefinitionHandle EmitBody (string name, MethodAttributes attrs,
return Metadata.AddMethodDefinition (
attrs, MethodImplAttributes.IL,
Metadata.GetOrAddString (name),
sigBlobHandle,
signature,
bodyOffset, MetadataTokens.ParameterHandle (Metadata.GetRowCount (TableIndex.Param) + 1));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ sealed class TypeMapAssemblyEmitter
MemberReferenceHandle _jniEnvTypesRegisterNativesRef;
MemberReferenceHandle _readOnlySpanOfJniNativeMethodCtorRef;

BlobHandle _activationCtorSignature;
BlobHandle _createInstanceSignature;

EntityHandle _anchorTypeHandle;

ExportMethodDispatchEmitter? _exportMethodDispatchEmitter;
Expand Down Expand Up @@ -950,38 +953,50 @@ void EmitCreateInstanceBody (Action<TrackedInstructionEncoder> emitIL)
{
_pe.EmitBody ("CreateInstance",
MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig,
sig => sig.MethodSignature (isInstanceMethod: true).Parameters (2,
rt => rt.Type ().Type (_iJavaPeerableRef, false),
p => {
p.AddParameter ().Type ().IntPtr ();
p.AddParameter ().Type ().Type (_jniHandleOwnershipRef, true);
}),
GetCreateInstanceSignature (),
emitIL);
}

void EmitCreateInstanceBodyWithLocals (Action<BlobBuilder> encodeLocals, Action<TrackedInstructionEncoder> emitIL)
{
_pe.EmitBody ("CreateInstance",
MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig,
sig => sig.MethodSignature (isInstanceMethod: true).Parameters (2,
rt => rt.Type ().Type (_iJavaPeerableRef, false),
p => {
p.AddParameter ().Type ().IntPtr ();
p.AddParameter ().Type ().Type (_jniHandleOwnershipRef, true);
}),
GetCreateInstanceSignature (),
emitIL,
encodeLocals);
}

MemberReferenceHandle AddActivationCtorRef (EntityHandle declaringTypeRef)
{
return _pe.AddMemberRef (declaringTypeRef, ".ctor",
sig => sig.MethodSignature (isInstanceMethod: true).Parameters (2,
rt => rt.Void (),
p => {
p.AddParameter ().Type ().IntPtr ();
p.AddParameter ().Type ().Type (_jniHandleOwnershipRef, true);
}));
return _pe.AddMemberRef (declaringTypeRef, ".ctor", GetActivationCtorSignature ());
}

BlobHandle GetActivationCtorSignature ()
{
if (_activationCtorSignature.IsNil) {
_activationCtorSignature = _pe.GetOrAddSignature (
sig => sig.MethodSignature (isInstanceMethod: true).Parameters (2,
rt => rt.Void (),
p => {
p.AddParameter ().Type ().IntPtr ();
p.AddParameter ().Type ().Type (_jniHandleOwnershipRef, true);
}));
}
return _activationCtorSignature;
}

BlobHandle GetCreateInstanceSignature ()
{
if (_createInstanceSignature.IsNil) {
_createInstanceSignature = _pe.GetOrAddSignature (
sig => sig.MethodSignature (isInstanceMethod: true).Parameters (2,
rt => rt.Type ().Type (_iJavaPeerableRef, false),
p => {
p.AddParameter ().Type ().IntPtr ();
p.AddParameter ().Type ().Type (_jniHandleOwnershipRef, true);
}));
}
return _createInstanceSignature;
}

MemberReferenceHandle AddManagedCtorRef (EntityHandle declaringTypeRef, IReadOnlyList<TypeRefData> parameterTypes)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,49 @@ public void EmitBody_ILCallbackCallsAddMemberRef_SignatureNotCorrupted ()
Assert.Equal ("System.Int32", paramType);
}

[Fact]
public void EmitBody_PreencodedSignature_PreservesMethodSignature ()
{
var pe = new PEAssemblyBuilder (new Version (11, 0, 0, 0));
pe.EmitPreamble ("PreencodedSigTest", "PreencodedSigTest.dll");
var objectRef = pe.Metadata.AddTypeReference (pe.SystemRuntimeRef,
pe.Metadata.GetOrAddString ("System"), pe.Metadata.GetOrAddString ("Object"));
pe.Metadata.AddTypeDefinition (
TypeAttributes.Public | TypeAttributes.Class,
pe.Metadata.GetOrAddString ("Test"),
pe.Metadata.GetOrAddString ("MyType"),
objectRef,
MetadataTokens.FieldDefinitionHandle (pe.Metadata.GetRowCount (TableIndex.Field) + 1),
MetadataTokens.MethodDefinitionHandle (pe.Metadata.GetRowCount (TableIndex.MethodDef) + 1));
var signature = new BlobBuilder ();
signature.WriteByte ((byte) SignatureAttributes.Instance);
signature.WriteCompressedInteger (1);
signature.WriteByte ((byte) SignatureTypeCode.String);
signature.WriteByte ((byte) SignatureTypeCode.Int32);

pe.EmitBody (
"PreencodedMethod",
MethodAttributes.Public,
pe.Metadata.GetOrAddBlob (signature),
encoder => {
encoder.OpCode (ILOpCode.Ldnull);
encoder.Return (returnsValue: true);
});
Comment on lines +420 to +423
using var stream = new MemoryStream ();
pe.WritePE (stream);
stream.Position = 0;
using var peReader = new PEReader (stream);
var reader = peReader.GetMetadataReader ();
var method = reader.TypeDefinitions
.SelectMany (handle => reader.GetTypeDefinition (handle).GetMethods ())
.Select (handle => reader.GetMethodDefinition (handle))
.Single (method => reader.GetString (method.Name) == "PreencodedMethod");
var decoded = method.DecodeSignature (SignatureTypeProvider.Instance, null);

Assert.Equal ("System.String", decoded.ReturnType);
Assert.Equal ("System.Int32", Assert.Single (decoded.ParameterTypes));
}

[Fact]
public void Generate_JiStyleInvoker_FirstParamIsByRef ()
{
Expand Down
Loading