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); }
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); }
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); }
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); }
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); }