public override MethodIL EmitIL() { var emitter = new ILEmitter(); ILCodeStream codeStream = emitter.NewCodeStream(); // Load the stored 'this' codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(HelperObjectField)); // Load all arguments except 'this' for (int i = 0; i < Signature.Length; i++) { codeStream.EmitLdArg(i + 1); } // Indirectly call the delegate target codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(ExtraFunctionPointerOrDataField)); CalliIntrinsic.EmitTransformedCalli(emitter, codeStream, Signature); //codeStream.Emit(ILOpcode.calli, emitter.NewToken(Signature)); codeStream.Emit(ILOpcode.ret); return(emitter.Link(this)); }
public override MethodIL EmitIL() { // Target has the same signature as the Invoke method, except it's static. MethodSignatureBuilder builder = new MethodSignatureBuilder(Signature); builder.Flags = Signature.Flags | MethodSignatureFlags.Static; var emitter = new ILEmitter(); ILCodeStream codeStream = emitter.NewCodeStream(); // Load all arguments except 'this' for (int i = 0; i < Signature.Length; i++) { codeStream.EmitLdArg(i + 1); } // Indirectly call the delegate target static method. codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(ExtraFunctionPointerOrDataField)); CalliIntrinsic.EmitTransformedCalli(emitter, codeStream, builder.ToSignature()); //codeStream.Emit(ILOpcode.calli, emitter.NewToken(builder.ToSignature())); codeStream.Emit(ILOpcode.ret); return(emitter.Link(this)); }
public override MethodIL EmitIL() { TypeDesc[] targetMethodParameters = new TypeDesc[Signature.Length + 1]; targetMethodParameters[0] = Context.GetWellKnownType(WellKnownType.Object); for (int i = 0; i < Signature.Length; i++) { targetMethodParameters[i + 1] = Signature[i]; } var targetMethodSignature = new MethodSignature( Signature.Flags | MethodSignatureFlags.Static, 0, Signature.ReturnType, targetMethodParameters); var emitter = new ILEmitter(); ILCodeStream codeStream = emitter.NewCodeStream(); // Load the stored 'this' codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(HelperObjectField)); // Load all arguments except 'this' for (int i = 0; i < Signature.Length; i++) { codeStream.EmitLdArg(i + 1); } // Indirectly call the delegate target static method. codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(ExtraFunctionPointerOrDataField)); CalliIntrinsic.EmitTransformedCalli(emitter, codeStream, targetMethodSignature); //codeStream.Emit(ILOpcode.calli, emitter.NewToken(targetMethodSignature)); codeStream.Emit(ILOpcode.ret); return(emitter.Link(this)); }
public override MethodIL EmitIL() { ILEmitter emitter = new ILEmitter(); ILCodeStream codeStream = emitter.NewCodeStream(); ArrayType invocationListArrayType = SystemDelegateType.MakeArrayType(); ILLocalVariable delegateArrayLocal = emitter.NewLocal(invocationListArrayType); ILLocalVariable invocationCountLocal = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32)); ILLocalVariable iteratorLocal = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32)); ILLocalVariable delegateToCallLocal = emitter.NewLocal(SystemDelegateType); ILLocalVariable returnValueLocal = 0; if (!Signature.ReturnType.IsVoid) { returnValueLocal = emitter.NewLocal(Signature.ReturnType); } // Fill in delegateArrayLocal // Delegate[] delegateArrayLocal = (Delegate[])this.m_helperObject // ldarg.0 (this pointer) // ldfld Delegate.HelperObjectField // castclass Delegate[] // stloc delegateArrayLocal codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(HelperObjectField)); codeStream.Emit(ILOpcode.castclass, emitter.NewToken(invocationListArrayType)); codeStream.EmitStLoc(delegateArrayLocal); // Fill in invocationCountLocal // int invocationCountLocal = this.m_extraFunctionPointerOrData // ldarg.0 (this pointer) // ldfld Delegate.m_extraFunctionPointerOrData // stloc invocationCountLocal codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(ExtraFunctionPointerOrDataField)); codeStream.EmitStLoc(invocationCountLocal); // Fill in iteratorLocal // int iteratorLocal = 0; // ldc.0 // stloc iteratorLocal codeStream.EmitLdc(0); codeStream.EmitStLoc(iteratorLocal); // Loop across every element of the array. ILCodeLabel startOfLoopLabel = emitter.NewCodeLabel(); codeStream.EmitLabel(startOfLoopLabel); // Implement as do/while loop. We only have this stub in play if we're in the multicast situation // Find the delegate to call // Delegate = delegateToCallLocal = delegateArrayLocal[iteratorLocal]; // ldloc delegateArrayLocal // ldloc iteratorLocal // ldelem System.Delegate // stloc delegateToCallLocal codeStream.EmitLdLoc(delegateArrayLocal); codeStream.EmitLdLoc(iteratorLocal); codeStream.Emit(ILOpcode.ldelem, emitter.NewToken(SystemDelegateType)); codeStream.EmitStLoc(delegateToCallLocal); // Call the delegate // returnValueLocal = delegateToCallLocal(...); // ldloc delegateToCallLocal // ldfld System.Delegate.m_firstParameter // ldarg 1, n // ldloc delegateToCallLocal // ldfld System.Delegate.m_functionPointer // calli returnValueType thiscall (all the params) // IF there is a return value // stloc returnValueLocal codeStream.EmitLdLoc(delegateToCallLocal); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(FirstParameterField)); for (int i = 0; i < Signature.Length; i++) { codeStream.EmitLdArg(i + 1); } codeStream.EmitLdLoc(delegateToCallLocal); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(FunctionPointerField)); CalliIntrinsic.EmitTransformedCalli(emitter, codeStream, Signature); //codeStream.Emit(ILOpcode.calli, emitter.NewToken(Signature)); if (returnValueLocal != 0) { codeStream.EmitStLoc(returnValueLocal); } // Increment iteratorLocal // ++iteratorLocal; // ldloc iteratorLocal // ldc.i4.1 // add // stloc iteratorLocal codeStream.EmitLdLoc(iteratorLocal); codeStream.EmitLdc(1); codeStream.Emit(ILOpcode.add); codeStream.EmitStLoc(iteratorLocal); // Check to see if the loop is done codeStream.EmitLdLoc(invocationCountLocal); codeStream.EmitLdLoc(iteratorLocal); codeStream.Emit(ILOpcode.bne_un, startOfLoopLabel); // Return to caller. If the delegate has a return value, be certain to return that. // return returnValueLocal; // ldloc returnValueLocal // ret if (returnValueLocal != 0) { codeStream.EmitLdLoc(returnValueLocal); } codeStream.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)); }