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