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