Skip to content

Commit

Permalink
Fix NRE on EmitCalli (#44452)
Browse files Browse the repository at this point in the history
  • Loading branch information
wzchua authored Nov 19, 2020
1 parent 8bbbf6d commit cb035a3
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -482,20 +482,12 @@ internal override SignatureHelper GetMemberRefSignature(
Type[][]? optionalCustomModifiers,
Type[]? optionalParameterTypes)
{
SignatureHelper sig = SignatureHelper.GetMethodSigHelper(call, returnType);
if (parameterTypes != null)
{
for (int i = 0; i < parameterTypes.Length; i++)
{
sig.AddArgument(parameterTypes[i], requiredCustomModifiers![i], optionalCustomModifiers![i]);
}
}
SignatureHelper sig = SignatureHelper.GetMethodSigHelper(null, call, returnType, null, null, parameterTypes, requiredCustomModifiers, optionalCustomModifiers);

if (optionalParameterTypes != null && optionalParameterTypes.Length != 0)
{
// add the sentinel
sig.AddSentinel();
foreach (Type t in optionalParameterTypes)
sig.AddArgument(t);
sig.AddArguments(optionalParameterTypes, null, null);
}
return sig;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,32 +417,14 @@ private int GetMemberRefToken(MethodBase method, Type[]? optionalParameterTypes)

internal SignatureHelper GetMemberRefSignature(CallingConventions call, Type? returnType,
Type[]? parameterTypes, Type[][]? requiredCustomModifiers, Type[][]? optionalCustomModifiers,
IEnumerable<Type>? optionalParameterTypes, int cGenericParameters)
Type[]? optionalParameterTypes, int cGenericParameters)
{
SignatureHelper sig = SignatureHelper.GetMethodSigHelper(this, call, returnType, cGenericParameters);
SignatureHelper sig = SignatureHelper.GetMethodSigHelper(this, call, cGenericParameters, returnType, null, null, parameterTypes, requiredCustomModifiers, optionalCustomModifiers);

if (parameterTypes != null)
if (optionalParameterTypes != null && optionalParameterTypes.Length != 0)
{
for (int i = 0; i < parameterTypes.Length; i++)
{
sig.AddArgument(parameterTypes[i], requiredCustomModifiers![i], optionalCustomModifiers![i]);
}
}

if (optionalParameterTypes != null)
{
int i = 0;
foreach (Type type in optionalParameterTypes)
{
// add the sentinel
if (i == 0)
{
sig.AddSentinel();
}

sig.AddArgument(type);
i++;
}
sig.AddSentinel();
sig.AddArguments(optionalParameterTypes, null, null);
}

return sig;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,39 @@ public void TestEmitCalliBlittable()
Assert.Equal(result, resultValue);
}

[Fact]
public void TestEmitCalliManagedBlittable()
{
int a = 1, b = 1, result = 2;

ModuleBuilder moduleBuilder = Helpers.DynamicModule();
TypeBuilder typeBuilder = moduleBuilder.DefineType("T", TypeAttributes.Public);
Type returnType = typeof(int);

MethodBuilder methodBuilder = typeBuilder.DefineMethod("F",
MethodAttributes.Public | MethodAttributes.Static, returnType, new Type[] { typeof(IntPtr), typeof(int), typeof(int) });
methodBuilder.SetImplementationFlags(MethodImplAttributes.NoInlining);

MethodInfo method = typeof(ILGeneratorEmit4).GetMethod(nameof(ILGeneratorEmit4.Int32Sum), BindingFlags.NonPublic | BindingFlags.Static) ?? throw new InvalidOperationException("method is null");
IntPtr funcPtr = method.MethodHandle.GetFunctionPointer();

ILGenerator il = methodBuilder.GetILGenerator();
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Ldarg_0);
il.EmitCalli(OpCodes.Calli, CallingConventions.Standard, returnType, new Type[] { typeof(int), typeof(int) }, null);
il.Emit(OpCodes.Ret);

Type dynamicType = typeBuilder.CreateType();

object resultValue = dynamicType
.GetMethod("F", BindingFlags.Public | BindingFlags.Static)
.Invoke(null, new object[] { funcPtr, a, b });

Assert.IsType(returnType, resultValue);
Assert.Equal(result, resultValue);
}

[Fact]
public void TestDynamicMethodEmitCalliBlittable()
{
Expand Down

0 comments on commit cb035a3

Please sign in to comment.