void dump(raw_ostream &OS, int Indent, PDB_DumpLevel Level) const override;
+ std::unique_ptr<PDBSymbolTypeFunctionSig> getSignature() const;
+
DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function)
FORWARD_SYMBOL_METHOD(getAccess)
DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionSig)
+ std::unique_ptr<PDBSymbol> getReturnType() const;
+ std::unique_ptr<IPDBEnumSymbols> getArguments() const;
+ std::unique_ptr<PDBSymbol> getClassParent() const;
+
void dump(raw_ostream &OS, int Indent, PDB_DumpLevel Level) const override;
+ void dumpArgList(raw_ostream &OS) const;
FORWARD_SYMBOL_METHOD(getCallingConvention)
FORWARD_SYMBOL_METHOD(getClassParentId)
auto ChildrenEnum = getChildStats(Stats);
OS << stream_indent(Indent + 2) << "Children: " << Stats << "\n";
while (auto Child = ChildrenEnum->getNext()) {
+ // Skip uninteresting types. These are useful to print as part of type
+ // hierarchies, but as general children of the global scope, they are
+ // not very interesting.
+ switch (Child->getSymTag()) {
+ case PDB_SymType::ArrayType:
+ case PDB_SymType::BaseClass:
+ case PDB_SymType::BuiltinType:
+ case PDB_SymType::CompilandEnv:
+ case PDB_SymType::CustomType:
+ case PDB_SymType::Dimension:
+ case PDB_SymType::Friend:
+ case PDB_SymType::ManagedType:
+ case PDB_SymType::VTableShape:
+ case PDB_SymType::PointerType:
+ case PDB_SymType::FunctionSig:
+ case PDB_SymType::FunctionArg:
+ continue;
+ default:
+ break;
+ }
Child->dump(OS, Indent + 4, PDB_DumpLevel::Normal);
OS << "\n";
}
std::unique_ptr<IPDBRawSymbol> Symbol)
: PDBSymbol(PDBSession, std::move(Symbol)) {}
+std::unique_ptr<PDBSymbolTypeFunctionSig> PDBSymbolFunc::getSignature() const {
+ return Session.getConcreteSymbolById<PDBSymbolTypeFunctionSig>(getTypeId());
+}
+
void PDBSymbolFunc::dump(raw_ostream &OS, int Indent,
PDB_DumpLevel Level) const {
OS << stream_indent(Indent);
uint32_t FuncStart = getRelativeVirtualAddress();
uint32_t FuncEnd = FuncStart + getLength();
if (FuncStart == 0 && FuncEnd == 0) {
- OS << "func [???]";
+ OS << "func [???] ";
} else {
OS << "func ";
OS << "[" << format_hex(FuncStart, 8);
OS << " ";
uint32_t FuncSigId = getTypeId();
- if (auto FuncSig = Session.getConcreteSymbolById<PDBSymbolTypeFunctionSig>(
- FuncSigId)) {
- OS << "(" << FuncSig->getCallingConvention() << ") ";
- }
+ if (auto FuncSig = getSignature()) {
+ // If we have a signature, dump the name with the signature.
+ if (auto ReturnType = FuncSig->getReturnType()) {
+ ReturnType->dump(OS, 0, PDB_DumpLevel::Compact);
+ OS << " ";
+ }
+
+ OS << FuncSig->getCallingConvention() << " ";
- uint32_t ClassId = getClassParentId();
- if (ClassId != 0) {
- if (auto Class = Session.getSymbolById(ClassId)) {
- if (auto UDT = dyn_cast<PDBSymbolTypeUDT>(Class.get()))
- OS << UDT->getName() << "::";
- else
- OS << "{class " << Class->getSymTag() << "}::";
+ if (auto ClassParent = FuncSig->getClassParent()) {
+ ClassParent->dump(OS, 0, PDB_DumpLevel::Compact);
+ OS << "::";
}
+
+ OS << getName();
+ FuncSig->dumpArgList(OS);
+ } else {
+ uint32_t ClassId = getClassParentId();
+ if (ClassId != 0) {
+ if (auto Class = Session.getSymbolById(ClassId)) {
+ if (auto UDT = dyn_cast<PDBSymbolTypeUDT>(Class.get()))
+ OS << UDT->getName() << "::";
+ else
+ OS << "{class " << Class->getSymTag() << "}::";
+ }
+ }
+ OS << getName();
}
- OS << getName();
} else {
OS << getName();
}
using namespace llvm;
+namespace {
+class FunctionArgEnumerator : public IPDBEnumSymbols {
+public:
+ typedef ConcreteSymbolEnumerator<PDBSymbolTypeFunctionArg> ArgEnumeratorType;
+
+ FunctionArgEnumerator(const IPDBSession &PDBSession,
+ const PDBSymbolTypeFunctionSig &Sig)
+ : Session(PDBSession),
+ Enumerator(Sig.findAllChildren<PDBSymbolTypeFunctionArg>()) {}
+
+ FunctionArgEnumerator(const IPDBSession &PDBSession,
+ std::unique_ptr<ArgEnumeratorType> ArgEnumerator)
+ : Session(PDBSession), Enumerator(std::move(ArgEnumerator)) {}
+
+ uint32_t getChildCount() const { return Enumerator->getChildCount(); }
+
+ std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const {
+ auto FunctionArgSymbol = Enumerator->getChildAtIndex(Index);
+ if (!FunctionArgSymbol)
+ return nullptr;
+ return Session.getSymbolById(FunctionArgSymbol->getTypeId());
+ }
+
+ std::unique_ptr<PDBSymbol> getNext() {
+ auto FunctionArgSymbol = Enumerator->getNext();
+ if (!FunctionArgSymbol)
+ return nullptr;
+ return Session.getSymbolById(FunctionArgSymbol->getTypeId());
+ }
+
+ void reset() { Enumerator->reset(); }
+
+ MyType *clone() const {
+ std::unique_ptr<ArgEnumeratorType> Clone(Enumerator->clone());
+ return new FunctionArgEnumerator(Session, std::move(Clone));
+ }
+
+private:
+ const IPDBSession &Session;
+ std::unique_ptr<ArgEnumeratorType> Enumerator;
+};
+}
+
PDBSymbolTypeFunctionSig::PDBSymbolTypeFunctionSig(
const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
: PDBSymbol(PDBSession, std::move(Symbol)) {}
-void PDBSymbolTypeFunctionSig::dump(raw_ostream &OS, int Indent,
- PDB_DumpLevel Level) const {
- OS << stream_indent(Indent);
+std::unique_ptr<PDBSymbol> PDBSymbolTypeFunctionSig::getReturnType() const {
+ return Session.getSymbolById(getTypeId());
+}
- uint32_t ReturnTypeId = getTypeId();
- if (auto ReturnType = Session.getSymbolById(ReturnTypeId)) {
- ReturnType->dump(OS, 0, PDB_DumpLevel::Compact);
- OS << " ";
- }
- // TODO: We need a way to detect if this is a pointer to function so that we
- // can print the * between the return type and the argument list. The only
- // way to do this is to pass the parent into this function, but that will
- // require a larger interface change.
- OS << getCallingConvention() << " ";
+std::unique_ptr<IPDBEnumSymbols>
+PDBSymbolTypeFunctionSig::getArguments() const {
+ return llvm::make_unique<FunctionArgEnumerator>(Session, *this);
+}
+
+std::unique_ptr<PDBSymbol> PDBSymbolTypeFunctionSig::getClassParent() const {
uint32_t ClassId = getClassParentId();
- if (ClassId != 0) {
- if (auto ClassParent = Session.getSymbolById(ClassId)) {
- OS << "(";
- ClassParent->dump(OS, 0, PDB_DumpLevel::Compact);
- OS << "::*)";
- }
- }
- OS.flush();
+ if (ClassId == 0)
+ return nullptr;
+ return Session.getSymbolById(ClassId);
+}
+
+void PDBSymbolTypeFunctionSig::dumpArgList(raw_ostream &OS) const {
OS << "(";
- if (auto ChildEnum = findAllChildren<PDBSymbolTypeFunctionArg>()) {
+ if (auto ChildEnum = getArguments()) {
uint32_t Index = 0;
while (auto Arg = ChildEnum->getNext()) {
Arg->dump(OS, 0, PDB_DumpLevel::Compact);
}
}
OS << ")";
+ if (isConstType())
+ OS << " const";
+ if (isVolatileType())
+ OS << " volatile";
+}
+
+void PDBSymbolTypeFunctionSig::dump(raw_ostream &OS, int Indent,
+ PDB_DumpLevel Level) const {
+ OS << stream_indent(Indent);
+
+ if (auto ReturnType = getReturnType()) {
+ ReturnType->dump(OS, 0, PDB_DumpLevel::Compact);
+ OS << " ";
+ }
+
+ OS << getCallingConvention() << " ";
+ if (auto ClassParent = getClassParent()) {
+ OS << "(";
+ ClassParent->dump(OS, 0, PDB_DumpLevel::Compact);
+ OS << "::*)";
+ }
+
+ dumpArgList(OS);
}
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
#include <utility>
if (isVolatileType())
OS << "volatile ";
uint32_t PointeeId = getTypeId();
- if (auto PointeeType = Session.getSymbolById(PointeeId))
- PointeeType->dump(OS, 0, PDB_DumpLevel::Compact);
- OS << ((isReference()) ? "&" : "*");
+ if (auto PointeeType = Session.getSymbolById(PointeeId)) {
+ // Function pointers get special treatment, since we need to print the * in
+ // the middle of the signature.
+ if (auto FuncSig = dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType.get())) {
+ if (auto ReturnType = FuncSig->getReturnType())
+ ReturnType->dump(OS, 0, PDB_DumpLevel::Compact);
+ OS << " (" << FuncSig->getCallingConvention() << " ";
+ OS << ((isReference()) ? "&" : "*") << ")";
+ FuncSig->dumpArgList(OS);
+ } else {
+ PointeeType->dump(OS, 0, PDB_DumpLevel::Compact);
+ OS << ((isReference()) ? "&" : "*");
+ }
+ }
}