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: 29 NativeTypeFunctionArg(NativeSession &Session, 30 std::unique_ptr<PDBSymbol> RealType) 31 : NativeRawSymbol(Session, PDB_SymType::FunctionArg, 0), 32 RealType(std::move(RealType)) {} 33 34 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 42 SymIndexId getTypeId() const override { return RealType->getSymIndexId(); } 43 44 std::unique_ptr<PDBSymbol> RealType; 45 }; 46 47 class NativeEnumFunctionArgs : public IPDBEnumChildren<PDBSymbol> { 48 public: 49 NativeEnumFunctionArgs(NativeSession &Session, 50 std::unique_ptr<NativeEnumTypes> TypeEnumerator) 51 : Session(Session), TypeEnumerator(std::move(TypeEnumerator)) {} 52 53 uint32_t getChildCount() const override { 54 return TypeEnumerator->getChildCount(); 55 } 56 std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override { 57 return wrap(TypeEnumerator->getChildAtIndex(Index)); 58 } 59 std::unique_ptr<PDBSymbol> getNext() override { 60 return wrap(TypeEnumerator->getNext()); 61 } 62 63 void reset() override { TypeEnumerator->reset(); } 64 65 private: 66 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 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 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 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 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 109 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> 135 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 145 SymIndexId NativeTypeFunctionSig::getClassParentId() const { 146 if (!IsMemberFunction) 147 return 0; 148 149 return ClassParentId; 150 } 151 152 PDB_CallingConv NativeTypeFunctionSig::getCallingConvention() const { 153 return IsMemberFunction ? MemberFunc.CallConv : Proc.CallConv; 154 } 155 156 uint32_t NativeTypeFunctionSig::getCount() const { 157 return IsMemberFunction ? (1 + MemberFunc.getParameterCount()) 158 : Proc.getParameterCount(); 159 } 160 161 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 169 int32_t NativeTypeFunctionSig::getThisAdjust() const { 170 return IsMemberFunction ? MemberFunc.getThisPointerAdjustment() : 0; 171 } 172 173 bool NativeTypeFunctionSig::hasConstructor() const { 174 if (!IsMemberFunction) 175 return false; 176 177 return (MemberFunc.getOptions() & FunctionOptions::Constructor) != 178 FunctionOptions::None; 179 } 180 181 bool NativeTypeFunctionSig::isConstType() const { return false; } 182 183 bool NativeTypeFunctionSig::isConstructorVirtualBase() const { 184 if (!IsMemberFunction) 185 return false; 186 187 return (MemberFunc.getOptions() & 188 FunctionOptions::ConstructorWithVirtualBases) != 189 FunctionOptions::None; 190 } 191 192 bool NativeTypeFunctionSig::isCxxReturnUdt() const { 193 FunctionOptions Options = 194 IsMemberFunction ? MemberFunc.getOptions() : Proc.getOptions(); 195 return (Options & FunctionOptions::CxxReturnUdt) != FunctionOptions::None; 196 } 197 198 bool NativeTypeFunctionSig::isUnalignedType() const { return false; } 199 200 bool NativeTypeFunctionSig::isVolatileType() const { return false; } 201