1 //===- NativeTypeFunctionSig.cpp - info about function signature -*- 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-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"
10
11 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
12 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
13 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
14 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
15 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
16 #include "llvm/DebugInfo/PDB/PDBExtras.h"
17
18 using namespace llvm;
19 using namespace llvm::codeview;
20 using namespace llvm::pdb;
21
22 namespace {
23 // This is kind of a silly class, hence why we keep it private to the file.
24 // It's only purpose is to wrap the real type record. I guess this is so that
25 // we can have the lexical parent point to the function instead of the global
26 // scope.
27 class NativeTypeFunctionArg : public NativeRawSymbol {
28 public:
NativeTypeFunctionArg(NativeSession & Session,std::unique_ptr<PDBSymbol> RealType)29 NativeTypeFunctionArg(NativeSession &Session,
30 std::unique_ptr<PDBSymbol> RealType)
31 : NativeRawSymbol(Session, PDB_SymType::FunctionArg, 0),
32 RealType(std::move(RealType)) {}
33
dump(raw_ostream & OS,int Indent,PdbSymbolIdField ShowIdFields,PdbSymbolIdField RecurseIdFields) const34 void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
35 PdbSymbolIdField RecurseIdFields) const override {
36 NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
37
38 dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
39 PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
40 }
41
getTypeId() const42 SymIndexId getTypeId() const override { return RealType->getSymIndexId(); }
43
44 std::unique_ptr<PDBSymbol> RealType;
45 };
46
47 class NativeEnumFunctionArgs : public IPDBEnumChildren<PDBSymbol> {
48 public:
NativeEnumFunctionArgs(NativeSession & Session,std::unique_ptr<NativeEnumTypes> TypeEnumerator)49 NativeEnumFunctionArgs(NativeSession &Session,
50 std::unique_ptr<NativeEnumTypes> TypeEnumerator)
51 : Session(Session), TypeEnumerator(std::move(TypeEnumerator)) {}
52
getChildCount() const53 uint32_t getChildCount() const override {
54 return TypeEnumerator->getChildCount();
55 }
getChildAtIndex(uint32_t Index) const56 std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override {
57 return wrap(TypeEnumerator->getChildAtIndex(Index));
58 }
getNext()59 std::unique_ptr<PDBSymbol> getNext() override {
60 return wrap(TypeEnumerator->getNext());
61 }
62
reset()63 void reset() override { TypeEnumerator->reset(); }
64
65 private:
wrap(std::unique_ptr<PDBSymbol> S) const66 std::unique_ptr<PDBSymbol> wrap(std::unique_ptr<PDBSymbol> S) const {
67 if (!S)
68 return nullptr;
69 auto NTFA = std::make_unique<NativeTypeFunctionArg>(Session, std::move(S));
70 return PDBSymbol::create(Session, std::move(NTFA));
71 }
72 NativeSession &Session;
73 std::unique_ptr<NativeEnumTypes> TypeEnumerator;
74 };
75 } // namespace
76
NativeTypeFunctionSig(NativeSession & Session,SymIndexId Id,codeview::TypeIndex Index,codeview::ProcedureRecord Proc)77 NativeTypeFunctionSig::NativeTypeFunctionSig(NativeSession &Session,
78 SymIndexId Id,
79 codeview::TypeIndex Index,
80 codeview::ProcedureRecord Proc)
81 : NativeRawSymbol(Session, PDB_SymType::FunctionSig, Id),
82 Proc(std::move(Proc)), Index(Index), IsMemberFunction(false) {}
83
NativeTypeFunctionSig(NativeSession & Session,SymIndexId Id,codeview::TypeIndex Index,codeview::MemberFunctionRecord MemberFunc)84 NativeTypeFunctionSig::NativeTypeFunctionSig(
85 NativeSession &Session, SymIndexId Id, codeview::TypeIndex Index,
86 codeview::MemberFunctionRecord MemberFunc)
87 : NativeRawSymbol(Session, PDB_SymType::FunctionSig, Id),
88 MemberFunc(std::move(MemberFunc)), Index(Index), IsMemberFunction(true) {}
89
initialize()90 void NativeTypeFunctionSig::initialize() {
91 if (IsMemberFunction) {
92 ClassParentId =
93 Session.getSymbolCache().findSymbolByTypeIndex(MemberFunc.ClassType);
94 initializeArgList(MemberFunc.ArgumentList);
95 } else {
96 initializeArgList(Proc.ArgumentList);
97 }
98 }
99
100 NativeTypeFunctionSig::~NativeTypeFunctionSig() = default;
101
initializeArgList(codeview::TypeIndex ArgListTI)102 void NativeTypeFunctionSig::initializeArgList(codeview::TypeIndex ArgListTI) {
103 TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
104 CVType CVT = Tpi.typeCollection().getType(ArgListTI);
105
106 cantFail(TypeDeserializer::deserializeAs<ArgListRecord>(CVT, ArgList));
107 }
108
dump(raw_ostream & OS,int Indent,PdbSymbolIdField ShowIdFields,PdbSymbolIdField RecurseIdFields) const109 void NativeTypeFunctionSig::dump(raw_ostream &OS, int Indent,
110 PdbSymbolIdField ShowIdFields,
111 PdbSymbolIdField RecurseIdFields) const {
112
113 NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
114
115 dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session,
116 PdbSymbolIdField::LexicalParent, ShowIdFields,
117 RecurseIdFields);
118
119 dumpSymbolField(OS, "callingConvention", getCallingConvention(), Indent);
120 dumpSymbolField(OS, "count", getCount(), Indent);
121 dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session,
122 PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields);
123 if (IsMemberFunction)
124 dumpSymbolField(OS, "thisAdjust", getThisAdjust(), Indent);
125 dumpSymbolField(OS, "constructor", hasConstructor(), Indent);
126 dumpSymbolField(OS, "constType", isConstType(), Indent);
127 dumpSymbolField(OS, "isConstructorVirtualBase", isConstructorVirtualBase(),
128 Indent);
129 dumpSymbolField(OS, "isCxxReturnUdt", isCxxReturnUdt(), Indent);
130 dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent);
131 dumpSymbolField(OS, "volatileType", isVolatileType(), Indent);
132 }
133
134 std::unique_ptr<IPDBEnumSymbols>
findChildren(PDB_SymType Type) const135 NativeTypeFunctionSig::findChildren(PDB_SymType Type) const {
136 if (Type != PDB_SymType::FunctionArg)
137 return std::make_unique<NullEnumerator<PDBSymbol>>();
138
139 auto NET = std::make_unique<NativeEnumTypes>(Session,
140 /* copy */ ArgList.ArgIndices);
141 return std::unique_ptr<IPDBEnumSymbols>(
142 new NativeEnumFunctionArgs(Session, std::move(NET)));
143 }
144
getClassParentId() const145 SymIndexId NativeTypeFunctionSig::getClassParentId() const {
146 if (!IsMemberFunction)
147 return 0;
148
149 return ClassParentId;
150 }
151
getCallingConvention() const152 PDB_CallingConv NativeTypeFunctionSig::getCallingConvention() const {
153 return IsMemberFunction ? MemberFunc.CallConv : Proc.CallConv;
154 }
155
getCount() const156 uint32_t NativeTypeFunctionSig::getCount() const {
157 return IsMemberFunction ? (1 + MemberFunc.getParameterCount())
158 : Proc.getParameterCount();
159 }
160
getTypeId() const161 SymIndexId NativeTypeFunctionSig::getTypeId() const {
162 TypeIndex ReturnTI =
163 IsMemberFunction ? MemberFunc.getReturnType() : Proc.getReturnType();
164
165 SymIndexId Result = Session.getSymbolCache().findSymbolByTypeIndex(ReturnTI);
166 return Result;
167 }
168
getThisAdjust() const169 int32_t NativeTypeFunctionSig::getThisAdjust() const {
170 return IsMemberFunction ? MemberFunc.getThisPointerAdjustment() : 0;
171 }
172
hasConstructor() const173 bool NativeTypeFunctionSig::hasConstructor() const {
174 if (!IsMemberFunction)
175 return false;
176
177 return (MemberFunc.getOptions() & FunctionOptions::Constructor) !=
178 FunctionOptions::None;
179 }
180
isConstType() const181 bool NativeTypeFunctionSig::isConstType() const { return false; }
182
isConstructorVirtualBase() const183 bool NativeTypeFunctionSig::isConstructorVirtualBase() const {
184 if (!IsMemberFunction)
185 return false;
186
187 return (MemberFunc.getOptions() &
188 FunctionOptions::ConstructorWithVirtualBases) !=
189 FunctionOptions::None;
190 }
191
isCxxReturnUdt() const192 bool NativeTypeFunctionSig::isCxxReturnUdt() const {
193 FunctionOptions Options =
194 IsMemberFunction ? MemberFunc.getOptions() : Proc.getOptions();
195 return (Options & FunctionOptions::CxxReturnUdt) != FunctionOptions::None;
196 }
197
isUnalignedType() const198 bool NativeTypeFunctionSig::isUnalignedType() const { return false; }
199
isVolatileType() const200 bool NativeTypeFunctionSig::isVolatileType() const { return false; }
201