Ejemplo n.º 1
0
        public bool Equals(DynamicInvokeMethodSignature other)
        {
            DynamicInvokeMethodParameterKind thisReturnKind = ReturnType;

            if (thisReturnKind != other.ReturnType)
            {
                return(false);
            }

            if (GetNumerOfReturnTypePointerIndirections() != other.GetNumerOfReturnTypePointerIndirections())
            {
                return(false);
            }

            if (Length != other.Length)
            {
                return(false);
            }

            for (int i = 0; i < Length; i++)
            {
                DynamicInvokeMethodParameterKind thisParamKind = this[i];
                if (thisParamKind != other[i])
                {
                    return(false);
                }

                if (GetNumberOfParameterPointerIndirections(i) != other.GetNumberOfParameterPointerIndirections(i))
                {
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 2
0
        private int CompareTo(DynamicInvokeMethodThunk otherMethod)
        {
            int result = _targetSignature.Length - otherMethod._targetSignature.Length;

            if (result != 0)
            {
                return(result);
            }

            DynamicInvokeMethodParameterKind thisReturnType = _targetSignature.ReturnType;

            result = (int)thisReturnType - (int)otherMethod._targetSignature.ReturnType;
            if (result != 0)
            {
                return(result);
            }

            if (thisReturnType == DynamicInvokeMethodParameterKind.Pointer)
            {
                result = _targetSignature.GetNumerOfReturnTypePointerIndirections() - otherMethod._targetSignature.GetNumerOfReturnTypePointerIndirections();
                if (result != 0)
                {
                    return(result);
                }
            }

            for (int i = 0; i < _targetSignature.Length; i++)
            {
                DynamicInvokeMethodParameterKind thisParamType = _targetSignature[i];
                result = (int)thisParamType - (int)otherMethod._targetSignature[i];
                if (result != 0)
                {
                    return(result);
                }

                if (thisParamType == DynamicInvokeMethodParameterKind.Pointer)
                {
                    result = _targetSignature.GetNumberOfParameterPointerIndirections(i) - otherMethod._targetSignature.GetNumberOfParameterPointerIndirections(i);
                    if (result != 0)
                    {
                        return(result);
                    }
                }
            }

            Debug.Assert(this == otherMethod);
            return(0);
        }
Ejemplo n.º 3
0
        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));
        }
Ejemplo n.º 4
0
        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));
        }