Exemplo n.º 1
0
        private ILLocalVariable InitializeMarshallerVariable()
        {
            if (MarshallerLocalVariable != (ILLocalVariable)(-1))
            {
                return(MarshallerLocalVariable);
            }

            var marshallerType = MarshalAsDescriptor.MarshallerType;

            if (marshallerType.IsGenericDefinition)
            {
                ThrowHelper.ThrowTypeLoadException(marshallerType);
            }

            var customMarshallerType = Context.SystemModule.GetKnownType("System.Runtime.InteropServices", "ICustomMarshaler");
            var getInstanceMethod    = marshallerType.GetMethod(
                "GetInstance",
                new MethodSignature(MethodSignatureFlags.Static, 0, customMarshallerType, new[] { Context.GetWellKnownType(WellKnownType.String) }));

            if (ManagedType.IsValueType || ManagedType.IsPointer || ManagedType.IsFunctionPointer)
            {
                ThrowHelper.ThrowMarshalDirectiveException();
            }

            var initializeCustomMarshallerMethod = Context.GetHelperEntryPoint("InteropHelpers", "InitializeCustomMarshaller");

            ILEmitter emitter = _ilCodeStreams.Emitter;

            MarshallerLocalVariable = emitter.NewLocal(customMarshallerType);
            var cookie = MarshalAsDescriptor.Cookie;

            // Custom marshaller initialization should not be catched, so initialize early
            ILCodeStream fnptrLoadStream = _ilCodeStreams.FunctionPointerLoadStream;

            fnptrLoadStream.Emit(ILOpcode.ldtoken, emitter.NewToken(ManagedType));
            fnptrLoadStream.Emit(ILOpcode.ldtoken, emitter.NewToken(marshallerType));
            fnptrLoadStream.Emit(ILOpcode.ldstr, emitter.NewToken(cookie));
            if (getInstanceMethod != null)
            {
                fnptrLoadStream.Emit(ILOpcode.ldftn, emitter.NewToken(getInstanceMethod));
            }
            else
            {
                fnptrLoadStream.EmitLdc(0);
                fnptrLoadStream.Emit(ILOpcode.conv_i);
            }

            fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(initializeCustomMarshallerMethod));
            fnptrLoadStream.EmitStLoc(MarshallerLocalVariable);
            return(MarshallerLocalVariable);
        }
Exemplo n.º 2
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.º 3
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.º 4
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.º 5
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);
        }