Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:39

0001 //===- GlobalTypeTableBuilder.h ----------------------------------*- C++-*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_DEBUGINFO_CODEVIEW_GLOBALTYPETABLEBUILDER_H
0010 #define LLVM_DEBUGINFO_CODEVIEW_GLOBALTYPETABLEBUILDER_H
0011 
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/ADT/DenseMap.h"
0014 #include "llvm/ADT/SmallVector.h"
0015 #include "llvm/DebugInfo/CodeView/CVRecord.h"
0016 #include "llvm/DebugInfo/CodeView/SimpleTypeSerializer.h"
0017 #include "llvm/DebugInfo/CodeView/TypeCollection.h"
0018 #include "llvm/DebugInfo/CodeView/TypeHashing.h"
0019 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
0020 #include "llvm/Support/Allocator.h"
0021 #include <cassert>
0022 #include <cstdint>
0023 
0024 namespace llvm {
0025 namespace codeview {
0026 
0027 class ContinuationRecordBuilder;
0028 
0029 class GlobalTypeTableBuilder : public TypeCollection {
0030   /// Storage for records.  These need to outlive the TypeTableBuilder.
0031   BumpPtrAllocator &RecordStorage;
0032 
0033   /// A serializer that can write non-continuation leaf types.  Only used as
0034   /// a convenience function so that we can provide an interface method to
0035   /// write an unserialized record.
0036   SimpleTypeSerializer SimpleSerializer;
0037 
0038   /// Hash table.
0039   DenseMap<GloballyHashedType, TypeIndex> HashedRecords;
0040 
0041   /// Contains a list of all records indexed by TypeIndex.toArrayIndex().
0042   SmallVector<ArrayRef<uint8_t>, 2> SeenRecords;
0043 
0044   /// Contains a list of all hash values indexed by TypeIndex.toArrayIndex().
0045   SmallVector<GloballyHashedType, 2> SeenHashes;
0046 
0047 public:
0048   explicit GlobalTypeTableBuilder(BumpPtrAllocator &Storage);
0049   ~GlobalTypeTableBuilder();
0050 
0051   // TypeCollection overrides
0052   std::optional<TypeIndex> getFirst() override;
0053   std::optional<TypeIndex> getNext(TypeIndex Prev) override;
0054   CVType getType(TypeIndex Index) override;
0055   StringRef getTypeName(TypeIndex Index) override;
0056   bool contains(TypeIndex Index) override;
0057   uint32_t size() override;
0058   uint32_t capacity() override;
0059   bool replaceType(TypeIndex &Index, CVType Data, bool Stabilize) override;
0060 
0061   // public interface
0062   void reset();
0063   TypeIndex nextTypeIndex() const;
0064 
0065   BumpPtrAllocator &getAllocator() { return RecordStorage; }
0066 
0067   ArrayRef<ArrayRef<uint8_t>> records() const;
0068   ArrayRef<GloballyHashedType> hashes() const;
0069 
0070   template <typename CreateFunc>
0071   TypeIndex insertRecordAs(GloballyHashedType Hash, size_t RecordSize,
0072                            CreateFunc Create) {
0073     assert(RecordSize < UINT32_MAX && "Record too big");
0074     assert(RecordSize % 4 == 0 &&
0075            "RecordSize is not a multiple of 4 bytes which will cause "
0076            "misalignment in the output TPI stream!");
0077 
0078     auto Result = HashedRecords.try_emplace(Hash, nextTypeIndex());
0079 
0080     if (LLVM_UNLIKELY(Result.second /*inserted*/ ||
0081                       Result.first->second.isSimple())) {
0082       uint8_t *Stable = RecordStorage.Allocate<uint8_t>(RecordSize);
0083       MutableArrayRef<uint8_t> Data(Stable, RecordSize);
0084       ArrayRef<uint8_t> StableRecord = Create(Data);
0085       if (StableRecord.empty()) {
0086         // Records with forward references into the Type stream will be deferred
0087         // for insertion at a later time, on the second pass.
0088         Result.first->getSecond() = TypeIndex(SimpleTypeKind::NotTranslated);
0089         return TypeIndex(SimpleTypeKind::NotTranslated);
0090       }
0091       if (Result.first->second.isSimple()) {
0092         assert(Result.first->second.getIndex() ==
0093                (uint32_t)SimpleTypeKind::NotTranslated);
0094         // On the second pass, update with index to remapped record. The
0095         // (initially misbehaved) record will now come *after* other records
0096         // resolved in the first pass, with proper *back* references in the
0097         // stream.
0098         Result.first->second = nextTypeIndex();
0099       }
0100       SeenRecords.push_back(StableRecord);
0101       SeenHashes.push_back(Hash);
0102     }
0103 
0104     return Result.first->second;
0105   }
0106 
0107   TypeIndex insertRecordBytes(ArrayRef<uint8_t> Data);
0108   TypeIndex insertRecord(ContinuationRecordBuilder &Builder);
0109 
0110   template <typename T> TypeIndex writeLeafType(T &Record) {
0111     ArrayRef<uint8_t> Data = SimpleSerializer.serialize(Record);
0112     return insertRecordBytes(Data);
0113   }
0114 };
0115 
0116 } // end namespace codeview
0117 } // end namespace llvm
0118 
0119 #endif // LLVM_DEBUGINFO_CODEVIEW_GLOBALTYPETABLEBUILDER_H