[llvm] r342656 - [PDB] Add the ability to map forward references to full decls.

Benjamin Kramer via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 20 09:42:27 PDT 2018


On Thu, Sep 20, 2018 at 5:51 PM Zachary Turner via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: zturner
> Date: Thu Sep 20 08:50:13 2018
> New Revision: 342656
>
> URL: http://llvm.org/viewvc/llvm-project?rev=342656&view=rev
> Log:
> [PDB] Add the ability to map forward references to full decls.
>
> Some records point to an LF_CLASS, LF_UNION, LF_STRUCTURE, or LF_ENUM
> which is a forward reference and doesn't contain complete debug
> information. In these cases, we'd like to be able to quickly locate the
> full record. The TPI stream stores an array of pre-computed record hash
> values, one for each type record. If we pre-process this on startup, we
> can build a mapping from hash value -> {list of possible matching type
> indices}. Since hashes of full records are only based on the name and or
> unique name and not the full record contents, we can then use forward
> ref record to compute the hash of what *would* be the full record by
> just hashing the name, use this to get the list of possible matches, and
> iterate those looking for a match on name or unique name.
>
> llvm-pdbutil is updated to resolve forward references for the purposes
> of testing (plus it's just useful).
>
> Differential Revision: https://reviews.llvm.org/D52283
>
> Added:
>     llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.cpp
>     llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.pdb   (with props)
>     llvm/trunk/test/DebugInfo/PDB/pdb-resolve-forward-refs.test
> Modified:
>     llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h
>     llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiHashing.h
>     llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiStream.h
>     llvm/trunk/lib/DebugInfo/PDB/Native/TpiHashing.cpp
>     llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp
>     llvm/trunk/test/DebugInfo/PDB/every-type.test
>     llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test
>     llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp
>     llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.cpp
>     llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.h
>     llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp
>     llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h
>
> Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h?rev=342656&r1=342655&r2=342656&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h (original)
> +++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h Thu Sep 20
> 08:50:13 2018
> @@ -343,7 +343,6 @@ struct SrcHeaderBlockEntry {
>    char Reserved[8];
>  };
>
> -constexpr int I = sizeof(SrcHeaderBlockEntry);
>  static_assert(sizeof(SrcHeaderBlockEntry) == 40, "Incorrect struct
> size!");
>
>  } // namespace pdb
>
> Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiHashing.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiHashing.h?rev=342656&r1=342655&r2=342656&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiHashing.h (original)
> +++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiHashing.h Thu Sep 20
> 08:50:13 2018
> @@ -18,6 +18,54 @@ namespace pdb {
>
>  Expected<uint32_t> hashTypeRecord(const llvm::codeview::CVType &Type);
>
> +struct TagRecordHash {
> +  explicit TagRecordHash(codeview::ClassRecord CR, uint32_t Full,
> +                         uint32_t Forward)
> +      : Class(std::move(CR)), FullRecordHash(Full),
> ForwardDeclHash(Forward) {
> +    State = 0;
> +  }
> +
> +  explicit TagRecordHash(codeview::EnumRecord ER, uint32_t Full,
> +                         uint32_t Forward)
> +      : Enum(std::move(ER)), FullRecordHash(Full),
> ForwardDeclHash(Forward) {
> +    State = 1;
> +  }
> +
> +  explicit TagRecordHash(codeview::UnionRecord UR, uint32_t Full,
> +                         uint32_t Forward)
> +      : Union(std::move(UR)), FullRecordHash(Full),
> ForwardDeclHash(Forward) {
> +    State = 2;
> +  }
> +
> +  uint32_t FullRecordHash;
> +  uint32_t ForwardDeclHash;
> +
> +  codeview::TagRecord &getRecord() {
> +    switch (State) {
> +    case 0:
> +      return Class;
> +    case 1:
> +      return Enum;
> +    case 2:
> +      return Union;
> +    }
> +    llvm_unreachable("unreachable!");
> +  }
> +
> +private:
> +  union {
> +    codeview::ClassRecord Class;
> +    codeview::EnumRecord Enum;
> +    codeview::UnionRecord Union;
> +  };
> +
> +  uint8_t State = 0;
> +};
> +
> +/// Given a CVType referring to a class, structure, union, or enum,
> compute
> +/// the hash of its forward decl and full decl.
> +Expected<TagRecordHash> hashTagRecord(const codeview::CVType &Type);
> +
>  } // end namespace pdb
>  } // end namespace llvm
>
>
> Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiStream.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiStream.h?rev=342656&r1=342655&r2=342656&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiStream.h (original)
> +++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/TpiStream.h Thu Sep 20
> 08:50:13 2018
> @@ -58,10 +58,17 @@ public:
>
>    codeview::LazyRandomTypeCollection &typeCollection() { return *Types; }
>
> +  Expected<codeview::TypeIndex>
> +  findFullDeclForForwardRef(codeview::TypeIndex ForwardRefTI) const;
> +
>    BinarySubstreamRef getTypeRecordsSubstream() const;
>
>    Error commit();
>
> +  void buildHashMap();
> +
> +  bool supportsTypeLookup() const;
> +
>  private:
>    PDBFile &Pdb;
>    std::unique_ptr<msf::MappedBlockStream> Stream;
> @@ -77,6 +84,8 @@ private:
>    FixedStreamArray<codeview::TypeIndexOffset> TypeIndexOffsets;
>    HashTable<support::ulittle32_t> HashAdjusters;
>
> +  std::vector<std::vector<codeview::TypeIndex>> HashMap;
> +
>    const TpiStreamHeader *Header;
>  };
>  }
>
> Modified: llvm/trunk/lib/DebugInfo/PDB/Native/TpiHashing.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/TpiHashing.cpp?rev=342656&r1=342655&r2=342656&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/PDB/Native/TpiHashing.cpp (original)
> +++ llvm/trunk/lib/DebugInfo/PDB/Native/TpiHashing.cpp Thu Sep 20 08:50:13
> 2018
> @@ -50,6 +50,32 @@ static Expected<uint32_t> getHashForUdt(
>  }
>
>  template <typename T>
> +static Expected<TagRecordHash> getTagRecordHashForUdt(const CVType &Rec) {
> +  T Deserialized;
> +  if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
> +                                               Deserialized))
> +    return std::move(E);
> +
> +  ClassOptions Opts = Deserialized.getOptions();
> +
> +  bool ForwardRef = bool(Opts & ClassOptions::ForwardReference);
> +
> +  uint32_t ThisRecordHash = getHashForUdt(Deserialized, Rec.data());
> +
> +  // If we don't have a forward ref we can't compute the hash of it from
> the
> +  // full record because it requires hashing the entire buffer.
> +  if (!ForwardRef)
> +    return TagRecordHash{std::move(Deserialized), ThisRecordHash, 0};
> +
> +  bool Scoped = bool(Opts & ClassOptions::Scoped);
> +
> +  StringRef NameToHash =
> +      Scoped ? Deserialized.getUniqueName() : Deserialized.getName();
> +  uint32_t FullHash = hashStringV1(NameToHash);
> +  return TagRecordHash{std::move(Deserialized), FullHash, ThisRecordHash};
> +}
> +
> +template <typename T>
>  static Expected<uint32_t> getSourceLineHash(const CVType &Rec) {
>    T Deserialized;
>    if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
> @@ -60,6 +86,23 @@ static Expected<uint32_t> getSourceLineH
>    return hashStringV1(StringRef(Buf, 4));
>  }
>
> +Expected<TagRecordHash> llvm::pdb::hashTagRecord(const codeview::CVType
> &Type) {
> +  switch (Type.kind()) {
> +  case LF_CLASS:
> +  case LF_STRUCTURE:
> +  case LF_INTERFACE:
> +    return getTagRecordHashForUdt<ClassRecord>(Type);
> +  case LF_UNION:
> +    return getTagRecordHashForUdt<UnionRecord>(Type);
> +  case LF_ENUM:
> +    return getTagRecordHashForUdt<EnumRecord>(Type);
> +  default:
> +    assert(false && "Type is not a tag record!");
> +  }
> +  return make_error<StringError>("Invalid record type",
> +                                 inconvertibleErrorCode());
> +}
> +
>  Expected<uint32_t> llvm::pdb::hashTypeRecord(const CVType &Rec) {
>    switch (Rec.kind()) {
>    case LF_CLASS:
>
> Modified: llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp?rev=342656&r1=342655&r2=342656&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp (original)
> +++ llvm/trunk/lib/DebugInfo/PDB/Native/TpiStream.cpp Thu Sep 20 08:50:13
> 2018
> @@ -11,8 +11,11 @@
>
>  #include "llvm/ADT/iterator_range.h"
>  #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
> +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
> +#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
>  #include "llvm/DebugInfo/CodeView/TypeRecord.h"
>  #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
> +#include "llvm/DebugInfo/PDB/Native/Hash.h"
>  #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
>  #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
>  #include "llvm/DebugInfo/PDB/Native/RawError.h"
> @@ -140,6 +143,93 @@ uint16_t TpiStream::getTypeHashStreamAux
>  uint32_t TpiStream::getNumHashBuckets() const { return
> Header->NumHashBuckets; }
>  uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; }
>
> +void TpiStream::buildHashMap() {
> +  if (!HashMap.empty())
> +    return;
> +  if (HashValues.empty())
> +    return;
> +
> +  HashMap.resize(Header->NumHashBuckets);
> +
> +  TypeIndex TIB{Header->TypeIndexBegin};
> +  TypeIndex TIE{Header->TypeIndexEnd};
> +  while (TIB < TIE) {
> +    uint32_t HV = HashValues[TIB.toArrayIndex()];
> +    HashMap[HV].push_back(TIB++);
> +  }
> +}
> +
> +bool TpiStream::supportsTypeLookup() const { return !HashMap.empty(); }
> +
> +template <typename RecordT> static ClassOptions getUdtOptions(CVType CVT)
> {
> +  RecordT Record;
> +  if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) {
> +    consumeError(std::move(EC));
> +    return ClassOptions::None;
> +  }
> +  return Record.getOptions();
> +}
> +
> +static bool isUdtForwardRef(CVType CVT) {
> +  ClassOptions UdtOptions = ClassOptions::None;
> +  switch (CVT.kind()) {
> +  case LF_STRUCTURE:
> +  case LF_CLASS:
> +  case LF_INTERFACE:
> +    UdtOptions = getUdtOptions<ClassRecord>(std::move(CVT));
> +    break;
> +  case LF_ENUM:
> +    UdtOptions = getUdtOptions<EnumRecord>(std::move(CVT));
> +    break;
> +  case LF_UNION:
> +    UdtOptions = getUdtOptions<UnionRecord>(std::move(CVT));
> +    break;
> +  default:
> +    return false;
> +  }
> +  return (UdtOptions & ClassOptions::ForwardReference) !=
> ClassOptions::None;
> +}
> +
> +Expected<TypeIndex>
> +TpiStream::findFullDeclForForwardRef(TypeIndex ForwardRefTI) const {
> +  CVType F = Types->getType(ForwardRefTI);
> +  if (!isUdtForwardRef(F))
> +    return ForwardRefTI;
> +
> +  Expected<TagRecordHash> ForwardTRH = hashTagRecord(F);
> +  if (!ForwardTRH)
> +    return ForwardTRH.takeError();
> +
> +  TagRecordHash Copy = std::move(*ForwardTRH);
>

lib/DebugInfo/PDB/Native/TpiStream.cpp:203:17: error: unused variable
'Copy' [-Werror,-Wunused-variable]


> +  uint32_t BucketIdx = ForwardTRH->FullRecordHash %
> Header->NumHashBuckets;
> +
> +  for (TypeIndex TI : HashMap[BucketIdx]) {
> +    CVType CVT = Types->getType(TI);
> +    if (CVT.kind() != F.kind())
> +      continue;
> +
> +    Expected<TagRecordHash> FullTRH = hashTagRecord(CVT);
> +    if (!FullTRH)
> +      return FullTRH.takeError();
> +    if (ForwardTRH->FullRecordHash != FullTRH->FullRecordHash)
> +      continue;
> +    TagRecord &ForwardTR = ForwardTRH->getRecord();
> +    TagRecord &FullTR = FullTRH->getRecord();
> +
> +    if (!ForwardTR.hasUniqueName()) {
> +      if (ForwardTR.getName() == FullTR.getName())
> +        return TI;
> +      continue;
> +    }
> +
> +    if (!FullTR.hasUniqueName())
> +      continue;
> +    if (ForwardTR.getUniqueName() == FullTR.getUniqueName())
> +      return TI;
> +  }
> +  return ForwardRefTI;
> +}
> +
>  BinarySubstreamRef TpiStream::getTypeRecordsSubstream() const {
>    return TypeRecordsSubstream;
>  }
>
> Added: llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.cpp?rev=342656&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.cpp (added)
> +++ llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.cpp Thu Sep 20
> 08:50:13 2018
> @@ -0,0 +1,61 @@
> +// Build with "cl.exe /Z7 /GR- /GS- /GX- every-class.cpp /link
> /debug:full /nodefaultlib /incremental:no /entry:main"
> +
> +#include <stdint.h>
> +
> +// clang-format off
> +void *__purecall = 0;
> +
> +void __cdecl operator delete(void *, unsigned int) {}
> +void __cdecl operator delete(void *, unsigned __int64) {}
> +
> +struct Nothing {};
> +struct Constructor { Constructor() {} };
> +struct Assignment {
> +  Assignment &operator=(Assignment Other) { return *this; }
> +};
> +struct Cast {
> +  operator int() { return 42; }
> +};
> +
> +struct Nested {
> +  struct F {};
> +};
> +struct Operator {
> +  int operator+(int X) { return 42; }
> +};
> +
> +class Class {};
> +
> +union Union {};
> +
> +enum class Enum {A};
> +
> +
> +template<typename T> void f(T t) {}
> +
> +int main(int argc, char **argv) {
> +  struct Scoped {};
> +
> +  struct { } Anonymous;
> +
> +  f(Nothing{});
> +  f(Constructor{});
> +  f(Assignment{});
> +  f(Cast{});
> +  f(Nested{});
> +  f(Operator{});
> +  f(Nested::F{});
> +  f(Scoped{});
> +  f(Class{});
> +  f(Union{});
> +  f(Anonymous);
> +  f(Enum::A);
> +
> +
> +  f<const Nothing>(Nothing{});
> +  f<volatile Nothing>(Nothing{});
> +  f<const volatile Nothing>(Nothing{});
> +  f<__unaligned Nothing>(Nothing{});
> +
> +  return 0;
> +}
>
> Added: llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.pdb
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.pdb?rev=342656&view=auto
>
> ==============================================================================
> Binary file - no diff available.
>
> Propchange: llvm/trunk/test/DebugInfo/PDB/Inputs/every-class.pdb
>
> ------------------------------------------------------------------------------
>     svn:mime-type = application/octet-stream
>
> Modified: llvm/trunk/test/DebugInfo/PDB/every-type.test
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/every-type.test?rev=342656&r1=342655&r2=342656&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/PDB/every-type.test (original)
> +++ llvm/trunk/test/DebugInfo/PDB/every-type.test Thu Sep 20 08:50:13 2018
> @@ -9,12 +9,14 @@ we claim to understand.  We then test th
>
>
>  RUN: llvm-pdbutil dump
> -type-index=0x101A,0x102C,0x103D,0x104D,0x1098,0x10AA,0x10AC \
> -RUN:   -dependents %p/Inputs/every-type.pdb | FileCheck
> --check-prefix=TYPES %s
> +RUN:   -dont-resolve-forward-refs -dependents %p/Inputs/every-type.pdb \
> +RUN:   | FileCheck --check-prefix=TYPES %s
>
>  RUN: llvm-pdbutil pdb2yaml -tpi-stream -ipi-stream
> %p/Inputs/every-type.pdb > %t.pdb.yaml
>  RUN: llvm-pdbutil yaml2pdb -pdb=%t.yaml.pdb %t.pdb.yaml
>  RUN: llvm-pdbutil dump
> -type-index=0x101A,0x102C,0x103D,0x104D,0x1098,0x10AA,0x10AC \
> -RUN:   -dependents %t.yaml.pdb | FileCheck --check-prefix=TYPES %s
> +RUN:   -dependents -dont-resolve-forward-refs %t.yaml.pdb \
> +RUN:   | FileCheck --check-prefix=TYPES %s
>
>  TYPES:                           Types (TPI Stream)
>  TYPES-NEXT: ============================================================
>
> Added: llvm/trunk/test/DebugInfo/PDB/pdb-resolve-forward-refs.test
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdb-resolve-forward-refs.test?rev=342656&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/PDB/pdb-resolve-forward-refs.test (added)
> +++ llvm/trunk/test/DebugInfo/PDB/pdb-resolve-forward-refs.test Thu Sep 20
> 08:50:13 2018
> @@ -0,0 +1,98 @@
> +; RUN: llvm-pdbutil dump -types %p/Inputs/every-class.pdb \
> +; RUN:   | FileCheck %s
> +
> +; CHECK:                      Types (TPI Stream)
> +; CHECK: ============================================================
> +; CHECK:   Showing 157 records
> +; CHECK:   0x1008 | LF_STRUCTURE [size = 124]
> `main::__l2::<unnamed-type-Anonymous>`
> +; CHECK:            unique name: `.?AU<unnamed-type-Anonymous>@?1??main@
> @YAHHPEAPEAD at Z@`aa6523bc`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> 0x1007
> +; CHECK:            options: has unique name | scoped, sizeof 1
> +; CHECK:   0x1009 | LF_STRUCTURE [size = 88] `main::__l2::Scoped`
> +; CHECK:            unique name: `.?AUScoped@?1??main@@YAHHPEAPEAD at Z
> @`aa6523bc`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> 0x1007
> +; CHECK:            options: has unique name | scoped, sizeof 1
> +; CHECK:   0x1054 | LF_STRUCTURE [size = 48] `Nested::F`
> +; CHECK:            unique name: `.?AUF at Nested@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> <no type>
> +; CHECK:            options: forward ref (-> 0x1057) | has unique name |
> is nested, sizeof 0
> +; CHECK:   0x1056 | LF_STRUCTURE [size = 44] `Nested`
> +; CHECK:            unique name: `.?AUNested@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> 0x1055
> +; CHECK:            options: contains nested class | has unique name,
> sizeof 1
> +; CHECK:   0x1057 | LF_STRUCTURE [size = 48] `Nested::F`
> +; CHECK:            unique name: `.?AUF at Nested@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> 0x1007
> +; CHECK:            options: has unique name | is nested, sizeof 1
> +; CHECK:   0x1058 | LF_STRUCTURE [size = 52] `Constructor`
> +; CHECK:            unique name: `.?AUConstructor@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> <no type>
> +; CHECK:            options: forward ref (-> 0x105C) | has unique name,
> sizeof 0
> +; CHECK:   0x105C | LF_STRUCTURE [size = 52] `Constructor`
> +; CHECK:            unique name: `.?AUConstructor@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> 0x105B
> +; CHECK:            options: has ctor / dtor | has unique name, sizeof 1
> +; CHECK:   0x105D | LF_CLASS [size = 40] `Class`
> +; CHECK:            unique name: `.?AVClass@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> 0x1007
> +; CHECK:            options: has unique name, sizeof 1
> +; CHECK:   0x105E | LF_UNION [size = 32] `Union`
> +; CHECK:            unique name: `.?ATUnion@@`
> +; CHECK:            field list: 0x1007
> +; CHECK:            options: has unique name | sealed, sizeof 1
> +; CHECK:   0x105F | LF_STRUCTURE [size = 48] `Operator`
> +; CHECK:            unique name: `.?AUOperator@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> <no type>
> +; CHECK:            options: forward ref (-> 0x1064) | has unique name,
> sizeof 0
> +; CHECK:   0x1064 | LF_STRUCTURE [size = 48] `Operator`
> +; CHECK:            unique name: `.?AUOperator@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> 0x1063
> +; CHECK:            options: has unique name | overloaded operator,
> sizeof 1
> +; CHECK:   0x1066 | LF_ENUM [size = 36] `Enum`
> +; CHECK:            unique name: `.?AW4Enum@@`
> +; CHECK:            field list: 0x1065, underlying type: 0x0074 (int)
> +; CHECK:            options: has unique name
> +; CHECK:   0x1067 | LF_STRUCTURE [size = 40] `Cast`
> +; CHECK:            unique name: `.?AUCast@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> <no type>
> +; CHECK:            options: forward ref (-> 0x106B) | has unique name,
> sizeof 0
> +; CHECK:   0x106B | LF_STRUCTURE [size = 40] `Cast`
> +; CHECK:            unique name: `.?AUCast@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> 0x106A
> +; CHECK:            options: conversion operator | has unique name |
> overloaded operator, sizeof 1
> +; CHECK:   0x106C | LF_STRUCTURE [size = 44] `Nothing`
> +; CHECK:            unique name: `.?AUNothing@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> 0x1007
> +; CHECK:            options: has unique name, sizeof 1
> +; CHECK:   0x106D | LF_STRUCTURE [size = 52] `Assignment`
> +; CHECK:            unique name: `.?AUAssignment@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> <no type>
> +; CHECK:            options: forward ref (-> 0x1073) | has unique name,
> sizeof 0
> +; CHECK:   0x1073 | LF_STRUCTURE [size = 52] `Assignment`
> +; CHECK:            unique name: `.?AUAssignment@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> 0x1072
> +; CHECK:            options: has unique name | overloaded operator |
> overloaded operator=, sizeof 1
> +; CHECK:   0x1074 | LF_STRUCTURE [size = 44] `Nothing`
> +; CHECK:            unique name: `.?AUNothing@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> <no type>
> +; CHECK:            options: forward ref (<- 0x106C) | has unique name,
> sizeof 0
> +; CHECK:   0x1081 | LF_UNION [size = 32] `Union`
> +; CHECK:            unique name: `.?ATUnion@@`
> +; CHECK:            field list: <no type>
> +; CHECK:            options: forward ref (<- 0x105E) | has unique name,
> sizeof 0
> +; CHECK:   0x1084 | LF_STRUCTURE [size = 124]
> `main::__l2::<unnamed-type-Anonymous>`
> +; CHECK:            unique name: `.?AU<unnamed-type-Anonymous>@?1??main@
> @YAHHPEAPEAD at Z@`aa6523bc`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> <no type>
> +; CHECK:            options: forward ref (<- 0x1008) | has unique name |
> scoped, sizeof 0
> +; CHECK:   0x108E | LF_STRUCTURE [size = 44] `Nested`
> +; CHECK:            unique name: `.?AUNested@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> <no type>
> +; CHECK:            options: forward ref (<- 0x1056) | has unique name,
> sizeof 0
> +; CHECK:   0x1095 | LF_STRUCTURE [size = 88] `main::__l2::Scoped`
> +; CHECK:            unique name: `.?AUScoped@?1??main@@YAHHPEAPEAD at Z
> @`aa6523bc`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> <no type>
> +; CHECK:            options: forward ref (<- 0x1009) | has unique name |
> scoped, sizeof 0
> +; CHECK:   0x1098 | LF_CLASS [size = 40] `Class`
> +; CHECK:            unique name: `.?AVClass@@`
> +; CHECK:            vtable: <no type>, base list: <no type>, field list:
> <no type>
> +; CHECK:            options: forward ref (<- 0x105D) | has unique name,
> sizeof 0
>
> Modified: llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test?rev=342656&r1=342655&r2=342656&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test (original)
> +++ llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test Thu Sep 20 08:50:13
> 2018
> @@ -1,7 +1,9 @@
> -; RUN: llvm-pdbutil dump -all %p/Inputs/empty.pdb | FileCheck
> -check-prefix=ALL %s
> +; RUN: llvm-pdbutil dump -all -dont-resolve-forward-refs
> %p/Inputs/empty.pdb \
> +; RUN:   | FileCheck -check-prefix=ALL %s
>  ; RUN: llvm-pdbutil dump -summary -modules -files \
>  ; RUN:              %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG
> %s
> -; RUN: not llvm-pdbutil dump -summary %p/Inputs/bad-block-size.pdb 2>&1 |
> FileCheck -check-prefix=BAD-BLOCK-SIZE %s
> +; RUN: not llvm-pdbutil dump -summary %p/Inputs/bad-block-size.pdb 2>&1 \
> +; RUN:   | FileCheck -check-prefix=BAD-BLOCK-SIZE %s
>
>  ALL:                                Summary
>  ALL-NEXT: ============================================================
>
> Modified: llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp?rev=342656&r1=342655&r2=342656&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp (original)
> +++ llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp Thu Sep 20 08:50:13
> 2018
> @@ -1241,13 +1241,13 @@ static void
>  dumpFullTypeStream(LinePrinter &Printer, LazyRandomTypeCollection &Types,
>                     uint32_t NumTypeRecords, uint32_t NumHashBuckets,
>                     FixedStreamArray<support::ulittle32_t> HashValues,
> -                   bool Bytes, bool Extras) {
> +                   TpiStream *Stream, bool Bytes, bool Extras) {
>
>    Printer.formatLine("Showing {0:N} records", NumTypeRecords);
>    uint32_t Width = NumDigits(TypeIndex::FirstNonSimpleIndex +
> NumTypeRecords);
>
>    MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types,
> -                           NumHashBuckets, HashValues);
> +                           NumHashBuckets, HashValues, Stream);
>
>    if (auto EC = codeview::visitTypeStream(Types, V)) {
>      Printer.formatLine("An error occurred dumping type records: {0}",
> @@ -1263,7 +1263,8 @@ static void dumpPartialTypeStream(LinePr
>        NumDigits(TypeIndex::FirstNonSimpleIndex +
> Stream.getNumTypeRecords());
>
>    MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types,
> -                           Stream.getNumHashBuckets(),
> Stream.getHashValues());
> +                           Stream.getNumHashBuckets(),
> Stream.getHashValues(),
> +                           &Stream);
>
>    if (opts::dump::DumpTypeDependents) {
>      // If we need to dump all dependents, then iterate each index and find
> @@ -1325,7 +1326,8 @@ Error DumpOutputStyle::dumpTypesFromObje
>      Types.reset(Reader, 100);
>
>      if (opts::dump::DumpTypes) {
> -      dumpFullTypeStream(P, Types, 0, 0, {}, opts::dump::DumpTypeData,
> false);
> +      dumpFullTypeStream(P, Types, 0, 0, {}, nullptr,
> opts::dump::DumpTypeData,
> +                         false);
>      } else if (opts::dump::DumpTypeExtras) {
>        auto LocalHashes = LocallyHashedType::hashTypeCollection(Types);
>        auto GlobalHashes = GloballyHashedType::hashTypeCollection(Types);
> @@ -1394,11 +1396,14 @@ Error DumpOutputStyle::dumpTpiStream(uin
>
>    auto &Types = (StreamIdx == StreamTPI) ? File.types() : File.ids();
>
> +  // Enable resolving forward decls.
> +  Stream.buildHashMap();
> +
>    if (DumpTypes || !Indices.empty()) {
>      if (Indices.empty())
>        dumpFullTypeStream(P, Types, Stream.getNumTypeRecords(),
>                           Stream.getNumHashBuckets(),
> Stream.getHashValues(),
> -                         DumpBytes, DumpExtras);
> +                         &Stream, DumpBytes, DumpExtras);
>      else {
>        std::vector<TypeIndex> TiList(Indices.begin(), Indices.end());
>        dumpPartialTypeStream(P, Types, Stream, TiList, DumpBytes,
> DumpExtras,
>
> Modified: llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.cpp?rev=342656&r1=342655&r2=342656&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.cpp (original)
> +++ llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.cpp Thu Sep 20
> 08:50:13 2018
> @@ -12,6 +12,7 @@
>  #include "FormatUtil.h"
>  #include "LinePrinter.h"
>
> +#include "llvm-pdbutil.h"
>  #include "llvm/DebugInfo/CodeView/CVRecord.h"
>  #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
>  #include "llvm/DebugInfo/CodeView/CodeView.h"
> @@ -19,6 +20,7 @@
>  #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
>  #include "llvm/DebugInfo/CodeView/TypeRecord.h"
>  #include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
> +#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
>  #include "llvm/Support/FormatVariadic.h"
>  #include "llvm/Support/MathExtras.h"
>
> @@ -27,15 +29,37 @@ using namespace llvm::codeview;
>  using namespace llvm::pdb;
>
>  static std::string formatClassOptions(uint32_t IndentLevel,
> -                                      ClassOptions Options) {
> +                                      ClassOptions Options, TpiStream
> *Stream,
> +                                      TypeIndex CurrentTypeIndex) {
>    std::vector<std::string> Opts;
> +
> +  if (Stream && Stream->supportsTypeLookup() &&
> +      !opts::dump::DontResolveForwardRefs &&
> +      ((Options & ClassOptions::ForwardReference) != ClassOptions::None))
> {
> +    // If we're able to resolve forward references, do that.
> +    Expected<TypeIndex> ETI =
> +        Stream->findFullDeclForForwardRef(CurrentTypeIndex);
> +    if (!ETI) {
> +      consumeError(ETI.takeError());
> +      PUSH_FLAG(ClassOptions, ForwardReference, Options, "forward ref
> (???)");
> +    } else {
> +      const char *Direction = (*ETI == CurrentTypeIndex)
> +                                  ? "="
> +                                  : ((*ETI < CurrentTypeIndex) ? "<-" :
> "->");
> +      std::string Formatted =
> +          formatv("forward ref ({0} {1})", Direction, *ETI).str();
> +      PUSH_FLAG(ClassOptions, ForwardReference, Options,
> std::move(Formatted));
> +    }
> +  } else {
> +    PUSH_FLAG(ClassOptions, ForwardReference, Options, "forward ref");
> +  }
> +
>    PUSH_FLAG(ClassOptions, HasConstructorOrDestructor, Options,
>              "has ctor / dtor");
>    PUSH_FLAG(ClassOptions, ContainsNestedClass, Options,
>              "contains nested class");
>    PUSH_FLAG(ClassOptions, HasConversionOperator, Options,
>              "conversion operator");
> -  PUSH_FLAG(ClassOptions, ForwardReference, Options, "forward ref");
>    PUSH_FLAG(ClassOptions, HasUniqueName, Options, "has unique name");
>    PUSH_FLAG(ClassOptions, Intrinsic, Options, "intrin");
>    PUSH_FLAG(ClassOptions, Nested, Options, "is nested");
> @@ -194,6 +218,7 @@ static std::string formatFunctionOptions
>  }
>
>  Error MinimalTypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex
> Index) {
> +  CurrentTypeIndex = Index;
>    // formatLine puts the newline at the beginning, so we use formatLine
> here
>    // to start a new line, and then individual visit methods use format to
>    // append to the existing line.
> @@ -304,7 +329,8 @@ Error MinimalTypeDumpVisitor::visitKnown
>    P.formatLine("vtable: {0}, base list: {1}, field list: {2}",
>                 Class.VTableShape, Class.DerivationList, Class.FieldList);
>    P.formatLine("options: {0}, sizeof {1}",
> -               formatClassOptions(P.getIndentLevel(), Class.Options),
> +               formatClassOptions(P.getIndentLevel(), Class.Options,
> Stream,
> +                                  CurrentTypeIndex),
>                 Class.Size);
>    return Error::success();
>  }
> @@ -316,7 +342,8 @@ Error MinimalTypeDumpVisitor::visitKnown
>      P.formatLine("unique name: `{0}`", Union.UniqueName);
>    P.formatLine("field list: {0}", Union.FieldList);
>    P.formatLine("options: {0}, sizeof {1}",
> -               formatClassOptions(P.getIndentLevel(), Union.Options),
> +               formatClassOptions(P.getIndentLevel(), Union.Options,
> Stream,
> +                                  CurrentTypeIndex),
>                 Union.Size);
>    return Error::success();
>  }
> @@ -328,7 +355,8 @@ Error MinimalTypeDumpVisitor::visitKnown
>    P.formatLine("field list: {0}, underlying type: {1}", Enum.FieldList,
>                 Enum.UnderlyingType);
>    P.formatLine("options: {0}",
> -               formatClassOptions(P.getIndentLevel(), Enum.Options));
> +               formatClassOptions(P.getIndentLevel(), Enum.Options,
> Stream,
> +                                  CurrentTypeIndex));
>    return Error::success();
>  }
>
>
> Modified: llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.h?rev=342656&r1=342655&r2=342656&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.h (original)
> +++ llvm/trunk/tools/llvm-pdbutil/MinimalTypeDumper.h Thu Sep 20 08:50:13
> 2018
> @@ -20,15 +20,18 @@ class LazyRandomTypeCollection;
>
>  namespace pdb {
>  class LinePrinter;
> +class TpiStream;
>
>  class MinimalTypeDumpVisitor : public codeview::TypeVisitorCallbacks {
>  public:
>    MinimalTypeDumpVisitor(LinePrinter &P, uint32_t Width, bool RecordBytes,
>                           bool Hashes, codeview::LazyRandomTypeCollection
> &Types,
>                           uint32_t NumHashBuckets,
> -                         FixedStreamArray<support::ulittle32_t>
> HashValues)
> +                         FixedStreamArray<support::ulittle32_t>
> HashValues,
> +                         pdb::TpiStream *Stream)
>        : P(P), Width(Width), RecordBytes(RecordBytes), Hashes(Hashes),
> -        Types(Types), NumHashBuckets(NumHashBuckets),
> HashValues(HashValues) {}
> +        Types(Types), NumHashBuckets(NumHashBuckets),
> HashValues(HashValues),
> +        Stream(Stream) {}
>
>    Error visitTypeBegin(codeview::CVType &Record,
>                         codeview::TypeIndex Index) override;
> @@ -55,7 +58,9 @@ private:
>    bool Hashes = false;
>    codeview::LazyRandomTypeCollection &Types;
>    uint32_t NumHashBuckets;
> +  codeview::TypeIndex CurrentTypeIndex;
>    FixedStreamArray<support::ulittle32_t> HashValues;
> +  pdb::TpiStream *Stream = nullptr;
>  };
>  } // namespace pdb
>  } // namespace llvm
>
> Modified: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp?rev=342656&r1=342655&r2=342656&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp (original)
> +++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp Thu Sep 20 08:50:13 2018
> @@ -183,6 +183,8 @@ static cl::opt<bool> Enums("enums", cl::
>                             cl::sub(DiaDumpSubcommand));
>  static cl::opt<bool> Pointers("pointers", cl::desc("Dump enum types"),
>                                cl::sub(DiaDumpSubcommand));
> +static cl::opt<bool> UDTs("udts", cl::desc("Dump udt types"),
> +                          cl::sub(DiaDumpSubcommand));
>  static cl::opt<bool> Compilands("compilands",
>                                  cl::desc("Dump compiland information"),
>                                  cl::sub(DiaDumpSubcommand));
> @@ -465,6 +467,12 @@ cl::opt<bool> DumpTypeExtras("type-extra
>                               cl::desc("dump type hashes and index
> offsets"),
>                               cl::cat(TypeOptions),
> cl::sub(DumpSubcommand));
>
> +cl::opt<bool> DontResolveForwardRefs(
> +    "dont-resolve-forward-refs",
> +    cl::desc("When dumping type records for classes, unions, enums, and "
> +             "structs, don't try to resolve forward references"),
> +    cl::cat(TypeOptions), cl::sub(DumpSubcommand));
> +
>  cl::list<uint32_t> DumpTypeIndex(
>      "type-index", cl::ZeroOrMore, cl::CommaSeparated,
>      cl::desc("only dump types with the specified hexadecimal type index"),
>
> Modified: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h?rev=342656&r1=342655&r2=342656&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h (original)
> +++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h Thu Sep 20 08:50:13 2018
> @@ -160,6 +160,7 @@ extern llvm::cl::opt<bool> DumpIdExtras;
>  extern llvm::cl::list<uint32_t> DumpIdIndex;
>  extern llvm::cl::opt<uint32_t> DumpModi;
>  extern llvm::cl::opt<bool> JustMyCode;
> +extern llvm::cl::opt<bool> DontResolveForwardRefs;
>  extern llvm::cl::opt<bool> DumpSymbols;
>  extern llvm::cl::opt<bool> DumpSymRecordBytes;
>  extern llvm::cl::opt<bool> DumpGSIRecords;
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180920/1413c66c/attachment.html>


More information about the llvm-commits mailing list