Ejemplo n.º 1
0
        public static MethodIL EmitIL(MethodDesc method)
        {
            ILEmitter    emit       = new ILEmitter();
            ILCodeStream codeStream = emit.NewCodeStream();
            MethodDesc   typeLoadExceptionHelper = method.Context.GetHelperEntryPoint("ThrowHelpers", "ThrowTypeLoadException");

            codeStream.EmitCallThrowHelper(emit, typeLoadExceptionHelper);
            return(emit.Link());
        }
Ejemplo n.º 2
0
        public override MethodIL EmitIL()
        {
            var          emitter    = new ILEmitter();
            ILCodeStream codeStream = emitter.NewCodeStream();

            MetadataType throwHelpersType = Context.SystemModule.GetKnownType("Internal.Runtime.CompilerHelpers", "ThrowHelpers");
            MethodDesc   throwHelper      = throwHelpersType.GetKnownMethod("ThrowNotSupportedException", null);

            codeStream.EmitCallThrowHelper(emitter, throwHelper);

            return(emitter.Link(this));
        }
Ejemplo n.º 3
0
        public static MethodIL EmitIL(MethodDesc method)
        {
            Debug.Assert(method.OwningType.IsDelegate);
            Debug.Assert(method.IsRuntimeImplemented);

            if (method.Name == "BeginInvoke" || method.Name == "EndInvoke")
            {
                // BeginInvoke and EndInvoke are not supported on .NET Core
                ILEmitter    emit       = new ILEmitter();
                ILCodeStream codeStream = emit.NewCodeStream();
                MethodDesc   notSupportedExceptionHelper = method.Context.GetHelperEntryPoint("ThrowHelpers", "ThrowPlatformNotSupportedException");
                codeStream.EmitCallThrowHelper(emit, notSupportedExceptionHelper);
                return(emit.Link(method));
            }

            if (method.Name == ".ctor")
            {
                TypeSystemContext context = method.Context;

                ILEmitter emit = new ILEmitter();

                TypeDesc   delegateType         = context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType;
                MethodDesc objectCtorMethod     = context.GetWellKnownType(WellKnownType.Object).GetDefaultConstructor();
                FieldDesc  functionPointerField = delegateType.GetKnownField("m_functionPointer");
                FieldDesc  firstParameterField  = delegateType.GetKnownField("m_firstParameter");

                ILCodeStream codeStream = emit.NewCodeStream();
                codeStream.EmitLdArg(0);
                codeStream.Emit(ILOpcode.call, emit.NewToken(objectCtorMethod));
                codeStream.EmitLdArg(0);
                codeStream.EmitLdArg(1);
                codeStream.Emit(ILOpcode.stfld, emit.NewToken(firstParameterField));
                codeStream.EmitLdArg(0);
                codeStream.EmitLdArg(2);
                codeStream.Emit(ILOpcode.stfld, emit.NewToken(functionPointerField));
                codeStream.Emit(ILOpcode.ret);

                return(emit.Link(method));
            }

            return(null);
        }
Ejemplo n.º 4
0
        public static MethodIL EmitIL(MethodDesc method)
        {
            Debug.Assert(method.OwningType.IsDelegate);
            Debug.Assert(method.IsRuntimeImplemented);

            if (method.Name == "BeginInvoke" || method.Name == "EndInvoke")
            {
                // BeginInvoke and EndInvoke are not supported on .NET Core
                ILEmitter    emit       = new ILEmitter();
                ILCodeStream codeStream = emit.NewCodeStream();
                MethodDesc   notSupportedExceptionHelper = method.Context.GetHelperEntryPoint("ThrowHelpers", "ThrowPlatformNotSupportedException");
                codeStream.EmitCallThrowHelper(emit, notSupportedExceptionHelper);
                return(emit.Link(method));
            }

            if (method.Name == ".ctor")
            {
                // TODO: this should be an assert that codegen never asks for this.
                // This is just a workaround for https://github.com/dotnet/corert/issues/2102
                // The code below is making a wild guess that we're creating a closed
                // instance delegate. Without shared generics, this should only happen
                // for virtual method (so we're fine there). With shared generics, this can
                // happen for anything and might be pretty wrong.
                TypeSystemContext context = method.Context;

                ILEmitter    emit             = new ILEmitter();
                TypeDesc     delegateType     = context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType;
                MethodDesc   initializeMethod = delegateType.GetKnownMethod("InitializeClosedInstanceSlow", null);
                ILCodeStream codeStream       = emit.NewCodeStream();

                codeStream.EmitLdArg(0);
                codeStream.EmitLdArg(1);
                codeStream.EmitLdArg(2);
                codeStream.Emit(ILOpcode.call, emit.NewToken(initializeMethod));
                codeStream.Emit(ILOpcode.ret);

                return(emit.Link(method));
            }

            return(null);
        }
Ejemplo n.º 5
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));
        }
        public static MethodIL EmitIL(MethodDesc method)
        {
            Debug.Assert(method.OwningType.IsDelegate);
            Debug.Assert(method.OwningType.IsTypeDefinition);
            Debug.Assert(method.IsRuntimeImplemented);

            if (method.Name == "BeginInvoke" || method.Name == "EndInvoke")
            {
                // BeginInvoke and EndInvoke are not supported on .NET Core
                ILEmitter    emit       = new ILEmitter();
                ILCodeStream codeStream = emit.NewCodeStream();
                MethodDesc   notSupportedExceptionHelper = method.Context.GetHelperEntryPoint("ThrowHelpers", "ThrowPlatformNotSupportedException");
                codeStream.EmitCallThrowHelper(emit, notSupportedExceptionHelper);
                return(emit.Link(method));
            }

            if (method.Name == ".ctor")
            {
                // We only support delegate creation if the IL follows the delegate creation verifiability requirements
                // described in ECMA-335 III.4.21 (newobj - create a new object). The codegen is expected to
                // intrinsically expand the pattern.
                // If the delegate creation doesn't follow the pattern, we generate code that throws at runtime.
                // We could potentially implement this (unreliably) through the use of reflection metadata,
                // but it remains to be proven that this is an actual customer scenario.
                ILEmitter    emit       = new ILEmitter();
                ILCodeStream codeStream = emit.NewCodeStream();
                MethodDesc   notSupportedExceptionHelper = method.Context.GetHelperEntryPoint("ThrowHelpers", "ThrowPlatformNotSupportedException");
                codeStream.EmitCallThrowHelper(emit, notSupportedExceptionHelper);
                return(emit.Link(method));
            }

            if (method.Name == "Invoke")
            {
                TypeSystemContext context = method.Context;

                ILEmitter    emit                 = new ILEmitter();
                TypeDesc     delegateType         = context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType;
                FieldDesc    firstParameterField  = delegateType.GetKnownField("m_firstParameter");
                FieldDesc    functionPointerField = delegateType.GetKnownField("m_functionPointer");
                ILCodeStream codeStream           = emit.NewCodeStream();

                codeStream.EmitLdArg(0);
                codeStream.Emit(ILOpcode.ldfld, emit.NewToken(firstParameterField.InstantiateAsOpen()));
                for (int i = 0; i < method.Signature.Length; i++)
                {
                    codeStream.EmitLdArg(i + 1);
                }
                codeStream.EmitLdArg(0);
                codeStream.Emit(ILOpcode.ldfld, emit.NewToken(functionPointerField.InstantiateAsOpen()));

                MethodSignature signature = method.Signature;
                if (method.OwningType.HasInstantiation)
                {
                    // If the owning type is generic, the signature will contain T's and U's.
                    // We need !0's and !1's.
                    TypeDesc[] typesToReplace   = new TypeDesc[method.OwningType.Instantiation.Length];
                    TypeDesc[] replacementTypes = new TypeDesc[typesToReplace.Length];
                    for (int i = 0; i < typesToReplace.Length; i++)
                    {
                        typesToReplace[i]   = method.OwningType.Instantiation[i];
                        replacementTypes[i] = context.GetSignatureVariable(i, method: false);
                    }
                    TypeDesc[] parameters = new TypeDesc[method.Signature.Length];
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        parameters[i] = method.Signature[i].ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
                    }
                    TypeDesc returnType = method.Signature.ReturnType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
                    signature = new MethodSignature(signature.Flags, signature.GenericParameterCount, returnType, parameters);
                }

                codeStream.Emit(ILOpcode.calli, emit.NewToken(signature));

                codeStream.Emit(ILOpcode.ret);

                return(emit.Link(method));
            }

            return(null);
        }
Ejemplo n.º 7
0
        public static MethodIL EmitIL(MethodDesc method)
        {
            Debug.Assert(method.OwningType.IsDelegate);
            Debug.Assert(method.OwningType.IsTypeDefinition);
            Debug.Assert(method.IsRuntimeImplemented);

            if (method.Name == "BeginInvoke" || method.Name == "EndInvoke")
            {
                // BeginInvoke and EndInvoke are not supported on .NET Core
                ILEmitter    emit       = new ILEmitter();
                ILCodeStream codeStream = emit.NewCodeStream();
                MethodDesc   notSupportedExceptionHelper = method.Context.GetHelperEntryPoint("ThrowHelpers", "ThrowPlatformNotSupportedException");
                codeStream.EmitCallThrowHelper(emit, notSupportedExceptionHelper);
                return(emit.Link(method));
            }

            if (method.Name == ".ctor")
            {
                // TODO: this should be an assert that codegen never asks for this.
                // This is just a workaround for https://github.com/dotnet/corert/issues/2102
                // The code below is making a wild guess that we're creating a closed
                // instance delegate. Without shared generics, this should only happen
                // for virtual method (so we're fine there). With shared generics, this can
                // happen for anything and might be pretty wrong.
                TypeSystemContext context = method.Context;

                ILEmitter    emit             = new ILEmitter();
                TypeDesc     delegateType     = context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType;
                MethodDesc   initializeMethod = delegateType.GetKnownMethod("InitializeClosedInstanceSlow", null);
                ILCodeStream codeStream       = emit.NewCodeStream();

                codeStream.EmitLdArg(0);
                codeStream.EmitLdArg(1);
                codeStream.EmitLdArg(2);
                codeStream.Emit(ILOpcode.call, emit.NewToken(initializeMethod));
                codeStream.Emit(ILOpcode.ret);

                return(emit.Link(method));
            }

            if (method.Name == "Invoke")
            {
                TypeSystemContext context = method.Context;

                ILEmitter    emit                 = new ILEmitter();
                TypeDesc     delegateType         = context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType;
                FieldDesc    firstParameterField  = delegateType.GetKnownField("m_firstParameter");
                FieldDesc    functionPointerField = delegateType.GetKnownField("m_functionPointer");
                ILCodeStream codeStream           = emit.NewCodeStream();

                codeStream.EmitLdArg(0);
                codeStream.Emit(ILOpcode.ldfld, emit.NewToken(firstParameterField.InstantiateAsOpen()));
                for (int i = 0; i < method.Signature.Length; i++)
                {
                    codeStream.EmitLdArg(i + 1);
                }
                codeStream.EmitLdArg(0);
                codeStream.Emit(ILOpcode.ldfld, emit.NewToken(functionPointerField.InstantiateAsOpen()));

                MethodSignature signature = method.Signature;
                if (method.OwningType.HasInstantiation)
                {
                    // If the owning type is generic, the signature will contain T's and U's.
                    // We need !0's and !1's.
                    TypeDesc[] typesToReplace   = new TypeDesc[method.OwningType.Instantiation.Length];
                    TypeDesc[] replacementTypes = new TypeDesc[typesToReplace.Length];
                    for (int i = 0; i < typesToReplace.Length; i++)
                    {
                        typesToReplace[i]   = method.OwningType.Instantiation[i];
                        replacementTypes[i] = context.GetSignatureVariable(i, method: false);
                    }
                    TypeDesc[] parameters = new TypeDesc[method.Signature.Length];
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        parameters[i] = method.Signature[i].ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
                    }
                    TypeDesc returnType = method.Signature.ReturnType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes);
                    signature = new MethodSignature(signature.Flags, signature.GenericParameterCount, returnType, parameters);
                }

                codeStream.Emit(ILOpcode.calli, emit.NewToken(signature));

                codeStream.Emit(ILOpcode.ret);

                return(emit.Link(method));
            }

            return(null);
        }