diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h index 6b7af0c87fe..a521acff547 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h @@ -24,6 +24,8 @@ public: void dump(raw_ostream &OS, int Indent, PDB_DumpLevel Level) const override; + std::unique_ptr getSignature() const; + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function) FORWARD_SYMBOL_METHOD(getAccess) diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h index 3737eccd5db..e81afcbd75e 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h @@ -24,7 +24,12 @@ public: DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionSig) + std::unique_ptr getReturnType() const; + std::unique_ptr getArguments() const; + std::unique_ptr 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) diff --git a/lib/DebugInfo/PDB/PDBSymbolExe.cpp b/lib/DebugInfo/PDB/PDBSymbolExe.cpp index 69f928415f1..366c748ca20 100644 --- a/lib/DebugInfo/PDB/PDBSymbolExe.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolExe.cpp @@ -47,6 +47,26 @@ void PDBSymbolExe::dump(raw_ostream &OS, int Indent, 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"; } diff --git a/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/lib/DebugInfo/PDB/PDBSymbolFunc.cpp index 1b52a2670b1..0195ce35ab0 100644 --- a/lib/DebugInfo/PDB/PDBSymbolFunc.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolFunc.cpp @@ -23,6 +23,10 @@ PDBSymbolFunc::PDBSymbolFunc(const IPDBSession &PDBSession, std::unique_ptr Symbol) : PDBSymbol(PDBSession, std::move(Symbol)) {} +std::unique_ptr PDBSymbolFunc::getSignature() const { + return Session.getConcreteSymbolById(getTypeId()); +} + void PDBSymbolFunc::dump(raw_ostream &OS, int Indent, PDB_DumpLevel Level) const { OS << stream_indent(Indent); @@ -30,7 +34,7 @@ void PDBSymbolFunc::dump(raw_ostream &OS, int 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); @@ -52,21 +56,34 @@ void PDBSymbolFunc::dump(raw_ostream &OS, int Indent, OS << " "; uint32_t FuncSigId = getTypeId(); - if (auto FuncSig = Session.getConcreteSymbolById( - FuncSigId)) { - OS << "(" << FuncSig->getCallingConvention() << ") "; - } - - uint32_t ClassId = getClassParentId(); - if (ClassId != 0) { - if (auto Class = Session.getSymbolById(ClassId)) { - if (auto UDT = dyn_cast(Class.get())) - OS << UDT->getName() << "::"; - else - OS << "{class " << Class->getSymTag() << "}::"; + 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() << " "; + + 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(Class.get())) + OS << UDT->getName() << "::"; + else + OS << "{class " << Class->getSymTag() << "}::"; + } + } + OS << getName(); } - OS << getName(); } else { OS << getName(); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp index 24497ed9890..db821d3db38 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp @@ -17,35 +17,72 @@ using namespace llvm; +namespace { +class FunctionArgEnumerator : public IPDBEnumSymbols { +public: + typedef ConcreteSymbolEnumerator ArgEnumeratorType; + + FunctionArgEnumerator(const IPDBSession &PDBSession, + const PDBSymbolTypeFunctionSig &Sig) + : Session(PDBSession), + Enumerator(Sig.findAllChildren()) {} + + FunctionArgEnumerator(const IPDBSession &PDBSession, + std::unique_ptr ArgEnumerator) + : Session(PDBSession), Enumerator(std::move(ArgEnumerator)) {} + + uint32_t getChildCount() const { return Enumerator->getChildCount(); } + + std::unique_ptr getChildAtIndex(uint32_t Index) const { + auto FunctionArgSymbol = Enumerator->getChildAtIndex(Index); + if (!FunctionArgSymbol) + return nullptr; + return Session.getSymbolById(FunctionArgSymbol->getTypeId()); + } + + std::unique_ptr getNext() { + auto FunctionArgSymbol = Enumerator->getNext(); + if (!FunctionArgSymbol) + return nullptr; + return Session.getSymbolById(FunctionArgSymbol->getTypeId()); + } + + void reset() { Enumerator->reset(); } + + MyType *clone() const { + std::unique_ptr Clone(Enumerator->clone()); + return new FunctionArgEnumerator(Session, std::move(Clone)); + } + +private: + const IPDBSession &Session; + std::unique_ptr Enumerator; +}; +} + PDBSymbolTypeFunctionSig::PDBSymbolTypeFunctionSig( const IPDBSession &PDBSession, std::unique_ptr 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 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 +PDBSymbolTypeFunctionSig::getArguments() const { + return llvm::make_unique(Session, *this); +} + +std::unique_ptr 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()) { + if (auto ChildEnum = getArguments()) { uint32_t Index = 0; while (auto Arg = ChildEnum->getNext()) { Arg->dump(OS, 0, PDB_DumpLevel::Compact); @@ -54,4 +91,27 @@ void PDBSymbolTypeFunctionSig::dump(raw_ostream &OS, int Indent, } } 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); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp b/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp index 05abb675fb6..dbad00696d6 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp @@ -10,6 +10,7 @@ #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 @@ -27,7 +28,18 @@ void PDBSymbolTypePointer::dump(raw_ostream &OS, int Indent, 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(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()) ? "&" : "*"); + } + } }