/// <summary>
        /// Builds a native hashtable containing data about each manifest resource
        /// </summary>
        /// <returns></returns>
        private byte[] GenerateIndexBlob(NodeFactory factory)
        {
            NativeWriter    nativeWriter          = new NativeWriter();
            Section         indexHashtableSection = nativeWriter.NewSection();
            VertexHashtable indexHashtable        = new VertexHashtable();

            indexHashtableSection.Place(indexHashtable);

            // Build a table with a tuple of Assembly Full Name, Resource Name, Offset within the resource data blob, Length
            // for each resource.
            // This generates a hashtable for the convenience of managed code since there's
            // a reader for VertexHashtable, but not for VertexSequence.

            foreach (ResourceIndexData indexData in _resourceDataNode.GetOrCreateIndexData(factory))
            {
                Vertex asmName      = nativeWriter.GetStringConstant(indexData.AssemblyName);
                Vertex resourceName = nativeWriter.GetStringConstant(indexData.ResourceName);
                Vertex offsetVertex = nativeWriter.GetUnsignedConstant((uint)indexData.NativeOffset);
                Vertex lengthVertex = nativeWriter.GetUnsignedConstant((uint)indexData.Length);

                Vertex indexVertex = nativeWriter.GetTuple(asmName, resourceName);
                indexVertex = nativeWriter.GetTuple(indexVertex, offsetVertex);
                indexVertex = nativeWriter.GetTuple(indexVertex, lengthVertex);

                int hashCode = TypeHashingAlgorithms.ComputeNameHashCode(indexData.AssemblyName);
                indexHashtable.Append((uint)hashCode, indexHashtableSection.Place(indexVertex));
            }

            byte[] blob = nativeWriter.Save();
            _endSymbol.SetSymbolOffset(blob.Length);
            return(blob);
        }
Ejemplo n.º 2
0
        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 fieldMapHashTable = new VertexHashtable();

            Section hashTableSection = writer.NewSection();

            hashTableSection.Place(fieldMapHashTable);

            foreach (var fieldMapping in factory.MetadataManager.GetFieldMapping(factory))
            {
                FieldDesc field = fieldMapping.Entity;

                if (field.IsLiteral || field.HasRva)
                {
                    continue;
                }

                FieldTableFlags flags;
                if (field.IsThreadStatic)
                {
                    flags = FieldTableFlags.ThreadStatic;
                }
                else if (field.IsStatic)
                {
                    flags = FieldTableFlags.Static;

                    if (field.HasGCStaticBase)
                    {
                        flags |= FieldTableFlags.IsGcSection;
                    }

                    if (field.OwningType.HasInstantiation)
                    {
                        flags |= FieldTableFlags.FieldOffsetEncodedDirectly;
                    }
                }
                else
                {
                    flags = FieldTableFlags.Instance | FieldTableFlags.FieldOffsetEncodedDirectly;
                }

                if (fieldMapping.MetadataHandle != 0)
                {
                    flags |= FieldTableFlags.HasMetadataHandle;
                }

                if (field.OwningType.IsCanonicalSubtype(CanonicalFormKind.Universal))
                {
                    flags |= FieldTableFlags.IsUniversalCanonicalEntry;
                }

                // Grammar of a hash table entry:
                // Flags + DeclaringType + MdHandle or Name + Cookie or Ordinal or Offset

                Vertex vertex = writer.GetUnsignedConstant((uint)flags);

                uint declaringTypeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(field.OwningType));
                vertex = writer.GetTuple(vertex,
                                         writer.GetUnsignedConstant(declaringTypeId));

                if ((flags & FieldTableFlags.HasMetadataHandle) != 0)
                {
                    // Only store the offset portion of the metadata handle to get better integer compression
                    vertex = writer.GetTuple(vertex,
                                             writer.GetUnsignedConstant((uint)(fieldMapping.MetadataHandle & MetadataManager.MetadataOffsetMask)));
                }
                else
                {
                    // No metadata handle means we need to store name
                    vertex = writer.GetTuple(vertex,
                                             writer.GetStringConstant(field.Name));
                }

                if ((flags & FieldTableFlags.IsUniversalCanonicalEntry) != 0)
                {
                    // TODO: USG
                    continue;
                }
                else
                {
                    switch (flags & FieldTableFlags.StorageClass)
                    {
                    case FieldTableFlags.ThreadStatic:
                        // TODO: thread statics
                        continue;

                    case FieldTableFlags.Static:
                    {
                        if (field.OwningType.HasInstantiation)
                        {
                            vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)(field.Offset.AsInt)));
                        }
                        else
                        {
                            MetadataType metadataType = (MetadataType)field.OwningType;

                            ISymbolNode staticsNode = field.HasGCStaticBase ?
                                                      factory.TypeGCStaticsSymbol(metadataType) :
                                                      factory.TypeNonGCStaticsSymbol(metadataType);

                            if (!field.HasGCStaticBase || factory.Target.Abi == TargetAbi.ProjectN)
                            {
                                uint index = _externalReferences.GetIndex(staticsNode, field.Offset.AsInt);
                                vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(index));
                            }
                            else
                            {
                                Debug.Assert(field.HasGCStaticBase && factory.Target.Abi == TargetAbi.CoreRT);

                                uint index = _externalReferences.GetIndex(staticsNode);
                                vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(index));
                                vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)(field.Offset.AsInt)));
                            }
                        }
                    }
                    break;

                    case FieldTableFlags.Instance:
                        vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)field.Offset.AsInt));
                        break;
                    }
                }

                int hashCode = field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific).GetHashCode();
                fieldMapHashTable.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 }));
        }
        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 structEntry in ((CompilerGeneratedInteropStubManager)factory.InteropStubManager).GetStructMarshallingTypes())
            {
                // the order of data written is as follows:
                //  0. managed struct type
                //  1. struct marshalling thunk
                //  2. struct unmarshalling thunk
                //  3. struct cleanup thunk
                //  4. size
                //  5. NumFields<< 1 | HasInvalidLayout
                //  6  for each field
                //      a. name
                //      b. offset

                var    structType = structEntry.StructType;
                var    nativeType = structEntry.NativeStructType;
                Vertex thunks     = writer.GetTuple(
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(structEntry.MarshallingThunk))),
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(structEntry.UnmarshallingThunk))),
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(structEntry.CleanupThunk))));

                uint size = (uint)nativeType.InstanceByteCount.AsInt;
                uint mask = (uint)(nativeType.Fields.Length << 1) | (uint)(nativeType.HasInvalidLayout ? 1 : 0);

                Vertex data = writer.GetTuple(
                    thunks,
                    writer.GetUnsignedConstant(size),
                    writer.GetUnsignedConstant(mask)
                    );

                for (int i = 0; i < nativeType.Fields.Length; i++)
                {
                    data = writer.GetTuple(
                        data,
                        writer.GetStringConstant(nativeType.Fields[i].Name),
                        writer.GetUnsignedConstant((uint)nativeType.Fields[i].Offset.AsInt)
                        );
                }

                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 }));
        }
Ejemplo n.º 4
0
        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 }));
        }