示例#1
0
        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);
                    }
                }
            }
        }
示例#2
0
        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);
            }
        }
示例#3
0
        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);
                }
            }
        }
示例#4
0
        /// <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");
                            }
                        }
                    }
                }
            }
        }
示例#5
0
        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);
            }
        }
示例#7
0
        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);
                }
            }
        }
示例#9
0
        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 }));
        }