private static void CreateMethod(CompilerClassLoader loader, TypeBuilder tb, ProxyMethod pm)
{
MethodBuilder mb = pm.mw.GetDefineMethodHelper().DefineMethod(loader.GetTypeWrapperFactory(), tb, pm.mw.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.Final);
List <string> exceptions = new List <string>();
foreach (TypeWrapper tw in pm.exceptions)
{
exceptions.Add(tw.Name);
}
AttributeHelper.SetThrowsAttribute(mb, exceptions.ToArray());
CodeEmitter ilgen = CodeEmitter.Create(mb);
ilgen.BeginExceptionBlock();
ilgen.Emit(OpCodes.Ldarg_0);
invocationHandlerField.EmitGet(ilgen);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ldsfld, pm.fb);
TypeWrapper[] parameters = pm.mw.GetParameters();
if (parameters.Length == 0)
{
ilgen.Emit(OpCodes.Ldnull);
}
else
{
ilgen.Emit_Ldc_I4(parameters.Length);
ilgen.Emit(OpCodes.Newarr, Types.Object);
for (int i = 0; i < parameters.Length; i++)
{
ilgen.Emit(OpCodes.Dup);
ilgen.Emit_Ldc_I4(i);
ilgen.Emit(OpCodes.Ldarg, (short)i);
if (parameters[i].IsNonPrimitiveValueType)
{
parameters[i].EmitBox(ilgen);
}
else if (parameters[i].IsPrimitive)
{
Boxer.EmitBox(ilgen, parameters[i]);
}
ilgen.Emit(OpCodes.Stelem_Ref);
}
}
invokeMethod.EmitCallvirt(ilgen);
TypeWrapper returnType = pm.mw.ReturnType;
CodeEmitterLocal returnValue = null;
if (returnType != PrimitiveTypeWrapper.VOID)
{
returnValue = ilgen.DeclareLocal(returnType.TypeAsSignatureType);
if (returnType.IsNonPrimitiveValueType)
{
returnType.EmitUnbox(ilgen);
}
else if (returnType.IsPrimitive)
{
Boxer.EmitUnbox(ilgen, returnType);
}
else if (returnType != CoreClasses.java.lang.Object.Wrapper)
{
ilgen.EmitCastclass(returnType.TypeAsSignatureType);
}
ilgen.Emit(OpCodes.Stloc, returnValue);
}
CodeEmitterLabel returnLabel = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Leave, returnLabel);
// TODO consider using a filter here (but we would need to add filter support to CodeEmitter)
ilgen.BeginCatchBlock(Types.Exception);
ilgen.Emit_Ldc_I4(0);
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.mapException.MakeGenericMethod(Types.Exception));
CodeEmitterLocal exception = ilgen.DeclareLocal(Types.Exception);
ilgen.Emit(OpCodes.Stloc, exception);
CodeEmitterLabel rethrow = ilgen.DefineLabel();
ilgen.Emit(OpCodes.Ldloc, exception);
errorClass.EmitInstanceOf(null, ilgen);
ilgen.Emit(OpCodes.Brtrue, rethrow);
ilgen.Emit(OpCodes.Ldloc, exception);
runtimeExceptionClass.EmitInstanceOf(null, ilgen);
ilgen.Emit(OpCodes.Brtrue, rethrow);
foreach (TypeWrapper tw in pm.exceptions)
{
ilgen.Emit(OpCodes.Ldloc, exception);
tw.EmitInstanceOf(null, ilgen);
ilgen.Emit(OpCodes.Brtrue, rethrow);
}
ilgen.Emit(OpCodes.Ldloc, exception);
undeclaredThrowableExceptionConstructor.EmitNewobj(ilgen);
ilgen.Emit(OpCodes.Throw);
ilgen.MarkLabel(rethrow);
ilgen.Emit(OpCodes.Rethrow);
ilgen.EndExceptionBlock();
ilgen.MarkLabel(returnLabel);
if (returnValue != null)
{
ilgen.Emit(OpCodes.Ldloc, returnValue);
}
ilgen.Emit(OpCodes.Ret);
ilgen.DoEmit();
}