1 //===- NativeTypeFunctionSig.cpp - info about function signature -*- C++-*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"
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"
18 using namespace llvm::codeview
;
19 using namespace llvm::pdb
;
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
26 class NativeTypeFunctionArg
: public NativeRawSymbol
{
28 NativeTypeFunctionArg(NativeSession
&Session
,
29 std::unique_ptr
<PDBSymbol
> RealType
)
30 : NativeRawSymbol(Session
, PDB_SymType::FunctionArg
, 0),
31 RealType(std::move(RealType
)) {}
33 void dump(raw_ostream
&OS
, int Indent
, PdbSymbolIdField ShowIdFields
,
34 PdbSymbolIdField RecurseIdFields
) const override
{
35 NativeRawSymbol::dump(OS
, Indent
, ShowIdFields
, RecurseIdFields
);
37 dumpSymbolIdField(OS
, "typeId", getTypeId(), Indent
, Session
,
38 PdbSymbolIdField::Type
, ShowIdFields
, RecurseIdFields
);
41 SymIndexId
getTypeId() const override
{ return RealType
->getSymIndexId(); }
43 std::unique_ptr
<PDBSymbol
> RealType
;
46 class NativeEnumFunctionArgs
: public IPDBEnumChildren
<PDBSymbol
> {
48 NativeEnumFunctionArgs(NativeSession
&Session
,
49 std::unique_ptr
<NativeEnumTypes
> TypeEnumerator
)
50 : Session(Session
), TypeEnumerator(std::move(TypeEnumerator
)) {}
52 uint32_t getChildCount() const override
{
53 return TypeEnumerator
->getChildCount();
55 std::unique_ptr
<PDBSymbol
> getChildAtIndex(uint32_t Index
) const override
{
56 return wrap(TypeEnumerator
->getChildAtIndex(Index
));
58 std::unique_ptr
<PDBSymbol
> getNext() override
{
59 return wrap(TypeEnumerator
->getNext());
62 void reset() override
{ TypeEnumerator
->reset(); }
65 std::unique_ptr
<PDBSymbol
> wrap(std::unique_ptr
<PDBSymbol
> S
) const {
68 auto NTFA
= std::make_unique
<NativeTypeFunctionArg
>(Session
, std::move(S
));
69 return PDBSymbol::create(Session
, std::move(NTFA
));
71 NativeSession
&Session
;
72 std::unique_ptr
<NativeEnumTypes
> TypeEnumerator
;
76 NativeTypeFunctionSig::NativeTypeFunctionSig(NativeSession
&Session
,
78 codeview::TypeIndex Index
,
79 codeview::ProcedureRecord Proc
)
80 : NativeRawSymbol(Session
, PDB_SymType::FunctionSig
, Id
),
81 Proc(std::move(Proc
)), Index(Index
), IsMemberFunction(false) {}
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) {}
89 void NativeTypeFunctionSig::initialize() {
90 if (IsMemberFunction
) {
92 Session
.getSymbolCache().findSymbolByTypeIndex(MemberFunc
.ClassType
);
93 initializeArgList(MemberFunc
.ArgumentList
);
95 initializeArgList(Proc
.ArgumentList
);
99 NativeTypeFunctionSig::~NativeTypeFunctionSig() {}
101 void NativeTypeFunctionSig::initializeArgList(codeview::TypeIndex ArgListTI
) {
102 TpiStream
&Tpi
= cantFail(Session
.getPDBFile().getPDBTpiStream());
103 CVType CVT
= Tpi
.typeCollection().getType(ArgListTI
);
105 cantFail(TypeDeserializer::deserializeAs
<ArgListRecord
>(CVT
, ArgList
));
108 void NativeTypeFunctionSig::dump(raw_ostream
&OS
, int Indent
,
109 PdbSymbolIdField ShowIdFields
,
110 PdbSymbolIdField RecurseIdFields
) const {
112 NativeRawSymbol::dump(OS
, Indent
, ShowIdFields
, RecurseIdFields
);
114 dumpSymbolIdField(OS
, "lexicalParentId", 0, Indent
, Session
,
115 PdbSymbolIdField::LexicalParent
, ShowIdFields
,
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(),
128 dumpSymbolField(OS
, "isCxxReturnUdt", isCxxReturnUdt(), Indent
);
129 dumpSymbolField(OS
, "unalignedType", isUnalignedType(), Indent
);
130 dumpSymbolField(OS
, "volatileType", isVolatileType(), Indent
);
133 std::unique_ptr
<IPDBEnumSymbols
>
134 NativeTypeFunctionSig::findChildren(PDB_SymType Type
) const {
135 if (Type
!= PDB_SymType::FunctionArg
)
136 return std::make_unique
<NullEnumerator
<PDBSymbol
>>();
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
)));
144 SymIndexId
NativeTypeFunctionSig::getClassParentId() const {
145 if (!IsMemberFunction
)
148 return ClassParentId
;
151 PDB_CallingConv
NativeTypeFunctionSig::getCallingConvention() const {
152 return IsMemberFunction
? MemberFunc
.CallConv
: Proc
.CallConv
;
155 uint32_t NativeTypeFunctionSig::getCount() const {
156 return IsMemberFunction
? (1 + MemberFunc
.getParameterCount())
157 : Proc
.getParameterCount();
160 SymIndexId
NativeTypeFunctionSig::getTypeId() const {
162 IsMemberFunction
? MemberFunc
.getReturnType() : Proc
.getReturnType();
164 SymIndexId Result
= Session
.getSymbolCache().findSymbolByTypeIndex(ReturnTI
);
168 int32_t NativeTypeFunctionSig::getThisAdjust() const {
169 return IsMemberFunction
? MemberFunc
.getThisPointerAdjustment() : 0;
172 bool NativeTypeFunctionSig::hasConstructor() const {
173 if (!IsMemberFunction
)
176 return (MemberFunc
.getOptions() & FunctionOptions::Constructor
) !=
177 FunctionOptions::None
;
180 bool NativeTypeFunctionSig::isConstType() const { return false; }
182 bool NativeTypeFunctionSig::isConstructorVirtualBase() const {
183 if (!IsMemberFunction
)
186 return (MemberFunc
.getOptions() &
187 FunctionOptions::ConstructorWithVirtualBases
) !=
188 FunctionOptions::None
;
191 bool NativeTypeFunctionSig::isCxxReturnUdt() const {
192 FunctionOptions Options
=
193 IsMemberFunction
? MemberFunc
.getOptions() : Proc
.getOptions();
194 return (Options
& FunctionOptions::CxxReturnUdt
) != FunctionOptions::None
;
197 bool NativeTypeFunctionSig::isUnalignedType() const { return false; }
199 bool NativeTypeFunctionSig::isVolatileType() const { return false; }