[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