Exemplo n.º 1
0
        public override MethodIL EmitIL()
        {
            ILEmitter       emitter     = new ILEmitter();
            ILCodeStream    codeStream  = emitter.NewCodeStream();
            ILLocalVariable returnValue = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32));

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

            codeStream.Emit(ILOpcode.call, emitter.NewToken(startup.GetKnownMethod("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.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)
            {
                TypeDesc environ = Context.SystemModule.GetKnownType("System", "Environment");
                codeStream.Emit(ILOpcode.call, emitter.NewToken(environ.GetKnownMethod("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.GetKnownMethod("Shutdown", null)));

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

            return(emitter.Link());
        }
            public override MethodIL EmitIL()
            {
                // Generate the instantiating stub. This loosely corresponds to following C#:
                // return Interface.Method(this, GetOrdinalInterface(this.m_pEEType, Index), [rest of parameters])

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

                FieldDesc  eeTypeField = Context.GetWellKnownType(WellKnownType.Object).GetKnownField("m_pEEType");
                MethodDesc getOrdinalInterfaceMethod = Context.GetHelperEntryPoint("SharedCodeHelpers", "GetOrdinalInterface");
                MethodDesc getCurrentContext         = Context.GetHelperEntryPoint("SharedCodeHelpers", "GetCurrentSharedThunkContext");

                // Load "this"
                codeStream.EmitLdArg(0);

                // Load the instantiating argument.
                if (_interfaceIndex == UseContextFromRuntime)
                {
                    codeStream.Emit(ILOpcode.call, emit.NewToken(getCurrentContext));
                }
                else
                {
                    codeStream.EmitLdArg(0);
                    codeStream.Emit(ILOpcode.ldfld, emit.NewToken(eeTypeField));
                    codeStream.EmitLdc(_interfaceIndex);
                    codeStream.Emit(ILOpcode.call, emit.NewToken(getOrdinalInterfaceMethod));
                }

                // Load rest of the arguments
                for (int i = 0; i < _targetMethod.Signature.Length; i++)
                {
                    codeStream.EmitLdArg(i + 1);
                }

                // Call an instance method on the target interface that has a fake instantiation parameter
                // in it's signature. This will be swapped by the actual instance method after codegen is done.
                codeStream.Emit(ILOpcode.call, emit.NewToken(_nakedTargetMethod));
                codeStream.Emit(ILOpcode.ret);

                return(emit.Link(this));
            }
Exemplo n.º 3
0
        public override MethodIL EmitIL()
        {
            ILEmitter    emitter    = new ILEmitter();
            ILCodeStream codeStream = emitter.NewCodeStream();

            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));
        }
            public override MethodIL EmitIL()
            {
                if (_owningType.ValueTypeRepresented.IsByRefLike)
                {
                    // If this is the fake unboxing thunk for ByRef-like types, just make a method that throws.
                    return(new ILStubMethodIL(this,
                                              new byte[] { (byte)ILOpcode.ldnull, (byte)ILOpcode.throw_ },
                                              Array.Empty <LocalVariableDefinition>(),
                                              Array.Empty <object>()));
                }

                // Generate the unboxing stub. This loosely corresponds to following C#:
                // return BoxedValue.InstanceMethod(this.m_pEEType, [rest of parameters])

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

                FieldDesc eeTypeField = Context.GetWellKnownType(WellKnownType.Object).GetKnownField("m_pEEType");

                // Load ByRef to the field with the value of the boxed valuetype
                codeStream.EmitLdArg(0);
                codeStream.Emit(ILOpcode.ldflda, emit.NewToken(Context.SystemModule.GetKnownType("System.Runtime.CompilerServices", "RawData").GetField("Data")));

                // Load the MethodTable of the boxed valuetype (this is the hidden generic context parameter expected
                // by the (canonical) instance method, but normally not part of the signature in IL).
                codeStream.EmitLdArg(0);
                codeStream.Emit(ILOpcode.ldfld, emit.NewToken(eeTypeField));

                // Load rest of the arguments
                for (int i = 0; i < _targetMethod.Signature.Length; i++)
                {
                    codeStream.EmitLdArg(i + 1);
                }

                // Call an instance method on the target valuetype that has a fake instantiation parameter
                // in it's signature. This will be swapped by the actual instance method after codegen is done.
                codeStream.Emit(ILOpcode.call, emit.NewToken(_nakedTargetMethod.InstantiateAsOpen()));
                codeStream.Emit(ILOpcode.ret);

                return(emit.Link(this));
            }
Exemplo n.º 5
0
        protected override void EmitCleanupManaged(ILCodeStream codeStream)
        {
            // Only do cleanup if it is IN
            if (!In)
            {
                return;
            }

            ILEmitter   emitter = _ilCodeStreams.Emitter;
            ILCodeLabel lNull   = emitter.NewCodeLabel();

            LoadManagedValue(codeStream);
            codeStream.Emit(ILOpcode.brfalse, lNull);

            LoadNativeValue(codeStream);
            LoadManagedValue(codeStream);
            codeStream.Emit(ILOpcode.call, emitter.NewToken(
                                Context.GetHelperEntryPoint("InteropHelpers", "AsAnyCleanupNative")));

            codeStream.EmitLabel(lNull);
        }
        public PInvokeILCodeStreams()
        {
            Emitter = new ILEmitter();

            // We have these code streams:
            // - FunctionPointerLoadStream is used to load the function pointer to call
            // - 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.
            // - CleanupCodestream is used to perform a guaranteed cleanup
            FunctionPointerLoadStream        = Emitter.NewCodeStream();
            MarshallingCodeStream            = Emitter.NewCodeStream();
            CallsiteSetupCodeStream          = Emitter.NewCodeStream();
            ReturnValueMarshallingCodeStream = Emitter.NewCodeStream();
            UnmarshallingCodestream          = Emitter.NewCodeStream();
            CleanupCodeStream = Emitter.NewCodeStream();
        }
Exemplo n.º 7
0
        /// <summary>
        /// Generates IL for the IsSupported property that reads this information from a field initialized by the runtime
        /// at startup. Only works for intrinsics that the code generator can generate detection code for.
        /// </summary>
        public static MethodIL EmitIsSupportedIL(MethodDesc method, FieldDesc isSupportedField)
        {
            Debug.Assert(IsIsSupportedMethod(method));
            Debug.Assert(isSupportedField.IsStatic && isSupportedField.FieldType.IsWellKnownType(WellKnownType.Int32));

            string id = InstructionSetSupport.GetHardwareIntrinsicId(method.Context.Target.Architecture, method.OwningType);

            Debug.Assert(method.Context.Target.Architecture == TargetArchitecture.X64 ||
                         method.Context.Target.Architecture == TargetArchitecture.X86);
            int flag = XArchIntrinsicConstants.FromHardwareIntrinsicId(id);

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

            codeStream.Emit(ILOpcode.ldsfld, emit.NewToken(isSupportedField));
            codeStream.EmitLdc(flag);
            codeStream.Emit(ILOpcode.and);
            codeStream.EmitLdc(0);
            codeStream.Emit(ILOpcode.cgt_un);
            codeStream.Emit(ILOpcode.ret);

            return(emit.Link(method));
        }
Exemplo n.º 8
0
        protected override void EmitMarshalReturnValueManagedToNative()
        {
            ILEmitter    emitter = _ilCodeStreams.Emitter;
            ILCodeStream returnValueMarshallingCodeStream = _ilCodeStreams.ReturnValueMarshallingCodeStream;
            ILCodeStream marshallingCodeStream            = _ilCodeStreams.MarshallingCodeStream;

            NativeParameterType = PInvokeMethodData.Context.GetWellKnownType(WellKnownType.IntPtr);

            var vSafeHandle  = emitter.NewLocal(ManagedParameterType);
            var vReturnValue = emitter.NewLocal(NativeParameterType);

            marshallingCodeStream.Emit(ILOpcode.newobj, emitter.NewToken(ManagedParameterType.GetDefaultConstructor()));
            marshallingCodeStream.EmitStLoc(vSafeHandle);

            returnValueMarshallingCodeStream.EmitStLoc(vReturnValue);

            returnValueMarshallingCodeStream.EmitLdLoc(vSafeHandle);
            returnValueMarshallingCodeStream.EmitLdLoc(vReturnValue);
            returnValueMarshallingCodeStream.Emit(ILOpcode.call, emitter.NewToken(
                                                      PInvokeMethodData.SafeHandleType.GetKnownMethod("SetHandle", null)));

            returnValueMarshallingCodeStream.EmitLdLoc(vSafeHandle);
        }
Exemplo n.º 9
0
        protected override void AllocManagedToNative(ILCodeStream codeStream)
        {
            ILEmitter   emitter = _ilCodeStreams.Emitter;
            ILCodeLabel lNull   = emitter.NewCodeLabel();

            codeStream.EmitLdc(0);
            codeStream.Emit(ILOpcode.conv_i);
            StoreNativeValue(codeStream);

            LoadManagedValue(codeStream);
            codeStream.Emit(ILOpcode.brfalse, lNull);

            TypeDesc nativeStructType = InteropStateManager.GetStructMarshallingNativeType(ManagedType);

            ILLocalVariable lNativeType = emitter.NewLocal(nativeStructType);

            codeStream.EmitLdLoca(lNativeType);
            codeStream.Emit(ILOpcode.initobj, emitter.NewToken(nativeStructType));
            codeStream.EmitLdLoca(lNativeType);
            StoreNativeValue(codeStream);

            codeStream.EmitLabel(lNull);
        }
Exemplo n.º 10
0
            public override MethodIL EmitIL()
            {
                ILEmitter    emit       = new ILEmitter();
                ILCodeStream codeStream = emit.NewCodeStream();

                // We only need the initial step over sequence point if there's any instructions before the call.
                if (Signature.Length > 0)
                {
                    codeStream.MarkDebuggerStepThroughPoint();
                }

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

                codeStream.MarkDebuggerStepInPoint();

                codeStream.Emit(ILOpcode.call, emit.NewToken(WrappedMethod));

                codeStream.Emit(ILOpcode.ret);

                return(emit.Link(this));
            }
Exemplo n.º 11
0
        protected override void AllocManagedToNative(ILCodeStream codeStream)
        {
            ILEmitter       emitter = _ilCodeStreams.Emitter;
            ILCodeLabel     lNull   = emitter.NewCodeLabel();
            ILLocalVariable lSize   = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32));

            LoadManagedValue(codeStream);
            codeStream.Emit(ILOpcode.brfalse, lNull);

            MethodDesc getNativeSizeHelper = Context.GetHelperEntryPoint("InteropHelpers", "AsAnyGetNativeSize");

            LoadManagedValue(codeStream);
            codeStream.Emit(ILOpcode.call, emitter.NewToken(getNativeSizeHelper));
            codeStream.Emit(ILOpcode.dup);
            codeStream.EmitStLoc(lSize);
            codeStream.Emit(ILOpcode.localloc);
            codeStream.Emit(ILOpcode.dup);
            StoreNativeValue(codeStream);
            codeStream.EmitLdc(0);
            codeStream.EmitLdLoc(lSize);
            codeStream.Emit(ILOpcode.initblk);

            codeStream.EmitLabel(lNull);
        }
Exemplo n.º 12
0
        protected override void TransformNativeToManaged(ILCodeStream codeStream)
        {
            ILEmitter   emitter  = _ilCodeStreams.Emitter;
            ILCodeLabel lNonNull = emitter.NewCodeLabel();

            LoadManagedValue(codeStream);
            codeStream.Emit(ILOpcode.brtrue, lNonNull);

            MethodDesc ctor = ManagedType.GetParameterlessConstructor();

            if (ctor == null)
            {
                throw new InvalidProgramException();
            }

            codeStream.Emit(ILOpcode.newobj, emitter.NewToken(ctor));
            StoreManagedValue(codeStream);

            codeStream.EmitLabel(lNonNull);
            LoadNativeAddr(codeStream);
            LoadManagedValue(codeStream);
            codeStream.Emit(ILOpcode.call, _ilCodeStreams.Emitter.NewToken(
                                InteropStateManager.GetStructMarshallingNativeToManagedThunk(ManagedType)));
        }
Exemplo n.º 13
0
        /// <summary>
        /// Provides method bodies for intrinsics recognized by the compiler that
        /// are specialized per instantiation. It can return null if the intrinsic
        /// is not recognized.
        /// </summary>
        private MethodIL TryGetPerInstantiationIntrinsicMethodIL(MethodDesc method)
        {
            Debug.Assert(method.IsIntrinsic);

            MetadataType owningType = method.OwningType.GetTypeDefinition() as MetadataType;

            if (owningType == null)
            {
                return(null);
            }

            string methodName = method.Name;

            switch (owningType.Name)
            {
            case "Activator":
            {
                TypeSystemContext context = owningType.Context;
                if (methodName == "CreateInstance" && method.Signature.Length == 0 && method.HasInstantiation &&
                    method.Instantiation[0] is TypeDesc activatedType &&
                    activatedType != context.UniversalCanonType &&
                    activatedType.IsValueType &&
                    activatedType.GetParameterlessConstructor() == null)
                {
                    ILEmitter    emit       = new ILEmitter();
                    ILCodeStream codeStream = emit.NewCodeStream();

                    var t = emit.NewLocal(context.GetSignatureVariable(0, method: true));
                    codeStream.EmitLdLoca(t);
                    codeStream.Emit(ILOpcode.initobj, emit.NewToken(context.GetSignatureVariable(0, method: true)));
                    codeStream.EmitLdLoc(t);
                    codeStream.Emit(ILOpcode.ret);

                    return(new InstantiatedMethodIL(method, emit.Link(method.GetMethodDefinition())));
                }
            }
            break;

            case "RuntimeHelpers":
            {
                if (owningType.Namespace == "System.Runtime.CompilerServices")
                {
                    return(RuntimeHelpersIntrinsics.EmitIL(method));
                }
            }
            break;

            case "Comparer`1":
            {
                if (methodName == "Create" && owningType.Namespace == "System.Collections.Generic")
                {
                    return(ComparerIntrinsics.EmitComparerCreate(method));
                }
            }
            break;

            case "EqualityComparer`1":
            {
                if (methodName == "Create" && owningType.Namespace == "System.Collections.Generic")
                {
                    return(ComparerIntrinsics.EmitEqualityComparerCreate(method));
                }
            }
            break;

            case "ComparerHelpers":
            {
                if (owningType.Namespace != "Internal.IntrinsicSupport")
                {
                    return(null);
                }

                if (methodName == "EnumOnlyCompare")
                {
                    //calls CompareTo for underlyingType to avoid boxing

                    TypeDesc elementType = method.Instantiation[0];
                    if (!elementType.IsEnum)
                    {
                        return(null);
                    }

                    TypeDesc   underlyingType            = elementType.UnderlyingType;
                    TypeDesc   returnType                = method.Context.GetWellKnownType(WellKnownType.Int32);
                    MethodDesc underlyingCompareToMethod = underlyingType.GetKnownMethod("CompareTo",
                                                                                         new MethodSignature(
                                                                                             MethodSignatureFlags.None,
                                                                                             genericParameterCount: 0,
                                                                                             returnType: returnType,
                                                                                             parameters: new TypeDesc[] { underlyingType }));

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

                    codeStream.EmitLdArga(0);
                    codeStream.EmitLdArg(1);
                    codeStream.Emit(ILOpcode.call, emitter.NewToken(underlyingCompareToMethod));
                    codeStream.Emit(ILOpcode.ret);

                    return(emitter.Link(method));
                }
            }
            break;

            case "EqualityComparerHelpers":
            {
                if (owningType.Namespace != "Internal.IntrinsicSupport")
                {
                    return(null);
                }

                if (methodName == "EnumOnlyEquals")
                {
                    // EnumOnlyEquals would basically like to do this:
                    // static bool EnumOnlyEquals<T>(T x, T y) where T: struct => x == y;
                    // This is not legal though.
                    // We don't want to do this:
                    // static bool EnumOnlyEquals<T>(T x, T y) where T: struct => x.Equals(y);
                    // Because it would box y.
                    // So we resort to some per-instantiation magic.

                    TypeDesc elementType = method.Instantiation[0];
                    if (!elementType.IsEnum)
                    {
                        return(null);
                    }

                    ILOpcode convInstruction;
                    if (((DefType)elementType).InstanceFieldSize.AsInt <= 4)
                    {
                        convInstruction = ILOpcode.conv_i4;
                    }
                    else
                    {
                        Debug.Assert(((DefType)elementType).InstanceFieldSize.AsInt == 8);
                        convInstruction = ILOpcode.conv_i8;
                    }

                    return(new ILStubMethodIL(method, new byte[] {
                            (byte)ILOpcode.ldarg_0,
                            (byte)convInstruction,
                            (byte)ILOpcode.ldarg_1,
                            (byte)convInstruction,
                            (byte)ILOpcode.prefix1, unchecked ((byte)ILOpcode.ceq),
                            (byte)ILOpcode.ret,
                        },
                                              Array.Empty <LocalVariableDefinition>(), null));
                }
                else if (methodName == "GetComparerForReferenceTypesOnly")
                {
                    TypeDesc elementType = method.Instantiation[0];
                    if (!elementType.IsRuntimeDeterminedSubtype &&
                        !elementType.IsCanonicalSubtype(CanonicalFormKind.Any) &&
                        !elementType.IsGCPointer)
                    {
                        return(new ILStubMethodIL(method, new byte[] {
                                (byte)ILOpcode.ldnull,
                                (byte)ILOpcode.ret
                            },
                                                  Array.Empty <LocalVariableDefinition>(), null));
                    }
                }
                else if (methodName == "StructOnlyEquals")
                {
                    TypeDesc elementType = method.Instantiation[0];
                    if (!elementType.IsRuntimeDeterminedSubtype &&
                        !elementType.IsCanonicalSubtype(CanonicalFormKind.Any) &&
                        !elementType.IsGCPointer)
                    {
                        Debug.Assert(elementType.IsValueType);

                        TypeSystemContext context    = elementType.Context;
                        MetadataType      helperType = context.SystemModule.GetKnownType("Internal.IntrinsicSupport", "EqualityComparerHelpers");

                        MethodDesc methodToCall;
                        if (elementType.IsEnum)
                        {
                            methodToCall = helperType.GetKnownMethod("EnumOnlyEquals", null).MakeInstantiatedMethod(elementType);
                        }
                        else if (elementType.IsNullable && ComparerIntrinsics.ImplementsIEquatable(elementType.Instantiation[0]))
                        {
                            methodToCall = helperType.GetKnownMethod("StructOnlyEqualsNullable", null).MakeInstantiatedMethod(elementType.Instantiation[0]);
                        }
                        else if (ComparerIntrinsics.ImplementsIEquatable(elementType))
                        {
                            methodToCall = helperType.GetKnownMethod("StructOnlyEqualsIEquatable", null).MakeInstantiatedMethod(elementType);
                        }
                        else
                        {
                            methodToCall = helperType.GetKnownMethod("StructOnlyNormalEquals", null).MakeInstantiatedMethod(elementType);
                        }

                        return(new ILStubMethodIL(method, new byte[]
                            {
                                (byte)ILOpcode.ldarg_0,
                                (byte)ILOpcode.ldarg_1,
                                (byte)ILOpcode.call, 1, 0, 0, 0,
                                (byte)ILOpcode.ret
                            },
                                                  Array.Empty <LocalVariableDefinition>(), new object[] { methodToCall }));
                    }
                }
            }
            break;
            }

            return(null);
        }
 public static void MarkDebuggerStepThroughPoint(this ILCodeStream codeStream)
 {
     codeStream.DefineSequencePoint("", 0xF00F00);
 }
 public static void MarkDebuggerStepInPoint(this ILCodeStream codeStream)
 {
     codeStream.DefineSequencePoint("", 0xFEEFEE);
 }
Exemplo n.º 16
0
 internal override void EmitElementCleanup(ILCodeStream codeStream, ILEmitter emitter)
 {
     codeStream.Emit(ILOpcode.call, emitter.NewToken(
                         Context.GetHelperEntryPoint("InteropHelpers", "CoTaskMemFree")));
 }
Exemplo n.º 17
0
 protected override void AllocManagedToNative(ILCodeStream codeStream)
 {
     LoadNativeAddr(codeStream);
     codeStream.Emit(ILOpcode.initobj, _ilCodeStreams.Emitter.NewToken(NativeType));
 }
Exemplo n.º 18
0
        protected override void EmitMarshalFieldNativeToManaged()
        {
            ILEmitter    emitter    = _ilCodeStreams.Emitter;
            ILCodeStream codeStream = _ilCodeStreams.UnmarshallingCodestream;

            // It generates the following IL:
            //  ManagedArg.s = new ElementType[Length];
            //
            //    for (uint index = 0u; index < Length; index += 1u)
            //    {
            //        ManagedArg.s[index] = NativeArg.s[index];
            //    }
            //

            ILCodeLabel lRangeCheck = emitter.NewCodeLabel();
            ILCodeLabel lLoopHeader = emitter.NewCodeLabel();

            Debug.Assert(ManagedType is ArrayType);

            var nativeArrayType = NativeType as InlineArrayType;

            Debug.Assert(nativeArrayType != null);

            var managedElementType = ((ArrayType)ManagedType).ElementType;

            ILLocalVariable vLength = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32));

            codeStream.EmitLdArg(1);
            // load the length
            EmitElementCount(codeStream, MarshalDirection.Reverse);
            codeStream.EmitStLoc(vLength);

            codeStream.EmitLdLoc(vLength);
            codeStream.Emit(ILOpcode.newarr, emitter.NewToken(managedElementType));
            codeStream.Emit(ILOpcode.stfld, emitter.NewToken(_managedField));


            var vIndex = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32));

            // index = 0
            codeStream.EmitLdc(0);
            codeStream.EmitStLoc(vIndex);
            codeStream.Emit(ILOpcode.br, lRangeCheck);

            codeStream.EmitLabel(lLoopHeader);

            // load managed type
            codeStream.EmitLdArg(1);
            codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(_managedField));

            codeStream.EmitLdLoc(vIndex);

            // load native type
            codeStream.EmitLdArg(0);
            codeStream.Emit(ILOpcode.ldflda, emitter.NewToken(_nativeField));
            codeStream.EmitLdLoc(vIndex);

            codeStream.Emit(ILOpcode.call, emitter.NewToken(
                                nativeArrayType.GetInlineArrayMethod(InlineArrayMethodKind.Getter)));

            // generate marshalling IL for the element
            GetElementMarshaller(MarshalDirection.Reverse)
            .EmitMarshallingIL(new PInvokeILCodeStreams(_ilCodeStreams.Emitter, codeStream));

            codeStream.EmitStElem(managedElementType);

            codeStream.EmitLdLoc(vIndex);
            codeStream.EmitLdc(1);
            codeStream.Emit(ILOpcode.add);
            codeStream.EmitStLoc(vIndex);

            codeStream.EmitLabel(lRangeCheck);

            codeStream.EmitLdLoc(vIndex);
            codeStream.EmitLdLoc(vLength);
            codeStream.Emit(ILOpcode.blt, lLoopHeader);
        }
Exemplo n.º 19
0
        protected override void EmitMarshalFieldManagedToNative()
        {
            // It generates the following code
            //if (ManagedArg.Field != null)
            //{
            //
            //  fixed (InlineArray* pUnsafe = &NativeArg.Field)
            //  {
            //        uint index = 0u;
            //        while ((ulong)index < (ulong)((long)ManagedArg.Field.Length))
            //        {
            //            NativeArg.s[index] = ManagedArg.Field[(int)index];
            //            index += 1u;
            //        }
            //  }
            //}

            ILEmitter    emitter         = _ilCodeStreams.Emitter;
            ILCodeStream codeStream      = _ilCodeStreams.MarshallingCodeStream;
            var          nativeArrayType = NativeType as InlineArrayType;

            Debug.Assert(nativeArrayType != null);
            Debug.Assert(ManagedType is ArrayType);

            var managedElementType = ((ArrayType)ManagedType).ElementType;

            ILCodeLabel lDone       = emitter.NewCodeLabel();
            ILCodeLabel lRangeCheck = emitter.NewCodeLabel();
            ILCodeLabel lLoopHeader = emitter.NewCodeLabel();

            ILLocalVariable vIndex  = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32));
            ILLocalVariable vLength = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32));
            ILLocalVariable vNative = emitter.NewLocal(NativeType.MakeByRefType(), isPinned: true);

            // check if ManagedType == null, then return
            codeStream.EmitLdArg(0);
            codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(_managedField));
            codeStream.Emit(ILOpcode.brfalse, lDone);

            codeStream.EmitLdArg(1);
            codeStream.Emit(ILOpcode.ldflda, emitter.NewToken(_nativeField));
            codeStream.EmitStLoc(vNative);

            EmitElementCount(codeStream, MarshalDirection.Forward);
            codeStream.EmitStLoc(vLength);

            codeStream.EmitLdc(0);
            codeStream.EmitStLoc(vIndex);
            codeStream.Emit(ILOpcode.br, lRangeCheck);

            codeStream.EmitLabel(lLoopHeader);
            codeStream.EmitLdArg(1);
            codeStream.Emit(ILOpcode.ldflda, emitter.NewToken(_nativeField));
            codeStream.EmitLdLoc(vIndex);

            codeStream.EmitLdArg(0);
            codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(_managedField));
            codeStream.EmitLdLoc(vIndex);

            codeStream.EmitLdElem(managedElementType);

            // generate marshalling IL for the element
            GetElementMarshaller(MarshalDirection.Forward)
            .EmitMarshallingIL(new PInvokeILCodeStreams(_ilCodeStreams.Emitter, codeStream));

            codeStream.Emit(ILOpcode.call, emitter.NewToken(
                                nativeArrayType.GetInlineArrayMethod(InlineArrayMethodKind.Setter)));

            codeStream.EmitLdLoc(vIndex);
            codeStream.EmitLdc(1);
            codeStream.Emit(ILOpcode.add);
            codeStream.EmitStLoc(vIndex);

            codeStream.EmitLabel(lRangeCheck);
            codeStream.EmitLdLoc(vIndex);

            codeStream.EmitLdLoc(vLength);
            codeStream.Emit(ILOpcode.blt, lLoopHeader);

            codeStream.EmitLabel(lDone);
        }
Exemplo n.º 20
0
        internal override void EmitElementCleanup(ILCodeStream codeStream, ILEmitter emitter)
        {
            var helper = InteropTypes.GetMarshal(Context).GetKnownMethod("FreeBSTR", null);

            codeStream.Emit(ILOpcode.call, emitter.NewToken(helper));
        }
Exemplo n.º 21
0
 protected override void TransformManagedToNative(ILCodeStream codeStream)
 {
     ThrowHelper.ThrowMarshalDirectiveException();
 }
Exemplo n.º 22
0
 protected override void AllocAndTransformManagedToNative(ILCodeStream codeStream)
 {
     LoadManagedAddr(codeStream);
     codeStream.Emit(ILOpcode.ldfld, _ilCodeStreams.Emitter.NewToken(InteropTypes.GetHandleRef(Context).GetKnownField("_handle")));
     StoreNativeValue(codeStream);
 }
Exemplo n.º 23
0
 protected override void EmitCleanupManaged(ILCodeStream codeStream)
 {
     LoadNativeValue(codeStream);
     codeStream.Emit(ILOpcode.call, _ilCodeStreams.Emitter.NewToken(
                         Context.GetHelperEntryPoint("InteropHelpers", "CoTaskMemFree")));
 }
Exemplo n.º 24
0
        protected override void EmitMarshalArgumentManagedToNative()
        {
            ILEmitter    emitter = _ilCodeStreams.Emitter;
            ILCodeStream marshallingCodeStream   = _ilCodeStreams.MarshallingCodeStream;
            ILCodeStream unmarshallingCodeStream = _ilCodeStreams.UnmarshallingCodestream;

            // we don't support [IN,OUT] together yet, either IN or OUT
            Debug.Assert(!(PInvokeParameterMetadata.Out && PInvokeParameterMetadata.In));

            var safeHandleType = PInvokeMethodData.SafeHandleType;

            if (Out)
            {
                // 1) If this is an output parameter we need to preallocate a SafeHandle to wrap the new native handle value. We
                //    must allocate this before the native call to avoid a failure point when we already have a native resource
                //    allocated. We must allocate a new SafeHandle even if we have one on input since both input and output native
                //    handles need to be tracked and released by a SafeHandle.
                // 2) Initialize a local IntPtr that will be passed to the native call.
                // 3) After the native call, the new handle value is written into the output SafeHandle and that SafeHandle
                //    is propagated back to the caller.

                Debug.Assert(ManagedParameterType is ByRefType);
                var vOutArg = emitter.NewLocal(ManagedParameterType);
                marshallingCodeStream.EmitStLoc(vOutArg);

                TypeDesc resolvedType = ((ByRefType)ManagedParameterType).ParameterType;

                var nativeType  = PInvokeMethodData.Context.GetWellKnownType(WellKnownType.IntPtr).MakeByRefType();
                var vOutValue   = emitter.NewLocal(PInvokeMethodData.Context.GetWellKnownType(WellKnownType.IntPtr));
                var vSafeHandle = emitter.NewLocal(resolvedType);
                marshallingCodeStream.Emit(ILOpcode.newobj, emitter.NewToken(resolvedType.GetDefaultConstructor()));
                marshallingCodeStream.EmitStLoc(vSafeHandle);
                marshallingCodeStream.EmitLdLoca(vOutValue);

                unmarshallingCodeStream.EmitLdLoc(vSafeHandle);
                unmarshallingCodeStream.EmitLdLoc(vOutValue);
                unmarshallingCodeStream.Emit(ILOpcode.call, emitter.NewToken(
                                                 PInvokeMethodData.SafeHandleType.GetKnownMethod("SetHandle", null)));

                unmarshallingCodeStream.EmitLdLoc(vOutArg);
                unmarshallingCodeStream.EmitLdLoc(vSafeHandle);
                unmarshallingCodeStream.Emit(ILOpcode.stind_i);

                NativeParameterType = nativeType;
            }
            else
            {
                var vAddRefed   = emitter.NewLocal(PInvokeMethodData.Context.GetWellKnownType(WellKnownType.Boolean));
                var vSafeHandle = emitter.NewLocal(ManagedParameterType);

                marshallingCodeStream.EmitStLoc(vSafeHandle);
                marshallingCodeStream.EmitLdLoc(vSafeHandle);
                marshallingCodeStream.EmitLdLoca(vAddRefed);
                marshallingCodeStream.Emit(ILOpcode.call, emitter.NewToken(
                                               safeHandleType.GetKnownMethod("DangerousAddRef", null)));

                marshallingCodeStream.EmitLdLoc(vSafeHandle);
                marshallingCodeStream.Emit(ILOpcode.call, emitter.NewToken(
                                               safeHandleType.GetKnownMethod("DangerousGetHandle", null)));

                // TODO: This should be inside finally block and only executed it the handle was addrefed
                unmarshallingCodeStream.EmitLdLoc(vSafeHandle);
                unmarshallingCodeStream.Emit(ILOpcode.call, emitter.NewToken(
                                                 safeHandleType.GetKnownMethod("DangerousRelease", null)));

                NativeParameterType = PInvokeMethodData.Context.GetWellKnownType(WellKnownType.IntPtr);
            }
        }
Exemplo n.º 25
0
 protected override void EmitCleanupManaged(ILCodeStream codeStream)
 {
     LoadManagedAddr(codeStream);
     codeStream.Emit(ILOpcode.ldfld, _ilCodeStreams.Emitter.NewToken(InteropTypes.GetHandleRef(Context).GetKnownField("_wrapper")));
     codeStream.Emit(ILOpcode.call, _ilCodeStreams.Emitter.NewToken(InteropTypes.GetGC(Context).GetKnownMethod("KeepAlive", null)));
 }
Exemplo n.º 26
0
 protected override void TransformNativeToManaged(ILCodeStream codeStream)
 {
     ThrowHelper.ThrowTypeLoadException(ManagedType);
 }