public override MethodIL EmitIL() { ILEmitter emitter = new ILEmitter(); ILCodeStream argSetupStream = emitter.NewCodeStream(); ILCodeStream callSiteSetupStream = emitter.NewCodeStream(); // This function will look like // // !For each parameter to the delegate // !if (parameter is In Parameter) // localX is TypeOfParameterX& // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperIn(RuntimeTypeHandle) // stloc localX // !else // localX is TypeOfParameter // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperRef(RuntimeTypeHandle) // stloc localX // ldarg.3 // call DynamicInvokeArgSetupComplete(ref ArgSetupState) // *** Second instruction stream starts here *** // ldarg.1 // Load this pointer // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType thiscall(TypeOfParameter1, ...) // !if ((ReturnType == void) // ldnull // !else if (ReturnType is a byref) // ldobj StripByRef(ReturnType) // box StripByRef(ReturnType) // !else // box ReturnType // ret callSiteSetupStream.EmitLdArg(1); MethodSignature delegateSignature = _delegateInfo.Signature; TypeDesc[] targetMethodParameters = new TypeDesc[delegateSignature.Length]; for (int paramIndex = 0; paramIndex < delegateSignature.Length; paramIndex++) { TypeDesc paramType = delegateSignature[paramIndex]; TypeDesc localType = paramType; targetMethodParameters[paramIndex] = paramType; if (localType.IsByRef) { // Strip ByRef localType = ((ByRefType)localType).ParameterType; } else { // Only if this is not a ByRef, convert the parameter type to something boxable. // Everything but pointer types are boxable. localType = ConvertToBoxableType(localType); } ILLocalVariable local = emitter.NewLocal(localType.MakeByRefType()); callSiteSetupStream.EmitLdLoc(local); argSetupStream.Emit(ILOpcode.ldtoken, emitter.NewToken(localType)); if (paramType.IsByRef) { argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperRef", null))); } else { argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperIn", null))); callSiteSetupStream.Emit(ILOpcode.ldobj, emitter.NewToken(paramType)); } argSetupStream.EmitStLoc(local); } argSetupStream.EmitLdArg(3); argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeArgSetupComplete", null))); callSiteSetupStream.EmitLdArg(2); MethodSignature targetMethodSig = new MethodSignature(0, 0, delegateSignature.ReturnType, targetMethodParameters); callSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(targetMethodSig)); if (delegateSignature.ReturnType.IsVoid) { callSiteSetupStream.Emit(ILOpcode.ldnull); } else if (delegateSignature.ReturnType.IsByRef) { TypeDesc targetType = ((ByRefType)delegateSignature.ReturnType).ParameterType; callSiteSetupStream.Emit(ILOpcode.ldobj, emitter.NewToken(targetType)); callSiteSetupStream.Emit(ILOpcode.box, emitter.NewToken(targetType)); } else { callSiteSetupStream.Emit(ILOpcode.box, emitter.NewToken(delegateSignature.ReturnType)); } callSiteSetupStream.Emit(ILOpcode.ret); return(emitter.Link(this)); }
public override MethodIL EmitIL() { ILEmitter emitter = new ILEmitter(); ILCodeStream argSetupStream = emitter.NewCodeStream(); ILCodeStream thisCallSiteSetupStream = emitter.NewCodeStream(); ILCodeStream staticCallSiteSetupStream = emitter.NewCodeStream(); ILCodeStream returnCodeStream = emitter.NewCodeStream(); // This function will look like // // !For each parameter to the method // !if (parameter is In Parameter) // localX is TypeOfParameterX& // ldarg.2 // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperIn(ref ArgSetupState, RuntimeTypeHandle) // stloc localX // !else // localX is TypeOfParameter // ldarg.2 // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperRef(ref ArgSetupState, RuntimeTypeHandle) // stloc localX // ldarg.2 // call DynamicInvokeArgSetupComplete(ref ArgSetupState) // *** Thiscall instruction stream starts here *** // ldarg.3 // Load targetIsThisCall // brfalse Not_this_call // ldarg.0 // Load this pointer // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType thiscall(TypeOfParameter1, ...) // br Process_return // *** Static call instruction stream starts here *** // Not_this_call: // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType (TypeOfParameter1, ...) // *** Return code stream starts here *** // Process_return: // !if (ReturnType is Byref) // dup // brfalse ByRefNull // ldobj ReturnType // !if ((ReturnType == void) // ldnull // !elif (ReturnType is pointer) // System.Reflection.Pointer.Box(ReturnType) // !else // box ReturnType // ret // // !if (ReturnType is ByRef) // ByRefNull: // throw NullReferenceException ILCodeLabel lStaticCall = emitter.NewCodeLabel(); ILCodeLabel lProcessReturn = emitter.NewCodeLabel(); thisCallSiteSetupStream.EmitLdArg(3); // targetIsThisCall thisCallSiteSetupStream.Emit(ILOpcode.brfalse, lStaticCall); staticCallSiteSetupStream.EmitLabel(lStaticCall); thisCallSiteSetupStream.EmitLdArg(0); // thisPtr ILToken tokDynamicInvokeParamHelperRef = emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperRef", null)); ILToken tokDynamicInvokeParamHelperIn = emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperIn", null)); TypeDesc[] targetMethodSignature = new TypeDesc[_targetSignature.Length]; for (int paramIndex = 0; paramIndex < _targetSignature.Length; paramIndex++) { TypeDesc paramType = Context.GetSignatureVariable(paramIndex, true); DynamicInvokeMethodParameterKind paramKind = _targetSignature[paramIndex]; for (int i = 0; i < _targetSignature.GetNumberOfParameterPointerIndirections(paramIndex); i++) { paramType = paramType.MakePointerType(); } ILToken tokParamType = emitter.NewToken(paramType); ILLocalVariable local = emitter.NewLocal(paramType.MakeByRefType()); thisCallSiteSetupStream.EmitLdLoc(local); staticCallSiteSetupStream.EmitLdLoc(local); argSetupStream.EmitLdArg(2); // argSetupState argSetupStream.Emit(ILOpcode.ldtoken, tokParamType); if (paramKind == DynamicInvokeMethodParameterKind.Reference) { argSetupStream.Emit(ILOpcode.call, tokDynamicInvokeParamHelperRef); targetMethodSignature[paramIndex] = paramType.MakeByRefType(); } else { argSetupStream.Emit(ILOpcode.call, tokDynamicInvokeParamHelperIn); thisCallSiteSetupStream.EmitLdInd(paramType); staticCallSiteSetupStream.EmitLdInd(paramType); targetMethodSignature[paramIndex] = paramType; } argSetupStream.EmitStLoc(local); } argSetupStream.EmitLdArg(2); // argSetupState argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeArgSetupComplete", null))); thisCallSiteSetupStream.EmitLdArg(1); // methodToCall staticCallSiteSetupStream.EmitLdArg(1); // methodToCall DynamicInvokeMethodParameterKind returnKind = _targetSignature.ReturnType; TypeDesc returnType = returnKind != DynamicInvokeMethodParameterKind.None ? Context.GetSignatureVariable(_targetSignature.Length, true) : Context.GetWellKnownType(WellKnownType.Void); for (int i = 0; i < _targetSignature.GetNumerOfReturnTypePointerIndirections(); i++) { returnType = returnType.MakePointerType(); } if (returnKind == DynamicInvokeMethodParameterKind.Reference) { returnType = returnType.MakeByRefType(); } MethodSignature thisCallMethodSig = new MethodSignature(0, 0, returnType, targetMethodSignature); thisCallSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(thisCallMethodSig)); thisCallSiteSetupStream.Emit(ILOpcode.br, lProcessReturn); MethodSignature staticCallMethodSig = new MethodSignature(MethodSignatureFlags.Static, 0, returnType, targetMethodSignature); staticCallSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(staticCallMethodSig)); returnCodeStream.EmitLabel(lProcessReturn); ILCodeLabel lByRefReturnNull = null; if (returnKind == DynamicInvokeMethodParameterKind.None) { returnCodeStream.Emit(ILOpcode.ldnull); } else { TypeDesc returnTypeForBoxing = returnType; if (returnType.IsByRef) { // If this is a byref return, we need to dereference first returnTypeForBoxing = ((ByRefType)returnType).ParameterType; lByRefReturnNull = emitter.NewCodeLabel(); returnCodeStream.Emit(ILOpcode.dup); returnCodeStream.Emit(ILOpcode.brfalse, lByRefReturnNull); returnCodeStream.EmitLdInd(returnTypeForBoxing); } if (returnTypeForBoxing.IsPointer) { // Pointers box differently returnCodeStream.Emit(ILOpcode.ldtoken, emitter.NewToken(returnTypeForBoxing)); MethodDesc getTypeFromHandleMethod = Context.SystemModule.GetKnownType("System", "Type").GetKnownMethod("GetTypeFromHandle", null); returnCodeStream.Emit(ILOpcode.call, emitter.NewToken(getTypeFromHandleMethod)); MethodDesc pointerBoxMethod = Context.SystemModule.GetKnownType("System.Reflection", "Pointer").GetKnownMethod("Box", null); returnCodeStream.Emit(ILOpcode.call, emitter.NewToken(pointerBoxMethod)); } else { ILToken tokReturnType = emitter.NewToken(returnTypeForBoxing); returnCodeStream.Emit(ILOpcode.box, tokReturnType); } } returnCodeStream.Emit(ILOpcode.ret); if (lByRefReturnNull != null) { returnCodeStream.EmitLabel(lByRefReturnNull); MethodDesc nullReferencedExceptionHelper = Context.GetHelperEntryPoint("ThrowHelpers", "ThrowInvokeNullRefReturned"); returnCodeStream.EmitCallThrowHelper(emitter, nullReferencedExceptionHelper); } return(emitter.Link(this)); }
public override MethodIL EmitIL() { ILEmitter emitter = new ILEmitter(); ILCodeStream argSetupStream = emitter.NewCodeStream(); ILCodeStream thisCallSiteSetupStream = emitter.NewCodeStream(); ILCodeStream staticCallSiteSetupStream = emitter.NewCodeStream(); // This function will look like // // !For each parameter to the method // !if (parameter is In Parameter) // localX is TypeOfParameterX& // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperIn(RuntimeTypeHandle) // stloc localX // !else // localX is TypeOfParameter // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperRef(RuntimeTypeHandle) // stloc localX // ldarg.2 // call DynamicInvokeArgSetupComplete(ref ArgSetupState) // *** Thiscall instruction stream starts here *** // ldarg.3 // Load targetIsThisCall // brfalse Not_this_call // ldarg.0 // Load this pointer // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType thiscall(TypeOfParameter1, ...) // !if ((ReturnType == void) // ldnull // !elif (ReturnType is pointer) // System.Reflection.Pointer.Box(ReturnType) // !else // box ReturnType // ret // *** Static call instruction stream starts here *** // Not_this_call: // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType (TypeOfParameter1, ...) // !if ((ReturnType == void) // ldnull // !elif (ReturnType is pointer) // System.Reflection.Pointer.Box(ReturnType) // !else // box ReturnType // ret ILCodeLabel lStaticCall = emitter.NewCodeLabel(); thisCallSiteSetupStream.EmitLdArg(3); // targetIsThisCall thisCallSiteSetupStream.Emit(ILOpcode.brfalse, lStaticCall); staticCallSiteSetupStream.EmitLabel(lStaticCall); thisCallSiteSetupStream.EmitLdArg(0); // thisPtr ILToken tokDynamicInvokeParamHelperRef = emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperRef", null)); ILToken tokDynamicInvokeParamHelperIn = emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperIn", null)); TypeDesc[] targetMethodSignature = new TypeDesc[_targetSignature.Length]; for (int paramIndex = 0; paramIndex < _targetSignature.Length; paramIndex++) { TypeDesc paramType = Context.GetSignatureVariable(paramIndex, true); DynamicInvokeMethodParameterKind paramKind = _targetSignature[paramIndex]; if (paramKind == DynamicInvokeMethodParameterKind.Pointer) { for (int i = 0; i < _targetSignature.GetNumberOfParameterPointerIndirections(paramIndex); i++) { paramType = paramType.MakePointerType(); } } ILToken tokParamType = emitter.NewToken(paramType); ILLocalVariable local = emitter.NewLocal(paramType.MakeByRefType()); thisCallSiteSetupStream.EmitLdLoc(local); staticCallSiteSetupStream.EmitLdLoc(local); argSetupStream.Emit(ILOpcode.ldtoken, tokParamType); if (paramKind == DynamicInvokeMethodParameterKind.Reference) { argSetupStream.Emit(ILOpcode.call, tokDynamicInvokeParamHelperRef); targetMethodSignature[paramIndex] = paramType.MakeByRefType(); } else { argSetupStream.Emit(ILOpcode.call, tokDynamicInvokeParamHelperIn); thisCallSiteSetupStream.Emit(ILOpcode.ldobj, tokParamType); staticCallSiteSetupStream.Emit(ILOpcode.ldobj, tokParamType); targetMethodSignature[paramIndex] = paramType; } argSetupStream.EmitStLoc(local); } argSetupStream.EmitLdArg(2); // argSetupState argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeArgSetupComplete", null))); thisCallSiteSetupStream.EmitLdArg(1); // methodToCall staticCallSiteSetupStream.EmitLdArg(1); // methodToCall DynamicInvokeMethodParameterKind returnKind = _targetSignature.ReturnType; TypeDesc returnType = returnKind != DynamicInvokeMethodParameterKind.None ? Context.GetSignatureVariable(_targetSignature.Length, true) : Context.GetWellKnownType(WellKnownType.Void); if (returnKind == DynamicInvokeMethodParameterKind.Pointer) { for (int i = 0; i < _targetSignature.GetNumerOfReturnTypePointerIndirections(); i++) { returnType = returnType.MakePointerType(); } } MethodSignature thisCallMethodSig = new MethodSignature(0, 0, returnType, targetMethodSignature); thisCallSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(thisCallMethodSig)); MethodSignature staticCallMethodSig = new MethodSignature(MethodSignatureFlags.Static, 0, returnType, targetMethodSignature); staticCallSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(staticCallMethodSig)); if (returnKind == DynamicInvokeMethodParameterKind.None) { thisCallSiteSetupStream.Emit(ILOpcode.ldnull); staticCallSiteSetupStream.Emit(ILOpcode.ldnull); } else if (returnKind == DynamicInvokeMethodParameterKind.Pointer) { thisCallSiteSetupStream.Emit(ILOpcode.ldtoken, emitter.NewToken(returnType)); staticCallSiteSetupStream.Emit(ILOpcode.ldtoken, emitter.NewToken(returnType)); MethodDesc getTypeFromHandleMethod = Context.SystemModule.GetKnownType("System", "Type").GetKnownMethod("GetTypeFromHandle", null); thisCallSiteSetupStream.Emit(ILOpcode.call, emitter.NewToken(getTypeFromHandleMethod)); staticCallSiteSetupStream.Emit(ILOpcode.call, emitter.NewToken(getTypeFromHandleMethod)); MethodDesc pointerBoxMethod = Context.SystemModule.GetKnownType("System.Reflection", "Pointer").GetKnownMethod("Box", null); thisCallSiteSetupStream.Emit(ILOpcode.call, emitter.NewToken(pointerBoxMethod)); staticCallSiteSetupStream.Emit(ILOpcode.call, emitter.NewToken(pointerBoxMethod)); } else { Debug.Assert(returnKind == DynamicInvokeMethodParameterKind.Value); ILToken tokReturnType = emitter.NewToken(returnType); thisCallSiteSetupStream.Emit(ILOpcode.box, tokReturnType); staticCallSiteSetupStream.Emit(ILOpcode.box, tokReturnType); } thisCallSiteSetupStream.Emit(ILOpcode.ret); staticCallSiteSetupStream.Emit(ILOpcode.ret); return(emitter.Link(this)); }
public override MethodIL EmitIL() { ILEmitter emitter = new ILEmitter(); ILCodeStream argSetupStream = emitter.NewCodeStream(); ILCodeStream thisCallSiteSetupStream = emitter.NewCodeStream(); ILCodeStream staticCallSiteSetupStream = emitter.NewCodeStream(); // This function will look like // // !For each parameter to the method // !if (parameter is In Parameter) // localX is TypeOfParameterX& // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperIn(RuntimeTypeHandle) // stloc localX // !else // localX is TypeOfParameter // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperRef(RuntimeTypeHandle) // stloc localX // ldarg.2 // call DynamicInvokeArgSetupComplete(ref ArgSetupState) // *** Thiscall instruction stream starts here *** // ldarg.3 // Load targetIsThisCall // brfalse Not_this_call // ldarg.0 // Load this pointer // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType thiscall(TypeOfParameter1, ...) // !if ((ReturnType == void) // ldnull // !else // box ReturnType // ret // *** Static call instruction stream starts here *** // Not_this_call: // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType (TypeOfParameter1, ...) // !if ((ReturnType == void) // ldnull // !else // box ReturnType // ret ILCodeLabel lStaticCall = emitter.NewCodeLabel(); thisCallSiteSetupStream.EmitLdArg(3); // targetIsThisCall thisCallSiteSetupStream.Emit(ILOpcode.brfalse, lStaticCall); staticCallSiteSetupStream.EmitLabel(lStaticCall); thisCallSiteSetupStream.EmitLdArg(0); // thisPtr ILToken tokDynamicInvokeParamHelperRef = emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperRef", null)); ILToken tokDynamicInvokeParamHelperIn = emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperIn", null)); TypeDesc[] targetMethodSignature = new TypeDesc[_targetSignature.Length]; for (int paramIndex = 0; paramIndex < _targetSignature.Length; paramIndex++) { TypeDesc paramType = Context.GetSignatureVariable(paramIndex, true); ILToken tokParamType = emitter.NewToken(paramType); ILLocalVariable local = emitter.NewLocal(paramType.MakeByRefType()); thisCallSiteSetupStream.EmitLdLoc(local); staticCallSiteSetupStream.EmitLdLoc(local); argSetupStream.Emit(ILOpcode.ldtoken, tokParamType); if (_targetSignature[paramIndex] == DynamicInvokeMethodParameterKind.Reference) { argSetupStream.Emit(ILOpcode.call, tokDynamicInvokeParamHelperRef); targetMethodSignature[paramIndex] = paramType.MakeByRefType(); } else { argSetupStream.Emit(ILOpcode.call, tokDynamicInvokeParamHelperIn); thisCallSiteSetupStream.Emit(ILOpcode.ldobj, tokParamType); staticCallSiteSetupStream.Emit(ILOpcode.ldobj, tokParamType); targetMethodSignature[paramIndex] = paramType; } argSetupStream.EmitStLoc(local); } argSetupStream.EmitLdArg(2); // argSetupState argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeArgSetupComplete", null))); thisCallSiteSetupStream.EmitLdArg(1); // methodToCall staticCallSiteSetupStream.EmitLdArg(1); // methodToCall TypeDesc returnType = _targetSignature.HasReturnValue ? Context.GetSignatureVariable(_targetSignature.Length, true) : Context.GetWellKnownType(WellKnownType.Void); MethodSignature thisCallMethodSig = new MethodSignature(0, 0, returnType, targetMethodSignature); CalliIntrinsic.EmitTransformedCalli(emitter, thisCallSiteSetupStream, thisCallMethodSig); //thisCallSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(thisCallMethodSig)); MethodSignature staticCallMethodSig = new MethodSignature(MethodSignatureFlags.Static, 0, returnType, targetMethodSignature); CalliIntrinsic.EmitTransformedCalli(emitter, staticCallSiteSetupStream, staticCallMethodSig); //staticCallSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(staticCallMethodSig)); if (_targetSignature.HasReturnValue) { ILToken tokReturnType = emitter.NewToken(returnType); thisCallSiteSetupStream.Emit(ILOpcode.box, tokReturnType); staticCallSiteSetupStream.Emit(ILOpcode.box, tokReturnType); } else { thisCallSiteSetupStream.Emit(ILOpcode.ldnull); staticCallSiteSetupStream.Emit(ILOpcode.ldnull); } thisCallSiteSetupStream.Emit(ILOpcode.ret); staticCallSiteSetupStream.Emit(ILOpcode.ret); return(emitter.Link(this)); }