xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
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