private MethodDesc GetStructMarshallingCleanupStub(TypeDesc structType) { MethodDesc stub = InteropStateManager.GetStructMarshallingCleanupThunk(structType); Debug.Assert(stub != null); _structMarshallingTypes.Add(structType); return(stub); }
protected override void EmitCleanupManaged(ILCodeStream codeStream) { // Only do cleanup if it is IN if (!In) { return; } LoadNativeAddr(codeStream); codeStream.Emit(ILOpcode.call, _ilCodeStreams.Emitter.NewToken( InteropStateManager.GetStructMarshallingCleanupThunk(ManagedType))); }
internal IEnumerable <StructMarshallingThunks> GetStructMarshallingTypes() { foreach (var structType in _structMarshallingTypes) { yield return (new StructMarshallingThunks() { StructType = structType, NativeStructType = InteropStateManager.GetStructMarshallingNativeType(structType), MarshallingThunk = InteropStateManager.GetStructMarshallingManagedToNativeThunk(structType), UnmarshallingThunk = InteropStateManager.GetStructMarshallingNativeToManagedThunk(structType), CleanupThunk = InteropStateManager.GetStructMarshallingCleanupThunk(structType) }); } }
public override IEnumerable <DependencyListEntry> GetStaticDependencies(NodeFactory factory) { InteropStateManager stateManager = ((CompilerGeneratedInteropStubManager)factory.InteropStubManager)._interopStateManager; yield return(new DependencyListEntry(factory.NecessaryTypeSymbol(_type), "Struct Marshalling Stub")); // Not all StructMarshalingDataNodes require marshalling - some are only present because we want to // generate field offset information for Marshal.OffsetOf. if (MarshalHelpers.IsStructMarshallingRequired(_type)) { yield return(new DependencyListEntry(factory.MethodEntrypoint(stateManager.GetStructMarshallingManagedToNativeThunk(_type)), "Struct Marshalling stub")); yield return(new DependencyListEntry(factory.MethodEntrypoint(stateManager.GetStructMarshallingNativeToManagedThunk(_type)), "Struct Marshalling stub")); yield return(new DependencyListEntry(factory.MethodEntrypoint(stateManager.GetStructMarshallingCleanupThunk(_type)), "Struct Marshalling stub")); } }
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); codeStream.Emit(ILOpcode.call, emitter.NewToken( InteropStateManager.GetStructMarshallingCleanupThunk(ManagedType))); codeStream.EmitLabel(lNull); }
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // This node does not trigger generation of other nodes. if (relocsOnly) { return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this })); } var writer = new NativeWriter(); var typeMapHashTable = new VertexHashtable(); Section hashTableSection = writer.NewSection(); hashTableSection.Place(typeMapHashTable); foreach (var structType in factory.MetadataManager.GetTypesWithStructMarshalling()) { // the order of data written is as follows: // managed struct type // NumFields<< 2 | (HasInvalidLayout ? (2:0)) | (MarshallingRequired ? (1:0)) // If MarshallingRequired: // size // struct marshalling thunk // struct unmarshalling thunk // struct cleanup thunk // For each field field: // name // offset var nativeType = _interopStateManager.GetStructMarshallingNativeType(structType); Vertex marshallingData = null; if (MarshalHelpers.IsStructMarshallingRequired(structType)) { Vertex thunks = writer.GetTuple( writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(_interopStateManager.GetStructMarshallingManagedToNativeThunk(structType)))), writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(_interopStateManager.GetStructMarshallingNativeToManagedThunk(structType)))), writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(_interopStateManager.GetStructMarshallingCleanupThunk(structType))))); uint size = (uint)nativeType.InstanceFieldSize.AsInt; marshallingData = writer.GetTuple(writer.GetUnsignedConstant(size), thunks); } Vertex fieldOffsetData = null; for (int i = 0; i < nativeType.Fields.Length; i++) { var row = writer.GetTuple( writer.GetStringConstant(nativeType.Fields[i].Name), writer.GetUnsignedConstant((uint)nativeType.Fields[i].Offset.AsInt) ); fieldOffsetData = (fieldOffsetData != null) ? writer.GetTuple(fieldOffsetData, row) : row; } uint mask = (uint)((marshallingData != null) ? InteropDataConstants.HasMarshallers : 0) | (uint)(nativeType.HasInvalidLayout ? InteropDataConstants.HasInvalidLayout : 0) | (uint)(nativeType.Fields.Length << InteropDataConstants.FieldCountShift); Vertex data = writer.GetUnsignedConstant(mask); if (marshallingData != null) { data = writer.GetTuple(data, marshallingData); } if (fieldOffsetData != null) { data = writer.GetTuple(data, fieldOffsetData); } Vertex vertex = writer.GetTuple( writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(structType))), data ); int hashCode = structType.GetHashCode(); typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex)); } byte[] hashTableBytes = writer.Save(); _endSymbol.SetSymbolOffset(hashTableBytes.Length); return(new ObjectData(hashTableBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol })); }