1*0b57cec5SDimitry Andric //===- PDBSymbolFunc.cpp - --------------------------------------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" 10*0b57cec5SDimitry Andric 11*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h" 12*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" 13*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBSession.h" 14*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymDumper.h" 15*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolData.h" 16*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" 17*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBTypes.h" 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric #include <unordered_set> 20*0b57cec5SDimitry Andric #include <utility> 21*0b57cec5SDimitry Andric #include <vector> 22*0b57cec5SDimitry Andric 23*0b57cec5SDimitry Andric using namespace llvm; 24*0b57cec5SDimitry Andric using namespace llvm::pdb; 25*0b57cec5SDimitry Andric 26*0b57cec5SDimitry Andric namespace { 27*0b57cec5SDimitry Andric class FunctionArgEnumerator : public IPDBEnumChildren<PDBSymbolData> { 28*0b57cec5SDimitry Andric public: 29*0b57cec5SDimitry Andric typedef ConcreteSymbolEnumerator<PDBSymbolData> ArgEnumeratorType; 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric FunctionArgEnumerator(const IPDBSession &PDBSession, 32*0b57cec5SDimitry Andric const PDBSymbolFunc &PDBFunc) 33*0b57cec5SDimitry Andric : Session(PDBSession), Func(PDBFunc) { 34*0b57cec5SDimitry Andric // Arguments can appear multiple times if they have live range 35*0b57cec5SDimitry Andric // information, so we only take the first occurrence. 36*0b57cec5SDimitry Andric std::unordered_set<std::string> SeenNames; 37*0b57cec5SDimitry Andric auto DataChildren = Func.findAllChildren<PDBSymbolData>(); 38*0b57cec5SDimitry Andric while (auto Child = DataChildren->getNext()) { 39*0b57cec5SDimitry Andric if (Child->getDataKind() == PDB_DataKind::Param) { 40*0b57cec5SDimitry Andric std::string Name = Child->getName(); 41*0b57cec5SDimitry Andric if (SeenNames.find(Name) != SeenNames.end()) 42*0b57cec5SDimitry Andric continue; 43*0b57cec5SDimitry Andric Args.push_back(std::move(Child)); 44*0b57cec5SDimitry Andric SeenNames.insert(Name); 45*0b57cec5SDimitry Andric } 46*0b57cec5SDimitry Andric } 47*0b57cec5SDimitry Andric reset(); 48*0b57cec5SDimitry Andric } 49*0b57cec5SDimitry Andric 50*0b57cec5SDimitry Andric uint32_t getChildCount() const override { return Args.size(); } 51*0b57cec5SDimitry Andric 52*0b57cec5SDimitry Andric std::unique_ptr<PDBSymbolData> 53*0b57cec5SDimitry Andric getChildAtIndex(uint32_t Index) const override { 54*0b57cec5SDimitry Andric if (Index >= Args.size()) 55*0b57cec5SDimitry Andric return nullptr; 56*0b57cec5SDimitry Andric 57*0b57cec5SDimitry Andric return Session.getConcreteSymbolById<PDBSymbolData>( 58*0b57cec5SDimitry Andric Args[Index]->getSymIndexId()); 59*0b57cec5SDimitry Andric } 60*0b57cec5SDimitry Andric 61*0b57cec5SDimitry Andric std::unique_ptr<PDBSymbolData> getNext() override { 62*0b57cec5SDimitry Andric if (CurIter == Args.end()) 63*0b57cec5SDimitry Andric return nullptr; 64*0b57cec5SDimitry Andric const auto &Result = **CurIter; 65*0b57cec5SDimitry Andric ++CurIter; 66*0b57cec5SDimitry Andric return Session.getConcreteSymbolById<PDBSymbolData>(Result.getSymIndexId()); 67*0b57cec5SDimitry Andric } 68*0b57cec5SDimitry Andric 69*0b57cec5SDimitry Andric void reset() override { CurIter = Args.empty() ? Args.end() : Args.begin(); } 70*0b57cec5SDimitry Andric 71*0b57cec5SDimitry Andric private: 72*0b57cec5SDimitry Andric typedef std::vector<std::unique_ptr<PDBSymbolData>> ArgListType; 73*0b57cec5SDimitry Andric const IPDBSession &Session; 74*0b57cec5SDimitry Andric const PDBSymbolFunc &Func; 75*0b57cec5SDimitry Andric ArgListType Args; 76*0b57cec5SDimitry Andric ArgListType::const_iterator CurIter; 77*0b57cec5SDimitry Andric }; 78*0b57cec5SDimitry Andric } 79*0b57cec5SDimitry Andric 80*0b57cec5SDimitry Andric std::unique_ptr<IPDBEnumChildren<PDBSymbolData>> 81*0b57cec5SDimitry Andric PDBSymbolFunc::getArguments() const { 82*0b57cec5SDimitry Andric return llvm::make_unique<FunctionArgEnumerator>(Session, *this); 83*0b57cec5SDimitry Andric } 84*0b57cec5SDimitry Andric 85*0b57cec5SDimitry Andric void PDBSymbolFunc::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric bool PDBSymbolFunc::isDestructor() const { 88*0b57cec5SDimitry Andric std::string Name = getName(); 89*0b57cec5SDimitry Andric if (Name.empty()) 90*0b57cec5SDimitry Andric return false; 91*0b57cec5SDimitry Andric if (Name[0] == '~') 92*0b57cec5SDimitry Andric return true; 93*0b57cec5SDimitry Andric if (Name == "__vecDelDtor") 94*0b57cec5SDimitry Andric return true; 95*0b57cec5SDimitry Andric return false; 96*0b57cec5SDimitry Andric } 97*0b57cec5SDimitry Andric 98*0b57cec5SDimitry Andric std::unique_ptr<IPDBEnumLineNumbers> PDBSymbolFunc::getLineNumbers() const { 99*0b57cec5SDimitry Andric auto Len = RawSymbol->getLength(); 100*0b57cec5SDimitry Andric return Session.findLineNumbersByAddress(RawSymbol->getVirtualAddress(), 101*0b57cec5SDimitry Andric Len ? Len : 1); 102*0b57cec5SDimitry Andric } 103*0b57cec5SDimitry Andric 104*0b57cec5SDimitry Andric uint32_t PDBSymbolFunc::getCompilandId() const { 105*0b57cec5SDimitry Andric if (auto Lines = getLineNumbers()) { 106*0b57cec5SDimitry Andric if (auto FirstLine = Lines->getNext()) { 107*0b57cec5SDimitry Andric return FirstLine->getCompilandId(); 108*0b57cec5SDimitry Andric } 109*0b57cec5SDimitry Andric } 110*0b57cec5SDimitry Andric return 0; 111*0b57cec5SDimitry Andric } 112