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)); }
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)); }
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(); }
/// <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)); }
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); }
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); }
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)); }
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 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))); }
/// <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); }
internal override void EmitElementCleanup(ILCodeStream codeStream, ILEmitter emitter) { codeStream.Emit(ILOpcode.call, emitter.NewToken( Context.GetHelperEntryPoint("InteropHelpers", "CoTaskMemFree"))); }
protected override void AllocManagedToNative(ILCodeStream codeStream) { LoadNativeAddr(codeStream); codeStream.Emit(ILOpcode.initobj, _ilCodeStreams.Emitter.NewToken(NativeType)); }
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); }
internal override void EmitElementCleanup(ILCodeStream codeStream, ILEmitter emitter) { var helper = InteropTypes.GetMarshal(Context).GetKnownMethod("FreeBSTR", null); codeStream.Emit(ILOpcode.call, emitter.NewToken(helper)); }
protected override void TransformManagedToNative(ILCodeStream codeStream) { ThrowHelper.ThrowMarshalDirectiveException(); }
protected override void AllocAndTransformManagedToNative(ILCodeStream codeStream) { LoadManagedAddr(codeStream); codeStream.Emit(ILOpcode.ldfld, _ilCodeStreams.Emitter.NewToken(InteropTypes.GetHandleRef(Context).GetKnownField("_handle"))); StoreNativeValue(codeStream); }
protected override void EmitCleanupManaged(ILCodeStream codeStream) { LoadNativeValue(codeStream); codeStream.Emit(ILOpcode.call, _ilCodeStreams.Emitter.NewToken( Context.GetHelperEntryPoint("InteropHelpers", "CoTaskMemFree"))); }
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); } }
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))); }
protected override void TransformNativeToManaged(ILCodeStream codeStream) { ThrowHelper.ThrowTypeLoadException(ManagedType); }