diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:32:52 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:32:52 +0000 | 
| commit | 08bbd35a80bf7765fe0d3043f9eb5a2f2786b649 (patch) | |
| tree | 80108f0f128657f8623f8f66ad9735b4d88e7b47 /lib/DebugInfo/CodeView | |
| parent | 7c7aba6e5fef47a01a136be655b0a92cfd7090f6 (diff) | |
Notes
Diffstat (limited to 'lib/DebugInfo/CodeView')
| -rw-r--r-- | lib/DebugInfo/CodeView/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | lib/DebugInfo/CodeView/CVTypeVisitor.cpp | 2 | ||||
| -rw-r--r-- | lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp | 30 | ||||
| -rw-r--r-- | lib/DebugInfo/CodeView/EnumTables.cpp | 10 | ||||
| -rw-r--r-- | lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp | 157 | ||||
| -rw-r--r-- | lib/DebugInfo/CodeView/SymbolDumper.cpp | 2 | ||||
| -rw-r--r-- | lib/DebugInfo/CodeView/SymbolRecordMapping.cpp | 2 | ||||
| -rw-r--r-- | lib/DebugInfo/CodeView/TypeDatabase.cpp | 146 | ||||
| -rw-r--r-- | lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp | 330 | ||||
| -rw-r--r-- | lib/DebugInfo/CodeView/TypeDumpVisitor.cpp | 2 | ||||
| -rw-r--r-- | lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp | 82 | ||||
| -rw-r--r-- | lib/DebugInfo/CodeView/TypeName.cpp | 243 | ||||
| -rw-r--r-- | lib/DebugInfo/CodeView/TypeTableCollection.cpp | 58 | 
13 files changed, 465 insertions, 602 deletions
diff --git a/lib/DebugInfo/CodeView/CMakeLists.txt b/lib/DebugInfo/CodeView/CMakeLists.txt index f916695a84392..b94bb0c80c793 100644 --- a/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/lib/DebugInfo/CodeView/CMakeLists.txt @@ -24,11 +24,10 @@ add_llvm_library(LLVMDebugInfoCodeView    SymbolRecordMapping.cpp    SymbolDumper.cpp    SymbolSerializer.cpp -  TypeDatabase.cpp -  TypeDatabaseVisitor.cpp    TypeDumpVisitor.cpp    TypeIndex.cpp    TypeIndexDiscovery.cpp +  TypeName.cpp    TypeRecordMapping.cpp    TypeSerializer.cpp    TypeStreamMerger.cpp diff --git a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp index f0debd9e97023..22f166a2335d6 100644 --- a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp @@ -12,8 +12,6 @@  #include "llvm/ADT/TinyPtrVector.h"  #include "llvm/DebugInfo/CodeView/CodeViewError.h"  #include "llvm/DebugInfo/CodeView/TypeCollection.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" -#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"  #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"  #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"  #include "llvm/DebugInfo/CodeView/TypeServerHandler.h" diff --git a/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp b/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp index 334c5e002bbca..d69eca018e0c1 100644 --- a/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp +++ b/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp @@ -53,12 +53,16 @@ DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(      std::shared_ptr<DebugSubsection> Subsection, CodeViewContainer Container)      : Subsection(std::move(Subsection)), Container(Container) {} +DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( +    const DebugSubsectionRecord &Contents, CodeViewContainer Container) +    : Contents(Contents), Container(Container) {} +  uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() { -  // The length of the entire subsection is always padded to 4 bytes, regardless -  // of the container kind. -  uint32_t Size = sizeof(DebugSubsectionHeader) + -                  alignTo(Subsection->calculateSerializedSize(), 4); -  return Size; +  uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize() +                                 : Contents.getRecordData().getLength(); +  // The length of the entire subsection is always padded to 4 bytes, +  // regardless of the container kind. +  return sizeof(DebugSubsectionHeader) + alignTo(DataSize, 4);  }  Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const { @@ -66,16 +70,22 @@ Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const {           "Debug Subsection not properly aligned");    DebugSubsectionHeader Header; -  Header.Kind = uint32_t(Subsection->kind()); +  Header.Kind = uint32_t(Subsection ? Subsection->kind() : Contents.kind());    // The value written into the Header's Length field is only padded to the    // container's alignment -  Header.Length = -      alignTo(Subsection->calculateSerializedSize(), alignOf(Container)); +  uint32_t DataSize = Subsection ? Subsection->calculateSerializedSize() +                                 : Contents.getRecordData().getLength(); +  Header.Length = alignTo(DataSize, alignOf(Container));    if (auto EC = Writer.writeObject(Header))      return EC; -  if (auto EC = Subsection->commit(Writer)) -    return EC; +  if (Subsection) { +    if (auto EC = Subsection->commit(Writer)) +      return EC; +  } else { +    if (auto EC = Writer.writeStreamRef(Contents.getRecordData())) +      return EC; +  }    if (auto EC = Writer.padToAlignment(4))      return EC; diff --git a/lib/DebugInfo/CodeView/EnumTables.cpp b/lib/DebugInfo/CodeView/EnumTables.cpp index 01d8ccf2d31e8..ec00af28395e5 100644 --- a/lib/DebugInfo/CodeView/EnumTables.cpp +++ b/lib/DebugInfo/CodeView/EnumTables.cpp @@ -82,6 +82,13 @@ static const EnumEntry<uint16_t> RegisterNames[] = {      CV_ENUM_CLASS_ENT(RegisterId, R15),  }; +static const EnumEntry<uint32_t> PublicSymFlagNames[] = { +    CV_ENUM_CLASS_ENT(PublicSymFlags, Code), +    CV_ENUM_CLASS_ENT(PublicSymFlags, Function), +    CV_ENUM_CLASS_ENT(PublicSymFlags, Managed), +    CV_ENUM_CLASS_ENT(PublicSymFlags, MSIL), +}; +  static const EnumEntry<uint8_t> ProcSymFlagNames[] = {      CV_ENUM_CLASS_ENT(ProcSymFlags, HasFP),      CV_ENUM_CLASS_ENT(ProcSymFlags, HasIRET), @@ -338,6 +345,9 @@ ArrayRef<EnumEntry<uint16_t>> getRegisterNames() {    return makeArrayRef(RegisterNames);  } +ArrayRef<EnumEntry<uint32_t>> getPublicSymFlagNames() { +  return makeArrayRef(PublicSymFlagNames); +}  ArrayRef<EnumEntry<uint8_t>> getProcSymFlagNames() {    return makeArrayRef(ProcSymFlagNames);  } diff --git a/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp b/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp index 39eb4099ce9e6..20f7e72c3af39 100644 --- a/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp +++ b/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp @@ -11,7 +11,7 @@  #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"  #include "llvm/DebugInfo/CodeView/CodeViewError.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/DebugInfo/CodeView/TypeName.h"  #include "llvm/DebugInfo/CodeView/TypeServerHandler.h"  #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" @@ -31,15 +31,13 @@ LazyRandomTypeCollection::LazyRandomTypeCollection(uint32_t RecordCountHint)  LazyRandomTypeCollection::LazyRandomTypeCollection(      const CVTypeArray &Types, uint32_t RecordCountHint,      PartialOffsetArray PartialOffsets) -    : Database(RecordCountHint), Types(Types), DatabaseVisitor(Database), -      PartialOffsets(PartialOffsets) { -  KnownOffsets.resize(Database.capacity()); +    : NameStorage(Allocator), Types(Types), PartialOffsets(PartialOffsets) { +  Records.resize(RecordCountHint);  }  LazyRandomTypeCollection::LazyRandomTypeCollection(ArrayRef<uint8_t> Data,                                                     uint32_t RecordCountHint)      : LazyRandomTypeCollection(RecordCountHint) { -  reset(Data);  }  LazyRandomTypeCollection::LazyRandomTypeCollection(StringRef Data, @@ -52,50 +50,88 @@ LazyRandomTypeCollection::LazyRandomTypeCollection(const CVTypeArray &Types,                                                     uint32_t NumRecords)      : LazyRandomTypeCollection(Types, NumRecords, PartialOffsetArray()) {} -void LazyRandomTypeCollection::reset(StringRef Data) { -  reset(makeArrayRef(Data.bytes_begin(), Data.bytes_end())); -} - -void LazyRandomTypeCollection::reset(ArrayRef<uint8_t> Data) { +void LazyRandomTypeCollection::reset(StringRef Data, uint32_t RecordCountHint) { +  Count = 0;    PartialOffsets = PartialOffsetArray();    BinaryStreamReader Reader(Data, support::little);    error(Reader.readArray(Types, Reader.getLength())); -  KnownOffsets.resize(Database.capacity()); +  // Clear and then resize, to make sure existing data gets destroyed. +  Records.clear(); +  Records.resize(RecordCountHint); +} + +void LazyRandomTypeCollection::reset(ArrayRef<uint8_t> Data, +                                     uint32_t RecordCountHint) { +  reset(toStringRef(Data), RecordCountHint); +} + +uint32_t LazyRandomTypeCollection::getOffsetOfType(TypeIndex Index) { +  error(ensureTypeExists(Index)); +  assert(contains(Index)); + +  return Records[Index.toArrayIndex()].Offset;  }  CVType LazyRandomTypeCollection::getType(TypeIndex Index) {    error(ensureTypeExists(Index)); -  return Database.getTypeRecord(Index); +  assert(contains(Index)); + +  return Records[Index.toArrayIndex()].Type;  }  StringRef LazyRandomTypeCollection::getTypeName(TypeIndex Index) { -  if (!Index.isSimple()) { -    // Try to make sure the type exists.  Even if it doesn't though, it may be -    // because we're dumping a symbol stream with no corresponding type stream -    // present, in which case we still want to be able to print <unknown UDT> -    // for the type names. -    consumeError(ensureTypeExists(Index)); +  if (Index.isNoneType() || Index.isSimple()) +    return TypeIndex::simpleTypeName(Index); + +  // Try to make sure the type exists.  Even if it doesn't though, it may be +  // because we're dumping a symbol stream with no corresponding type stream +  // present, in which case we still want to be able to print <unknown UDT> +  // for the type names. +  if (auto EC = ensureTypeExists(Index)) { +    consumeError(std::move(EC)); +    return "<unknown UDT>";    } -  return Database.getTypeName(Index); +  uint32_t I = Index.toArrayIndex(); +  ensureCapacityFor(Index); +  if (Records[I].Name.data() == nullptr) { +    StringRef Result = NameStorage.save(computeTypeName(*this, Index)); +    Records[I].Name = Result; +  } +  return Records[I].Name;  }  bool LazyRandomTypeCollection::contains(TypeIndex Index) { -  return Database.contains(Index); +  if (Records.size() <= Index.toArrayIndex()) +    return false; +  if (!Records[Index.toArrayIndex()].Type.valid()) +    return false; +  return true;  } -uint32_t LazyRandomTypeCollection::size() { return Database.size(); } +uint32_t LazyRandomTypeCollection::size() { return Count; } -uint32_t LazyRandomTypeCollection::capacity() { return Database.capacity(); } +uint32_t LazyRandomTypeCollection::capacity() { return Records.size(); }  Error LazyRandomTypeCollection::ensureTypeExists(TypeIndex TI) { -  if (!Database.contains(TI)) { -    if (auto EC = visitRangeForType(TI)) -      return EC; -  } -  return Error::success(); +  if (contains(TI)) +    return Error::success(); + +  return visitRangeForType(TI); +} + +void LazyRandomTypeCollection::ensureCapacityFor(TypeIndex Index) { +  uint32_t MinSize = Index.toArrayIndex() + 1; + +  if (MinSize <= capacity()) +    return; + +  uint32_t NewCapacity = MinSize * 3 / 2; + +  assert(NewCapacity > capacity()); +  Records.resize(NewCapacity);  }  Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) { @@ -111,7 +147,7 @@ Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) {    auto Prev = std::prev(Next);    TypeIndex TIB = Prev->Type; -  if (Database.contains(TIB)) { +  if (contains(TIB)) {      // They've asked us to fetch a type index, but the entry we found in the      // partial offsets array has already been visited.  Since we visit an entire      // block every time, that means this record should have been previously @@ -122,13 +158,12 @@ Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) {    TypeIndex TIE;    if (Next == PartialOffsets.end()) { -    TIE = TypeIndex::fromArrayIndex(Database.capacity()); +    TIE = TypeIndex::fromArrayIndex(capacity());    } else {      TIE = Next->Type;    } -  if (auto EC = visitRange(TIB, Prev->Offset, TIE)) -    return EC; +  visitRange(TIB, Prev->Offset, TIE);    return Error::success();  } @@ -157,34 +192,31 @@ Error LazyRandomTypeCollection::fullScanForType(TypeIndex TI) {    assert(PartialOffsets.empty());    TypeIndex CurrentTI = TypeIndex::fromArrayIndex(0); -  uint32_t Offset = 0;    auto Begin = Types.begin(); -  if (!Database.empty()) { +  if (Count > 0) {      // In the case of type streams which we don't know the number of records of,      // it's possible to search for a type index triggering a full scan, but then      // later additional records are added since we didn't know how many there      // would be until we did a full visitation, then you try to access the new      // type triggering another full scan.  To avoid this, we assume that if the -    // database has some records, this must be what's going on.  So we ask the -    // database for the largest type index less than the one we're searching for -    // and only do the forward scan from there. -    auto Prev = Database.largestTypeIndexLessThan(TI); -    assert(Prev.hasValue() && "Empty database with valid types?"); -    Offset = KnownOffsets[Prev->toArrayIndex()]; -    CurrentTI = *Prev; -    ++CurrentTI; +    // database has some records, this must be what's going on.  We can also +    // assume that this index must be larger than the largest type index we've +    // visited, so we start from there and scan forward. +    uint32_t Offset = Records[LargestTypeIndex.toArrayIndex()].Offset; +    CurrentTI = LargestTypeIndex + 1;      Begin = Types.at(Offset);      ++Begin; -    Offset = Begin.offset();    }    auto End = Types.end();    while (Begin != End) { -    if (auto EC = visitOneRecord(CurrentTI, Offset, *Begin)) -      return EC; - -    Offset += Begin.getRecordLength(); +    ensureCapacityFor(CurrentTI); +    LargestTypeIndex = std::max(LargestTypeIndex, CurrentTI); +    auto Idx = CurrentTI.toArrayIndex(); +    Records[Idx].Type = *Begin; +    Records[Idx].Offset = Begin.offset(); +    ++Count;      ++Begin;      ++CurrentTI;    } @@ -194,36 +226,19 @@ Error LazyRandomTypeCollection::fullScanForType(TypeIndex TI) {    return Error::success();  } -Error LazyRandomTypeCollection::visitRange(TypeIndex Begin, -                                           uint32_t BeginOffset, -                                           TypeIndex End) { - +void LazyRandomTypeCollection::visitRange(TypeIndex Begin, uint32_t BeginOffset, +                                          TypeIndex End) {    auto RI = Types.at(BeginOffset);    assert(RI != Types.end()); +  ensureCapacityFor(End);    while (Begin != End) { -    if (auto EC = visitOneRecord(Begin, BeginOffset, *RI)) -      return EC; - -    BeginOffset += RI.getRecordLength(); +    LargestTypeIndex = std::max(LargestTypeIndex, Begin); +    auto Idx = Begin.toArrayIndex(); +    Records[Idx].Type = *RI; +    Records[Idx].Offset = RI.offset(); +    ++Count;      ++Begin;      ++RI;    } - -  return Error::success(); -} - -Error LazyRandomTypeCollection::visitOneRecord(TypeIndex TI, uint32_t Offset, -                                               CVType &Record) { -  assert(!Database.contains(TI)); -  if (auto EC = codeview::visitTypeRecord(Record, TI, DatabaseVisitor)) -    return EC; -  // Keep the KnownOffsets array the same size as the Database's capacity. Since -  // we don't always know how many records are in the type stream, we need to be -  // prepared for the database growing and receicing a type index that can't fit -  // in our current buffer. -  if (KnownOffsets.size() < Database.capacity()) -    KnownOffsets.resize(Database.capacity()); -  KnownOffsets[TI.toArrayIndex()] = Offset; -  return Error::success();  } diff --git a/lib/DebugInfo/CodeView/SymbolDumper.cpp b/lib/DebugInfo/CodeView/SymbolDumper.cpp index 36abafc079edb..b9fa9b6a6ad7e 100644 --- a/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -524,7 +524,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,  Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) {    DictScope S(W, "PublicSym"); -  printTypeIndex("Type", Public.Index); +  W.printFlags("Flags", uint32_t(Public.Flags), getPublicSymFlagNames());    W.printNumber("Seg", Public.Segment);    W.printNumber("Off", Public.Offset);    W.printString("Name", Public.Name); diff --git a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp index d731dc1b0a372..923837a45d9fc 100644 --- a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp +++ b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp @@ -361,7 +361,7 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,  Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,                                              PublicSym32 &Public) { -  error(IO.mapInteger(Public.Index)); +  error(IO.mapEnum(Public.Flags));    error(IO.mapInteger(Public.Offset));    error(IO.mapInteger(Public.Segment));    error(IO.mapStringZ(Public.Name)); diff --git a/lib/DebugInfo/CodeView/TypeDatabase.cpp b/lib/DebugInfo/CodeView/TypeDatabase.cpp deleted file mode 100644 index 08f848b36a9d5..0000000000000 --- a/lib/DebugInfo/CodeView/TypeDatabase.cpp +++ /dev/null @@ -1,146 +0,0 @@ -//===- TypeDatabase.cpp --------------------------------------- *- C++ --*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" - -using namespace llvm; -using namespace llvm::codeview; - -TypeDatabase::TypeDatabase(uint32_t Capacity) : TypeNameStorage(Allocator) { -  CVUDTNames.resize(Capacity); -  TypeRecords.resize(Capacity); -  ValidRecords.resize(Capacity); -} - -TypeIndex TypeDatabase::appendType(StringRef Name, const CVType &Data) { -  LargestTypeIndex = getAppendIndex(); -  if (LargestTypeIndex.toArrayIndex() >= capacity()) -    grow(); -  recordType(Name, LargestTypeIndex, Data); -  return LargestTypeIndex; -} - -void TypeDatabase::recordType(StringRef Name, TypeIndex Index, -                              const CVType &Data) { -  LargestTypeIndex = empty() ? Index : std::max(Index, LargestTypeIndex); - -  if (LargestTypeIndex.toArrayIndex() >= capacity()) -    grow(Index); - -  uint32_t AI = Index.toArrayIndex(); - -  assert(!contains(Index)); -  assert(AI < capacity()); - -  CVUDTNames[AI] = Name; -  TypeRecords[AI] = Data; -  ValidRecords.set(AI); -  ++Count; -} - -/// Saves the name in a StringSet and creates a stable StringRef. -StringRef TypeDatabase::saveTypeName(StringRef TypeName) { -  return TypeNameStorage.save(TypeName); -} - -StringRef TypeDatabase::getTypeName(TypeIndex Index) const { -  if (Index.isNoneType() || Index.isSimple()) -    return TypeIndex::simpleTypeName(Index); - -  if (contains(Index)) -    return CVUDTNames[Index.toArrayIndex()]; - -  return "<unknown UDT>"; -} - -const CVType &TypeDatabase::getTypeRecord(TypeIndex Index) const { -  assert(contains(Index)); -  return TypeRecords[Index.toArrayIndex()]; -} - -CVType &TypeDatabase::getTypeRecord(TypeIndex Index) { -  assert(contains(Index)); -  return TypeRecords[Index.toArrayIndex()]; -} - -bool TypeDatabase::contains(TypeIndex Index) const { -  uint32_t AI = Index.toArrayIndex(); -  if (AI >= capacity()) -    return false; - -  return ValidRecords.test(AI); -} - -uint32_t TypeDatabase::size() const { return Count; } - -uint32_t TypeDatabase::capacity() const { return TypeRecords.size(); } - -CVType TypeDatabase::getType(TypeIndex Index) { return getTypeRecord(Index); } - -StringRef TypeDatabase::getTypeName(TypeIndex Index) { -  return static_cast<const TypeDatabase *>(this)->getTypeName(Index); -} - -bool TypeDatabase::contains(TypeIndex Index) { -  return static_cast<const TypeDatabase *>(this)->contains(Index); -} - -uint32_t TypeDatabase::size() { -  return static_cast<const TypeDatabase *>(this)->size(); -} - -uint32_t TypeDatabase::capacity() { -  return static_cast<const TypeDatabase *>(this)->capacity(); -} - -void TypeDatabase::grow() { grow(LargestTypeIndex + 1); } - -void TypeDatabase::grow(TypeIndex NewIndex) { -  uint32_t NewSize = NewIndex.toArrayIndex() + 1; - -  if (NewSize <= capacity()) -    return; - -  uint32_t NewCapacity = NewSize * 3 / 2; - -  TypeRecords.resize(NewCapacity); -  CVUDTNames.resize(NewCapacity); -  ValidRecords.resize(NewCapacity); -} - -bool TypeDatabase::empty() const { return size() == 0; } - -Optional<TypeIndex> TypeDatabase::largestTypeIndexLessThan(TypeIndex TI) const { -  uint32_t AI = TI.toArrayIndex(); -  int N = ValidRecords.find_prev(AI); -  if (N == -1) -    return None; -  return TypeIndex::fromArrayIndex(N); -} - -TypeIndex TypeDatabase::getAppendIndex() const { -  if (empty()) -    return TypeIndex::fromArrayIndex(0); - -  return LargestTypeIndex + 1; -} - -Optional<TypeIndex> TypeDatabase::getFirst() { -  int N = ValidRecords.find_first(); -  if (N == -1) -    return None; -  return TypeIndex::fromArrayIndex(N); -} - -Optional<TypeIndex> TypeDatabase::getNext(TypeIndex Prev) { -  int N = ValidRecords.find_next(Prev.toArrayIndex()); -  if (N == -1) -    return None; -  return TypeIndex::fromArrayIndex(N); -} diff --git a/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp b/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp deleted file mode 100644 index 8d97f8b1cb401..0000000000000 --- a/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp +++ /dev/null @@ -1,330 +0,0 @@ -//===- TypeDatabaseVisitor.cpp -------------------------------- *- C++ --*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" - -#include "llvm/ADT/SmallString.h" - -using namespace llvm; - -using namespace llvm::codeview; - -Error TypeDatabaseVisitor::visitTypeBegin(CVType &Record) { -  assert(!IsInFieldList); -  // Reset Name to the empty string. If the visitor sets it, we know it. -  Name = ""; - -  if (Record.Type == LF_FIELDLIST) { -    // Record that we're in a field list so that members do not get assigned -    // type indices. -    IsInFieldList = true; -  } -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) { -  if (auto EC = visitTypeBegin(Record)) -    return EC; - -  CurrentTypeIndex = Index; -  return Error::success(); -} - -StringRef TypeDatabaseVisitor::getTypeName(TypeIndex Index) const { -  return TypeDB->getTypeName(Index); -} - -StringRef TypeDatabaseVisitor::saveTypeName(StringRef Name) { -  return TypeDB->saveTypeName(Name); -} - -Error TypeDatabaseVisitor::visitTypeEnd(CVType &CVR) { -  if (CVR.Type == LF_FIELDLIST) { -    assert(IsInFieldList); -    IsInFieldList = false; -  } -  assert(!IsInFieldList); - -  // Record every type that is not a field list member, even if Name is empty. -  // CVUDTNames is indexed by type index, and must have one entry for every -  // type.  Field list members are not recorded, and are only referenced by -  // their containing field list record. -  if (CurrentTypeIndex) -    TypeDB->recordType(Name, *CurrentTypeIndex, CVR); -  else -    TypeDB->appendType(Name, CVR); - -  CurrentTypeIndex.reset(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitMemberBegin(CVMemberRecord &Record) { -  assert(IsInFieldList); -  // Reset Name to the empty string. If the visitor sets it, we know it. -  Name = ""; -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitMemberEnd(CVMemberRecord &Record) { -  assert(IsInFieldList); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            FieldListRecord &FieldList) { -  Name = "<field list>"; -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVRecord<TypeLeafKind> &CVR, -                                            StringIdRecord &String) { -  // Put this in the database so it gets printed with LF_UDT_SRC_LINE. -  Name = String.getString(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ArgListRecord &Args) { -  auto Indices = Args.getIndices(); -  uint32_t Size = Indices.size(); -  SmallString<256> TypeName("("); -  for (uint32_t I = 0; I < Size; ++I) { -    StringRef ArgTypeName = getTypeName(Indices[I]); -    TypeName.append(ArgTypeName); -    if (I + 1 != Size) -      TypeName.append(", "); -  } -  TypeName.push_back(')'); -  Name = saveTypeName(TypeName); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            StringListRecord &Strings) { -  auto Indices = Strings.getIndices(); -  uint32_t Size = Indices.size(); -  SmallString<256> TypeName("\""); -  for (uint32_t I = 0; I < Size; ++I) { -    StringRef ArgTypeName = getTypeName(Indices[I]); -    TypeName.append(ArgTypeName); -    if (I + 1 != Size) -      TypeName.append("\" \""); -  } -  TypeName.push_back('\"'); -  Name = saveTypeName(TypeName); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ClassRecord &Class) { -  Name = Class.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, UnionRecord &Union) { -  Name = Union.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) { -  Name = Enum.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) { -  Name = AT.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) { -  Name = VFT.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            MemberFuncIdRecord &Id) { -  Name = Id.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            ProcedureRecord &Proc) { -  StringRef ReturnTypeName = getTypeName(Proc.getReturnType()); -  StringRef ArgListTypeName = getTypeName(Proc.getArgumentList()); -  SmallString<256> TypeName(ReturnTypeName); -  TypeName.push_back(' '); -  TypeName.append(ArgListTypeName); -  Name = saveTypeName(TypeName); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            MemberFunctionRecord &MF) { -  StringRef ReturnTypeName = getTypeName(MF.getReturnType()); -  StringRef ClassTypeName = getTypeName(MF.getClassType()); -  StringRef ArgListTypeName = getTypeName(MF.getArgumentList()); -  SmallString<256> TypeName(ReturnTypeName); -  TypeName.push_back(' '); -  TypeName.append(ClassTypeName); -  TypeName.append("::"); -  TypeName.append(ArgListTypeName); -  Name = saveTypeName(TypeName); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) { -  Name = Func.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            TypeServer2Record &TS) { -  Name = TS.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { - -  if (Ptr.isPointerToMember()) { -    const MemberPointerInfo &MI = Ptr.getMemberInfo(); - -    StringRef PointeeName = getTypeName(Ptr.getReferentType()); -    StringRef ClassName = getTypeName(MI.getContainingType()); -    SmallString<256> TypeName(PointeeName); -    TypeName.push_back(' '); -    TypeName.append(ClassName); -    TypeName.append("::*"); -    Name = saveTypeName(TypeName); -  } else { -    SmallString<256> TypeName; -    if (Ptr.isConst()) -      TypeName.append("const "); -    if (Ptr.isVolatile()) -      TypeName.append("volatile "); -    if (Ptr.isUnaligned()) -      TypeName.append("__unaligned "); - -    TypeName.append(getTypeName(Ptr.getReferentType())); - -    if (Ptr.getMode() == PointerMode::LValueReference) -      TypeName.append("&"); -    else if (Ptr.getMode() == PointerMode::RValueReference) -      TypeName.append("&&"); -    else if (Ptr.getMode() == PointerMode::Pointer) -      TypeName.append("*"); - -    if (!TypeName.empty()) -      Name = saveTypeName(TypeName); -  } -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) { -  uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers()); - -  StringRef ModifiedName = getTypeName(Mod.getModifiedType()); -  SmallString<256> TypeName; -  if (Mods & uint16_t(ModifierOptions::Const)) -    TypeName.append("const "); -  if (Mods & uint16_t(ModifierOptions::Volatile)) -    TypeName.append("volatile "); -  if (Mods & uint16_t(ModifierOptions::Unaligned)) -    TypeName.append("__unaligned "); -  TypeName.append(ModifiedName); -  Name = saveTypeName(TypeName); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            VFTableShapeRecord &Shape) { -  Name = -      saveTypeName("<vftable " + utostr(Shape.getEntryCount()) + " methods>"); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            NestedTypeRecord &Nested) { -  Name = Nested.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            OneMethodRecord &Method) { -  Name = Method.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            OverloadedMethodRecord &Method) { -  Name = Method.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            DataMemberRecord &Field) { -  Name = Field.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            StaticDataMemberRecord &Field) { -  Name = Field.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            EnumeratorRecord &Enum) { -  Name = Enum.getName(); -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            BaseClassRecord &Base) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            VirtualBaseClassRecord &VBase) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            ListContinuationRecord &Cont) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord( -    CVType &CVR, UdtModSourceLineRecord &ModSourceLine) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, -                                            UdtSourceLineRecord &SourceLine) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord( -    CVType &CVR, MethodOverloadListRecord &Overloads) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, LabelRecord &R) { -  return Error::success(); -} - -Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR, -                                            VFPtrRecord &VFP) { -  return Error::success(); -} diff --git a/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp index 04b0384d81902..5899667050151 100644 --- a/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp +++ b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp @@ -13,8 +13,6 @@  #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"  #include "llvm/DebugInfo/CodeView/Formatters.h"  #include "llvm/DebugInfo/CodeView/TypeCollection.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" -#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"  #include "llvm/DebugInfo/CodeView/TypeIndex.h"  #include "llvm/DebugInfo/CodeView/TypeRecord.h"  #include "llvm/Support/BinaryByteStream.h" diff --git a/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp b/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp index 8704cea607867..1226d5be3f3c4 100644 --- a/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp +++ b/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp @@ -357,6 +357,82 @@ static void discoverTypeIndices(ArrayRef<uint8_t> Content, TypeLeafKind Kind,    }  } +static bool discoverTypeIndices(ArrayRef<uint8_t> Content, SymbolKind Kind, +                                SmallVectorImpl<TiReference> &Refs) { +  uint32_t Count; +  // FIXME: In the future it would be nice if we could avoid hardcoding these +  // values.  One idea is to define some structures representing these types +  // that would allow the use of offsetof(). +  switch (Kind) { +  case SymbolKind::S_GPROC32: +  case SymbolKind::S_LPROC32: +  case SymbolKind::S_GPROC32_ID: +  case SymbolKind::S_LPROC32_ID: +  case SymbolKind::S_LPROC32_DPC: +  case SymbolKind::S_LPROC32_DPC_ID: +    Refs.push_back({TiRefKind::IndexRef, 24, 1}); // LF_FUNC_ID +    break; +  case SymbolKind::S_UDT: +    Refs.push_back({TiRefKind::TypeRef, 0, 1}); // UDT +    break; +  case SymbolKind::S_GDATA32: +  case SymbolKind::S_LDATA32: +    Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type +    break; +  case SymbolKind::S_BUILDINFO: +    Refs.push_back({TiRefKind::IndexRef, 0, 1}); // Compile flags +    break; +  case SymbolKind::S_LOCAL: +    Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type +    break; +  case SymbolKind::S_CONSTANT: +    Refs.push_back({TiRefKind::TypeRef, 0, 1}); // Type +    break; +  case SymbolKind::S_REGREL32: +    Refs.push_back({TiRefKind::TypeRef, 4, 1}); // Type +    break; +  case SymbolKind::S_CALLSITEINFO: +    Refs.push_back({TiRefKind::TypeRef, 8, 1}); // Call signature +    break; +  case SymbolKind::S_CALLERS: +  case SymbolKind::S_CALLEES: +    // The record is a count followed by an array of type indices. +    Count = *reinterpret_cast<const ulittle32_t *>(Content.data()); +    Refs.push_back({TiRefKind::IndexRef, 4, Count}); // Callees +    break; +  case SymbolKind::S_INLINESITE: +    Refs.push_back({TiRefKind::IndexRef, 8, 1}); // ID of inlinee +    break; + +  // Defranges don't have types, just registers and code offsets. +  case SymbolKind::S_DEFRANGE_REGISTER: +  case SymbolKind::S_DEFRANGE_REGISTER_REL: +  case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL: +  case SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: +  case SymbolKind::S_DEFRANGE_SUBFIELD_REGISTER: +  case SymbolKind::S_DEFRANGE_SUBFIELD: +    break; + +  // No type refernces. +  case SymbolKind::S_LABEL32: +  case SymbolKind::S_OBJNAME: +  case SymbolKind::S_COMPILE: +  case SymbolKind::S_COMPILE2: +  case SymbolKind::S_COMPILE3: +  case SymbolKind::S_BLOCK32: +  case SymbolKind::S_FRAMEPROC: +    break; +  // Scope ending symbols. +  case SymbolKind::S_END: +  case SymbolKind::S_INLINESITE_END: +  case SymbolKind::S_PROC_ID_END: +    break; +  default: +    return false; // Unknown symbol. +  } +  return true; +} +  void llvm::codeview::discoverTypeIndices(const CVType &Type,                                           SmallVectorImpl<TiReference> &Refs) {    ::discoverTypeIndices(Type.content(), Type.kind(), Refs); @@ -369,3 +445,9 @@ void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,    TypeLeafKind K = static_cast<TypeLeafKind>(uint16_t(P->RecordKind));    ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs);  } + +bool llvm::codeview::discoverTypeIndices(const CVSymbol &Sym, +                                         SmallVectorImpl<TiReference> &Refs) { +  SymbolKind K = Sym.kind(); +  return ::discoverTypeIndices(Sym.content(), K, Refs); +} diff --git a/lib/DebugInfo/CodeView/TypeName.cpp b/lib/DebugInfo/CodeView/TypeName.cpp new file mode 100644 index 0000000000000..2eb8b81862f3c --- /dev/null +++ b/lib/DebugInfo/CodeView/TypeName.cpp @@ -0,0 +1,243 @@ +//===- TypeName.cpp ------------------------------------------- *- C++ --*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/CodeView/TypeName.h" + +#include "llvm/ADT/SmallString.h" +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" +#include "llvm/Support/FormatVariadic.h" + +using namespace llvm; +using namespace llvm::codeview; + +namespace { +class TypeNameComputer : public TypeVisitorCallbacks { +  /// The type collection.  Used to calculate names of nested types. +  TypeCollection &Types; +  TypeIndex CurrentTypeIndex = TypeIndex::None(); + +  /// Name of the current type. Only valid before visitTypeEnd. +  SmallString<256> Name; + +public: +  explicit TypeNameComputer(TypeCollection &Types) : Types(Types) {} + +  StringRef name() const { return Name; } + +  /// Paired begin/end actions for all types. Receives all record data, +  /// including the fixed-length record prefix. +  Error visitTypeBegin(CVType &Record) override; +  Error visitTypeBegin(CVType &Record, TypeIndex Index) override; +  Error visitTypeEnd(CVType &Record) override; + +#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \ +  Error visitKnownRecord(CVType &CVR, Name##Record &Record) override; +#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) +#define MEMBER_RECORD(EnumName, EnumVal, Name) +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" +}; +} // namespace + +Error TypeNameComputer::visitTypeBegin(CVType &Record) { +  llvm_unreachable("Must call visitTypeBegin with a TypeIndex!"); +  return Error::success(); +} + +Error TypeNameComputer::visitTypeBegin(CVType &Record, TypeIndex Index) { +  // Reset Name to the empty string. If the visitor sets it, we know it. +  Name = ""; +  CurrentTypeIndex = Index; +  return Error::success(); +} + +Error TypeNameComputer::visitTypeEnd(CVType &CVR) { return Error::success(); } + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, +                                         FieldListRecord &FieldList) { +  Name = "<field list>"; +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVRecord<TypeLeafKind> &CVR, +                                         StringIdRecord &String) { +  Name = String.getString(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) { +  auto Indices = Args.getIndices(); +  uint32_t Size = Indices.size(); +  Name = "("; +  for (uint32_t I = 0; I < Size; ++I) { +    assert(Indices[I] < CurrentTypeIndex); + +    Name.append(Types.getTypeName(Indices[I])); +    if (I + 1 != Size) +      Name.append(", "); +  } +  Name.push_back(')'); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, +                                         StringListRecord &Strings) { +  auto Indices = Strings.getIndices(); +  uint32_t Size = Indices.size(); +  Name = "\""; +  for (uint32_t I = 0; I < Size; ++I) { +    Name.append(Types.getTypeName(Indices[I])); +    if (I + 1 != Size) +      Name.append("\" \""); +  } +  Name.push_back('\"'); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, ClassRecord &Class) { +  Name = Class.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, UnionRecord &Union) { +  Name = Union.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, EnumRecord &Enum) { +  Name = Enum.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArrayRecord &AT) { +  Name = AT.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) { +  Name = VFT.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) { +  Name = Id.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) { +  StringRef Ret = Types.getTypeName(Proc.getReturnType()); +  StringRef Params = Types.getTypeName(Proc.getArgumentList()); +  Name = formatv("{0} {1}", Ret, Params).sstr<256>(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, +                                         MemberFunctionRecord &MF) { +  StringRef Ret = Types.getTypeName(MF.getReturnType()); +  StringRef Class = Types.getTypeName(MF.getClassType()); +  StringRef Params = Types.getTypeName(MF.getArgumentList()); +  Name = formatv("{0} {1}::{2}", Ret, Class, Params).sstr<256>(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) { +  Name = Func.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) { +  Name = TS.getName(); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { + +  if (Ptr.isPointerToMember()) { +    const MemberPointerInfo &MI = Ptr.getMemberInfo(); + +    StringRef Pointee = Types.getTypeName(Ptr.getReferentType()); +    StringRef Class = Types.getTypeName(MI.getContainingType()); +    Name = formatv("{0} {1}::*", Pointee, Class); +  } else { +    if (Ptr.isConst()) +      Name.append("const "); +    if (Ptr.isVolatile()) +      Name.append("volatile "); +    if (Ptr.isUnaligned()) +      Name.append("__unaligned "); + +    Name.append(Types.getTypeName(Ptr.getReferentType())); + +    if (Ptr.getMode() == PointerMode::LValueReference) +      Name.append("&"); +    else if (Ptr.getMode() == PointerMode::RValueReference) +      Name.append("&&"); +    else if (Ptr.getMode() == PointerMode::Pointer) +      Name.append("*"); +  } +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) { +  uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers()); + +  SmallString<256> TypeName; +  if (Mods & uint16_t(ModifierOptions::Const)) +    Name.append("const "); +  if (Mods & uint16_t(ModifierOptions::Volatile)) +    Name.append("volatile "); +  if (Mods & uint16_t(ModifierOptions::Unaligned)) +    Name.append("__unaligned "); +  Name.append(Types.getTypeName(Mod.getModifiedType())); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, +                                         VFTableShapeRecord &Shape) { +  Name = formatv("<vftable {0} methods>", Shape.getEntryCount()); +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord( +    CVType &CVR, UdtModSourceLineRecord &ModSourceLine) { +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, +                                         UdtSourceLineRecord &SourceLine) { +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) { +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, +                                         MethodOverloadListRecord &Overloads) { +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) { +  return Error::success(); +} + +Error TypeNameComputer::visitKnownRecord(CVType &CVR, LabelRecord &R) { +  return Error::success(); +} + +std::string llvm::codeview::computeTypeName(TypeCollection &Types, +                                            TypeIndex Index) { +  TypeNameComputer Computer(Types); +  CVType Record = Types.getType(Index); +  if (auto EC = visitTypeRecord(Record, Index, Computer)) { +    consumeError(std::move(EC)); +    return "<unknown UDT>"; +  } +  return Computer.name(); +} diff --git a/lib/DebugInfo/CodeView/TypeTableCollection.cpp b/lib/DebugInfo/CodeView/TypeTableCollection.cpp index 8d974d522f283..4eca5aeaa0ae3 100644 --- a/lib/DebugInfo/CodeView/TypeTableCollection.cpp +++ b/lib/DebugInfo/CodeView/TypeTableCollection.cpp @@ -10,7 +10,7 @@  #include "llvm/DebugInfo/CodeView/TypeTableCollection.h"  #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeName.h"  #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"  #include "llvm/Support/BinaryByteStream.h"  #include "llvm/Support/BinaryStreamReader.h" @@ -18,14 +18,10 @@  using namespace llvm;  using namespace llvm::codeview; -static void error(Error &&EC) { -  assert(!static_cast<bool>(EC)); -  if (EC) -    consumeError(std::move(EC)); -} -  TypeTableCollection::TypeTableCollection(ArrayRef<ArrayRef<uint8_t>> Records) -    : Records(Records), Database(Records.size()) {} +    : NameStorage(Allocator), Records(Records) { +  Names.resize(Records.size()); +}  Optional<TypeIndex> TypeTableCollection::getFirst() {    if (empty()) @@ -34,50 +30,38 @@ Optional<TypeIndex> TypeTableCollection::getFirst() {  }  Optional<TypeIndex> TypeTableCollection::getNext(TypeIndex Prev) { +  assert(contains(Prev));    ++Prev; -  assert(Prev.toArrayIndex() <= size());    if (Prev.toArrayIndex() == size())      return None;    return Prev;  } -void TypeTableCollection::ensureTypeExists(TypeIndex Index) { -  assert(hasCapacityFor(Index)); - -  if (Database.contains(Index)) -    return; - -  BinaryByteStream Bytes(Records[Index.toArrayIndex()], support::little); - -  CVType Type; -  uint32_t Len; -  VarStreamArrayExtractor<CVType> Extract; -  error(Extract(Bytes, Len, Type)); - -  TypeDatabaseVisitor DBV(Database); -  error(codeview::visitTypeRecord(Type, Index, DBV)); -  assert(Database.contains(Index)); -} -  CVType TypeTableCollection::getType(TypeIndex Index) { -  ensureTypeExists(Index); -  return Database.getTypeRecord(Index); +  assert(Index.toArrayIndex() < Records.size()); +  ArrayRef<uint8_t> Bytes = Records[Index.toArrayIndex()]; +  const RecordPrefix *Prefix = +      reinterpret_cast<const RecordPrefix *>(Bytes.data()); +  TypeLeafKind Kind = static_cast<TypeLeafKind>(uint16_t(Prefix->RecordKind)); +  return CVType(Kind, Bytes);  }  StringRef TypeTableCollection::getTypeName(TypeIndex Index) { -  if (!Index.isSimple()) -    ensureTypeExists(Index); -  return Database.getTypeName(Index); +  if (Index.isNoneType() || Index.isSimple()) +    return TypeIndex::simpleTypeName(Index); + +  uint32_t I = Index.toArrayIndex(); +  if (Names[I].data() == nullptr) { +    StringRef Result = NameStorage.save(computeTypeName(*this, Index)); +    Names[I] = Result; +  } +  return Names[I];  }  bool TypeTableCollection::contains(TypeIndex Index) { -  return Database.contains(Index); +  return Index.toArrayIndex() <= size();  }  uint32_t TypeTableCollection::size() { return Records.size(); }  uint32_t TypeTableCollection::capacity() { return Records.size(); } - -bool TypeTableCollection::hasCapacityFor(TypeIndex Index) const { -  return Index.toArrayIndex() < Records.size(); -}  | 
