private void AddDependenciesDueToPInvokeStructDelegateField(ref DependencyList dependencies, NodeFactory factory, TypeDesc typeDesc) { if (typeDesc is ByRefType) { typeDesc = typeDesc.GetParameterType(); } MetadataType metadataType = typeDesc as MetadataType; if (metadataType != null) { foreach (FieldDesc field in metadataType.GetFields()) { if (field.IsStatic) { continue; } TypeDesc fieldType = field.FieldType; if (fieldType.IsDelegate) { AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, fieldType); } else if (MarshalHelpers.IsStructMarshallingRequired(fieldType)) { AddDependenciesDueToPInvokeStructDelegateField(ref dependencies, factory, fieldType); } } } }
public override void AddDependeciesDueToPInvoke(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) { if (method.IsPInvoke) { dependencies = dependencies ?? new DependencyList(); MethodSignature methodSig = method.Signature; AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, methodSig.ReturnType); // struct may contain delegate fields, hence we need to add dependencies for it if (MarshalHelpers.IsStructMarshallingRequired(methodSig.ReturnType)) { AddDependenciesDueToPInvokeStructDelegateField(ref dependencies, factory, methodSig.ReturnType); } for (int i = 0; i < methodSig.Length; i++) { AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, methodSig[i]); if (MarshalHelpers.IsStructMarshallingRequired(methodSig[i])) { AddDependenciesDueToPInvokeStructDelegateField(ref dependencies, factory, methodSig[i]); } } } if (method.HasInstantiation) { dependencies = dependencies ?? new DependencyList(); AddMarshalAPIsGenericDependencies(ref dependencies, factory, method); } }
private static void AddParameterMarshallingDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) { if (type.IsDelegate) { dependencies.Add(factory.DelegateMarshallingData((DefType)type), "Delegate marshaling"); } // struct may contain delegate fields, hence we need to add dependencies for it if (type.IsByRef) { type = ((ParameterizedType)type).ParameterType; } if (MarshalHelpers.IsStructMarshallingRequired(type)) { foreach (FieldDesc field in type.GetFields()) { if (field.IsStatic) { continue; } AddParameterMarshallingDependencies(ref dependencies, factory, field.FieldType); } } }
/// <summary> /// For Marshal generic APIs(eg. Marshal.StructureToPtr<T>, GetFunctionPointerForDelegate) we add /// the generic parameter as dependencies so that we can generate runtime data for them /// </summary> public override void AddMarshalAPIsGenericDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) { Debug.Assert(method.HasInstantiation); TypeDesc owningType = method.OwningType; MetadataType metadataType = owningType as MetadataType; if (metadataType != null && metadataType.Module == factory.TypeSystemContext.SystemModule) { if (metadataType.Name == "Marshal" && metadataType.Namespace == "System.Runtime.InteropServices") { string methodName = method.Name; if (methodName == "GetFunctionPointerForDelegate" || methodName == "GetDelegateForFunctionPointer" || methodName == "PtrToStructure" || methodName == "StructureToPtr" || methodName == "SizeOf" || methodName == "OffsetOf") { foreach (TypeDesc type in method.Instantiation) { dependencies = dependencies ?? new DependencyList(); if (type.IsDelegate) { dependencies.Add(factory.DelegateMarshallingData((DefType)type), "Delegate marshlling"); } else if (MarshalHelpers.IsStructMarshallingRequired(type) || (methodName == "OffsetOf" && type is DefType)) { dependencies.Add(factory.StructMarshallingData((DefType)type), "Struct marshalling"); } } } } } }
private void AddPInvokeParameterDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc parameter) { if (parameter.IsDelegate) { dependencies.Add(factory.NecessaryTypeSymbol(parameter), "Delegate Marshalling Stub"); dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetOpenStaticDelegateMarshallingStub(parameter)), "Delegate Marshalling Stub"); dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetClosedDelegateMarshallingStub(parameter)), "Delegate Marshalling Stub"); dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetForwardDelegateCreationStub(parameter)), "Delegate Marshalling Stub"); } else if (MarshalHelpers.IsStructMarshallingRequired(parameter)) { var stub = (Internal.IL.Stubs.StructMarshallingThunk)factory.InteropStubManager.GetStructMarshallingManagedToNativeStub(parameter); dependencies.Add(factory.ConstructedTypeSymbol(factory.InteropStubManager.GetStructMarshallingType(parameter)), "Struct Marshalling Type"); dependencies.Add(factory.MethodEntrypoint(stub), "Struct Marshalling stub"); dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetStructMarshallingNativeToManagedStub(parameter)), "Struct Marshalling stub"); dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetStructMarshallingCleanupStub(parameter)), "Struct Marshalling stub"); foreach (var inlineArrayCandidate in stub.GetInlineArrayCandidates()) { dependencies.Add(factory.ConstructedTypeSymbol(factory.InteropStubManager.GetInlineArrayType(inlineArrayCandidate)), "Struct Marshalling Type"); foreach (var method in inlineArrayCandidate.ElementType.GetMethods()) { dependencies.Add(factory.MethodEntrypoint(method), "inline array marshalling stub"); } } } }
private void AddDependenciesDueToPInvokeStruct(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) { if (MarshalHelpers.IsStructMarshallingRequired(type)) { dependencies.Add(factory.NecessaryTypeSymbol(type), "Struct Marshalling Stub"); var stub = (StructMarshallingThunk)GetStructMarshallingManagedToNativeStub(type); dependencies.Add(factory.MethodEntrypoint(stub), "Struct Marshalling stub"); dependencies.Add(factory.MethodEntrypoint(GetStructMarshallingNativeToManagedStub(type)), "Struct Marshalling stub"); dependencies.Add(factory.MethodEntrypoint(GetStructMarshallingCleanupStub(type)), "Struct Marshalling stub"); AddDependenciesDueToPInvokeStructDelegateField(ref dependencies, factory, type); } }
private void AddPInvokeParameterDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc parameter) { if (parameter.IsDelegate) { dependencies.Add(factory.NecessaryTypeSymbol(parameter), "Delegate Marshalling Stub"); dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetOpenStaticDelegateMarshallingStub(parameter)), "Delegate Marshalling Stub"); dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetClosedDelegateMarshallingStub(parameter)), "Delegate Marshalling Stub"); } else if (MarshalHelpers.IsStructMarshallingRequired(parameter)) { dependencies.Add(factory.ConstructedTypeSymbol(factory.InteropStubManager.GetStructMarshallingType(parameter)), "Struct Marshalling Type"); dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetStructMarshallingManagedToNativeStub(parameter)), "Struct Marshalling stub"); dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetStructMarshallingNativeToManagedStub(parameter)), "Struct Marshalling stub"); dependencies.Add(factory.MethodEntrypoint(factory.InteropStubManager.GetStructMarshallingCleanupStub(parameter)), "Struct Marshalling stub"); } }
private void AddParameterMarshallingDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method, TypeDesc type) { if (type.IsDelegate) { dependencies.Add(factory.DelegateMarshallingData((DefType)type), "Delegate marshaling"); } TypeSystemContext context = type.Context; if ((type.IsWellKnownType(WellKnownType.MulticastDelegate) || type == context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType)) { // If we hit this p/invoke as part of delegate marshalling (i.e. this is a delegate // that has another delegate in the signature), blame the delegate type, not the marshalling thunk. // This should ideally warn from the use site (e.g. where GetDelegateForFunctionPointer // is called) but it's currently hard to get a warning from those spots and this guarantees // we won't miss a spot (e.g. a p/invoke that has a delegate and that delegate contains // a System.Delegate parameter). MethodDesc reportedMethod = method; if (reportedMethod is Internal.IL.Stubs.DelegateMarshallingMethodThunk delegateThunkMethod) { reportedMethod = delegateThunkMethod.InvokeMethod; } _logger.LogWarning(reportedMethod, DiagnosticId.CorrectnessOfAbstractDelegatesCannotBeGuaranteed, DiagnosticUtilities.GetMethodSignatureDisplayName(method)); } // struct may contain delegate fields, hence we need to add dependencies for it if (type.IsByRef) { type = ((ParameterizedType)type).ParameterType; } if (MarshalHelpers.IsStructMarshallingRequired(type)) { foreach (FieldDesc field in type.GetFields()) { if (field.IsStatic) { continue; } AddParameterMarshallingDependencies(ref dependencies, factory, method, field.FieldType); } } }
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")); } }
private void AddDependenciesDueToPInvokeStruct(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) { if (MarshalHelpers.IsStructMarshallingRequired(type)) { dependencies.Add(factory.NecessaryTypeSymbol(type), "Struct Marshalling Stub"); var stub = (StructMarshallingThunk)GetStructMarshallingManagedToNativeStub(type); dependencies.Add(factory.MethodEntrypoint(stub), "Struct Marshalling stub"); dependencies.Add(factory.MethodEntrypoint(GetStructMarshallingNativeToManagedStub(type)), "Struct Marshalling stub"); dependencies.Add(factory.MethodEntrypoint(GetStructMarshallingCleanupStub(type)), "Struct Marshalling stub"); foreach (var inlineArrayCandidate in stub.GetInlineArrayCandidates()) { foreach (var method in inlineArrayCandidate.ElementType.GetMethods()) { dependencies.Add(factory.MethodEntrypoint(method), "inline array marshalling stub"); } } } }
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 })); }