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