| //===- PDBSymbolFunc.cpp - --------------------------------------*- C++ -*-===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" | |
| #include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h" | |
| #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" | |
| #include "llvm/DebugInfo/PDB/IPDBSession.h" | |
| #include "llvm/DebugInfo/PDB/PDBSymDumper.h" | |
| #include "llvm/DebugInfo/PDB/PDBSymbolData.h" | |
| #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" | |
| #include "llvm/DebugInfo/PDB/PDBTypes.h" | |
| #include <unordered_set> | |
| #include <utility> | |
| #include <vector> | |
| using namespace llvm; | |
| using namespace llvm::pdb; | |
| namespace { | |
| class FunctionArgEnumerator : public IPDBEnumChildren<PDBSymbolData> { | |
| public: | |
| typedef ConcreteSymbolEnumerator<PDBSymbolData> ArgEnumeratorType; | |
| FunctionArgEnumerator(const IPDBSession &PDBSession, | |
| const PDBSymbolFunc &PDBFunc) | |
| : Session(PDBSession), Func(PDBFunc) { | |
| // Arguments can appear multiple times if they have live range | |
| // information, so we only take the first occurrence. | |
| std::unordered_set<std::string> SeenNames; | |
| auto DataChildren = Func.findAllChildren<PDBSymbolData>(); | |
| while (auto Child = DataChildren->getNext()) { | |
| if (Child->getDataKind() == PDB_DataKind::Param) { | |
| std::string Name = Child->getName(); | |
| if (SeenNames.find(Name) != SeenNames.end()) | |
| continue; | |
| Args.push_back(std::move(Child)); | |
| SeenNames.insert(Name); | |
| } | |
| } | |
| reset(); | |
| } | |
| uint32_t getChildCount() const override { return Args.size(); } | |
| std::unique_ptr<PDBSymbolData> | |
| getChildAtIndex(uint32_t Index) const override { | |
| if (Index >= Args.size()) | |
| return nullptr; | |
| return Session.getConcreteSymbolById<PDBSymbolData>( | |
| Args[Index]->getSymIndexId()); | |
| } | |
| std::unique_ptr<PDBSymbolData> getNext() override { | |
| if (CurIter == Args.end()) | |
| return nullptr; | |
| const auto &Result = **CurIter; | |
| ++CurIter; | |
| return Session.getConcreteSymbolById<PDBSymbolData>(Result.getSymIndexId()); | |
| } | |
| void reset() override { CurIter = Args.empty() ? Args.end() : Args.begin(); } | |
| FunctionArgEnumerator *clone() const override { | |
| return new FunctionArgEnumerator(Session, Func); | |
| } | |
| private: | |
| typedef std::vector<std::unique_ptr<PDBSymbolData>> ArgListType; | |
| const IPDBSession &Session; | |
| const PDBSymbolFunc &Func; | |
| ArgListType Args; | |
| ArgListType::const_iterator CurIter; | |
| }; | |
| } | |
| PDBSymbolFunc::PDBSymbolFunc(const IPDBSession &PDBSession, | |
| std::unique_ptr<IPDBRawSymbol> Symbol) | |
| : PDBSymbol(PDBSession, std::move(Symbol)) { | |
| assert(RawSymbol->getSymTag() == PDB_SymType::Function); | |
| } | |
| std::unique_ptr<IPDBEnumChildren<PDBSymbolData>> | |
| PDBSymbolFunc::getArguments() const { | |
| return llvm::make_unique<FunctionArgEnumerator>(Session, *this); | |
| } | |
| void PDBSymbolFunc::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } | |
| bool PDBSymbolFunc::isDestructor() const { | |
| std::string Name = getName(); | |
| if (Name.empty()) | |
| return false; | |
| if (Name[0] == '~') | |
| return true; | |
| if (Name == "__vecDelDtor") | |
| return true; | |
| return false; | |
| } | |
| std::unique_ptr<IPDBEnumLineNumbers> PDBSymbolFunc::getLineNumbers() const { | |
| auto Len = RawSymbol->getLength(); | |
| return Session.findLineNumbersByAddress(RawSymbol->getVirtualAddress(), | |
| Len ? Len : 1); | |
| } | |
| uint32_t PDBSymbolFunc::getCompilandId() const { | |
| if (auto Lines = getLineNumbers()) { | |
| if (auto FirstLine = Lines->getNext()) { | |
| return FirstLine->getCompilandId(); | |
| } | |
| } | |
| return 0; | |
| } |