} // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            Debug.Assert(ElementType == null ||
                ElementType.HandleType == HandleType.TypeDefinition ||
                ElementType.HandleType == HandleType.TypeReference ||
                ElementType.HandleType == HandleType.TypeSpecification);
            writer.Write(ElementType);
            writer.Write(Rank);
            writer.Write(Sizes);
            writer.Write(LowerBounds);
        } // Save
        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 ISymbolNode[] { this });

            var writer = new NativeWriter();
            var typeMapHashTable = new VertexHashtable();

            Section hashTableSection = writer.NewSection();
            hashTableSection.Place(typeMapHashTable);

            foreach (var mappingEntry in factory.MetadataManager.GetTypeDefinitionMapping())
            {
                if (!factory.CompilationModuleGroup.ContainsType(mappingEntry.Entity))
                    continue;

                // We are looking for any EEType - constructed or not, it has to be in the mapping
                // table so that we can map it to metadata.
                EETypeNode node = null;
                
                if (!mappingEntry.Entity.IsGenericDefinition)
                {
                    node = factory.ConstructedTypeSymbol(mappingEntry.Entity) as EETypeNode;
                }
                
                if (node == null || !node.Marked)
                {
                    // This might have been a typeof() expression.
                    node = factory.NecessaryTypeSymbol(mappingEntry.Entity) as EETypeNode;
                }

                if (node.Marked)
                {
                    Vertex vertex = writer.GetTuple(
                        writer.GetUnsignedConstant(_externalReferences.GetIndex(node)),
                        writer.GetUnsignedConstant((uint)mappingEntry.MetadataHandle)
                        );

                    int hashCode = node.Type.GetHashCode();
                    typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex));
                }
            }

            MemoryStream ms = new MemoryStream();
            writer.Save(ms);
            byte[] hashTableBytes = ms.ToArray();

            _endSymbol.SetSymbolOffset(hashTableBytes.Length);

            return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolNode[] { 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 ISymbolNode[] { this });

            var writer = new NativeWriter();
            var typeMapHashTable = new VertexHashtable();

            Section hashTableSection = writer.NewSection();
            hashTableSection.Place(typeMapHashTable);

            foreach (var node in factory.MetadataManager.GetCctorContextMapping())
            {
                MetadataType type = node.Type;

                Debug.Assert(factory.TypeSystemContext.HasLazyStaticConstructor(type));

                // If this type doesn't generate an EEType in the current compilation, don't report it in the table.
                // If nobody can get to the EEType, they can't ask to run the cctor. We don't need to force generate it.
                if (!factory.MetadataManager.TypeGeneratesEEType(type))
                    continue;

                // Hash table is hashed by the hashcode of the owning type.
                // Each entry has: the EEType of the type, followed by the non-GC static base.
                // The non-GC static base is prefixed by the class constructor context.

                // Unfortunately we need to adjust for the cctor context just so that we can subtract it again at runtime...
                int delta = NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.TypeSystemContext.Target, type);

                Vertex vertex = writer.GetTuple(
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(type))),
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(node, delta))
                    );

                int hashCode = type.GetHashCode();
                typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex));
            }

            MemoryStream ms = new MemoryStream();
            writer.Save(ms);
            byte[] hashTableBytes = ms.ToArray();

            _endSymbol.SetSymbolOffset(hashTableBytes.Length);

            return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolNode[] { 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 ISymbolNode[] { this });

            var writer = new NativeWriter();
            var typeMapHashTable = new VertexHashtable();

            Section hashTableSection = writer.NewSection();
            hashTableSection.Place(typeMapHashTable);

            foreach (var mappingEntry in factory.MetadataManager.GetTypeDefinitionMapping())
            {
                if (!factory.CompilationModuleGroup.ContainsType(mappingEntry.Entity))
                    continue;

                // Types that don't have EETypes don't need mapping table entries because there's no risk of them
                // not unifying to the same System.Type at runtime.
                if (!factory.MetadataManager.TypeGeneratesEEType(mappingEntry.Entity))
                    continue;
                
                // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted.
                IEETypeNode typeSymbol = factory.NecessaryTypeSymbol(mappingEntry.Entity);

                Vertex vertex = writer.GetTuple(
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(typeSymbol)),
                    writer.GetUnsignedConstant((uint)mappingEntry.MetadataHandle)
                    );

                int hashCode = typeSymbol.Type.GetHashCode();
                typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex));
            }

            MemoryStream ms = new MemoryStream();
            writer.Save(ms);
            byte[] hashTableBytes = ms.ToArray();

            _endSymbol.SetSymbolOffset(hashTableBytes.Length);

            return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolNode[] { this, _endSymbol });
        }
Exemple #5
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 ISymbolNode[] { this });

            var writer = new NativeWriter();
            var typeMapHashTable = new VertexHashtable();

            Section hashTableSection = writer.NewSection();
            hashTableSection.Place(typeMapHashTable);

            foreach (var arrayType in factory.MetadataManager.GetArrayTypeMapping())
            {
                if (!arrayType.IsSzArray)
                    continue;

                if (!factory.MetadataManager.TypeGeneratesEEType(arrayType))
                    continue;

                // TODO: This should only be emitted for arrays of value types. The type loader builds everything else.

                // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted.
                IEETypeNode arrayTypeSymbol = factory.NecessaryTypeSymbol(arrayType);

                Vertex vertex = writer.GetUnsignedConstant(_externalReferences.GetIndex(arrayTypeSymbol));

                int hashCode = arrayType.GetHashCode();
                typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex));
            }

            MemoryStream ms = new MemoryStream();
            writer.Save(ms);
            byte[] hashTableBytes = ms.ToArray();

            _endSymbol.SetSymbolOffset(hashTableBytes.Length);

            return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolNode[] { this, _endSymbol });
        }
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            Debug.Assert(MethodBody == null ||
                MethodBody.HandleType == HandleType.QualifiedMethod ||
                MethodBody.HandleType == HandleType.MemberReference);
            writer.Write(MethodBody);
            Debug.Assert(MethodDeclaration == null ||
                MethodDeclaration.HandleType == HandleType.QualifiedMethod ||
                MethodDeclaration.HandleType == HandleType.MemberReference);
            writer.Write(MethodDeclaration);
        } // Save
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            Debug.Assert(Parent == null ||
                Parent.HandleType == HandleType.TypeDefinition ||
                Parent.HandleType == HandleType.TypeReference ||
                Parent.HandleType == HandleType.TypeSpecification);
            writer.Write(Parent);
            writer.Write(Name);
            Debug.Assert(Signature == null ||
                Signature.HandleType == HandleType.MethodSignature ||
                Signature.HandleType == HandleType.FieldSignature);
            writer.Write(Signature);
            writer.Write(CustomAttributes);
        } // Save
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            writer.Write(Flags);
            Debug.Assert(Type == null ||
                Type.HandleType == HandleType.TypeDefinition ||
                Type.HandleType == HandleType.TypeReference ||
                Type.HandleType == HandleType.TypeSpecification);
            writer.Write(Type);
            Debug.Assert(Value == null ||
                Value.HandleType == HandleType.TypeDefinition ||
                Value.HandleType == HandleType.TypeReference ||
                Value.HandleType == HandleType.TypeSpecification ||
                Value.HandleType == HandleType.ConstantBooleanArray ||
                Value.HandleType == HandleType.ConstantBooleanValue ||
                Value.HandleType == HandleType.ConstantByteArray ||
                Value.HandleType == HandleType.ConstantByteValue ||
                Value.HandleType == HandleType.ConstantCharArray ||
                Value.HandleType == HandleType.ConstantCharValue ||
                Value.HandleType == HandleType.ConstantDoubleArray ||
                Value.HandleType == HandleType.ConstantDoubleValue ||
                Value.HandleType == HandleType.ConstantHandleArray ||
                Value.HandleType == HandleType.ConstantInt16Array ||
                Value.HandleType == HandleType.ConstantInt16Value ||
                Value.HandleType == HandleType.ConstantInt32Array ||
                Value.HandleType == HandleType.ConstantInt32Value ||
                Value.HandleType == HandleType.ConstantInt64Array ||
                Value.HandleType == HandleType.ConstantInt64Value ||
                Value.HandleType == HandleType.ConstantReferenceValue ||
                Value.HandleType == HandleType.ConstantSByteArray ||
                Value.HandleType == HandleType.ConstantSByteValue ||
                Value.HandleType == HandleType.ConstantSingleArray ||
                Value.HandleType == HandleType.ConstantSingleValue ||
                Value.HandleType == HandleType.ConstantStringArray ||
                Value.HandleType == HandleType.ConstantStringValue ||
                Value.HandleType == HandleType.ConstantUInt16Array ||
                Value.HandleType == HandleType.ConstantUInt16Value ||
                Value.HandleType == HandleType.ConstantUInt32Array ||
                Value.HandleType == HandleType.ConstantUInt32Value ||
                Value.HandleType == HandleType.ConstantUInt64Array ||
                Value.HandleType == HandleType.ConstantUInt64Value);
            writer.Write(Value);
        } // Save
        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 }));
            }

            NativeWriter writer      = new NativeWriter();
            Section      section     = writer.NewSection();
            VertexArray  vertexArray = new VertexArray(section);

            section.Place(vertexArray);

            Dictionary <byte[], BlobVertex> blobCache = new Dictionary <byte[], BlobVertex>(ByteArrayComparer.Instance);

            foreach (MethodWithGCInfo method in factory.EnumerateCompiledMethods())
            {
                MemoryStream methodDebugBlob = new MemoryStream();

                byte[] bounds = method.DebugLocInfos;
                byte[] vars   = method.DebugVarInfos;

                NibbleWriter nibbleWriter = new NibbleWriter();
                nibbleWriter.WriteUInt((uint)(bounds?.Length ?? 0));
                nibbleWriter.WriteUInt((uint)(vars?.Length ?? 0));

                byte[] header = nibbleWriter.ToArray();
                methodDebugBlob.Write(header, 0, header.Length);

                if (bounds?.Length > 0)
                {
                    methodDebugBlob.Write(bounds, 0, bounds.Length);
                }

                if (vars?.Length > 0)
                {
                    methodDebugBlob.Write(vars, 0, vars.Length);
                }

                byte[] debugBlobArrayKey = methodDebugBlob.ToArray();
                if (!blobCache.TryGetValue(debugBlobArrayKey, out BlobVertex debugBlob))
                {
                    debugBlob = new BlobVertex(methodDebugBlob.ToArray());
                    blobCache.Add(debugBlobArrayKey, debugBlob);
                }
                vertexArray.Set(factory.RuntimeFunctionsTable.GetIndex(method), new DebugInfoVertex(debugBlob));
            }

            vertexArray.ExpandLayout();

            MemoryStream writerContent = new MemoryStream();

            writer.Save(writerContent);

            return(new ObjectData(
                       data: writerContent.ToArray(),
                       relocs: null,
                       alignment: 8,
                       definedSymbols: new ISymbolDefinitionNode[] { this }));
        }
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            writer.Write(Scope);
            writer.Write(Name);
            writer.Write(NestedTypes);
            writer.Write(CustomAttributes);
        } // Save
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            Debug.Assert(ElementType == null ||
                ElementType.HandleType == HandleType.TypeDefinition ||
                ElementType.HandleType == HandleType.TypeReference ||
                ElementType.HandleType == HandleType.TypeSpecification ||
                ElementType.HandleType == HandleType.ModifiedType);
            writer.Write(ElementType);
        } // Save
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            Debug.Assert(ParentScopeOrNamespace == null ||
                ParentScopeOrNamespace.HandleType == HandleType.NamespaceReference ||
                ParentScopeOrNamespace.HandleType == HandleType.ScopeReference);
            writer.Write(ParentScopeOrNamespace);
            writer.Write(Name);
        } // Save
 public static void Write(this NativeWriter writer, double value)
 {
     writer.WriteDouble(value);
 }
 public static void Write(this NativeWriter writer, float value)
 {
     writer.WriteFloat(value);
 }
 public static void Write(this NativeWriter writer, char value)
 {
     writer.WriteUnsigned((uint)value);
 }
 public static void Write(this NativeWriter writer, string value)
 {
     Debug.Assert(value != null);
     writer.WriteString(value);
 }
 public static void Write(this NativeWriter writer, long value)
 {
     writer.WriteSignedLong(value);
 }
 public static void Write(this NativeWriter writer, uint value)
 {
     writer.WriteUnsigned(value);
 }
 public static void Write(this NativeWriter writer, short value)
 {
     writer.WriteSigned(value);
 }
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            writer.Write(Attributes);
            writer.Write(Method);
        } // Save
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            Debug.Assert(ParentScopeOrNamespace == null ||
                ParentScopeOrNamespace.HandleType == HandleType.NamespaceDefinition ||
                ParentScopeOrNamespace.HandleType == HandleType.ScopeDefinition);
            writer.Write(ParentScopeOrNamespace);
            writer.Write(Name);
            writer.Write(TypeDefinitions);
            writer.Write(TypeForwarders);
            writer.Write(NamespaceDefinitions);
        } // Save
Exemple #22
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 }));
        }
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            writer.Write(CallingConvention);
            Debug.Assert(Type == null ||
                Type.HandleType == HandleType.TypeDefinition ||
                Type.HandleType == HandleType.TypeReference ||
                Type.HandleType == HandleType.TypeSpecification ||
                Type.HandleType == HandleType.ModifiedType);
            writer.Write(Type);
            Debug.Assert(Parameters.TrueForAll(handle => handle == null ||
                handle.HandleType == HandleType.TypeDefinition ||
                handle.HandleType == HandleType.TypeReference ||
                handle.HandleType == HandleType.TypeSpecification ||
                handle.HandleType == HandleType.ModifiedType));
            writer.Write(Parameters);
        } // Save
Exemple #24
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 }));
            }

            Dictionary <EcmaMethod, HashSet <EcmaMethod> > inlineeToInliners = new Dictionary <EcmaMethod, HashSet <EcmaMethod> >();

            // Build a map from inlinee to the list of inliners
            // We are only interested in the generic definitions of these.
            foreach (MethodWithGCInfo methodNode in factory.EnumerateCompiledMethods(_module, CompiledMethodCategory.All))
            {
                MethodDesc[] inlinees          = methodNode.InlinedMethods;
                MethodDesc   inliner           = methodNode.Method;
                EcmaMethod   inlinerDefinition = (EcmaMethod)inliner.GetTypicalMethodDefinition();

                // Only encode inlining info for inliners within the active module
                Debug.Assert(inlinerDefinition.Module == _module);

                foreach (MethodDesc inlinee in inlinees)
                {
                    MethodDesc inlineeDefinition = inlinee.GetTypicalMethodDefinition();
                    if (!(inlineeDefinition is EcmaMethod ecmaInlineeDefinition))
                    {
                        // We don't record non-ECMA methods because they don't have tokens that
                        // diagnostic tools could reason about anyway.
                        continue;
                    }

                    if (!factory.CompilationModuleGroup.VersionsWithMethodBody(inlinee))
                    {
                        // We cannot record inlining info across version bubble as cross-bubble assemblies
                        // are not guaranteed to preserve token values. Only non-versionable methods may be
                        // inlined across the version bubble.
                        Debug.Assert(inlinee.IsNonVersionable());
                        continue;
                    }

                    if (!inlineeToInliners.TryGetValue(ecmaInlineeDefinition, out HashSet <EcmaMethod> inliners))
                    {
                        inliners = new HashSet <EcmaMethod>();
                        inlineeToInliners.Add(ecmaInlineeDefinition, inliners);
                    }
                    inliners.Add((EcmaMethod)inlinerDefinition);
                }
            }

            // Serialize the map as a hash table
            NativeWriter writer  = new NativeWriter();
            Section      section = writer.NewSection();

            VertexHashtable hashtable = new VertexHashtable();

            section.Place(hashtable);

            foreach (var inlineeWithInliners in inlineeToInliners)
            {
                EcmaMethod inlinee    = inlineeWithInliners.Key;
                int        inlineeRid = MetadataTokens.GetRowNumber(inlinee.Handle);
                int        hashCode   = ReadyToRunHashCode.ModuleNameHashCode(inlinee.Module);
                hashCode ^= inlineeRid;

                // Format of the sequence:
                // Inlinee RID with flag in the lowest bit
                // - if flag is set, followed by module ID
                // Followed by inliner RIDs deltas with flag in the lowest bit
                // - if flag is set, followed by module ID

                var sig = new VertexSequence();

                bool isForeignInlinee = inlinee.Module != _module;
                sig.Append(new UnsignedConstant((uint)(inlineeRid << 1 | (isForeignInlinee ? 1 : 0))));
                if (isForeignInlinee)
                {
                    sig.Append(new UnsignedConstant((uint)factory.ManifestMetadataTable.ModuleToIndex(inlinee.Module)));
                }

                List <EcmaMethod> sortedInliners = new List <EcmaMethod>(inlineeWithInliners.Value);
                sortedInliners.MergeSort((a, b) =>
                {
                    if (a == b)
                    {
                        return(0);
                    }

                    int aRid = MetadataTokens.GetRowNumber(a.Handle);
                    int bRid = MetadataTokens.GetRowNumber(b.Handle);
                    if (aRid < bRid)
                    {
                        return(-1);
                    }
                    else if (aRid > bRid)
                    {
                        return(1);
                    }

                    int result = a.Module.CompareTo(b.Module);
                    Debug.Assert(result != 0);
                    return(result);
                });

                int baseRid = 0;
                foreach (EcmaMethod inliner in sortedInliners)
                {
                    int inlinerRid = MetadataTokens.GetRowNumber(inliner.Handle);
                    int ridDelta   = inlinerRid - baseRid;
                    baseRid = inlinerRid;
                    Debug.Assert(ridDelta >= 0);
                    bool isForeignInliner = inliner.Module != _module;
                    sig.Append(new UnsignedConstant((uint)(ridDelta << 1 | (isForeignInliner ? 1 : 0))));
                    if (isForeignInliner)
                    {
                        sig.Append(new UnsignedConstant((uint)factory.ManifestMetadataTable.ModuleToIndex(inliner.Module)));
                    }
                }

                hashtable.Append((uint)hashCode, section.Place(sig));
            }

            MemoryStream writerContent = new MemoryStream();

            writer.Save(writerContent);

            return(new ObjectData(
                       data: writerContent.ToArray(),
                       relocs: null,
                       alignment: 8,
                       definedSymbols: new ISymbolDefinitionNode[] { this }));
        }
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            writer.Write(Flags);
            writer.Write(Name);
            writer.Write(MajorVersion);
            writer.Write(MinorVersion);
            writer.Write(BuildNumber);
            writer.Write(RevisionNumber);
            writer.Write(PublicKeyOrToken);
            writer.Write(Culture);
            writer.Write(CustomAttributes);
        } // Save
 internal override void Save(NativeWriter writer)
 {
     writer.WriteUInt32(Signature);
     writer.Write(ScopeDefinitions);
 }
 public static void Write(this NativeWriter writer, sbyte value)
 {
     writer.WriteUInt8((byte)value);
 }
        public void Write(Stream stream)
        {
            _visitor = new RecordVisitor();

            _visitor.Run(ScopeDefinitions.AsEnumerable());
            _visitor.Run(UnreachableTypeReferences.AsEnumerable());

            IEnumerable <MetadataRecord> records = _visitor.Graph.Vertices.Where(v => v != _visitor.MetaSourceVertex);

            var writer = new NativeWriter();

            var section = writer.NewSection();

            _metadataHeader.ScopeDefinitions = ScopeDefinitions;
            section.Place(_metadataHeader);

            foreach (var rec in records)
            {
                section.Place(rec);
            }

            writer.Save(stream);

            if (LogWriter != null)
            {
                // Create a CSV file, one line per meta-data record.
                LogWriter.WriteLine("Handle, Kind, Name, Children");
                // needed to enumerate children of a meta-data record
                var childVisitor = new WriteChildrenVisitor(LogWriter);

                foreach (var rec in records)
                {
                    // First the metadata handle
                    LogWriter.Write(rec.Handle._value.ToString("x8"));
                    LogWriter.Write(", ");

                    // Next the handle type
                    LogWriter.Write(rec.HandleType.ToString());
                    LogWriter.Write(", ");

                    // 3rd, the name, Quote the string if not already quoted
                    string asString      = rec.ToString(false);
                    bool   alreadyQuoted = asString.StartsWith("\"") && asString.EndsWith("\"");
                    if (!alreadyQuoted)
                    {
                        LogWriter.Write("\"");
                        asString = asString.Replace("\\", "\\\\").Replace("\"", "\\\"");  // Quote " and \
                    }
                    // TODO we assume that a quoted string is escaped properly
                    LogWriter.Write(asString);

                    if (!alreadyQuoted)
                    {
                        LogWriter.Write("\"");
                    }
                    LogWriter.Write(", ");

                    // Finally write out the handle IDs for my children
                    LogWriter.Write("\"");
                    childVisitor.Reset();
                    rec.Visit(childVisitor);
                    LogWriter.Write("\"");
                    LogWriter.WriteLine();
                }
                LogWriter.Flush();
            }
        }
 internal override void Save(NativeWriter writer)
 {
     throw new NotImplementedException();
 }
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, Array.Empty <ISymbolDefinitionNode>()));
            }

            NativeWriter hashtableWriter = new NativeWriter();

            Section         hashtableSection = hashtableWriter.NewSection();
            VertexHashtable vertexHashtable  = new VertexHashtable();

            hashtableSection.Place(vertexHashtable);

            Dictionary <byte[], BlobVertex> uniqueFixups     = new Dictionary <byte[], BlobVertex>(ByteArrayComparer.Instance);
            Dictionary <byte[], BlobVertex> uniqueSignatures = new Dictionary <byte[], BlobVertex>(ByteArrayComparer.Instance);

            foreach (MethodWithGCInfo method in factory.EnumerateCompiledMethods(null, CompiledMethodCategory.Instantiated))
            {
                Debug.Assert(method.Method.HasInstantiation || method.Method.OwningType.HasInstantiation);

                int methodIndex = factory.RuntimeFunctionsTable.GetIndex(method);

                // In composite R2R format, always enforce owning type to let us share generic instantiations among modules
                EcmaMethod  typicalMethod = (EcmaMethod)method.Method.GetTypicalMethodDefinition();
                ModuleToken moduleToken   = new ModuleToken(typicalMethod.Module, typicalMethod.Handle);

                ArraySignatureBuilder signatureBuilder = new ArraySignatureBuilder();
                signatureBuilder.EmitMethodSignature(
                    new MethodWithToken(method.Method, moduleToken, constrainedType: null, unboxing: false, context: null),
                    enforceDefEncoding: true,
                    enforceOwningType: _factory.CompilationModuleGroup.EnforceOwningType(moduleToken.Module),
                    factory.SignatureContext,
                    isInstantiatingStub: false);
                byte[]     signature = signatureBuilder.ToArray();
                BlobVertex signatureBlob;
                if (!uniqueSignatures.TryGetValue(signature, out signatureBlob))
                {
                    signatureBlob = new BlobVertex(signature);
                    hashtableSection.Place(signatureBlob);
                    uniqueSignatures.Add(signature, signatureBlob);
                }

                byte[]     fixup     = method.GetFixupBlob(factory);
                BlobVertex fixupBlob = null;
                if (fixup != null && !uniqueFixups.TryGetValue(fixup, out fixupBlob))
                {
                    fixupBlob = new BlobVertex(fixup);
                    hashtableSection.Place(fixupBlob);
                    uniqueFixups.Add(fixup, fixupBlob);
                }

                EntryPointVertex entryPointVertex = new EntryPointWithBlobVertex((uint)methodIndex, fixupBlob, signatureBlob);
                hashtableSection.Place(entryPointVertex);
                vertexHashtable.Append(unchecked ((uint)ReadyToRunHashCode.MethodHashCode(method.Method)), entryPointVertex);
            }

            MemoryStream hashtableContent = new MemoryStream();

            hashtableWriter.Save(hashtableContent);
            return(new ObjectData(
                       data: hashtableContent.ToArray(),
                       relocs: null,
                       alignment: 8,
                       definedSymbols: new ISymbolDefinitionNode[] { this }));
        }
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            writer.Write(Number);
            writer.Write(Flags);
            writer.Write(Kind);
            writer.Write(Name);
            Debug.Assert(Constraints.TrueForAll(handle => handle == null ||
                handle.HandleType == HandleType.TypeDefinition ||
                handle.HandleType == HandleType.TypeReference ||
                handle.HandleType == HandleType.TypeSpecification));
            writer.Write(Constraints);
            writer.Write(CustomAttributes);
        } // Save
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            // Dependencies for this node are tracked by the method code nodes
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this }));
            }

            // Ensure the native layout data has been saved, in order to get valid Vertex offsets for the signature Vertices
            factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory);

            NativeWriter    nativeWriter  = new NativeWriter();
            VertexHashtable hashtable     = new VertexHashtable();
            Section         nativeSection = nativeWriter.NewSection();

            nativeSection.Place(hashtable);

            foreach (TypeDesc type in factory.MetadataManager.GetTypesWithConstructedEETypes())
            {
                if (!IsEligibleToHaveATemplate(type))
                {
                    continue;
                }

                if (factory.Target.Abi == TargetAbi.ProjectN)
                {
                    // If the type does not have fully constructed type, don't emit it.
                    // TODO: Remove the workaround once we stop using the STS dependency analysis.
                    if (!factory.ConstructedTypeSymbol(type).Marked)
                    {
                        continue;
                    }
                }

                // Type's native layout info
                DefType defType = GetActualTemplateTypeForType(factory, type);
                NativeLayoutTemplateTypeLayoutVertexNode templateNode = factory.NativeLayout.TemplateTypeLayout(defType);

                // If this template isn't considered necessary, don't emit it.
                if (!templateNode.Marked)
                {
                    continue;
                }
                Vertex nativeLayout = templateNode.SavedVertex;

                // Hashtable Entry
                Vertex entry = nativeWriter.GetTuple(
                    nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(factory.NecessaryTypeSymbol(type))),
                    nativeWriter.GetUnsignedConstant((uint)nativeLayout.VertexOffset));

                // Add to the hash table, hashed by the containing type's hashcode
                uint hashCode = (uint)type.GetHashCode();
                hashtable.Append(hashCode, nativeSection.Place(entry));
            }

            byte[] streamBytes = nativeWriter.Save();

            _endSymbol.SetSymbolOffset(streamBytes.Length);

            return(new ObjectData(streamBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }));
        }
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            writer.Write(Flags);
            writer.Write(ImplFlags);
            writer.Write(Name);
            writer.Write(Signature);
            writer.Write(Parameters);
            writer.Write(GenericParameters);
            writer.Write(CustomAttributes);
        } // Save
        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 }));
            }

            // Ensure the native layout blob has been saved
            factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory);

            var writer           = new NativeWriter();
            var typeMapHashTable = new VertexHashtable();

            Section hashTableSection = writer.NewSection();

            hashTableSection.Place(typeMapHashTable);

            // Get a list of all methods that have a method body and metadata from the metadata manager.
            foreach (var mappingEntry in factory.MetadataManager.GetMethodMapping(factory))
            {
                MethodDesc method = mappingEntry.Entity;

                if (!factory.MetadataManager.ShouldMethodBeInInvokeMap(method))
                {
                    continue;
                }

                bool useUnboxingStub = method.OwningType.IsValueType && !method.Signature.IsStatic;

                InvokeTableFlags flags = 0;

                if (method.HasInstantiation)
                {
                    flags |= InvokeTableFlags.IsGenericMethod;
                }

                if (method.GetCanonMethodTarget(CanonicalFormKind.Specific).RequiresInstArg())
                {
                    bool goesThroughInstantiatingUnboxingThunk = method.OwningType.IsValueType && !method.Signature.IsStatic && !method.HasInstantiation;
                    if (!goesThroughInstantiatingUnboxingThunk)
                    {
                        flags |= InvokeTableFlags.RequiresInstArg;
                    }
                }

                if (method.IsDefaultConstructor)
                {
                    flags |= InvokeTableFlags.IsDefaultConstructor;
                }

                if (ReflectionVirtualInvokeMapNode.NeedsVirtualInvokeInfo(method))
                {
                    flags |= InvokeTableFlags.HasVirtualInvoke;
                }

                if (!method.IsAbstract)
                {
                    flags |= InvokeTableFlags.HasEntrypoint;
                }

                if (mappingEntry.MetadataHandle != 0)
                {
                    flags |= InvokeTableFlags.HasMetadataHandle;
                }

                if (!factory.MetadataManager.HasReflectionInvokeStubForInvokableMethod(method))
                {
                    flags |= InvokeTableFlags.NeedsParameterInterpretation;
                }

                if (method.IsCanonicalMethod(CanonicalFormKind.Universal))
                {
                    flags |= InvokeTableFlags.IsUniversalCanonicalEntry;
                }

                // TODO: native signature for P/Invokes and UnmanagedCallersOnly methods
                if (method.IsRawPInvoke() || method.IsUnmanagedCallersOnly)
                {
                    continue;
                }

                // Grammar of an entry in the hash table:
                // Flags + DeclaringType + MetadataHandle/NameAndSig + Entrypoint + DynamicInvokeMethod + [NumGenericArgs + GenericArgs]

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

                if ((flags & InvokeTableFlags.HasMetadataHandle) != 0)
                {
                    // Only store the offset portion of the metadata handle to get better integer compression
                    vertex = writer.GetTuple(vertex,
                                             writer.GetUnsignedConstant((uint)(mappingEntry.MetadataHandle & MetadataManager.MetadataOffsetMask)));
                }
                else
                {
                    var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition()));
                    vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset));
                }

                // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted.
                IEETypeNode owningTypeSymbol = factory.NecessaryTypeSymbol(method.OwningType);
                vertex = writer.GetTuple(vertex,
                                         writer.GetUnsignedConstant(_externalReferences.GetIndex(owningTypeSymbol)));

                if ((flags & InvokeTableFlags.HasEntrypoint) != 0)
                {
                    vertex = writer.GetTuple(vertex,
                                             writer.GetUnsignedConstant(_externalReferences.GetIndex(
                                                                            factory.MethodEntrypoint(method.GetCanonMethodTarget(CanonicalFormKind.Specific), useUnboxingStub))));
                }

                if ((flags & InvokeTableFlags.NeedsParameterInterpretation) == 0)
                {
                    MethodDesc canonInvokeStubMethod = factory.MetadataManager.GetCanonicalReflectionInvokeStub(method);
                    if (canonInvokeStubMethod.IsSharedByGenericInstantiations)
                    {
                        vertex = writer.GetTuple(vertex,
                                                 writer.GetUnsignedConstant(((uint)factory.MetadataManager.DynamicInvokeTemplateData.GetIdForMethod(canonInvokeStubMethod, factory) << 1) | 1));
                    }
                    else
                    {
                        vertex = writer.GetTuple(vertex,
                                                 writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(canonInvokeStubMethod)) << 1));
                    }
                }

                if ((flags & InvokeTableFlags.IsGenericMethod) != 0)
                {
                    if ((flags & InvokeTableFlags.IsUniversalCanonicalEntry) != 0)
                    {
                        var nameAndSigGenericMethod = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(method));
                        vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)nameAndSigGenericMethod.SavedVertex.VertexOffset));
                    }
                    else if ((flags & InvokeTableFlags.RequiresInstArg) == 0 || (flags & InvokeTableFlags.HasEntrypoint) == 0)
                    {
                        VertexSequence args = new VertexSequence();
                        for (int i = 0; i < method.Instantiation.Length; i++)
                        {
                            uint argId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(method.Instantiation[i]));
                            args.Append(writer.GetUnsignedConstant(argId));
                        }
                        vertex = writer.GetTuple(vertex, args);
                    }
                    else
                    {
                        uint dictionaryId = _externalReferences.GetIndex(factory.MethodGenericDictionary(method));
                        vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(dictionaryId));
                    }
                }

                int hashCode = method.GetCanonMethodTarget(CanonicalFormKind.Specific).OwningType.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 }));
        }
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            Debug.Assert(Method == null ||
                Method.HandleType == HandleType.QualifiedMethod ||
                Method.HandleType == HandleType.MemberReference);
            writer.Write(Method);
            Debug.Assert(GenericTypeArguments.TrueForAll(handle => handle == null ||
                handle.HandleType == HandleType.TypeDefinition ||
                handle.HandleType == HandleType.TypeReference ||
                handle.HandleType == HandleType.TypeSpecification));
            writer.Write(GenericTypeArguments);
            writer.Write(CustomAttributes);
        } // Save
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            // Dependencies for this node are tracked by the method code nodes
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this }));
            }

            // Ensure the native layout data has been saved, in order to get valid Vertex offsets for the signature Vertices
            factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory);

            NativeWriter    nativeWriter  = new NativeWriter();
            VertexHashtable hashtable     = new VertexHashtable();
            Section         nativeSection = nativeWriter.NewSection();

            nativeSection.Place(hashtable);


            foreach (MethodDesc method in factory.MetadataManager.GetCompiledMethods())
            {
                if (!IsMethodEligibleForTracking(method))
                {
                    continue;
                }

                // Get the method pointer vertex

                bool        getUnboxingStub      = method.OwningType.IsValueType && !method.Signature.IsStatic;
                IMethodNode methodEntryPointNode = factory.MethodEntrypoint(method, getUnboxingStub);
                Vertex      methodPointer        = nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(methodEntryPointNode));

                // Get native layout vertices for the declaring type

                ISymbolNode declaringTypeNode = factory.NecessaryTypeSymbol(method.OwningType);
                Vertex      declaringType     = nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(declaringTypeNode));

                // Get a vertex sequence for the method instantiation args if any

                VertexSequence arguments = new VertexSequence();
                foreach (var arg in method.Instantiation)
                {
                    ISymbolNode argNode = factory.NecessaryTypeSymbol(arg);
                    arguments.Append(nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(argNode)));
                }

                // Get the name and sig of the method.
                // Note: the method name and signature are stored in the NativeLayoutInfo blob, not in the hashtable we build here.

                NativeLayoutMethodNameAndSignatureVertexNode nameAndSig       = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition());
                NativeLayoutPlacedSignatureVertexNode        placedNameAndSig = factory.NativeLayout.PlacedSignatureVertex(nameAndSig);
                Debug.Assert(placedNameAndSig.SavedVertex != null);
                Vertex placedNameAndSigOffsetSig = nativeWriter.GetOffsetSignature(placedNameAndSig.SavedVertex);

                // Get the vertex for the completed method signature

                Vertex methodSignature = nativeWriter.GetTuple(declaringType, placedNameAndSigOffsetSig, arguments);

                // Make the generic method entry vertex

                Vertex entry = nativeWriter.GetTuple(methodSignature, methodPointer);

                // Add to the hash table, hashed by the containing type's hashcode
                uint hashCode = (uint)method.OwningType.GetHashCode();
                hashtable.Append(hashCode, nativeSection.Place(entry));
            }

            byte[] streamBytes = nativeWriter.Save();

            _endSymbol.SetSymbolOffset(streamBytes.Length);

            return(new ObjectData(streamBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }));
        }
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            writer.Write(IsOptional);
            Debug.Assert(ModifierType == null ||
                ModifierType.HandleType == HandleType.TypeDefinition ||
                ModifierType.HandleType == HandleType.TypeReference ||
                ModifierType.HandleType == HandleType.TypeSpecification);
            writer.Write(ModifierType);
            Debug.Assert(Type == null ||
                Type.HandleType == HandleType.TypeDefinition ||
                Type.HandleType == HandleType.TypeReference ||
                Type.HandleType == HandleType.TypeSpecification ||
                Type.HandleType == HandleType.ModifiedType);
            writer.Write(Type);
        } // Save
        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 ISymbolNode[] { this }));
            }

            // Build the GVM table entries from the list of interesting GVMTableEntryNodes
            foreach (var interestingEntry in factory.MetadataManager.GetTypeGVMEntries())
            {
                foreach (var typeGVMEntryInfo in interestingEntry.ScanForInterfaceGenericVirtualMethodEntries())
                {
                    AddGenericVirtualMethodImplementation(factory, typeGVMEntryInfo.CallingMethod, typeGVMEntryInfo.ImplementationType, typeGVMEntryInfo.ImplementationMethod);
                }
            }

            // Ensure the native layout blob has been saved
            factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory);

            NativeWriter    nativeFormatWriter = new NativeWriter();
            VertexHashtable gvmHashtable       = new VertexHashtable();

            Section gvmHashtableSection = nativeFormatWriter.NewSection();

            gvmHashtableSection.Place(gvmHashtable);

            // Emit the interface slot resolution entries
            foreach (var gvmEntry in _interfaceGvmSlots)
            {
                Debug.Assert(gvmEntry.Key.OwningType.IsInterface);

                MethodDesc callingMethod = gvmEntry.Key;

                // Emit the method signature and containing type of the current interface method
                uint   typeId     = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(callingMethod.OwningType));
                var    nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(callingMethod));
                Vertex vertex     = nativeFormatWriter.GetTuple(
                    nativeFormatWriter.GetUnsignedConstant(typeId),
                    nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset));

                // Emit the method name / sig and containing type of each GVM target method for the current interface method entry
                vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)gvmEntry.Value.Count));
                foreach (MethodDesc implementationMethod in gvmEntry.Value)
                {
                    nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(implementationMethod));
                    typeId     = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(implementationMethod.OwningType));
                    vertex     = nativeFormatWriter.GetTuple(
                        vertex,
                        nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset),
                        nativeFormatWriter.GetUnsignedConstant(typeId));

                    // Emit the interface GVM slot details for each type that implements the interface methods
                    {
                        Debug.Assert(_interfaceImpls.ContainsKey(implementationMethod));

                        var ifaceImpls = _interfaceImpls[implementationMethod];

                        // First, emit how many types have method implementations for this interface method entry
                        vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)ifaceImpls.Count));

                        // Emit each type that implements the interface method, and the interface signatures for the interfaces implemented by the type
                        foreach (var currentImpl in ifaceImpls)
                        {
                            TypeDesc implementationType = currentImpl.Key;

                            typeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(implementationType));
                            vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant(typeId));

                            // Emit information on which interfaces the current method entry provides implementations for
                            vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)currentImpl.Value.Count));
                            foreach (var ifaceId in currentImpl.Value)
                            {
                                // Emit the signature of the current interface implemented by the method
                                Debug.Assert(((uint)ifaceId) < implementationType.RuntimeInterfaces.Length);
                                TypeDesc currentInterface = implementationType.RuntimeInterfaces[ifaceId];
                                var      typeSig          = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.TypeSignatureVertex(currentInterface));
                                vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)typeSig.SavedVertex.VertexOffset));
                            }
                        }
                    }
                }

                int hashCode = callingMethod.OwningType.GetHashCode();
                gvmHashtable.Append((uint)hashCode, gvmHashtableSection.Place(vertex));
            }

            // Zero out the dictionary so that we AV if someone tries to insert after we're done.
            _interfaceGvmSlots = null;

            MemoryStream stream = new MemoryStream();

            nativeFormatWriter.Save(stream);
            byte[] streamBytes = stream.ToArray();

            _endSymbol.SetSymbolOffset(streamBytes.Length);

            return(new ObjectData(streamBytes, Array.Empty <Relocation>(), 1, new ISymbolNode[] { this, _endSymbol }));
        }
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            Debug.Assert(Value == null ||
                Value.HandleType == HandleType.ConstantByteValue ||
                Value.HandleType == HandleType.ConstantSByteValue ||
                Value.HandleType == HandleType.ConstantInt16Value ||
                Value.HandleType == HandleType.ConstantUInt16Value ||
                Value.HandleType == HandleType.ConstantInt32Value ||
                Value.HandleType == HandleType.ConstantUInt32Value ||
                Value.HandleType == HandleType.ConstantInt64Value ||
                Value.HandleType == HandleType.ConstantUInt64Value);
            writer.Write(Value);
            Debug.Assert(Type == null ||
                Type.HandleType == HandleType.TypeDefinition ||
                Type.HandleType == HandleType.TypeReference);
            writer.Write(Type);
        } // Save
        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 ISymbolNode[] { this }));
            }

            NativeWriter    nativeWriter  = new NativeWriter();
            VertexHashtable hashtable     = new VertexHashtable();
            Section         nativeSection = nativeWriter.NewSection();

            nativeSection.Place(hashtable);

            foreach (var dictionaryNode in factory.MetadataManager.GetCompiledGenericDictionaries())
            {
                MethodGenericDictionaryNode methodDictionary = dictionaryNode as MethodGenericDictionaryNode;
                if (methodDictionary == null)
                {
                    continue;
                }

                MethodDesc method = methodDictionary.OwningMethod;

                Debug.Assert(method.HasInstantiation && !method.IsCanonicalMethod(CanonicalFormKind.Any));

                Vertex fullMethodSignature;
                {
                    // Method's containing type
                    IEETypeNode containingTypeNode = factory.NecessaryTypeSymbol(method.OwningType);
                    Vertex      containingType     = nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(containingTypeNode));

                    // Method's instantiation arguments
                    VertexSequence arguments = new VertexSequence();
                    for (int i = 0; i < method.Instantiation.Length; i++)
                    {
                        IEETypeNode argNode = factory.NecessaryTypeSymbol(method.Instantiation[i]);
                        arguments.Append(nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(argNode)));
                    }

                    // Method name and signature
                    NativeLayoutVertexNode      nameAndSig       = factory.NativeLayout.MethodNameAndSignatureVertex(method.GetTypicalMethodDefinition());
                    NativeLayoutSavedVertexNode placedNameAndSig = factory.NativeLayout.PlacedSignatureVertex(nameAndSig);
                    Vertex placedNameAndSigVertexOffset          = nativeWriter.GetUnsignedConstant((uint)placedNameAndSig.SavedVertex.VertexOffset);

                    fullMethodSignature = nativeWriter.GetTuple(containingType, placedNameAndSigVertexOffset, arguments);
                }

                // Method's dictionary pointer
                Vertex dictionaryVertex = nativeWriter.GetUnsignedConstant(_externalReferences.GetIndex(dictionaryNode));

                Vertex entry = nativeWriter.GetTuple(dictionaryVertex, fullMethodSignature);

                hashtable.Append((uint)method.GetHashCode(), nativeSection.Place(entry));
            }

            MemoryStream stream = new MemoryStream();

            nativeWriter.Save(stream);
            byte[] streamBytes = stream.ToArray();

            _endSymbol.SetSymbolOffset(streamBytes.Length);

            return(new ObjectData(streamBytes, Array.Empty <Relocation>(), 1, new ISymbolNode[] { this, _endSymbol }));
        }
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            writer.Write(Flags);
            writer.Write(Name);
            writer.Write(Signature);
            writer.Write(MethodSemantics);
            Debug.Assert(DefaultValue == null ||
                DefaultValue.HandleType == HandleType.TypeDefinition ||
                DefaultValue.HandleType == HandleType.TypeReference ||
                DefaultValue.HandleType == HandleType.TypeSpecification ||
                DefaultValue.HandleType == HandleType.ConstantBooleanArray ||
                DefaultValue.HandleType == HandleType.ConstantBooleanValue ||
                DefaultValue.HandleType == HandleType.ConstantByteArray ||
                DefaultValue.HandleType == HandleType.ConstantByteValue ||
                DefaultValue.HandleType == HandleType.ConstantCharArray ||
                DefaultValue.HandleType == HandleType.ConstantCharValue ||
                DefaultValue.HandleType == HandleType.ConstantDoubleArray ||
                DefaultValue.HandleType == HandleType.ConstantDoubleValue ||
                DefaultValue.HandleType == HandleType.ConstantHandleArray ||
                DefaultValue.HandleType == HandleType.ConstantInt16Array ||
                DefaultValue.HandleType == HandleType.ConstantInt16Value ||
                DefaultValue.HandleType == HandleType.ConstantInt32Array ||
                DefaultValue.HandleType == HandleType.ConstantInt32Value ||
                DefaultValue.HandleType == HandleType.ConstantInt64Array ||
                DefaultValue.HandleType == HandleType.ConstantInt64Value ||
                DefaultValue.HandleType == HandleType.ConstantReferenceValue ||
                DefaultValue.HandleType == HandleType.ConstantSByteArray ||
                DefaultValue.HandleType == HandleType.ConstantSByteValue ||
                DefaultValue.HandleType == HandleType.ConstantSingleArray ||
                DefaultValue.HandleType == HandleType.ConstantSingleValue ||
                DefaultValue.HandleType == HandleType.ConstantStringArray ||
                DefaultValue.HandleType == HandleType.ConstantStringValue ||
                DefaultValue.HandleType == HandleType.ConstantUInt16Array ||
                DefaultValue.HandleType == HandleType.ConstantUInt16Value ||
                DefaultValue.HandleType == HandleType.ConstantUInt32Array ||
                DefaultValue.HandleType == HandleType.ConstantUInt32Value ||
                DefaultValue.HandleType == HandleType.ConstantUInt64Array ||
                DefaultValue.HandleType == HandleType.ConstantUInt64Value);
            writer.Write(DefaultValue);
            writer.Write(CustomAttributes);
        } // Save
Exemple #42
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 }));
            }

            // Build the GVM table entries from the list of interesting GVMTableEntryNodes
            foreach (var interestingEntry in factory.MetadataManager.GetTypeGVMEntries())
            {
                foreach (var typeGVMEntryInfo in interestingEntry.ScanForGenericVirtualMethodEntries())
                {
                    AddGenericVirtualMethodImplementation(factory, typeGVMEntryInfo.CallingMethod, typeGVMEntryInfo.ImplementationMethod);
                }
            }

            // Ensure the native layout blob has been saved
            factory.MetadataManager.NativeLayoutInfo.SaveNativeLayoutInfoWriter(factory);

            NativeWriter    nativeFormatWriter = new NativeWriter();
            VertexHashtable gvmHashtable       = new VertexHashtable();

            Section gvmHashtableSection = nativeFormatWriter.NewSection();

            gvmHashtableSection.Place(gvmHashtable);

            // Emit the GVM target information entries
            foreach (var gvmEntry in _gvmImplemenations)
            {
                Debug.Assert(!gvmEntry.Key.OwningType.IsInterface);

                foreach (var implementationEntry in gvmEntry.Value)
                {
                    MethodDesc callingMethod        = gvmEntry.Key;
                    TypeDesc   implementationType   = implementationEntry.Key;
                    MethodDesc implementationMethod = implementationEntry.Value;

                    uint   callingTypeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(callingMethod.OwningType));
                    Vertex vertex        = nativeFormatWriter.GetUnsignedConstant(callingTypeId);

                    uint targetTypeId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(implementationType));
                    vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant(targetTypeId));

                    var nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(callingMethod));
                    vertex = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset));

                    nameAndSig = factory.NativeLayout.PlacedSignatureVertex(factory.NativeLayout.MethodNameAndSignatureVertex(implementationMethod));
                    vertex     = nativeFormatWriter.GetTuple(vertex, nativeFormatWriter.GetUnsignedConstant((uint)nameAndSig.SavedVertex.VertexOffset));

                    int hashCode = callingMethod.OwningType.GetHashCode();
                    hashCode = ((hashCode << 13) ^ hashCode) ^ implementationType.GetHashCode();

                    gvmHashtable.Append((uint)hashCode, gvmHashtableSection.Place(vertex));
                }
            }

            // Zero out the dictionary so that we AV if someone tries to insert after we're done.
            _gvmImplemenations = null;

            byte[] streamBytes = nativeFormatWriter.Save();

            _endSymbol.SetSymbolOffset(streamBytes.Length);

            return(new ObjectData(streamBytes, Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }));
        }
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            writer.Write(Method);
            writer.Write(EnclosingType);
        } // Save
Exemple #44
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;
                }

                // CppCodegen: implement thread statics
                if (factory.Target.Abi == TargetAbi.CppCodegen && field.IsThreadStatic)
                {
                    continue;
                }

                FieldTableFlags flags;
                if (field.IsStatic)
                {
                    if (field.IsThreadStatic)
                    {
                        flags = FieldTableFlags.ThreadStatic;
                    }
                    else if (field.HasGCStaticBase)
                    {
                        flags = FieldTableFlags.GCStatic;
                    }
                    else
                    {
                        flags = FieldTableFlags.NonGCStatic;
                    }

                    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.Any))
                {
                    flags |= FieldTableFlags.IsAnyCanonicalEntry;
                }

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

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

                // 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)
                {
                    vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(checked ((uint)field.GetFieldOrdinal())));
                }
                else
                {
                    switch (flags & FieldTableFlags.StorageClass)
                    {
                    case FieldTableFlags.ThreadStatic:
                    case FieldTableFlags.GCStatic:
                    case FieldTableFlags.NonGCStatic:
                    {
                        if (field.OwningType.HasInstantiation)
                        {
                            vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant((uint)(field.Offset.AsInt)));
                        }
                        else
                        {
                            MetadataType metadataType = (MetadataType)field.OwningType;

                            ISymbolNode staticsNode;
                            if (field.IsThreadStatic)
                            {
                                staticsNode = factory.TypeThreadStaticIndex(metadataType);
                            }
                            else if (field.HasGCStaticBase)
                            {
                                staticsNode = factory.TypeGCStaticsSymbol(metadataType);
                            }
                            else
                            {
                                staticsNode = factory.TypeNonGCStaticsSymbol(metadataType);
                            }

                            if (!field.IsThreadStatic && !field.HasGCStaticBase)
                            {
                                uint index = _externalReferences.GetIndex(staticsNode, field.Offset.AsInt);
                                vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(index));
                            }
                            else
                            {
                                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 }));
        }
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            writer.Write(Flags);
            writer.Write(Name);
            writer.Write(HashAlgorithm);
            writer.Write(MajorVersion);
            writer.Write(MinorVersion);
            writer.Write(BuildNumber);
            writer.Write(RevisionNumber);
            writer.Write(PublicKey);
            writer.Write(Culture);
            writer.Write(RootNamespaceDefinition);
            writer.Write(CustomAttributes);
        } // Save
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            Debug.Assert(ParentNamespaceOrType == null ||
                ParentNamespaceOrType.HandleType == HandleType.NamespaceReference ||
                ParentNamespaceOrType.HandleType == HandleType.TypeReference);
            writer.Write(ParentNamespaceOrType);
            writer.Write(TypeName);
            writer.Write(CustomAttributes);
        } // Save
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            writer.Write(Flags);
            Debug.Assert(BaseType == null ||
                BaseType.HandleType == HandleType.TypeDefinition ||
                BaseType.HandleType == HandleType.TypeReference ||
                BaseType.HandleType == HandleType.TypeSpecification);
            writer.Write(BaseType);
            writer.Write(NamespaceDefinition);
            writer.Write(Name);
            writer.Write(Size);
            writer.Write(PackingSize);
            writer.Write(EnclosingType);
            writer.Write(NestedTypes);
            writer.Write(Methods);
            writer.Write(Fields);
            writer.Write(Properties);
            writer.Write(Events);
            writer.Write(GenericParameters);
            Debug.Assert(Interfaces.TrueForAll(handle => handle == null ||
                handle.HandleType == HandleType.TypeDefinition ||
                handle.HandleType == HandleType.TypeReference ||
                handle.HandleType == HandleType.TypeSpecification));
            writer.Write(Interfaces);
            writer.Write(MethodImpls);
            writer.Write(CustomAttributes);
        } // Save
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            writer.Write(Number);
        } // Save
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            Debug.Assert(GenericType == null ||
                GenericType.HandleType == HandleType.TypeDefinition ||
                GenericType.HandleType == HandleType.TypeReference ||
                GenericType.HandleType == HandleType.TypeSpecification);
            writer.Write(GenericType);
            Debug.Assert(GenericTypeArguments.TrueForAll(handle => handle == null ||
                handle.HandleType == HandleType.TypeDefinition ||
                handle.HandleType == HandleType.TypeReference ||
                handle.HandleType == HandleType.TypeSpecification));
            writer.Write(GenericTypeArguments);
        } // Save
 public static void Write(this NativeWriter writer, bool value)
 {
     writer.WriteUInt8((byte)(value ? 1 : 0));
 }
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            Debug.Assert(Signature == null ||
                Signature.HandleType == HandleType.TypeDefinition ||
                Signature.HandleType == HandleType.TypeReference ||
                Signature.HandleType == HandleType.TypeInstantiationSignature ||
                Signature.HandleType == HandleType.SZArraySignature ||
                Signature.HandleType == HandleType.ArraySignature ||
                Signature.HandleType == HandleType.PointerSignature ||
                Signature.HandleType == HandleType.ByReferenceSignature ||
                Signature.HandleType == HandleType.TypeVariableSignature ||
                Signature.HandleType == HandleType.MethodTypeVariableSignature);
            writer.Write(Signature);
            writer.Write(CustomAttributes);
        } // Save
        } // GetHashCode

        internal override void Save(NativeWriter writer)
        {
            writer.Write(Value);
        } // Save
Exemple #53
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, Array.Empty <ISymbolDefinitionNode>()));
            }

            ReadyToRunCodegenNodeFactory r2rFactory      = (ReadyToRunCodegenNodeFactory)factory;
            List <EntryPoint>            ridToEntryPoint = new List <EntryPoint>();

            foreach (MethodWithGCInfo method in r2rFactory.EnumerateCompiledMethods())
            {
                if (method.Method is EcmaMethod ecmaMethod)
                {
                    // Strip away the token type bits, keep just the low 24 bits RID
                    uint rid = SignatureBuilder.RidFromToken((mdToken)MetadataTokens.GetToken(ecmaMethod.Handle));
                    Debug.Assert(rid != 0);
                    rid--;

                    while (ridToEntryPoint.Count <= rid)
                    {
                        ridToEntryPoint.Add(EntryPoint.Null);
                    }

                    int methodIndex = r2rFactory.RuntimeFunctionsTable.GetIndex(method);
                    ridToEntryPoint[(int)rid] = new EntryPoint(methodIndex, method);
                }
            }

            NativeWriter writer = new NativeWriter();

            Section     arraySection = writer.NewSection();
            VertexArray vertexArray  = new VertexArray(arraySection);

            arraySection.Place(vertexArray);

            Section fixupSection = writer.NewSection();

            Dictionary <byte[], BlobVertex> uniqueFixups = new Dictionary <byte[], BlobVertex>(ByteArrayComparer.Instance);

            for (int rid = 0; rid < ridToEntryPoint.Count; rid++)
            {
                EntryPoint entryPoint = ridToEntryPoint[rid];
                if (!entryPoint.IsNull)
                {
                    byte[] fixups = entryPoint.Method.GetFixupBlob(factory);

                    BlobVertex fixupBlobVertex = null;
                    if (fixups != null && !uniqueFixups.TryGetValue(fixups, out fixupBlobVertex))
                    {
                        fixupBlobVertex = new BlobVertex(fixups);
                        fixupSection.Place(fixupBlobVertex);
                        uniqueFixups.Add(fixups, fixupBlobVertex);
                    }
                    EntryPointVertex entryPointVertex = new EntryPointVertex((uint)entryPoint.MethodIndex, fixupBlobVertex);
                    vertexArray.Set(rid, entryPointVertex);
                }
            }

            vertexArray.ExpandLayout();

            MemoryStream arrayContent = new MemoryStream();

            writer.Save(arrayContent);
            return(new ObjectData(
                       data: arrayContent.ToArray(),
                       relocs: null,
                       alignment: 8,
                       definedSymbols: new ISymbolDefinitionNode[] { this }));
        }
        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 ISymbolNode[] { this }));
            }

            NativeWriter    writer    = new NativeWriter();
            VertexHashtable hashtable = new VertexHashtable();
            Section         section   = writer.NewSection();

            section.Place(hashtable);

            foreach (var type in factory.MetadataManager.GetTypesWithConstructedEETypes())
            {
                if (!type.HasInstantiation || type.IsCanonicalSubtype(CanonicalFormKind.Any) || type.IsGenericDefinition)
                {
                    continue;
                }

                MetadataType metadataType = type as MetadataType;
                if (metadataType == null)
                {
                    continue;
                }

                VertexBag bag = new VertexBag();

                if (metadataType.GCStaticFieldSize.AsInt > 0)
                {
                    ISymbolNode gcStaticIndirection = factory.Indirection(factory.TypeGCStaticsSymbol(metadataType));
                    bag.AppendUnsigned(BagElementKind.GcStaticData, _nativeStaticsReferences.GetIndex(gcStaticIndirection));
                }
                if (metadataType.NonGCStaticFieldSize.AsInt > 0)
                {
                    int cctorOffset = 0;
                    if (factory.TypeSystemContext.HasLazyStaticConstructor(type))
                    {
                        cctorOffset += NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.TypeSystemContext.Target, metadataType);
                    }

                    ISymbolNode nonGCStaticIndirection = factory.Indirection(factory.TypeNonGCStaticsSymbol(metadataType), cctorOffset);
                    bag.AppendUnsigned(BagElementKind.NonGcStaticData, _nativeStaticsReferences.GetIndex(nonGCStaticIndirection));
                }

                // TODO: TLS

                if (bag.ElementsCount > 0)
                {
                    uint   typeId      = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(type));
                    Vertex staticsInfo = writer.GetTuple(writer.GetUnsignedConstant(typeId), bag);

                    hashtable.Append((uint)type.GetHashCode(), section.Place(staticsInfo));
                }
            }

            byte[] hashTableBytes = writer.Save();

            _endSymbol.SetSymbolOffset(hashTableBytes.Length);

            return(new ObjectData(hashTableBytes, Array.Empty <Relocation>(), 1, new ISymbolNode[] { 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 ISymbolNode[] { this });

            var writer = new NativeWriter();
            var typeMapHashTable = new VertexHashtable();

            Section hashTableSection = writer.NewSection();
            hashTableSection.Place(typeMapHashTable);

            // Get a list of all methods that have a method body and metadata from the metadata manager.
            foreach (var mappingEntry in factory.MetadataManager.GetMethodMapping())
            {
                MethodDesc method = mappingEntry.Entity;

                // The current format requires us to have an EEType for the owning type. We might want to lift this.
                if (!factory.MetadataManager.TypeGeneratesEEType(method.OwningType))
                    continue;

                // We have a method body, we have a metadata token, but we can't get an invoke stub. Bail.
                if (!factory.MetadataManager.HasReflectionInvokeStub(method))
                    continue;

                InvokeTableFlags flags = 0;

                if (method.HasInstantiation)
                    flags |= InvokeTableFlags.IsGenericMethod;

                if (method.GetCanonMethodTarget(CanonicalFormKind.Specific).RequiresInstArg())
                    flags |= InvokeTableFlags.RequiresInstArg;

                // TODO: better check for default public(!) constructor
                if (method.IsConstructor && method.Signature.Length == 0)
                    flags |= InvokeTableFlags.IsDefaultConstructor;

                // TODO: HasVirtualInvoke

                if (!method.IsAbstract)
                    flags |= InvokeTableFlags.HasEntrypoint;

                // Once we have a true multi module compilation story, we'll need to start emitting entries where this is not set.
                flags |= InvokeTableFlags.HasMetadataHandle;

                // TODO: native signature for P/Invokes and NativeCallable methods
                if (method.IsRawPInvoke() || method.IsNativeCallable)
                    continue;

                // Grammar of an entry in the hash table:
                // Flags + DeclaringType + MetadataHandle/NameAndSig + Entrypoint + DynamicInvokeMethod + [NumGenericArgs + GenericArgs]

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

                if ((flags & InvokeTableFlags.HasMetadataHandle) != 0)
                {
                    // Only store the offset portion of the metadata handle to get better integer compression
                    vertex = writer.GetTuple(vertex,
                        writer.GetUnsignedConstant((uint)(mappingEntry.MetadataHandle & MetadataGeneration.MetadataOffsetMask)));
                }
                else
                {
                    // TODO: no MD handle case
                }

                // Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted.
                IEETypeNode owningTypeSymbol = factory.NecessaryTypeSymbol(method.OwningType);
                vertex = writer.GetTuple(vertex,
                    writer.GetUnsignedConstant(_externalReferences.GetIndex(owningTypeSymbol)));

                if ((flags & InvokeTableFlags.HasEntrypoint) != 0)
                {
                    vertex = writer.GetTuple(vertex,
                        writer.GetUnsignedConstant(_externalReferences.GetIndex(
                            factory.MethodEntrypoint(method.GetCanonMethodTarget(CanonicalFormKind.Specific)))));
                }

                // TODO: data to generate the generic dictionary with the type loader
                MethodDesc invokeStubMethod = factory.MetadataManager.GetReflectionInvokeStub(method);
                MethodDesc canonInvokeStubMethod = invokeStubMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
                if (invokeStubMethod != canonInvokeStubMethod)
                {
                    vertex = writer.GetTuple(vertex,
                        writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.FatFunctionPointer(invokeStubMethod), FatFunctionPointerConstants.Offset) << 1));
                }
                else
                {
                    vertex = writer.GetTuple(vertex,
                        writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(invokeStubMethod)) << 1));
                }

                if ((flags & InvokeTableFlags.IsGenericMethod) != 0)
                {
                    if ((flags & InvokeTableFlags.RequiresInstArg) == 0 || (flags & InvokeTableFlags.HasEntrypoint) == 0)
                    {
                        VertexSequence args = new VertexSequence();
                        for (int i = 0; i < method.Instantiation.Length; i++)
                        {
                            uint argId = _externalReferences.GetIndex(factory.NecessaryTypeSymbol(method.Instantiation[i]));
                            args.Append(writer.GetUnsignedConstant(argId));
                        }
                        vertex = writer.GetTuple(vertex, args);
                    }
                    else
                    {
                        uint dictionaryId = _externalReferences.GetIndex(factory.MethodGenericDictionary(method));
                        vertex = writer.GetTuple(vertex, writer.GetUnsignedConstant(dictionaryId));
                    }
                }

                int hashCode = method.GetCanonMethodTarget(CanonicalFormKind.Specific).OwningType.GetHashCode();
                typeMapHashTable.Append((uint)hashCode, hashTableSection.Place(vertex));
            }

            MemoryStream ms = new MemoryStream();
            writer.Save(ms);
            byte[] hashTableBytes = ms.ToArray();

            _endSymbol.SetSymbolOffset(hashTableBytes.Length);

            return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolNode[] { this, _endSymbol });
        }
Exemple #56
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 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.InstanceFieldSize.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 }));
        }