[llvm-pdbdump] Many minor fixes and improvements

A short list of some of the improvements:

1) Now supports -all command line argument, which implies many
   other command line arguments to simplify usage.
2) Now supports -no-compiler-generated command line argument to
   exclude compiler generated types.
3) Prints base class list.
4) -class-definitions implies -types.
5) Proper display of bitfields.
6) Can now distinguish between struct/class/interface/union.

And a few other minor tweaks.

llvm-svn: 230933
This commit is contained in:
Zachary Turner 2015-03-02 04:39:56 +00:00
parent 968ceddca9
commit 7797c726b9
18 changed files with 303 additions and 69 deletions

View File

@ -26,6 +26,8 @@ raw_ostream &operator<<(raw_ostream &OS, const PDB_ThunkOrdinal &Thunk);
raw_ostream &operator<<(raw_ostream &OS, const PDB_Checksum &Checksum);
raw_ostream &operator<<(raw_ostream &OS, const PDB_Lang &Lang);
raw_ostream &operator<<(raw_ostream &OS, const PDB_SymType &Tag);
raw_ostream &operator<<(raw_ostream &OS, const PDB_MemberAccess &Access);
raw_ostream &operator<<(raw_ostream &OS, const PDB_UdtType &Type);
raw_ostream &operator<<(raw_ostream &OS, const PDB_UniqueId &Id);
raw_ostream &operator<<(raw_ostream &OS, const Variant &Value);

View File

@ -470,8 +470,31 @@ struct Variant {
uint16_t UInt16;
uint32_t UInt32;
uint64_t UInt64;
void* Pointer;
};
#define VARIANT_EQUAL_CASE(Enum) \
case PDB_VariantType::Enum: \
return Enum == Other.Enum;
bool operator==(const Variant &Other) const {
if (Type != Other.Type)
return false;
switch (Type) {
VARIANT_EQUAL_CASE(Bool)
VARIANT_EQUAL_CASE(Int8)
VARIANT_EQUAL_CASE(Int16)
VARIANT_EQUAL_CASE(Int32)
VARIANT_EQUAL_CASE(Int64)
VARIANT_EQUAL_CASE(Single)
VARIANT_EQUAL_CASE(Double)
VARIANT_EQUAL_CASE(UInt8)
VARIANT_EQUAL_CASE(UInt16)
VARIANT_EQUAL_CASE(UInt32)
VARIANT_EQUAL_CASE(UInt64)
default:
return true;
}
}
#undef VARIANT_EQUAL_CASE
bool operator!=(const Variant &Other) const { return !(*this == Other); }
};
} // namespace llvm

View File

@ -247,6 +247,25 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_SymType &Tag) {
return OS;
}
raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_MemberAccess &Access) {
switch (Access) {
CASE_OUTPUT_ENUM_CLASS_STR(PDB_MemberAccess, Public, "public", OS)
CASE_OUTPUT_ENUM_CLASS_STR(PDB_MemberAccess, Protected, "protected", OS)
CASE_OUTPUT_ENUM_CLASS_STR(PDB_MemberAccess, Private, "private", OS)
}
return OS;
}
raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_UdtType &Type) {
switch (Type) {
CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Class, "class", OS)
CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Struct, "struct", OS)
CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Interface, "interface", OS)
CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Union, "union", OS)
}
return OS;
}
raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_UniqueId &Id) {
static const char *Lookup = "0123456789ABCDEF";
@ -304,7 +323,6 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const Variant &Value) {
default:
OS << Value.Type;
}
OS << " {" << Value.Type << "}";
return OS;
}

View File

@ -30,13 +30,13 @@
; FULL_CLASS: ---TYPES---
; FULL_CLASS: Classes
; FULL_CLASS-DAG: class A {
; FULL_CLASS-DAG: struct A {
; FULL_CLASS: public:
; FULL_CLASS: virtual void PureFunc() = 0
; FULL_CLASS: virtual void VirtualFunc()
; FULL_CLASS: void RegularFunc()
; FULL_CLASS: }
; FULL_CLASS-DAG: class MemberTest {
; FULL_CLASS-DAG: struct MemberTest {
; FULL_CLASS: data +0x00 MemberTest::NestedEnum m_nested_enum
; FULL_CLASS: data +0x04 int m_typedef
; FULL_CLASS: data +0x08 bool m_bool

View File

@ -0,0 +1,64 @@
// Compile with "cl /c /Zi /GR- ClassLayoutTest.cpp"
// Link with "link ClassLayoutTest.obj /debug /nodefaultlib /entry:main"
namespace MembersTest {
class A {
public:
typedef int NestedTypedef;
enum NestedEnum {
NestedEnumValue1
};
void MemberFunc() {}
private:
int IntMemberVar;
double DoubleMemberVar;
};
}
namespace GlobalsTest {
int IntVar;
double DoubleVar;
typedef int Typedef;
enum Enum {
Val1
} EnumVar;
Typedef TypedefVar;
}
namespace BaseClassTest {
class A {};
class B : public virtual A {};
class C : public virtual A {};
class D : protected B, private C {};
}
namespace UdtKindTest {
struct A {};
class B {};
union C {};
}
namespace BitFieldTest {
struct A {
int Bits1 : 1;
int Bits2 : 2;
int Bits3 : 3;
int Bits4 : 4;
int Bits22 : 22;
int Offset0x04;
};
};
int main(int argc, char **argv) {
MembersTest::A v1;
v1.MemberFunc();
BaseClassTest::D v2;
UdtKindTest::A v3;
UdtKindTest::B v4;
UdtKindTest::C v5;
BitFieldTest::A v7;
return 0;
}

View File

@ -0,0 +1,57 @@
; RUN: llvm-pdbdump -all %p/Inputs/ClassLayoutTest.pdb > %t
; RUN: FileCheck -input-file=%t %s -check-prefix=GLOBALS_TEST
; RUN: FileCheck -input-file=%t %s -check-prefix=MEMBERS_TEST
; RUN: FileCheck -input-file=%t %s -check-prefix=BASE_CLASS_A
; RUN: FileCheck -input-file=%t %s -check-prefix=BASE_CLASS_B
; RUN: FileCheck -input-file=%t %s -check-prefix=BASE_CLASS_C
; RUN: FileCheck -input-file=%t %s -check-prefix=BASE_CLASS_D
; RUN: FileCheck -input-file=%t %s -check-prefix=UDT_KIND_TEST
; RUN: FileCheck -input-file=%t %s -check-prefix=BITFIELD_TEST
; GLOBALS_TEST: ---GLOBALS---
; GLOBALS_TEST-DAG: int GlobalsTest::IntVar
; GLOBALS_TEST-DAG: double GlobalsTest::DoubleVar
; GLOBALS_TEST-DAG: GlobalsTest::Enum GlobalsTest::EnumVar
; MEMBERS_TEST: ---TYPES---
; MEMBERS_TEST: class MembersTest::A {
; MEMBERS_TEST-DAG: typedef int NestedTypedef
; MEMBERS_TEST-DAG: enum NestedEnum
; MEMBERS_TEST: public:
; MEMBERS_TEST-NEXT: void MemberFunc()
; MEMBERS_TEST-NEXT: private:
; MEMBERS_TEST-DAG: int IntMemberVar
; MEMBERS_TEST-DAG: double DoubleMemberVar
; MEMBERS_TEST: }
; BASE_CLASS_A: ---TYPES---
; BASE_CLASS_A: class BaseClassTest::A {}
; BASE_CLASS_B: ---TYPES---
; BASE_CLASS_B: class BaseClassTest::B
; BASE_CLASS_B-NEXT: : public virtual BaseClassTest::A {
; BASE_CLASS_C: ---TYPES---
; BASE_CLASS_C: class BaseClassTest::C
; BASE_CLASS_C-NEXT: : public virtual BaseClassTest::A {
; BASE_CLASS_D: ---TYPES---
; BASE_CLASS_D: class BaseClassTest::D
; BASE_CLASS_D-DAG: protected BaseClassTest::B
; BASE_CLASS_D-DAG: private BaseClassTest::C
; BASE_CLASS_D-DAG: protected virtual BaseClassTest::A
; UDT_KIND_TEST: ---TYPES---
; UDT_KIND_TEST-DAG: union UdtKindTest::C {}
; UDT_KIND_TEST-DAG: class UdtKindTest::B {}
; UDT_KIND_TEST-DAG: struct UdtKindTest::A {}
; BITFIELD_TEST: ---TYPES---
; BITFIELD_TEST: struct BitFieldTest::A {
; BITFIELD_TEST-NEXT: public:
; BITFIELD_TEST-NEXT: +0x00 int Bits1 : 1
; BITFIELD_TEST-NEXT: +0x00 int Bits2 : 2
; BITFIELD_TEST-NEXT: +0x00 int Bits3 : 3
; BITFIELD_TEST-NEXT: +0x00 int Bits4 : 4
; BITFIELD_TEST-NEXT: +0x00 int Bits22 : 22
; BITFIELD_TEST-NEXT: +0x04 int Offset0x04

View File

@ -18,7 +18,7 @@
; NO_FILTER: Typedefs
; NO_FILTER: typedef int GlobalTypedef
; NO_FILTER: Classes:
; NO_FILTER: class __vc_attributes
; NO_FILTER: struct __vc_attributes
; NO_FILTER: class FilterTestClass
; NO_FILTER-DAG: typedef int NestedTypedef
; NO_FILTER-DAG: enum NestedEnum

View File

@ -81,7 +81,7 @@ void BuiltinDumper::start(const PDBSymbolTypeBuiltin &Symbol) {
WithColor(Printer, PDB_ColorItem::Type).get() << "HRESULT";
break;
default:
WithColor(Printer, PDB_ColorItem::Type).get() << "(unknown)";
WithColor(Printer, PDB_ColorItem::Type).get() << "void";
break;
}
}

View File

@ -33,8 +33,29 @@ ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P)
void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
std::string Name = Class.getName();
WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
auto Bases = Class.findAllChildren<PDBSymbolTypeBaseClass>();
if (Bases->getChildCount() > 0) {
Printer.Indent();
Printer.NewLine();
Printer << ":";
uint32_t BaseIndex = 0;
while (auto Base = Bases->getNext()) {
Printer << " ";
WithColor(Printer, PDB_ColorItem::Keyword).get() << Base->getAccess();
if (Base->isVirtualBaseClass())
WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual";
WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base->getName();
if (++BaseIndex < Bases->getChildCount()) {
Printer.NewLine();
Printer << ",";
}
}
Printer.Unindent();
}
Printer << " {";
auto Children = Class.findAllChildren();
if (Children->getChildCount() == 0) {
@ -62,9 +83,10 @@ void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
auto &AccessGroup = Groups.find((int)Access)->second;
if (auto Func = dyn_cast<PDBSymbolFunc>(Child.get())) {
if (Func->isCompilerGenerated())
if (Func->isCompilerGenerated() && opts::ExcludeCompilerGenerated)
continue;
if (Func->getLength() == 0 && !Func->isPureVirtual())
if (Func->getLength() == 0 && !Func->isPureVirtual() &&
!Func->isIntroVirtualFunction())
continue;
Child.release();
AccessGroup.Functions.push_back(std::unique_ptr<PDBSymbolFunc>(Func));

View File

@ -124,7 +124,9 @@ void CompilandDumper::dump(const PDBSymbolThunk &Symbol) {
<< "[" << format_hex(RVA, 10) << " - "
<< format_hex(RVA + Symbol.getLength(), 10) << "]";
}
Printer << " (" << Ordinal << ") ";
Printer << " (";
WithColor(Printer, PDB_ColorItem::Register).get() << Ordinal;
Printer << ") ";
std::string Name = Symbol.getName();
if (!Name.empty())
WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;

View File

@ -112,28 +112,28 @@ void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) {
uint32_t FuncStart = Symbol.getRelativeVirtualAddress();
uint32_t FuncEnd = FuncStart + Symbol.getLength();
Printer << "func ";
WithColor(Printer, PDB_ColorItem::Address).get() << "["
<< format_hex(FuncStart, 8);
Printer << "func [";
WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10);
if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>()) {
uint32_t Prologue = DebugStart->getRelativeVirtualAddress() - FuncStart;
WithColor(Printer, PDB_ColorItem::Offset).get() << "+" << Prologue;
}
WithColor(Printer, PDB_ColorItem::Address).get() << " - "
<< format_hex(FuncEnd, 8);
Printer << " - ";
WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10);
if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>()) {
uint32_t Epilogue = FuncEnd - DebugEnd->getRelativeVirtualAddress();
WithColor(Printer, PDB_ColorItem::Offset).get() << "-" << Epilogue;
}
WithColor(Printer, PDB_ColorItem::Address).get() << "] ";
Printer << "] (";
if (Symbol.hasFramePointer())
WithColor(Printer, PDB_ColorItem::Address).get()
<< "(" << Symbol.getLocalBasePointerRegisterId() << ")";
else
WithColor(Printer, PDB_ColorItem::Address).get() << "(FPO)";
if (Symbol.hasFramePointer()) {
WithColor(Printer, PDB_ColorItem::Register).get()
<< Symbol.getLocalBasePointerRegisterId();
} else {
WithColor(Printer, PDB_ColorItem::Register).get() << "FPO";
}
Printer << ") ";
Printer << " ";
if (Symbol.isVirtual() || Symbol.isPureVirtual())
WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual ";

View File

@ -9,6 +9,8 @@
#include "LinePrinter.h"
#include "llvm-pdbdump.h"
#include "llvm/Support/Regex.h"
#include <algorithm>
@ -16,7 +18,13 @@
using namespace llvm;
LinePrinter::LinePrinter(int Indent, llvm::raw_ostream &Stream)
: OS(Stream), IndentSpaces(Indent), CurrentIndent(0) {}
: OS(Stream), IndentSpaces(Indent), CurrentIndent(0) {
SetFilters(TypeFilters, opts::ExcludeTypes.begin(), opts::ExcludeTypes.end());
SetFilters(SymbolFilters, opts::ExcludeSymbols.begin(),
opts::ExcludeSymbols.end());
SetFilters(CompilandFilters, opts::ExcludeCompilands.begin(),
opts::ExcludeCompilands.end());
}
void LinePrinter::Indent() { CurrentIndent += IndentSpaces; }
@ -86,6 +94,7 @@ void WithColor::translateColor(PDB_ColorItem C, raw_ostream::Colors &Color,
Color = raw_ostream::MAGENTA;
Bold = true;
return;
case PDB_ColorItem::Register:
case PDB_ColorItem::Offset:
Color = raw_ostream::YELLOW;
Bold = false;

View File

@ -25,33 +25,25 @@ class LinePrinter {
public:
LinePrinter(int Indent, raw_ostream &Stream);
template <typename Iter> void SetTypeFilters(Iter Begin, Iter End) {
TypeFilters.clear();
for (; Begin != End; ++Begin)
TypeFilters.push_back(StringRef(*Begin));
}
template <typename Iter> void SetSymbolFilters(Iter Begin, Iter End) {
SymbolFilters.clear();
for (; Begin != End; ++Begin)
SymbolFilters.push_back(StringRef(*Begin));
}
template <typename Iter> void SetCompilandFilters(Iter Begin, Iter End) {
CompilandFilters.clear();
for (; Begin != End; ++Begin)
CompilandFilters.push_back(StringRef(*Begin));
}
void Indent();
void Unindent();
void NewLine();
raw_ostream &getStream() { return OS; }
int getIndentLevel() const { return CurrentIndent; }
bool IsTypeExcluded(llvm::StringRef TypeName);
bool IsSymbolExcluded(llvm::StringRef SymbolName);
bool IsCompilandExcluded(llvm::StringRef CompilandName);
private:
template <typename Iter>
void SetFilters(std::list<Regex> &List, Iter Begin, Iter End) {
List.clear();
for (; Begin != End; ++Begin)
List.push_back(StringRef(*Begin));
}
raw_ostream &OS;
int IndentSpaces;
int CurrentIndent;
@ -77,6 +69,7 @@ enum class PDB_ColorItem {
Path,
SectionHeader,
LiteralValue,
Register,
};
class WithColor {

View File

@ -31,7 +31,8 @@ void TypedefDumper::start(const PDBSymbolTypeTypedef &Symbol) {
uint32_t TargetId = Symbol.getTypeId();
if (auto TypeSymbol = Symbol.getSession().getSymbolById(TargetId))
TypeSymbol->dump(*this);
WithColor(Printer, PDB_ColorItem::Type).get() << " " << Symbol.getName();
WithColor(Printer, PDB_ColorItem::Identifier).get() << " "
<< Symbol.getName();
}
void TypedefDumper::dump(const PDBSymbolTypeArray &Symbol) {}
@ -74,5 +75,5 @@ void TypedefDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
void TypedefDumper::dump(const PDBSymbolTypeUDT &Symbol) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
WithColor(Printer, PDB_ColorItem::Type).get() << " " << Symbol.getName();
WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
}

View File

@ -31,6 +31,8 @@ VariableDumper::VariableDumper(LinePrinter &P)
: PDBSymDumper(true), Printer(P) {}
void VariableDumper::start(const PDBSymbolData &Var) {
if (Var.isCompilerGenerated() && opts::ExcludeCompilerGenerated)
return;
if (Printer.IsSymbolExcluded(Var.getName()))
return;
@ -41,23 +43,31 @@ void VariableDumper::start(const PDBSymbolData &Var) {
switch (auto LocType = Var.getLocationType()) {
case PDB_LocType::Static:
Printer << "[";
WithColor(Printer, PDB_ColorItem::Address).get()
<< "[" << format_hex(Var.getRelativeVirtualAddress(), 10) << "] ";
<< format_hex(Var.getRelativeVirtualAddress(), 10);
Printer << "] ";
WithColor(Printer, PDB_ColorItem::Keyword).get() << "static ";
dumpSymbolTypeAndName(*VarType, Var.getName());
break;
case PDB_LocType::Constant:
WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
dumpSymbolTypeAndName(*VarType, Var.getName());
Printer << "[";
Printer << " = ";
WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getValue();
Printer << "]";
break;
case PDB_LocType::ThisRel:
WithColor(Printer, PDB_ColorItem::Offset).get()
<< "+" << format_hex(Var.getOffset(), 4) << " ";
dumpSymbolTypeAndName(*VarType, Var.getName());
break;
case PDB_LocType::BitField:
WithColor(Printer, PDB_ColorItem::Offset).get()
<< "+" << format_hex(Var.getOffset(), 4) << " ";
dumpSymbolTypeAndName(*VarType, Var.getName());
Printer << " : ";
WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getLength();
break;
default:
Printer << "unknown(" << LocType << ") ";
WithColor(Printer, PDB_ColorItem::Identifier).get() << Var.getName();

View File

@ -56,26 +56,44 @@ cl::list<std::string> InputFilenames(cl::Positional,
cl::desc("<input PDB files>"),
cl::OneOrMore);
cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"));
cl::opt<bool> Symbols("symbols",
cl::desc("Display symbols for each compiland"));
cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"));
cl::opt<bool> Types("types", cl::desc("Display types"));
cl::opt<bool> ClassDefs("class-definitions",
cl::desc("Display full class definitions"));
cl::OptionCategory TypeCategory("Symbol Type Options");
cl::OptionCategory FilterCategory("Filtering Options");
cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
cl::cat(TypeCategory));
cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"),
cl::cat(TypeCategory));
cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
cl::cat(TypeCategory));
cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory));
cl::opt<bool>
ClassDefs("class-definitions",
cl::desc("Display full class definitions (implies -types)"),
cl::cat(TypeCategory));
cl::opt<bool>
All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
cl::cat(TypeCategory));
cl::list<std::string>
ExcludeTypes("exclude-types",
cl::desc("Exclude types by regular expression"),
cl::ZeroOrMore);
cl::ZeroOrMore, cl::cat(FilterCategory));
cl::list<std::string>
ExcludeSymbols("exclude-symbols",
cl::desc("Exclude symbols by regular expression"),
cl::ZeroOrMore);
cl::ZeroOrMore, cl::cat(FilterCategory));
cl::list<std::string>
ExcludeCompilands("exclude-compilands",
cl::desc("Exclude compilands by regular expression"),
cl::ZeroOrMore);
cl::ZeroOrMore, cl::cat(FilterCategory));
cl::opt<bool> ExcludeCompilerGenerated(
"no-compiler-generated",
cl::desc("Don't show compiler generated types and symbols"),
cl::cat(FilterCategory));
cl::opt<bool>
ExcludeSystemLibraries("no-system-libs",
cl::desc("Don't show symbols from system libraries"),
cl::cat(FilterCategory));
}
static void dumpInput(StringRef Path) {
@ -103,11 +121,6 @@ static void dumpInput(StringRef Path) {
}
LinePrinter Printer(2, outs());
Printer.SetTypeFilters(opts::ExcludeTypes.begin(), opts::ExcludeTypes.end());
Printer.SetSymbolFilters(opts::ExcludeSymbols.begin(),
opts::ExcludeSymbols.end());
Printer.SetCompilandFilters(opts::ExcludeCompilands.begin(),
opts::ExcludeCompilands.end());
auto GlobalScope(Session->getGlobalScope());
std::string FileName(GlobalScope->getSymbolsFileName());
@ -220,6 +233,23 @@ int main(int argc_, const char *argv_[]) {
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
if (opts::ClassDefs)
opts::Types = true;
if (opts::All) {
opts::Compilands = true;
opts::Symbols = true;
opts::Globals = true;
opts::Types = true;
opts::ClassDefs = true;
}
if (opts::ExcludeCompilerGenerated) {
opts::ExcludeTypes.push_back("__vc_attributes");
opts::ExcludeCompilands.push_back("* Linker *");
}
if (opts::ExcludeSystemLibraries) {
opts::ExcludeCompilands.push_back(
"f:\\binaries\\Intermediate\\vctools\\crt_bld");
}
#if defined(HAVE_DIA_SDK)
CoInitializeEx(nullptr, COINIT_MULTITHREADED);

View File

@ -10,19 +10,22 @@
#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
#define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
struct newline {
newline(int IndentWidth) : Width(IndentWidth) {}
int Width;
};
namespace opts {
extern llvm::cl::opt<bool> Compilands;
extern llvm::cl::opt<bool> Symbols;
extern llvm::cl::opt<bool> Globals;
extern llvm::cl::opt<bool> Types;
extern llvm::cl::opt<bool> ClassDefs;
extern llvm::cl::opt<bool> All;
inline raw_ostream &operator<<(raw_ostream &OS, const newline &Indent) {
OS << "\n";
OS.indent(Indent.Width);
return OS;
}
extern llvm::cl::opt<bool> ExcludeCompilerGenerated;
extern llvm::cl::list<std::string> ExcludeTypes;
extern llvm::cl::list<std::string> ExcludeSymbols;
extern llvm::cl::list<std::string> ExcludeCompilands;
}
#endif