Ejemplo n.º 1
0
        public override MethodIL EmitIL()
        {
            ILEmitter emitter = new ILEmitter();
            ILCodeStream codeStream = emitter.NewCodeStream();

            MetadataType startup = Context.GetHelperType("StartupCodeHelpers");

            // Initialize command line args
            string initArgsName = (Context.Target.OperatingSystem == TargetOS.Windows)
                                ? "InitializeCommandLineArgsW"
                                : "InitializeCommandLineArgs";
            MethodDesc initArgs = startup.GetKnownMethod(initArgsName, null);
            codeStream.Emit(ILOpcode.ldarg_0); // argc
            codeStream.Emit(ILOpcode.ldarg_1); // argv
            codeStream.Emit(ILOpcode.call, emitter.NewToken(initArgs));

            // Call program Main
            if (_mainMethod.Signature.Length > 0)
            {
                codeStream.Emit(ILOpcode.call, emitter.NewToken(startup.GetKnownMethod("GetMainMethodArguments", null)));
            }
            codeStream.Emit(ILOpcode.call, emitter.NewToken(_mainMethod));
            if (_mainMethod.Signature.ReturnType.IsVoid)
            {
                codeStream.EmitLdc(0);
            }

            codeStream.Emit(ILOpcode.ret);

            return emitter.Link(this);
        }
Ejemplo n.º 2
0
        public static MethodIL EmitIL(MethodDesc target)
        {
            Debug.Assert(target.Name == "EETypePtrOf");
            Debug.Assert(target.Signature.Length == 0
                && target.Signature.ReturnType == target.OwningType);
            Debug.Assert(target.Instantiation.Length == 1);

            ILEmitter emitter = new ILEmitter();
            var codeStream = emitter.NewCodeStream();

            TypeSystemContext context = target.Context;
            TypeDesc runtimeTypeHandleType = context.GetWellKnownType(WellKnownType.RuntimeTypeHandle);
            MethodDesc getValueInternalMethod = runtimeTypeHandleType.GetKnownMethod("GetValueInternal", null);
            MethodDesc eetypePtrCtorMethod = context.SystemModule
                .GetKnownType("System", "EETypePtr")
                .GetKnownMethod(".ctor", new MethodSignature(0, 0, context.GetWellKnownType(WellKnownType.Void),
                new TypeDesc[] { context.GetWellKnownType(WellKnownType.IntPtr) }));

            // The sequence of these instructions is important. JIT is able to optimize out
            // the LDTOKEN+GetValueInternal call into "load EEType pointer onto the evaluation stack".
            codeStream.Emit(ILOpcode.ldtoken, emitter.NewToken(context.GetSignatureVariable(0, true)));
            codeStream.Emit(ILOpcode.call, emitter.NewToken(getValueInternalMethod));
            codeStream.Emit(ILOpcode.newobj, emitter.NewToken(eetypePtrCtorMethod));
            codeStream.Emit(ILOpcode.ret);

            return emitter.Link(target);
        }
Ejemplo n.º 3
0
        public static MethodIL EmitIL(MethodDesc target)
        {
            Debug.Assert(target.Name == "Call");
            Debug.Assert(target.Signature.Length > 0
                && target.Signature[0] == target.Context.GetWellKnownType(WellKnownType.IntPtr));

            ILEmitter emitter = new ILEmitter();
            var codeStream = emitter.NewCodeStream();

            // Load all the arguments except the first one (IntPtr address)
            for (int i = 1; i < target.Signature.Length; i++)
            {
                codeStream.EmitLdArg(i);
            }

            // now load IntPtr address
            codeStream.EmitLdArg(0);

            // Create a signature for the calli by copying the signature of the containing method
            // while skipping the first argument
            MethodSignature template = target.Signature;
            TypeDesc returnType = template.ReturnType;
            TypeDesc[] parameters = new TypeDesc[template.Length - 1];
            for (int i = 1; i < template.Length; i++)
            {
                parameters[i - 1] = template[i];
            }

            var signature = new MethodSignature(template.Flags, 0, returnType, parameters);

            codeStream.Emit(ILOpcode.calli, emitter.NewToken(signature));
            codeStream.Emit(ILOpcode.ret);

            return emitter.Link();
        }
Ejemplo n.º 4
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.º 5
0
        public static MethodIL EmitIL(MethodDesc target)
        {
            Debug.Assert(target.Name == "Call");
            Debug.Assert(target.Signature.Length > 0
                && target.Signature[0] == target.Context.GetWellKnownType(WellKnownType.IntPtr));

            ILEmitter emitter = new ILEmitter();
            var codeStream = emitter.NewCodeStream();

            // Load all the arguments except the first one (IntPtr address)
            for (int i = 1; i < target.Signature.Length; i++)
            {
                codeStream.EmitLdArg(i);
            }

            // now load IntPtr address
            codeStream.EmitLdArg(0);

            // Create a signature for the calli by copying the signature of the containing method
            // while skipping the first argument
            MethodSignature template = target.Signature;
            TypeDesc returnType = template.ReturnType;
            TypeDesc[] parameters = new TypeDesc[template.Length - 1];
            for (int i = 1; i < template.Length; i++)
            {
                parameters[i - 1] = template[i];
            }

            var signature = new MethodSignature(template.Flags, 0, returnType, parameters);

            bool useTransformedCalli = true;

            if ((signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask) != 0)
            {
                // Fat function pointer only ever exist for managed targets.
                useTransformedCalli = false;
            }

            if (((MetadataType)target.OwningType).Name == "RawCalliHelper")
            {
                // RawCalliHelper doesn't need the transform.
                useTransformedCalli = false;
            }

            if (useTransformedCalli)
                EmitTransformedCalli(emitter, codeStream, signature);
            else
                codeStream.Emit(ILOpcode.calli, emitter.NewToken(signature));
            
            codeStream.Emit(ILOpcode.ret);

            return emitter.Link(target);
        }
Ejemplo n.º 6
0
        private static MethodIL EmitSizeOf(MethodDesc method)
        {
            Debug.Assert(method.Signature.IsStatic && method.Signature.Length == 0);

            TypeSystemContext context = method.Context;

            ILEmitter emit = new ILEmitter();
            ILCodeStream codeStream = emit.NewCodeStream();
            codeStream.Emit(ILOpcode.sizeof_, emit.NewToken(context.GetSignatureVariable(0, method: true)));
            codeStream.Emit(ILOpcode.ret);
            return emit.Link(method);
        }
Ejemplo n.º 7
0
        public override MethodIL EmitIL()
        {
            ILEmitter emitter = new ILEmitter();

            var codeStream = emitter.NewCodeStream();

            for (int i = 0; i < Signature.Length; i++)
            {
                codeStream.EmitLdArg(i + 1);
            }

            codeStream.Emit(ILOpcode.call, emitter.NewToken(_target));
            codeStream.Emit(ILOpcode.ret);

            return emitter.Link();
        }
Ejemplo n.º 8
0
        public override MethodIL EmitIL()
        {
            ILEmitter emitter = new ILEmitter();
            ILCodeStream codeStream = emitter.NewCodeStream();

            ModuleDesc developerExperience = Context.ResolveAssembly(new AssemblyName("System.Private.DeveloperExperience.Console"), false);
            if (developerExperience != null)
            {
                TypeDesc connectorType = developerExperience.GetKnownType("Internal.DeveloperExperience", "DeveloperExperienceConnectorConsole");
                MethodDesc initializeMethod = connectorType.GetKnownMethod("Initialize", null);
                codeStream.Emit(ILOpcode.call, emitter.NewToken(initializeMethod));
            }

            MetadataType startup = Context.GetHelperType("StartupCodeHelpers");

            // Initialize command line args if the class library supports this
            string initArgsName = (Context.Target.OperatingSystem == TargetOS.Windows)
                                ? "InitializeCommandLineArgsW"
                                : "InitializeCommandLineArgs";
            MethodDesc initArgs = startup.GetMethod(initArgsName, null);
            if (initArgs != null)
            {
                codeStream.Emit(ILOpcode.ldarg_0); // argc
                codeStream.Emit(ILOpcode.ldarg_1); // argv
                codeStream.Emit(ILOpcode.call, emitter.NewToken(initArgs));
            }

            // Call program Main
            if (_mainMethod.Signature.Length > 0)
            {
                // TODO: better exception
                if (initArgs == null)
                    throw new Exception("Main() has parameters, but the class library doesn't support them");

                codeStream.Emit(ILOpcode.call, emitter.NewToken(startup.GetKnownMethod("GetMainMethodArguments", null)));
            }
            codeStream.Emit(ILOpcode.call, emitter.NewToken(_mainMethod));
            if (_mainMethod.Signature.ReturnType.IsVoid)
            {
                codeStream.EmitLdc(0);
            }

            codeStream.Emit(ILOpcode.ret);

            return emitter.Link(this);
        }
Ejemplo n.º 9
0
        public static MethodIL EmitIL(MethodDesc target)
        {
            Debug.Assert(target.Name == "AddrOf");
            Debug.Assert(target.Signature.Length == 1
                && target.Signature.ReturnType == target.Context.GetWellKnownType(WellKnownType.IntPtr));

            ILEmitter emitter = new ILEmitter();
            var codeStream = emitter.NewCodeStream();

            codeStream.EmitLdArg(0);

            var fptrField = target.Context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType.GetKnownField("m_extraFunctionPointerOrData");
            codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(fptrField));

            codeStream.Emit(ILOpcode.ret);

            return emitter.Link();
        }
Ejemplo n.º 10
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.º 11
0
        public static MethodIL EmitIL(MethodDesc target)
        {
            Debug.Assert(target.Name == "CompareExchange" || target.Name == "Exchange");

            //
            // Find non-generic method to forward the generic method to.
            //

            int parameterCount = target.Signature.Length;
            Debug.Assert(parameterCount == 3 || parameterCount == 2);

            var objectType = target.Context.GetWellKnownType(WellKnownType.Object);

            var parameters = new TypeDesc[parameterCount];
            parameters[0] = objectType.MakeByRefType();
            for (int i = 1; i < parameters.Length; i++)
                parameters[i] = objectType;

            MethodSignature nonGenericSignature = new MethodSignature(MethodSignatureFlags.Static, 0, objectType, parameters);

            MethodDesc nonGenericMethod = target.OwningType.GetMethod(target.Name, nonGenericSignature);

            // TODO: Better exception type. Should be: "CoreLib doesn't have a required thing in it".
            if (nonGenericMethod == null)
                throw new NotImplementedException();

            //
            // Emit the forwarder
            //

            ILEmitter emitter = new ILEmitter();
            var codeStream = emitter.NewCodeStream();

            // Reload all arguments
            for (int i = 0; i < parameterCount; i++)
                codeStream.EmitLdArg(i);

            codeStream.Emit(ILOpcode.call, emitter.NewToken(nonGenericMethod));
            codeStream.Emit(ILOpcode.ret);

            return emitter.Link();
        }
Ejemplo n.º 12
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.º 13
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.º 14
0
        public static MethodIL EmitIL(MethodDesc target)
        {
            Debug.Assert(target.Name == "CreateInstanceIntrinsic");
            Debug.Assert(target.Instantiation.Length == 1);

            ILEmitter emitter    = new ILEmitter();
            var       codeStream = emitter.NewCodeStream();

            // TODO: This won't work for shared generics
            // https://github.com/dotnet/corert/issues/368

            TypeDesc   type       = target.Instantiation[0];
            MethodDesc ctorMethod = type.GetDefaultConstructor();

            if (ctorMethod == null)
            {
                if (type.IsValueType)
                {
                    var loc = emitter.NewLocal(type);
                    codeStream.EmitLdLoca(loc);
                    codeStream.Emit(ILOpcode.initobj, emitter.NewToken(type));
                    codeStream.EmitLdLoc(loc);
                }
                else
                {
                    var missingCtor = type.Context.SystemModule.GetKnownType("System", "Activator").
                                      GetNestedType("ClassWithMissingConstructor").GetDefaultConstructor();

                    codeStream.Emit(ILOpcode.newobj, emitter.NewToken(missingCtor));
                }
            }
            else
            {
                codeStream.Emit(ILOpcode.newobj, emitter.NewToken(ctorMethod));
            }

            codeStream.Emit(ILOpcode.ret);

            return(emitter.Link(target));
        }
Ejemplo n.º 15
0
        public static MethodIL EmitIL(MethodDesc target)
        {
            Debug.Assert(target.Name == "CreateInstanceIntrinsic");
            Debug.Assert(target.Instantiation.Length == 1);

            ILEmitter emitter = new ILEmitter();
            var codeStream = emitter.NewCodeStream();

            // TODO: This won't work for shared generics
            // https://github.com/dotnet/corert/issues/368

            TypeDesc type = target.Instantiation[0];
            MethodDesc ctorMethod = type.GetDefaultConstructor();

            if (ctorMethod == null)
            {
                if (type.IsValueType)
                {
                    var loc = emitter.NewLocal(type);
                    codeStream.EmitLdLoca(loc);
                    codeStream.Emit(ILOpcode.initobj, emitter.NewToken(type));
                    codeStream.EmitLdLoc(loc);
                }
                else
                {
                    var missingCtor = type.Context.SystemModule.GetKnownType("System", "Activator").
                        GetNestedType("ClassWithMissingConstructor").GetDefaultConstructor();

                    codeStream.Emit(ILOpcode.newobj, emitter.NewToken(missingCtor));
                }
            }
            else
            {
                codeStream.Emit(ILOpcode.newobj, emitter.NewToken(ctorMethod));
            }

            codeStream.Emit(ILOpcode.ret);

            return emitter.Link(target);
        }
Ejemplo n.º 16
0
        public override MethodIL EmitIL()
        {
            ILEmitter emitter = new ILEmitter();
            ILCodeStream codeStream = emitter.NewCodeStream();
            ILLocalVariable returnValue = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32));

            TypeDesc startup = Context.SystemModule.GetType("Internal.Runtime.CompilerHelpers", "StartupCodeHelpers");
            
            codeStream.Emit(ILOpcode.call, emitter.NewToken(startup.GetMethod("Initialize", null)));

            // Initialize command line args
            // TODO: For Windows change to "InitializeCommandLineArgsW" with wmain wchar_t change.
            string initArgsName = (Context.Target.OperatingSystem == TargetOS.Windows)
                                ? "InitializeCommandLineArgs"
                                : "InitializeCommandLineArgs";
            MethodDesc initArgs = startup.GetMethod(initArgsName, null);
            codeStream.Emit(ILOpcode.ldarg_0); // argc
            codeStream.Emit(ILOpcode.ldarg_1); // argv
            codeStream.Emit(ILOpcode.call, emitter.NewToken(initArgs));

            // Call program Main
            if (_mainMethod.Signature.Length > 0)
            {
                TypeDesc environ = Context.SystemModule.GetType("System", "Environment");
                codeStream.Emit(ILOpcode.call, emitter.NewToken(environ.GetMethod("GetCommandLineArgs", null)));
            }
            codeStream.Emit(ILOpcode.call, emitter.NewToken(_mainMethod));
            if (_mainMethod.Signature.ReturnType.IsVoid)
            {
                codeStream.EmitLdc(0);
            }
            codeStream.EmitStLoc(returnValue);

            codeStream.Emit(ILOpcode.call, emitter.NewToken(startup.GetMethod("Shutdown", null)));

            codeStream.EmitLdLoc(returnValue);
            codeStream.Emit(ILOpcode.ret);

            return emitter.Link();
        }
        public override MethodIL EmitIL()
        {
            ILEmitter    emitter    = new ILEmitter();
            ILCodeStream codeStream = emitter.NewCodeStream();

            // InstantiateAsOpen covers the weird case of generic enums
            TypeDesc owningTypeAsOpen = _owningType.InstantiateAsOpen();

            ILCodeLabel lNotEqual = emitter.NewCodeLabel();

            // if (!(obj is {enumtype}))
            //     return false;

            codeStream.EmitLdArg(1);
            codeStream.Emit(ILOpcode.isinst, emitter.NewToken(owningTypeAsOpen));
            codeStream.Emit(ILOpcode.dup);
            codeStream.Emit(ILOpcode.brfalse, lNotEqual);

            // return ({underlyingtype})this == ({underlyingtype})obj;

            // PREFER: ILOpcode.unbox, but the codegen for that is pretty bad
            codeStream.Emit(ILOpcode.ldflda, emitter.NewToken(Context.GetWellKnownType(WellKnownType.Object).GetKnownField("m_pEEType")));
            codeStream.EmitLdc(Context.Target.PointerSize);
            codeStream.Emit(ILOpcode.add);
            codeStream.EmitLdInd(owningTypeAsOpen);

            codeStream.EmitLdArg(0);
            codeStream.EmitLdInd(owningTypeAsOpen);

            codeStream.Emit(ILOpcode.ceq);

            codeStream.Emit(ILOpcode.ret);

            codeStream.EmitLabel(lNotEqual);
            codeStream.Emit(ILOpcode.pop);
            codeStream.EmitLdc(0);
            codeStream.Emit(ILOpcode.ret);

            return(emitter.Link(this));
        }
Ejemplo n.º 18
0
        public static MethodIL EmitIL(
#if READYTORUN
            ILCompiler.CompilationModuleGroup compilationModuleGroup,
#endif // READYTORUN
            MethodDesc method)
        {
            Debug.Assert(((MetadataType)method.OwningType).Name == "Interlocked");

            if (method.HasInstantiation && method.Name == "CompareExchange")
            {
#if READYTORUN
                // Check to see if the tokens needed to describe the CompareExchange are naturally present within
                // the compilation. The current implementation of stable tokens used by cross module inlining is not
                // compatible with rewriting the IL of a compiler generated intrinsic. Fortunately, it turns out
                // that the managed implementation of this intrinsic is correct, just a few more IL instructions.
                if (compilationModuleGroup.ContainsType(method.OwningType))
#endif // READYTORUN
                {
                    TypeDesc   objectType            = method.Context.GetWellKnownType(WellKnownType.Object);
                    MethodDesc compareExchangeObject = method.OwningType.GetKnownMethod("CompareExchange",
                                                                                        new MethodSignature(
                                                                                            MethodSignatureFlags.Static,
                                                                                            genericParameterCount: 0,
                                                                                            returnType: objectType,
                                                                                            parameters: new TypeDesc[] { objectType.MakeByRefType(), objectType, objectType }));

                    ILEmitter    emit       = new ILEmitter();
                    ILCodeStream codeStream = emit.NewCodeStream();
                    codeStream.EmitLdArg(0);
                    codeStream.EmitLdArg(1);
                    codeStream.EmitLdArg(2);
                    codeStream.Emit(ILOpcode.call, emit.NewToken(compareExchangeObject));
                    codeStream.Emit(ILOpcode.ret);
                    return(emit.Link(method));
                }
            }

            return(null);
        }
Ejemplo n.º 19
0
        public override MethodIL EmitIL()
        {
            ILEmitter    emit       = new ILEmitter();
            ILCodeStream codeStream = emit.NewCodeStream();

            Debug.Assert(Signature[0] == _helperMethod.Signature[0]);
            codeStream.EmitLdArg(0);

            Debug.Assert(_helperMethod.Signature[1].IsString);
            codeStream.Emit(ILOpcode.ldstr, emit.NewToken(DefaultAssemblyName));

            for (int i = 2; i < _helperMethod.Signature.Length; i++)
            {
                // The helper method could be expecting more arguments than what we have - check for that
                // The thunk represents one of the 6 possible overloads:
                // (String), (String, bool), (String, bool, bool)
                // (String, Func<...>, Func<...>), (String, Func<...>, Func<...>, bool), (String, Func<...>, Func<...>, bool, bool)
                // We only need 2 helpers to support all 6 overloads. The default value for the bools is false.

                if (i - 1 < Signature.Length)
                {
                    // Pass user's parameter
                    Debug.Assert(_helperMethod.Signature[i] == Signature[i - 1]);
                    codeStream.EmitLdArg(i - 1);
                }
                else
                {
                    // Pass a default value
                    Debug.Assert(_helperMethod.Signature[i].IsWellKnownType(WellKnownType.Boolean));
                    codeStream.EmitLdc(0);
                }
            }

            codeStream.Emit(ILOpcode.call, emit.NewToken(_helperMethod));
            codeStream.Emit(ILOpcode.ret);

            return(emit.Link(this));
        }
Ejemplo n.º 20
0
        public static MethodIL EmitIL(MethodDesc method)
        {
            Debug.Assert(((MetadataType)method.OwningType).Name == "MemoryMarshal");
            string methodName = method.Name;

            if (method.Instantiation.Length != 1)
            {
                return(null); // we only handle the generic method GetArrayDataReference<T>(T[])
            }

            if (methodName == "GetArrayDataReference")
            {
                ILEmitter    emit       = new ILEmitter();
                ILCodeStream codeStream = emit.NewCodeStream();
                codeStream.EmitLdArg(0);
                codeStream.Emit(ILOpcode.ldflda, emit.NewToken(method.Context.SystemModule.GetKnownType("System.Runtime.CompilerServices", "RawArrayData").GetField("Data")));
                codeStream.Emit(ILOpcode.ret);
                return(emit.Link(method));
            }

            // unknown method
            return(null);
        }
Ejemplo n.º 21
0
        private static MethodIL EmitReadWrite(MethodDesc method, bool write, bool unaligned = false)
        {
            Debug.Assert(method.Signature.IsStatic && method.Signature.Length == (write ? 2 : 1));

            TypeSystemContext context = method.Context;

            ILEmitter    emit       = new ILEmitter();
            ILCodeStream codeStream = emit.NewCodeStream();

            codeStream.EmitLdArg(0);
            if (write)
            {
                codeStream.EmitLdArg(1);
            }
            if (unaligned)
            {
                codeStream.EmitUnaligned();
            }
            codeStream.Emit(write ? ILOpcode.stobj : ILOpcode.ldobj,
                            emit.NewToken(context.GetSignatureVariable(0, method: true)));
            codeStream.Emit(ILOpcode.ret);
            return(emit.Link(method));
        }
Ejemplo n.º 22
0
        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));

            EmitTransformedCalli(emitter, codeStream, targetMethodSignature);
            //codeStream.Emit(ILOpcode.calli, emitter.NewToken(targetMethodSignature));

            codeStream.Emit(ILOpcode.ret);

            return(emitter.Link(this));
        }
Ejemplo n.º 23
0
        public static MethodIL EmitIL(MethodDesc target)
        {
            Debug.Assert(target.Name == "Call");
            Debug.Assert(target.Signature.Length > 0 &&
                         target.Signature[0] == target.Context.GetWellKnownType(WellKnownType.IntPtr));

            ILEmitter emitter    = new ILEmitter();
            var       codeStream = emitter.NewCodeStream();

            // Load all the arguments except the first one (IntPtr address)
            for (int i = 1; i < target.Signature.Length; i++)
            {
                codeStream.EmitLdArg(i);
            }

            // now load IntPtr address
            codeStream.EmitLdArg(0);

            // Create a signature for the calli by copying the signature of the containing method
            // while skipping the first argument
            MethodSignature template   = target.Signature;
            TypeDesc        returnType = template.ReturnType;

            TypeDesc[] parameters = new TypeDesc[template.Length - 1];
            for (int i = 1; i < template.Length; i++)
            {
                parameters[i - 1] = template[i];
            }

            var signature = new MethodSignature(template.Flags, 0, returnType, parameters);

            codeStream.Emit(ILOpcode.calli, emitter.NewToken(signature));
            codeStream.Emit(ILOpcode.ret);

            return(emitter.Link(target));
        }
Ejemplo n.º 24
0
        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));
            codeStream.Emit(ILOpcode.calli, emitter.NewToken(builder.ToSignature()));
            codeStream.Emit(ILOpcode.ret);

            return(emitter.Link(this));
        }
Ejemplo n.º 25
0
        public static MethodIL EmitIL(MethodDesc target)
        {
            Debug.Assert(target.Name == "AddrOf");
            Debug.Assert(target.Signature.Length == 1
                && target.Signature.ReturnType == target.Context.GetWellKnownType(WellKnownType.IntPtr));

            ILEmitter emitter = new ILEmitter();
            var codeStream = emitter.NewCodeStream();

            codeStream.EmitLdArg(0);

            var fptrField = target.Context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType.GetField("m_extraFunctionPointerOrData");
            if (fptrField == null)
            {
                // TODO: Better exception type. Should be: "CoreLib doesn't have a required thing in it".
                throw new NotImplementedException();
            }

            codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(fptrField));

            codeStream.Emit(ILOpcode.ret);

            return emitter.Link();
        }
Ejemplo n.º 26
0
        public MethodIL EmitIL()
        {
            MethodSignature targetMethodSignature = _targetMethod.Signature;

            // We have 4 code streams:
            // - _marshallingCodeStream is used to convert each argument into a native type and 
            // store that into the local
            // - callsiteSetupCodeStream is used to used to load each previously generated local
            // and call the actual target native method.
            // - _returnValueMarshallingCodeStream is used to convert the native return value 
            // to managed one.
            // - _unmarshallingCodestream is used to propagate [out] native arguments values to 
            // managed ones.
            _emitter = new ILEmitter();
            ILCodeStream fnptrLoadStream = _emitter.NewCodeStream();
            _marshallingCodeStream = _emitter.NewCodeStream();
            ILCodeStream callsiteSetupCodeStream = _emitter.NewCodeStream();
            _returnValueMarshallingCodeStream = _emitter.NewCodeStream();
            _unmarshallingCodestream = _emitter.NewCodeStream();

            TypeDesc[] nativeParameterTypes = new TypeDesc[targetMethodSignature.Length];

            //
            // Parameter marshalling
            //

            //
            // Convert each argument to something we can pass to native and store it in a local.
            // Then load the local in the second code stream.
            //
            for (int i = 0; i < targetMethodSignature.Length; i++)
            {
                // TODO: throw if there's custom marshalling

                _marshallingCodeStream.EmitLdArg(i);

                TypeDesc nativeType = MarshalArgument(targetMethodSignature[i]);

                nativeParameterTypes[i] = nativeType;

                ILLocalVariable vMarshalledTypeTemp = _emitter.NewLocal(nativeType);
                _marshallingCodeStream.EmitStLoc(vMarshalledTypeTemp);

                callsiteSetupCodeStream.EmitLdLoc(vMarshalledTypeTemp);
            }

            //
            // Return value marshalling
            //

            // TODO: throw if SetLastError is true
            // TODO: throw if there's custom marshalling

            TypeDesc nativeReturnType = MarshalReturnValue(targetMethodSignature.ReturnType);

            if (UseLazyResolution(_targetMethod, _importMetadata.Module))
            {
                MetadataType lazyHelperType = _targetMethod.Context.GetHelperType("InteropHelpers");
                FieldDesc lazyDispatchCell = new PInvokeLazyFixupField((DefType)_targetMethod.OwningType, _importMetadata);
                fnptrLoadStream.Emit(ILOpcode.ldsflda, _emitter.NewToken(lazyDispatchCell));
                fnptrLoadStream.Emit(ILOpcode.call, _emitter.NewToken(lazyHelperType.GetKnownMethod("ResolvePInvoke", null)));

                MethodSignatureFlags unmanagedCallConv = PInvokeMetadata.GetUnmanagedCallingConvention(_importMetadata.Attributes);

                MethodSignature nativeCalliSig = new MethodSignature(
                    targetMethodSignature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes);

                ILLocalVariable vNativeFunctionPointer = _emitter.NewLocal(_targetMethod.Context.GetWellKnownType(WellKnownType.IntPtr));
                fnptrLoadStream.EmitStLoc(vNativeFunctionPointer);
                callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer);
                callsiteSetupCodeStream.Emit(ILOpcode.calli, _emitter.NewToken(nativeCalliSig));
            }
            else
            {
                // Eager call
                PInvokeMetadata nativeImportMetadata =
                    new PInvokeMetadata(_importMetadata.Module, _importMetadata.Name ?? _targetMethod.Name, _importMetadata.Attributes);

                MethodSignature nativeSig = new MethodSignature(
                    targetMethodSignature.Flags, 0, nativeReturnType, nativeParameterTypes);

                MethodDesc nativeMethod =
                    new PInvokeTargetNativeMethod(_targetMethod.OwningType, nativeSig, nativeImportMetadata);

                callsiteSetupCodeStream.Emit(ILOpcode.call, _emitter.NewToken(nativeMethod));
            }
            
            _unmarshallingCodestream.Emit(ILOpcode.ret);

            return _emitter.Link(_targetMethod);
        }
        public static MethodIL EmitIL(MethodDesc methodThatShouldThrow, TypeSystemException exception)
        {
            TypeSystemContext context = methodThatShouldThrow.Context;

            MethodDesc helper;

            Type exceptionType = exception.GetType();

            if (exceptionType == typeof(TypeSystemException.TypeLoadException))
            {
                //
                // There are two ThrowTypeLoadException helpers. Find the one which matches the number of
                // arguments "exception" was initialized with.
                //
                helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowTypeLoadException");

                if (helper.Signature.Length != exception.Arguments.Count + 1)
                {
                    helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowTypeLoadExceptionWithArgument");
                }
            }
            else if (exceptionType == typeof(TypeSystemException.MissingFieldException))
            {
                helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowMissingFieldException");
            }
            else if (exceptionType == typeof(TypeSystemException.MissingMethodException))
            {
                helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowMissingMethodException");
            }
            else if (exceptionType == typeof(TypeSystemException.FileNotFoundException))
            {
                helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowFileNotFoundException");
            }
            else if (exceptionType == typeof(TypeSystemException.InvalidProgramException))
            {
                //
                // There are two ThrowInvalidProgramException helpers. Find the one which matches the number of
                // arguments "exception" was initialized with.
                //

                helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowInvalidProgramException");

                if (helper.Signature.Length != exception.Arguments.Count + 1)
                {
                    helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowInvalidProgramExceptionWithArgument");
                }
            }
            else if (exceptionType == typeof(TypeSystemException.BadImageFormatException))
            {
                helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowBadImageFormatException");
            }
            else
            {
                throw new NotImplementedException();
            }

            Debug.Assert(helper.Signature.Length == exception.Arguments.Count + 1);

            var emitter    = new ILEmitter();
            var codeStream = emitter.NewCodeStream();

            var infinityLabel = emitter.NewCodeLabel();

            codeStream.EmitLabel(infinityLabel);

            codeStream.EmitLdc((int)exception.StringID);

            foreach (var arg in exception.Arguments)
            {
                codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(arg));
            }

            codeStream.Emit(ILOpcode.call, emitter.NewToken(helper));

            // The call will never return, but we still need to emit something. Emit a jump so that
            // we don't have to bother balancing the stack if the method returns something.
            codeStream.Emit(ILOpcode.br, infinityLabel);

            return(emitter.Link(methodThatShouldThrow));
        }
Ejemplo n.º 28
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.º 29
0
        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);
        }
Ejemplo n.º 30
0
        public override MethodIL EmitIL()
        {
            const DelegateThunkKind maxThunkKind = DelegateThunkKind.ObjectArrayThunk;

            ILEmitter emitter = new ILEmitter();

            var codeStream = emitter.NewCodeStream();

            ILCodeLabel returnNullLabel = emitter.NewCodeLabel();

            ILCodeLabel[] labels = new ILCodeLabel[(int)maxThunkKind];
            for (DelegateThunkKind i = 0; i < maxThunkKind; i++)
            {
                MethodDesc thunk = _delegateInfo.Thunks[i];
                if (thunk != null)
                    labels[(int)i] = emitter.NewCodeLabel();
                else
                    labels[(int)i] = returnNullLabel;
            }

            codeStream.EmitLdArg(1);
            codeStream.EmitSwitch(labels);

            codeStream.Emit(ILOpcode.br, returnNullLabel);

            for (DelegateThunkKind i = 0; i < maxThunkKind; i++)
            {
                MethodDesc thunk = _delegateInfo.Thunks[i];
                if (thunk != null)
                {
                    codeStream.EmitLabel(labels[(int)i]);

                    codeStream.Emit(ILOpcode.ldftn, emitter.NewToken(thunk.InstantiateAsOpen()));
                    codeStream.Emit(ILOpcode.ret);
                }
            }

            codeStream.EmitLabel(returnNullLabel);
            codeStream.EmitLdc(0);
            codeStream.Emit(ILOpcode.conv_i);
            codeStream.Emit(ILOpcode.ret);

            return emitter.Link(this);
        }
Ejemplo n.º 31
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);
        }
Ejemplo n.º 32
0
        public static MethodIL EmitIL(MethodDesc methodThatShouldThrow, TypeSystemException exception)
        {
            TypeSystemContext context = methodThatShouldThrow.Context;

            MethodDesc helper;

            Type exceptionType = exception.GetType();
            if (exceptionType == typeof(TypeSystemException.TypeLoadException))
            {
                //
                // There are two ThrowTypeLoadException helpers. Find the one which matches the number of
                // arguments "exception" was initialized with.
                //
                helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowTypeLoadException");

                if (helper.Signature.Length != exception.Arguments.Count + 1)
                {
                    helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowTypeLoadExceptionWithArgument");
                }
            }
            else if (exceptionType == typeof(TypeSystemException.MissingFieldException))
            {
                helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowMissingFieldException");
            }
            else if (exceptionType == typeof(TypeSystemException.MissingMethodException))
            {
                helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowMissingMethodException");
            }
            else if (exceptionType == typeof(TypeSystemException.FileNotFoundException))
            {
                helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowFileNotFoundException");
            }
            else if (exceptionType == typeof(TypeSystemException.InvalidProgramException))
            {
                helper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowInvalidProgramException");
            }
            else
            {
                throw new NotImplementedException();
            }

            Debug.Assert(helper.Signature.Length == exception.Arguments.Count + 1);

            var emitter = new ILEmitter();
            var codeStream = emitter.NewCodeStream();

            var infinityLabel = emitter.NewCodeLabel();
            codeStream.EmitLabel(infinityLabel);

            codeStream.EmitLdc((int)exception.StringID);

            foreach (var arg in exception.Arguments)
            {
                codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(arg));
            }

            codeStream.Emit(ILOpcode.call, emitter.NewToken(helper));

            // The call will never return, but we still need to emit something. Emit a jump so that
            // we don't have to bother balancing the stack if the method returns something.
            codeStream.Emit(ILOpcode.br, infinityLabel);

            return emitter.Link(methodThatShouldThrow);
        }
Ejemplo n.º 33
0
        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));
            codeStream.Emit(ILOpcode.calli, emitter.NewToken(targetMethodSignature));
            codeStream.Emit(ILOpcode.ret);

            return emitter.Link(this);
        }
Ejemplo n.º 34
0
        public static MethodIL EmitIL(MethodDesc method)
        {
            Debug.Assert(((MetadataType)method.OwningType).Name == "RuntimeHelpers");
            string methodName = method.Name;

            if (methodName == "GetRawSzArrayData")
            {
                ILEmitter    emit       = new ILEmitter();
                ILCodeStream codeStream = emit.NewCodeStream();
                codeStream.EmitLdArg(0);
                codeStream.Emit(ILOpcode.ldflda, emit.NewToken(method.Context.SystemModule.GetKnownType("System.Runtime.CompilerServices", "RawArrayData").GetField("Data")));
                codeStream.Emit(ILOpcode.ret);
                return(emit.Link(method));
            }

            // All the methods handled below are per-instantiation generic methods
            if (method.Instantiation.Length != 1 || method.IsTypicalMethodDefinition)
            {
                return(null);
            }

            TypeDesc elementType = method.Instantiation[0];

            // Fallback to non-intrinsic implementation for universal generics
            if (elementType.IsCanonicalSubtype(CanonicalFormKind.Universal))
            {
                return(null);
            }

            bool result;

            if (methodName == "IsReferenceOrContainsReferences")
            {
                result = elementType.IsGCPointer || (elementType is DefType defType && defType.ContainsGCPointers);
            }
            else if (methodName == "IsReference")
            {
                result = elementType.IsGCPointer;
            }
            else if (methodName == "IsBitwiseEquatable")
            {
                // Ideally we could detect automatically whether a type is trivially equatable
                // (i.e., its operator == could be implemented via memcmp). But for now we'll
                // do the simple thing and hardcode the list of types we know fulfill this contract.
                // n.b. This doesn't imply that the type's CompareTo method can be memcmp-implemented,
                // as a method like CompareTo may need to take a type's signedness into account.
                switch (elementType.UnderlyingType.Category)
                {
                case TypeFlags.Boolean:
                case TypeFlags.Byte:
                case TypeFlags.SByte:
                case TypeFlags.Char:
                case TypeFlags.UInt16:
                case TypeFlags.Int16:
                case TypeFlags.UInt32:
                case TypeFlags.Int32:
                case TypeFlags.UInt64:
                case TypeFlags.Int64:
                case TypeFlags.IntPtr:
                case TypeFlags.UIntPtr:
                    result = true;
                    break;

                default:
                    var mdType = elementType as MetadataType;
                    if (mdType != null && mdType.Name == "Rune" && mdType.Namespace == "System.Text")
                    {
                        result = true;
                    }
                    else if (mdType != null && mdType.Name == "Char8" && mdType.Namespace == "System")
                    {
                        result = true;
                    }
                    else
                    {
                        result = false;
                    }
                    break;
                }
            }
            else
            {
                return(null);
            }

            ILOpcode opcode = result ? ILOpcode.ldc_i4_1 : ILOpcode.ldc_i4_0;

            return(new ILStubMethodIL(method, new byte[] { (byte)opcode, (byte)ILOpcode.ret }, Array.Empty <LocalVariableDefinition>(), Array.Empty <object>()));
        }
Ejemplo n.º 35
0
        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);
        }
Ejemplo n.º 36
0
        public MethodIL EmitIL()
        {
            MethodSignature targetMethodSignature = _targetMethod.Signature;

            // We have two code streams - one is used to convert each argument into a native type
            // and store that into the local. The other is used to load each previously generated local
            // and call the actual target native method.
            _emitter = new ILEmitter();
            _marshallingCodeStream = _emitter.NewCodeStream();
            ILCodeStream callsiteSetupCodeStream = _emitter.NewCodeStream();
            _returnValueMarshallingCodeStream = _emitter.NewCodeStream();

            TypeDesc[] nativeParameterTypes = new TypeDesc[targetMethodSignature.Length];

            //
            // Parameter marshalling
            //

            //
            // Convert each argument to something we can pass to native and store it in a local.
            // Then load the local in the second code stream.
            //
            for (int i = 0; i < targetMethodSignature.Length; i++)
            {
                // TODO: throw if there's custom marshalling
                TypeDesc parameterType = targetMethodSignature[i];

                _marshallingCodeStream.EmitLdArg(i);

                TypeDesc nativeType;
                if (parameterType.IsSzArray)
                {
                    nativeType = EmitArrayMarshalling((ArrayType)parameterType);
                }
                else if (parameterType.IsByRef)
                {
                    nativeType = EmitByRefMarshalling((ByRefType)parameterType);
                }
                else if (parameterType.IsString)
                {
                    nativeType = EmitStringMarshalling();
                }
                else if (parameterType.Category == TypeFlags.Boolean)
                {
                    nativeType = EmitBooleanMarshalling();
                }
                else
                {
                    if (!IsBlittableType(parameterType))
                        throw new NotSupportedException();

                    nativeType = parameterType.UnderlyingType;
                }

                nativeParameterTypes[i] = nativeType;

                ILLocalVariable vMarshalledTypeTemp = _emitter.NewLocal(nativeType);
                _marshallingCodeStream.EmitStLoc(vMarshalledTypeTemp);

                callsiteSetupCodeStream.EmitLdLoc(vMarshalledTypeTemp);
            }

            //
            // Return value marshalling
            //

            // TODO: throw if SetLastError is true
            // TODO: throw if there's custom marshalling
            TypeDesc returnType = targetMethodSignature.ReturnType;

            TypeDesc nativeReturnType;
            if (returnType.IsVoid)
            {
                nativeReturnType = returnType;
            }
            else if (returnType.Category == TypeFlags.Boolean)
            {
                nativeReturnType = EmitBooleanReturnValueMarshalling();
            }
            else
            {
                if (!IsBlittableType(returnType))
                    throw new NotSupportedException();

                nativeReturnType = returnType;
            }

            MethodSignature nativeSig = new MethodSignature(
                targetMethodSignature.Flags, 0, nativeReturnType, nativeParameterTypes);
            MethodDesc nativeMethod =
                new PInvokeTargetNativeMethod(_targetMethod.OwningType, nativeSig, _importMetadata);

            // Call the native method
            callsiteSetupCodeStream.Emit(ILOpcode.call, _emitter.NewToken(nativeMethod));
            callsiteSetupCodeStream.Emit(ILOpcode.ret);

            return _emitter.Link();
        }
Ejemplo n.º 37
0
        public MethodIL EmitIL()
        {
            MethodSignature targetMethodSignature = _targetMethod.Signature;

            // We have 4 code streams:
            // - _marshallingCodeStream is used to convert each argument into a native type and
            // store that into the local
            // - callsiteSetupCodeStream is used to used to load each previously generated local
            // and call the actual target native method.
            // - _returnValueMarshallingCodeStream is used to convert the native return value
            // to managed one.
            // - _unmarshallingCodestream is used to propagate [out] native arguments values to
            // managed ones.
            _emitter = new ILEmitter();
            ILCodeStream fnptrLoadStream = _emitter.NewCodeStream();

            _marshallingCodeStream = _emitter.NewCodeStream();
            ILCodeStream callsiteSetupCodeStream = _emitter.NewCodeStream();

            _returnValueMarshallingCodeStream = _emitter.NewCodeStream();
            _unmarshallingCodestream          = _emitter.NewCodeStream();

            TypeDesc[] nativeParameterTypes = new TypeDesc[targetMethodSignature.Length];

            //
            // Parameter marshalling
            //

            //
            // Convert each argument to something we can pass to native and store it in a local.
            // Then load the local in the second code stream.
            //
            for (int i = 0; i < targetMethodSignature.Length; i++)
            {
                // TODO: throw if there's custom marshalling

                _marshallingCodeStream.EmitLdArg(i);

                TypeDesc nativeType = MarshalArgument(targetMethodSignature[i]);

                nativeParameterTypes[i] = nativeType;

                ILLocalVariable vMarshalledTypeTemp = _emitter.NewLocal(nativeType);
                _marshallingCodeStream.EmitStLoc(vMarshalledTypeTemp);

                callsiteSetupCodeStream.EmitLdLoc(vMarshalledTypeTemp);
            }

            //
            // Return value marshalling
            //

            // TODO: throw if SetLastError is true
            // TODO: throw if there's custom marshalling

            TypeDesc nativeReturnType = MarshalReturnValue(targetMethodSignature.ReturnType);

            if (UseLazyResolution(_targetMethod, _importMetadata.Module))
            {
                MetadataType lazyHelperType   = _targetMethod.Context.GetHelperType("InteropHelpers");
                FieldDesc    lazyDispatchCell = new PInvokeLazyFixupField((DefType)_targetMethod.OwningType, _importMetadata);
                fnptrLoadStream.Emit(ILOpcode.ldsflda, _emitter.NewToken(lazyDispatchCell));
                fnptrLoadStream.Emit(ILOpcode.call, _emitter.NewToken(lazyHelperType.GetKnownMethod("ResolvePInvoke", null)));

                MethodSignatureFlags unmanagedCallConv = PInvokeMetadata.GetUnmanagedCallingConvention(_importMetadata.Attributes);

                MethodSignature nativeCalliSig = new MethodSignature(
                    targetMethodSignature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes);

                ILLocalVariable vNativeFunctionPointer = _emitter.NewLocal(_targetMethod.Context.GetWellKnownType(WellKnownType.IntPtr));
                fnptrLoadStream.EmitStLoc(vNativeFunctionPointer);
                callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer);
                callsiteSetupCodeStream.Emit(ILOpcode.calli, _emitter.NewToken(nativeCalliSig));
            }
            else
            {
                // Eager call
                PInvokeMetadata nativeImportMetadata =
                    new PInvokeMetadata(_importMetadata.Module, _importMetadata.Name ?? _targetMethod.Name, _importMetadata.Attributes);

                MethodSignature nativeSig = new MethodSignature(
                    targetMethodSignature.Flags, 0, nativeReturnType, nativeParameterTypes);

                MethodDesc nativeMethod =
                    new PInvokeTargetNativeMethod(_targetMethod.OwningType, nativeSig, nativeImportMetadata);

                callsiteSetupCodeStream.Emit(ILOpcode.call, _emitter.NewToken(nativeMethod));
            }

            _unmarshallingCodestream.Emit(ILOpcode.ret);

            return(_emitter.Link(_targetMethod));
        }
Ejemplo n.º 38
0
        public override MethodIL EmitIL()
        {
            // We will generate the following code:
            //
            // object ret;
            // object[] args = new object[parameterCount];
            // args[0] = param0;
            // args[1] = param1;
            //  ...
            // try {
            //      ret = ((Func<object[], object>)dlg.m_helperObject)(args);
            // } finally {
            //      param0 = (T0)args[0];   // only generated for each byref argument
            // }
            // return (TRet)ret;

            ILEmitter    emitter    = new ILEmitter();
            ILCodeStream codeStream = emitter.NewCodeStream();

            TypeDesc objectType      = Context.GetWellKnownType(WellKnownType.Object);
            TypeDesc objectArrayType = objectType.MakeArrayType();

            ILLocalVariable argsLocal = emitter.NewLocal(objectArrayType);

            bool hasReturnValue = !Signature.ReturnType.IsVoid;

            bool hasRefArgs = false;

            if (Signature.Length > 0)
            {
                codeStream.EmitLdc(Signature.Length);
                codeStream.Emit(ILOpcode.newarr, emitter.NewToken(objectType));
                codeStream.EmitStLoc(argsLocal);

                for (int i = 0; i < Signature.Length; i++)
                {
                    TypeDesc paramType    = Signature[i];
                    bool     paramIsByRef = false;

                    if (paramType.IsByRef)
                    {
                        hasRefArgs  |= paramType.IsByRef;
                        paramIsByRef = true;
                        paramType    = ((ByRefType)paramType).ParameterType;
                    }

                    hasRefArgs |= paramType.IsByRef;

                    codeStream.EmitLdLoc(argsLocal);
                    codeStream.EmitLdc(i);
                    codeStream.EmitLdArg(i + 1);

                    TypeDesc boxableParamType  = DelegateDynamicInvokeThunk.ConvertToBoxableType(paramType);
                    ILToken  boxableParamToken = emitter.NewToken(boxableParamType);

                    if (paramIsByRef)
                    {
                        codeStream.Emit(ILOpcode.ldobj, boxableParamToken);
                    }
                    codeStream.Emit(ILOpcode.box, boxableParamToken);
                    codeStream.Emit(ILOpcode.stelem_ref);
                }
            }
            else
            {
                MethodDesc emptyObjectArrayMethod = Context.GetHelperEntryPoint("DelegateHelpers", "GetEmptyObjectArray");
                codeStream.Emit(ILOpcode.call, emitter.NewToken(emptyObjectArrayMethod));
                codeStream.EmitStLoc(argsLocal);
            }

            if (hasRefArgs)
            {
                // we emit a try/finally to update the args array even if an exception is thrown
                // ilgen.BeginTryBody();
            }

            codeStream.EmitLdArg(0);
            codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(HelperObjectField));

            MetadataType funcType         = Context.SystemModule.GetKnownType("System", "Func`2");
            TypeDesc     instantiatedFunc = funcType.MakeInstantiatedType(objectArrayType, objectType);

            codeStream.Emit(ILOpcode.castclass, emitter.NewToken(instantiatedFunc));

            codeStream.EmitLdLoc(argsLocal);

            MethodDesc invokeMethod = instantiatedFunc.GetKnownMethod("Invoke", null);

            codeStream.Emit(ILOpcode.callvirt, emitter.NewToken(invokeMethod));

            ILLocalVariable retLocal = (ILLocalVariable)(-1);

            if (hasReturnValue)
            {
                retLocal = emitter.NewLocal(objectType);
                codeStream.EmitStLoc(retLocal);
            }
            else
            {
                codeStream.Emit(ILOpcode.pop);
            }

            if (hasRefArgs)
            {
                // ILGeneratorLabel returnLabel = new ILGeneratorLabel();
                // ilgen.Emit(OperationCode.Leave, returnLabel);
                // copy back ref/out args
                //ilgen.BeginFinallyBlock();

                for (int i = 0; i < Signature.Length; i++)
                {
                    TypeDesc paramType = Signature[i];
                    if (paramType.IsByRef)
                    {
                        paramType = ((ByRefType)paramType).ParameterType;
                        TypeDesc boxableParamType  = DelegateDynamicInvokeThunk.ConvertToBoxableType(paramType);
                        ILToken  boxableParamToken = emitter.NewToken(boxableParamType);

                        // Update parameter
                        codeStream.EmitLdArg(i + 1);
                        codeStream.EmitLdLoc(argsLocal);
                        codeStream.EmitLdc(i);
                        codeStream.Emit(ILOpcode.ldelem_ref);
                        codeStream.Emit(ILOpcode.unbox_any, boxableParamToken);
                        codeStream.Emit(ILOpcode.stobj, boxableParamToken);
                    }
                }
                // ilgen.Emit(OperationCode.Endfinally);
                // ilgen.EndTryBody();
                // ilgen.MarkLabel(returnLabel);
            }

            if (hasReturnValue)
            {
                TypeDesc boxableReturnType = DelegateDynamicInvokeThunk.ConvertToBoxableType(Signature.ReturnType);
                codeStream.EmitLdLoc(retLocal);
                codeStream.Emit(ILOpcode.unbox_any, emitter.NewToken(boxableReturnType));
            }

            codeStream.Emit(ILOpcode.ret);

            return(emitter.Link(this));
        }
Ejemplo n.º 39
0
        public override MethodIL EmitIL()
        {
            ILEmitter emitter = new ILEmitter();

            var codeStream = emitter.NewCodeStream();

            ILCodeLabel returnNullLabel = emitter.NewCodeLabel();

            bool hasDynamicInvokeThunk = (_delegateInfo.SupportedFeatures & DelegateFeature.DynamicInvoke) != 0 &&
                                         DynamicInvokeMethodThunk.SupportsSignature(_delegateInfo.Signature);

            ILCodeLabel[] labels = new ILCodeLabel[(int)DelegateThunkCollection.MaxThunkKind];
            for (DelegateThunkKind i = 0; i < DelegateThunkCollection.MaxThunkKind; i++)
            {
                MethodDesc thunk = _delegateInfo.Thunks[i];
                if (thunk != null ||
                    (i == DelegateThunkKind.DelegateInvokeThunk && hasDynamicInvokeThunk))
                {
                    labels[(int)i] = emitter.NewCodeLabel();
                }
                else
                {
                    labels[(int)i] = returnNullLabel;
                }
            }

            codeStream.EmitLdArg(1);
            codeStream.EmitSwitch(labels);

            codeStream.Emit(ILOpcode.br, returnNullLabel);

            for (DelegateThunkKind i = 0; i < DelegateThunkCollection.MaxThunkKind; i++)
            {
                MethodDesc targetMethod = null;

                // Dynamic invoke thunk is special since we're calling into a shared helper
                if (i == DelegateThunkKind.DelegateInvokeThunk && hasDynamicInvokeThunk)
                {
                    Debug.Assert(_delegateInfo.Thunks[i] == null);

                    var        sig   = new DynamicInvokeMethodSignature(_delegateInfo.Signature);
                    MethodDesc thunk = Context.GetDynamicInvokeThunk(sig);

                    if (thunk.HasInstantiation)
                    {
                        TypeDesc[] inst = DynamicInvokeMethodThunk.GetThunkInstantiationForMethod(_delegateInfo.Type.InstantiateAsOpen().GetMethod("Invoke", null));
                        targetMethod = Context.GetInstantiatedMethod(thunk, new Instantiation(inst));
                    }
                    else
                    {
                        targetMethod = thunk;
                    }
                }
                else
                {
                    MethodDesc thunk = _delegateInfo.Thunks[i];

                    if (thunk != null)
                    {
                        targetMethod = thunk.InstantiateAsOpen();
                    }
                }

                if (targetMethod != null)
                {
                    codeStream.EmitLabel(labels[(int)i]);
                    codeStream.Emit(ILOpcode.ldftn, emitter.NewToken(targetMethod));
                    codeStream.Emit(ILOpcode.ret);
                }
            }

            codeStream.EmitLabel(returnNullLabel);
            codeStream.EmitLdc(0);
            codeStream.Emit(ILOpcode.conv_i);
            codeStream.Emit(ILOpcode.ret);

            return(emitter.Link(this));
        }
        public override MethodIL EmitIL()
        {
            TypeDesc owningType = _owningType.InstantiateAsOpen();

            ILEmitter emitter = new ILEmitter();

            TypeDesc   eeTypePtrType     = Context.SystemModule.GetKnownType("System", "EETypePtr");
            MethodDesc eeTypePtrOfMethod = eeTypePtrType.GetKnownMethod("EETypePtrOf", null);
            ILToken    eeTypePtrToken    = emitter.NewToken(eeTypePtrType);

            var switchStream   = emitter.NewCodeStream();
            var getFieldStream = emitter.NewCodeStream();

            ArrayBuilder <ILCodeLabel> fieldGetters = new ArrayBuilder <ILCodeLabel>();

            foreach (FieldDesc field in owningType.GetFields())
            {
                if (field.IsStatic)
                {
                    continue;
                }

                ILCodeLabel label = emitter.NewCodeLabel();
                fieldGetters.Add(label);

                getFieldStream.EmitLabel(label);
                getFieldStream.EmitLdArg(2);

                // We need something we can instantiate EETypePtrOf over. Also, the classlib
                // code doesn't handle pointers.
                TypeDesc boxableFieldType = field.FieldType;
                if (boxableFieldType.IsPointer || boxableFieldType.IsFunctionPointer)
                {
                    boxableFieldType = Context.GetWellKnownType(WellKnownType.IntPtr);
                }

                // The fact that the type is a reference type is sufficient for the callers.
                // Don't unnecessarily create an MethodTable for the field type.
                if (!boxableFieldType.IsSignatureVariable && !boxableFieldType.IsValueType)
                {
                    boxableFieldType = Context.GetWellKnownType(WellKnownType.Object);
                }

                // If this is an enum, it's okay to Equals/GetHashCode the underlying type.
                // Don't unnecessarily create an MethodTable for the enum.
                boxableFieldType = boxableFieldType.UnderlyingType;

                MethodDesc ptrOfField = eeTypePtrOfMethod.MakeInstantiatedMethod(boxableFieldType);
                getFieldStream.Emit(ILOpcode.call, emitter.NewToken(ptrOfField));

                getFieldStream.Emit(ILOpcode.stobj, eeTypePtrToken);

                getFieldStream.EmitLdArg(0);
                getFieldStream.Emit(ILOpcode.ldflda, emitter.NewToken(field));

                getFieldStream.EmitLdArg(0);

                getFieldStream.Emit(ILOpcode.sub);

                getFieldStream.Emit(ILOpcode.ret);
            }

            if (fieldGetters.Count > 0)
            {
                switchStream.EmitLdArg(1);
                switchStream.EmitSwitch(fieldGetters.ToArray());
            }

            switchStream.EmitLdc(fieldGetters.Count);

            switchStream.Emit(ILOpcode.ret);

            return(emitter.Link(this));
        }
Ejemplo n.º 41
0
        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));
            codeStream.Emit(ILOpcode.calli, emitter.NewToken(builder.ToSignature()));
            codeStream.Emit(ILOpcode.ret);

            return emitter.Link(this);
        }
Ejemplo n.º 42
0
        private void EmitILForAccessor()
        {
            Debug.Assert(_method.OwningType.IsMdArray);

            var codeStream = _emitter.NewCodeStream();
            var context    = _method.Context;

            var int32Type = context.GetWellKnownType(WellKnownType.Int32);

            var totalLocalNum  = _emitter.NewLocal(int32Type);
            var lengthLocalNum = _emitter.NewLocal(int32Type);

            int pointerSize = context.Target.PointerSize;

            int argStartOffset = _method.Kind == ArrayMethodKind.AddressWithHiddenArg ? 2 : 1;

            var         rangeExceptionLabel        = _emitter.NewCodeLabel();
            ILCodeLabel typeMismatchExceptionLabel = null;

            if (_elementType.IsGCPointer)
            {
                // Type check
                if (_method.Kind == ArrayMethodKind.Set)
                {
                    MethodDesc checkArrayStore =
                        context.SystemModule.GetKnownType("System.Runtime", "RuntimeImports").GetKnownMethod("RhCheckArrayStore", null);

                    codeStream.EmitLdArg(0);
                    codeStream.EmitLdArg(_rank + argStartOffset);

                    codeStream.Emit(ILOpcode.call, _emitter.NewToken(checkArrayStore));
                }
                else if (_method.Kind == ArrayMethodKind.AddressWithHiddenArg)
                {
                    TypeDesc objectType = context.GetWellKnownType(WellKnownType.Object);
                    TypeDesc eetypeType = context.SystemModule.GetKnownType("Internal.Runtime", "EEType");

                    typeMismatchExceptionLabel = _emitter.NewCodeLabel();

                    ILCodeLabel typeCheckPassedLabel = _emitter.NewCodeLabel();

                    // Codegen will pass a null hidden argument if this is a `constrained.` call to the Address method.
                    // As per ECMA-335 III.2.3, the prefix suppresses the type check.
                    // if (hiddenArg == IntPtr.Zero)
                    //     goto TypeCheckPassed;
                    codeStream.EmitLdArg(1);
                    codeStream.Emit(ILOpcode.brfalse, typeCheckPassedLabel);

                    // EEType* actualElementType = this.EEType.RelatedParameterType; // ArrayElementType
                    codeStream.EmitLdArg(0);
                    codeStream.Emit(ILOpcode.call, _emitter.NewToken(objectType.GetKnownMethod("get_EEType", null)));
                    codeStream.Emit(ILOpcode.call,
                                    _emitter.NewToken(eetypeType.GetKnownMethod("get_RelatedParameterType", null)));

                    // EEType* expectedElementType = hiddenArg->RelatedParameterType; // ArrayElementType
                    codeStream.EmitLdArg(1);
                    codeStream.Emit(ILOpcode.call,
                                    _emitter.NewToken(eetypeType.GetKnownMethod("get_RelatedParameterType", null)));

                    // if (TypeCast.AreTypesEquivalent(expectedElementType, actualElementType))
                    //     ThrowHelpers.ThrowArrayTypeMismatchException();
                    codeStream.Emit(ILOpcode.call, _emitter.NewToken(
                                        context.SystemModule.GetKnownType("System.Runtime", "TypeCast").GetKnownMethod("AreTypesEquivalent", null)));
                    codeStream.Emit(ILOpcode.brfalse, typeMismatchExceptionLabel);

                    codeStream.EmitLabel(typeCheckPassedLabel);
                }
            }

            // Methods on Rank 1 MdArray need to be able to handle `this` that is an SzArray
            // because SzArray is castable to Rank 1 MdArray (but not the other way around).

            ILCodeLabel rangeCheckDoneLabel = null;

            if (_rank == 1)
            {
                TypeDesc        objectType    = context.GetWellKnownType(WellKnownType.Object);
                TypeDesc        eetypePtrType = context.SystemModule.GetKnownType("System", "EETypePtr");
                ILLocalVariable thisEEType    = _emitter.NewLocal(eetypePtrType);

                codeStream.EmitLdArg(0);
                codeStream.Emit(ILOpcode.call, _emitter.NewToken(objectType.GetKnownMethod("get_EETypePtr", null)));
                codeStream.EmitStLoc(thisEEType);
                codeStream.EmitLdLoca(thisEEType);
                codeStream.Emit(ILOpcode.call,
                                _emitter.NewToken(eetypePtrType.GetKnownMethod("get_IsSzArray", null)));

                ILCodeLabel notSzArrayLabel = _emitter.NewCodeLabel();
                codeStream.Emit(ILOpcode.brfalse, notSzArrayLabel);

                // We have an SzArray - do the bounds check differently
                EmitLoadInteriorAddress(codeStream, pointerSize);
                codeStream.Emit(ILOpcode.dup);
                codeStream.Emit(ILOpcode.ldind_i4);
                codeStream.EmitLdArg(argStartOffset);
                codeStream.EmitStLoc(totalLocalNum);
                codeStream.EmitLdLoc(totalLocalNum);
                codeStream.Emit(ILOpcode.ble_un, rangeExceptionLabel);

                codeStream.EmitLdc(pointerSize);
                codeStream.Emit(ILOpcode.add);

                rangeCheckDoneLabel = _emitter.NewCodeLabel();
                codeStream.Emit(ILOpcode.br, rangeCheckDoneLabel);

                codeStream.EmitLabel(notSzArrayLabel);
            }

            for (int i = 0; i < _rank; i++)
            {
                // The first two fields are EEType pointer and total length. Lengths for each dimension follows.
                int lengthOffset = (2 * pointerSize + i * sizeof(int));

                EmitLoadInteriorAddress(codeStream, lengthOffset);
                codeStream.Emit(ILOpcode.ldind_i4);
                codeStream.EmitStLoc(lengthLocalNum);

                codeStream.EmitLdArg(i + argStartOffset);

                // Compare with length
                codeStream.Emit(ILOpcode.dup);
                codeStream.EmitLdLoc(lengthLocalNum);
                codeStream.Emit(ILOpcode.bge_un, rangeExceptionLabel);

                // Add to the running total if we have one already
                if (i > 0)
                {
                    codeStream.EmitLdLoc(totalLocalNum);
                    codeStream.EmitLdLoc(lengthLocalNum);
                    codeStream.Emit(ILOpcode.mul);
                    codeStream.Emit(ILOpcode.add);
                }
                codeStream.EmitStLoc(totalLocalNum);
            }

            // Compute element offset
            // TODO: This leaves unused space for lower bounds to match CoreCLR...
            int firstElementOffset = (2 * pointerSize + 2 * _rank * sizeof(int));

            EmitLoadInteriorAddress(codeStream, firstElementOffset);

            if (rangeCheckDoneLabel != null)
            {
                codeStream.EmitLabel(rangeCheckDoneLabel);
            }

            codeStream.EmitLdLoc(totalLocalNum);
            codeStream.Emit(ILOpcode.conv_u);

            int elementSize = _elementType.GetElementSize().AsInt;

            if (elementSize != 1)
            {
                codeStream.EmitLdc(elementSize);
                codeStream.Emit(ILOpcode.mul);
            }
            codeStream.Emit(ILOpcode.add);

            switch (_method.Kind)
            {
            case ArrayMethodKind.Get:
                codeStream.Emit(ILOpcode.ldobj, _emitter.NewToken(_elementType));
                break;

            case ArrayMethodKind.Set:
                codeStream.EmitLdArg(_rank + argStartOffset);
                codeStream.Emit(ILOpcode.stobj, _emitter.NewToken(_elementType));
                break;

            case ArrayMethodKind.AddressWithHiddenArg:
                break;
            }

            codeStream.Emit(ILOpcode.ret);

            codeStream.EmitLdc(0);
            codeStream.EmitLabel(rangeExceptionLabel); // Assumes that there is one "int" pushed on the stack
            codeStream.Emit(ILOpcode.pop);

            MethodDesc throwHelper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowIndexOutOfRangeException");

            codeStream.EmitCallThrowHelper(_emitter, throwHelper);

            if (typeMismatchExceptionLabel != null)
            {
                codeStream.EmitLabel(typeMismatchExceptionLabel);
                codeStream.EmitCallThrowHelper(_emitter, context.GetHelperEntryPoint("ThrowHelpers", "ThrowArrayTypeMismatchException"));
            }
        }
Ejemplo n.º 43
0
        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 is SignatureVariable || !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));

            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);
        }
Ejemplo n.º 44
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.º 46
0
        private void EmitILForAccessor()
        {
            Debug.Assert(_method.OwningType.IsMdArray);

            var codeStream = _emitter.NewCodeStream();
            var context    = _method.Context;

            var int32Type = context.GetWellKnownType(WellKnownType.Int32);

            var totalLocalNum  = _emitter.NewLocal(int32Type);
            var lengthLocalNum = _emitter.NewLocal(int32Type);

            int pointerSize = context.Target.PointerSize;

            int argStartOffset = _method.Kind == ArrayMethodKind.AddressWithHiddenArg ? 2 : 1;

            var         rangeExceptionLabel        = _emitter.NewCodeLabel();
            ILCodeLabel typeMismatchExceptionLabel = null;

            if (!_elementType.IsValueType)
            {
                // Type check
                if (_method.Kind == ArrayMethodKind.Set)
                {
                    MethodDesc checkArrayStore =
                        context.SystemModule.GetKnownType("System.Runtime", "RuntimeImports").GetKnownMethod("RhCheckArrayStore", null);

                    codeStream.EmitLdArg(0);
                    codeStream.EmitLdArg(_rank + argStartOffset);

                    codeStream.Emit(ILOpcode.call, _emitter.NewToken(checkArrayStore));
                }
                else if (_method.Kind == ArrayMethodKind.AddressWithHiddenArg)
                {
                    TypeDesc objectType    = context.GetWellKnownType(WellKnownType.Object);
                    TypeDesc eetypePtrType = context.SystemModule.GetKnownType("System", "EETypePtr");

                    typeMismatchExceptionLabel = _emitter.NewCodeLabel();

                    ILLocalVariable thisEEType = _emitter.NewLocal(eetypePtrType);

                    // EETypePtr actualElementType = this.EETypePtr.ArrayElementType;
                    codeStream.EmitLdArg(0);
                    codeStream.Emit(ILOpcode.call, _emitter.NewToken(objectType.GetKnownMethod("get_EETypePtr", null)));
                    codeStream.EmitStLoc(thisEEType);
                    codeStream.EmitLdLoca(thisEEType);
                    codeStream.Emit(ILOpcode.call,
                                    _emitter.NewToken(eetypePtrType.GetKnownMethod("get_ArrayElementType", null)));

                    // EETypePtr expectedElementType = hiddenArg.ArrayElementType;
                    codeStream.EmitLdArga(1);
                    codeStream.Emit(ILOpcode.call,
                                    _emitter.NewToken(eetypePtrType.GetKnownMethod("get_ArrayElementType", null)));

                    // if (expectedElementType != actualElementType)
                    //     ThrowHelpers.ThrowArrayTypeMismatchException();
                    codeStream.Emit(ILOpcode.call, _emitter.NewToken(eetypePtrType.GetKnownMethod("op_Equality", null)));
                    codeStream.Emit(ILOpcode.brfalse, typeMismatchExceptionLabel);
                }
            }

            for (int i = 0; i < _rank; i++)
            {
                // The first two fields are EEType pointer and total length. Lengths for each dimension follows.
                int lengthOffset = (2 * pointerSize + i * sizeof(int));

                EmitLoadInteriorAddress(codeStream, lengthOffset);
                codeStream.Emit(ILOpcode.ldind_i4);
                codeStream.EmitStLoc(lengthLocalNum);

                codeStream.EmitLdArg(i + argStartOffset);

                // Compare with length
                codeStream.Emit(ILOpcode.dup);
                codeStream.EmitLdLoc(lengthLocalNum);
                codeStream.Emit(ILOpcode.bge_un, rangeExceptionLabel);

                // Add to the running total if we have one already
                if (i > 0)
                {
                    codeStream.EmitLdLoc(totalLocalNum);
                    codeStream.EmitLdLoc(lengthLocalNum);
                    codeStream.Emit(ILOpcode.mul);
                    codeStream.Emit(ILOpcode.add);
                }
                codeStream.EmitStLoc(totalLocalNum);
            }

            // Compute element offset
            // TODO: This leaves unused space for lower bounds to match CoreCLR...
            int firstElementOffset = (2 * pointerSize + 2 * _rank * sizeof(int));

            EmitLoadInteriorAddress(codeStream, firstElementOffset);

            codeStream.EmitLdLoc(totalLocalNum);

            int elementSize = _elementType.GetElementSize().AsInt;

            if (elementSize != 1)
            {
                codeStream.EmitLdc(elementSize);
                codeStream.Emit(ILOpcode.mul);
            }
            codeStream.Emit(ILOpcode.add);

            switch (_method.Kind)
            {
            case ArrayMethodKind.Get:
                codeStream.Emit(ILOpcode.ldobj, _emitter.NewToken(_elementType));
                break;

            case ArrayMethodKind.Set:
                codeStream.EmitLdArg(_rank + argStartOffset);
                codeStream.Emit(ILOpcode.stobj, _emitter.NewToken(_elementType));
                break;

            case ArrayMethodKind.AddressWithHiddenArg:
                break;
            }

            codeStream.Emit(ILOpcode.ret);

            codeStream.EmitLdc(0);
            codeStream.EmitLabel(rangeExceptionLabel); // Assumes that there is one "int" pushed on the stack
            codeStream.Emit(ILOpcode.pop);

            MethodDesc throwHelper = context.GetHelperEntryPoint("ThrowHelpers", "ThrowIndexOutOfRangeException");

            codeStream.EmitCallThrowHelper(_emitter, throwHelper);

            if (typeMismatchExceptionLabel != null)
            {
                codeStream.EmitLabel(typeMismatchExceptionLabel);
                codeStream.EmitCallThrowHelper(_emitter, context.GetHelperEntryPoint("ThrowHelpers", "ThrowArrayTypeMismatchException"));
            }
        }
Ejemplo n.º 47
0
        public MethodIL EmitIL()
        {
            MethodSignature targetMethodSignature = _targetMethod.Signature;

            // We have 4 code streams:
            // - _marshallingCodeStream is used to convert each argument into a native type and
            // store that into the local
            // - callsiteSetupCodeStream is used to used to load each previously generated local
            // and call the actual target native method.
            // - _returnValueMarshallingCodeStream is used to convert the native return value
            // to managed one.
            // - _unmarshallingCodestream is used to propagate [out] native arguments values to
            // managed ones.
            _emitter = new ILEmitter();
            _marshallingCodeStream = _emitter.NewCodeStream();
            ILCodeStream callsiteSetupCodeStream = _emitter.NewCodeStream();

            _returnValueMarshallingCodeStream = _emitter.NewCodeStream();
            _unmarshallingCodestream          = _emitter.NewCodeStream();

            TypeDesc[] nativeParameterTypes = new TypeDesc[targetMethodSignature.Length];

            //
            // Parameter marshalling
            //

            //
            // Convert each argument to something we can pass to native and store it in a local.
            // Then load the local in the second code stream.
            //
            for (int i = 0; i < targetMethodSignature.Length; i++)
            {
                // TODO: throw if there's custom marshalling

                _marshallingCodeStream.EmitLdArg(i);

                TypeDesc nativeType = MarshalArgument(targetMethodSignature[i]);

                nativeParameterTypes[i] = nativeType;

                ILLocalVariable vMarshalledTypeTemp = _emitter.NewLocal(nativeType);
                _marshallingCodeStream.EmitStLoc(vMarshalledTypeTemp);

                callsiteSetupCodeStream.EmitLdLoc(vMarshalledTypeTemp);
            }

            //
            // Return value marshalling
            //

            // TODO: throw if SetLastError is true
            // TODO: throw if there's custom marshalling

            TypeDesc nativeReturnType = MarshalReturnValue(targetMethodSignature.ReturnType);

            MethodSignature nativeSig = new MethodSignature(
                targetMethodSignature.Flags, 0, nativeReturnType, nativeParameterTypes);
            MethodDesc nativeMethod =
                new PInvokeTargetNativeMethod(_targetMethod.OwningType, nativeSig, _importMetadata);

            // Call the native method
            callsiteSetupCodeStream.Emit(ILOpcode.call, _emitter.NewToken(nativeMethod));

            _unmarshallingCodestream.Emit(ILOpcode.ret);

            return(_emitter.Link());
        }
Ejemplo n.º 48
0
        public static MethodIL EmitIL(MethodDesc method)
        {
            if (!RequiresMarshalling(method))
                return null;

            try
            {
                return new PInvokeMarshallingILEmitter(method).EmitIL();
            }
            catch (NotSupportedException)
            {
                ILEmitter emitter = new ILEmitter();
                string message = "Method '" + method.ToString() +
                    "' requires non-trivial marshalling that is not yet supported by this compiler.";

                TypeSystemContext context = method.Context;
                MethodSignature ctorSignature = new MethodSignature(0, 0, context.GetWellKnownType(WellKnownType.Void),
                    new TypeDesc[] { context.GetWellKnownType(WellKnownType.String) });
                MethodDesc exceptionCtor = method.Context.GetWellKnownType(WellKnownType.Exception).GetKnownMethod(".ctor", ctorSignature);

                ILCodeStream codeStream = emitter.NewCodeStream();
                codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(message));
                codeStream.Emit(ILOpcode.newobj, emitter.NewToken(exceptionCtor));
                codeStream.Emit(ILOpcode.throw_);
                codeStream.Emit(ILOpcode.ret);

                return emitter.Link();
            }
        }
Ejemplo n.º 49
0
        private MethodIL EmitIL()
        {
            // We have 4 code streams:
            // - _marshallingCodeStream is used to convert each argument into a native type and
            // store that into the local
            // - callsiteSetupCodeStream is used to used to load each previously generated local
            // and call the actual target native method.
            // - _returnValueMarshallingCodeStream is used to convert the native return value
            // to managed one.
            // - _unmarshallingCodestream is used to propagate [out] native arguments values to
            // managed ones.

            ILEmitter    emitter                          = new ILEmitter();
            ILCodeStream fnptrLoadStream                  = emitter.NewCodeStream();
            ILCodeStream marshallingCodeStream            = emitter.NewCodeStream();
            ILCodeStream callsiteSetupCodeStream          = emitter.NewCodeStream();
            ILCodeStream returnValueMarshallingCodeStream = emitter.NewCodeStream();
            ILCodeStream unmarshallingCodestream          = emitter.NewCodeStream();

            // Marshal the arguments
            for (int i = 0; i < _marshallers.Length; i++)
            {
                Marshaller marshaller = _marshallers[i];
                marshaller.EmitMarshallingIL(emitter, marshallingCodeStream, callsiteSetupCodeStream, unmarshallingCodestream, returnValueMarshallingCodeStream);
            }

            // make the call
            TypeDesc nativeReturnType = _marshallers[0].NativeType;

            TypeDesc[] nativeParameterTypes = new TypeDesc[_marshallers.Length - 1];

            for (int i = 1; i < _marshallers.Length; i++)
            {
                nativeParameterTypes[i - 1] = _marshallers[i].NativeType;
            }

            MethodDesc      targetMethod   = _methodData.TargetMethod;
            PInvokeMetadata importMetadata = _methodData.ImportMetadata;
            PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration = _methodData.PInvokeILEmitterConfiguration;

            // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke
            if ((importMetadata.Attributes & PInvokeAttributes.SetLastError) == PInvokeAttributes.SetLastError)
            {
                callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(
                                                 _methodData.PInvokeMarshal.GetKnownMethod("ClearLastWin32Error", null)));
            }

            if (MarshalHelpers.UseLazyResolution(targetMethod, importMetadata.Module, pinvokeILEmitterConfiguration))
            {
                MetadataType lazyHelperType   = targetMethod.Context.GetHelperType("InteropHelpers");
                FieldDesc    lazyDispatchCell = new PInvokeLazyFixupField((DefType)targetMethod.OwningType, importMetadata);
                fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell));
                fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType.GetKnownMethod("ResolvePInvoke", null)));

                MethodSignatureFlags unmanagedCallConv = PInvokeMetadata.GetUnmanagedCallingConvention(importMetadata.Attributes);

                MethodSignature nativeCalliSig = new MethodSignature(
                    targetMethod.Signature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes);

                ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(targetMethod.Context.GetWellKnownType(WellKnownType.IntPtr));
                fnptrLoadStream.EmitStLoc(vNativeFunctionPointer);
                callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer);
                callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeCalliSig));
            }
            else
            {
                // Eager call
                PInvokeMetadata nativeImportMetadata =
                    new PInvokeMetadata(importMetadata.Module, importMetadata.Name ?? targetMethod.Name, importMetadata.Attributes);

                MethodSignature nativeSig = new MethodSignature(
                    targetMethod.Signature.Flags, 0, nativeReturnType, nativeParameterTypes);

                MethodDesc nativeMethod =
                    new PInvokeTargetNativeMethod(targetMethod.OwningType, nativeSig, nativeImportMetadata, pinvokeILEmitterConfiguration.GetNextNativeMethodId());

                callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(nativeMethod));
            }

            // if the SetLastError flag is set in DllImport, call the PInvokeMarshal.SaveLastWin32Error so that last error can be used later
            // by calling PInvokeMarshal.GetLastWin32Error
            if ((importMetadata.Attributes & PInvokeAttributes.SetLastError) == PInvokeAttributes.SetLastError)
            {
                callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(
                                                 _methodData.PInvokeMarshal.GetKnownMethod("SaveLastWin32Error", null)));
            }

            unmarshallingCodestream.Emit(ILOpcode.ret);

            return(emitter.Link(targetMethod));
        }
Ejemplo n.º 50
0
        private void EmitILForAccessor()
        {
            Debug.Assert(_rank > 0);

            var codeStream = _emitter.NewCodeStream();

            var int32Type = _method.Context.GetWellKnownType(WellKnownType.Int32);

            var totalLocalNum  = _emitter.NewLocal(int32Type);
            var lengthLocalNum = _emitter.NewLocal(int32Type);

            int pointerSize = _method.Context.Target.PointerSize;

            var rangeExceptionLabel = _emitter.NewCodeLabel();

            // TODO: type check

            for (int i = 0; i < _rank; i++)
            {
                // The first two fields are EEType pointer and total length. Lengths for each dimension follows.
                int lengthOffset = (2 * pointerSize + i * int32Type.GetElementSize());

                EmitLoadInteriorAddress(codeStream, lengthOffset);
                codeStream.Emit(ILOpcode.ldind_i4);
                codeStream.EmitStLoc(lengthLocalNum);

                codeStream.EmitLdArg(i + 1);

                // Compare with length
                codeStream.Emit(ILOpcode.dup);
                codeStream.EmitLdLoc(lengthLocalNum);
                codeStream.Emit(ILOpcode.bge_un, rangeExceptionLabel);

                // Add to the running total if we have one already
                if (i > 0)
                {
                    codeStream.EmitLdLoc(totalLocalNum);
                    codeStream.EmitLdLoc(lengthLocalNum);
                    codeStream.Emit(ILOpcode.mul);
                    codeStream.Emit(ILOpcode.add);
                }
                codeStream.EmitStLoc(totalLocalNum);
            }

            // Compute element offset
            // TODO: This leaves unused space for lower bounds to match CoreCLR...
            int firstElementOffset = (2 * pointerSize + 2 * _rank * int32Type.GetElementSize());

            EmitLoadInteriorAddress(codeStream, firstElementOffset);

            codeStream.EmitLdLoc(totalLocalNum);

            int elementSize = _elementType.GetElementSize();

            if (elementSize != 1)
            {
                codeStream.EmitLdc(elementSize);
                codeStream.Emit(ILOpcode.mul);
            }
            codeStream.Emit(ILOpcode.add);

            switch (_method.Kind)
            {
            case ArrayMethodKind.Get:
                codeStream.Emit(ILOpcode.ldobj, _emitter.NewToken(_elementType));
                break;

            case ArrayMethodKind.Set:
                codeStream.EmitLdArg(_rank + 1);
                codeStream.Emit(ILOpcode.stobj, _emitter.NewToken(_elementType));
                break;

            case ArrayMethodKind.Address:
                break;
            }

            codeStream.Emit(ILOpcode.ret);

            codeStream.EmitLdc(0);
            codeStream.EmitLabel(rangeExceptionLabel); // Assumes that there is one "int" pushed on the stack
            codeStream.Emit(ILOpcode.pop);

            MethodDesc throwHelper = _method.Context.GetHelperEntryPoint("ArrayMethodILHelpers", "ThrowIndexOutOfRangeException");

            codeStream.EmitCallThrowHelper(_emitter, throwHelper);

#if false
            if (typeMismatchExceptionLabel != null)
            {
                var tokTypeMismatchExcepCtor = GetToken(GetException(kArrayTypeMismatchException).GetDefaultConstructor());

                codeStream.EmitLabel(typeMismatchExceptionLabel);
                codeStream.Emit(ILOpcode.newobj, tokTypeMismatchExcepCtor, 0);
                codeStream.Emit(ILOpcode.throw_);
            }
#endif
        }
Ejemplo n.º 51
0
        public MethodIL EmitIL()
        {
            MethodSignature targetMethodSignature = _targetMethod.Signature;

            // We have 4 code streams:
            // - _marshallingCodeStream is used to convert each argument into a native type and 
            // store that into the local
            // - callsiteSetupCodeStream is used to used to load each previously generated local
            // and call the actual target native method.
            // - _returnValueMarshallingCodeStream is used to convert the native return value 
            // to managed one.
            // - _unmarshallingCodestream is used to propagate [out] native arguments values to 
            // managed ones.
            _emitter = new ILEmitter();
            _marshallingCodeStream = _emitter.NewCodeStream();
            ILCodeStream callsiteSetupCodeStream = _emitter.NewCodeStream();
            _returnValueMarshallingCodeStream = _emitter.NewCodeStream();
            _unmarshallingCodestream = _emitter.NewCodeStream();

            TypeDesc[] nativeParameterTypes = new TypeDesc[targetMethodSignature.Length];

            //
            // Parameter marshalling
            //

            //
            // Convert each argument to something we can pass to native and store it in a local.
            // Then load the local in the second code stream.
            //
            for (int i = 0; i < targetMethodSignature.Length; i++)
            {
                // TODO: throw if there's custom marshalling

                _marshallingCodeStream.EmitLdArg(i);

                TypeDesc nativeType = MarshalArgument(targetMethodSignature[i]);

                nativeParameterTypes[i] = nativeType;

                ILLocalVariable vMarshalledTypeTemp = _emitter.NewLocal(nativeType);
                _marshallingCodeStream.EmitStLoc(vMarshalledTypeTemp);

                callsiteSetupCodeStream.EmitLdLoc(vMarshalledTypeTemp);
            }

            //
            // Return value marshalling
            //

            // TODO: throw if SetLastError is true
            // TODO: throw if there's custom marshalling

            TypeDesc nativeReturnType = MarshalReturnValue(targetMethodSignature.ReturnType);

            MethodSignature nativeSig = new MethodSignature(
                targetMethodSignature.Flags, 0, nativeReturnType, nativeParameterTypes);
            MethodDesc nativeMethod =
                new PInvokeTargetNativeMethod(_targetMethod.OwningType, nativeSig, _importMetadata);

            // Call the native method
            callsiteSetupCodeStream.Emit(ILOpcode.call, _emitter.NewToken(nativeMethod));

            _unmarshallingCodestream.Emit(ILOpcode.ret);

            return _emitter.Link();
        }
Ejemplo n.º 52
0
        public override MethodIL EmitIL()
        {
            TypeDesc owningType = _owningType.InstantiateAsOpen();

            ILEmitter emitter = new ILEmitter();

            TypeDesc   eeTypePtrType     = Context.SystemModule.GetKnownType("System", "EETypePtr");
            MethodDesc eeTypePtrOfMethod = eeTypePtrType.GetKnownMethod("EETypePtrOf", null);
            ILToken    eeTypePtrToken    = emitter.NewToken(eeTypePtrType);

            var switchStream   = emitter.NewCodeStream();
            var getFieldStream = emitter.NewCodeStream();

            ArrayBuilder <ILCodeLabel> fieldGetters = new ArrayBuilder <ILCodeLabel>();

            foreach (FieldDesc field in owningType.GetFields())
            {
                if (field.IsStatic)
                {
                    continue;
                }

                ILCodeLabel label = emitter.NewCodeLabel();
                fieldGetters.Add(label);

                getFieldStream.EmitLabel(label);
                getFieldStream.EmitLdArg(2);

                // We need something we can instantiate EETypePtrOf over. Also, the classlib
                // code doesn't handle pointers.
                TypeDesc boxableFieldType = field.FieldType;
                if (boxableFieldType.IsPointer || boxableFieldType.IsFunctionPointer)
                {
                    boxableFieldType = Context.GetWellKnownType(WellKnownType.IntPtr);
                }

                MethodDesc ptrOfField = eeTypePtrOfMethod.MakeInstantiatedMethod(boxableFieldType);
                getFieldStream.Emit(ILOpcode.call, emitter.NewToken(ptrOfField));

                getFieldStream.Emit(ILOpcode.stobj, eeTypePtrToken);

                getFieldStream.EmitLdArg(0);
                getFieldStream.Emit(ILOpcode.ldflda, emitter.NewToken(field));

                getFieldStream.EmitLdArg(0);

                getFieldStream.Emit(ILOpcode.sub);

                getFieldStream.Emit(ILOpcode.ret);
            }

            if (fieldGetters.Count > 0)
            {
                switchStream.EmitLdArg(1);
                switchStream.EmitSwitch(fieldGetters.ToArray());
            }

            switchStream.EmitLdc(fieldGetters.Count);

            switchStream.Emit(ILOpcode.ret);

            return(emitter.Link(this));
        }
Ejemplo n.º 53
0
        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));

            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));
        }
Ejemplo n.º 54
0
        public MethodIL EmitIL()
        {
            // We have two code streams - one is used to convert each argument into a native type
            // and store that into the local. The other is used to load each previously generated local
            // and call the actual target native method.
            _emitter = new ILEmitter();
            _marshallingCodeStream = _emitter.NewCodeStream();
            ILCodeStream callsiteSetupCodeStream = _emitter.NewCodeStream();

            // TODO: throw if SetLastError is true
            // TODO: throw if there's custom marshalling
            TypeDesc nativeReturnType = _targetMethod.Signature.ReturnType;

            if (!IsSimpleType(nativeReturnType) && !nativeReturnType.IsVoid)
            {
                throw new NotSupportedException();
            }

            TypeDesc[] nativeParameterTypes = new TypeDesc[_targetMethod.Signature.Length];

            //
            // Convert each argument to something we can pass to native and store it in a local.
            // Then load the local in the second code stream.
            //
            for (int i = 0; i < _targetMethod.Signature.Length; i++)
            {
                // TODO: throw if there's custom marshalling
                TypeDesc parameterType = _targetMethod.Signature[i];

                _marshallingCodeStream.EmitLdArg(i);

                TypeDesc nativeType;
                if (parameterType.IsSzArray)
                {
                    nativeType = EmitArrayMarshalling((ArrayType)parameterType);
                }
                else if (parameterType.IsByRef)
                {
                    nativeType = EmitByRefMarshalling((ByRefType)parameterType);
                }
                else if (parameterType.IsString)
                {
                    nativeType = EmitStringMarshalling();
                }
                else
                {
                    if (!IsSimpleType(parameterType))
                    {
                        throw new NotSupportedException();
                    }

                    nativeType = parameterType;
                }

                nativeParameterTypes[i] = nativeType;

                int vMarshalledTypeTemp = _emitter.NewLocal(nativeType);
                _marshallingCodeStream.EmitStLoc(vMarshalledTypeTemp);

                callsiteSetupCodeStream.EmitLdLoc(vMarshalledTypeTemp);
            }

            MethodSignature nativeSig = new MethodSignature(
                _targetMethod.Signature.Flags, 0, nativeReturnType, nativeParameterTypes);
            MethodDesc nativeMethod =
                new PInvokeTargetNativeMethod(_targetMethod.OwningType, nativeSig, _importMetadata);

            // Call the native method
            callsiteSetupCodeStream.Emit(ILOpcode.call, _emitter.NewToken(nativeMethod));
            callsiteSetupCodeStream.Emit(ILOpcode.ret);

            return(_emitter.Link());
        }
Ejemplo n.º 55
0
        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));
        }
Ejemplo n.º 56
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
            // !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));
        }