//===- NativeTypeFunctionSig.cpp - info about function signature -*- C++-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" #include "llvm/DebugInfo/PDB/PDBExtras.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" using namespace llvm; using namespace llvm::codeview; using namespace llvm::pdb; namespace { // This is kind of a silly class, hence why we keep it private to the file. // It's only purpose is to wrap the real type record. I guess this is so that // we can have the lexical parent point to the function instead of the global // scope. class NativeTypeFunctionArg : public NativeRawSymbol { public: NativeTypeFunctionArg(NativeSession &Session, std::unique_ptr RealType) : NativeRawSymbol(Session, PDB_SymType::FunctionArg, 0), RealType(std::move(RealType)) {} void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, PdbSymbolIdField RecurseIdFields) const override { NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session, PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields); } SymIndexId getTypeId() const override { return RealType->getSymIndexId(); } std::unique_ptr RealType; }; class NativeEnumFunctionArgs : public IPDBEnumChildren { public: NativeEnumFunctionArgs(NativeSession &Session, std::unique_ptr TypeEnumerator) : Session(Session), TypeEnumerator(std::move(TypeEnumerator)) {} uint32_t getChildCount() const override { return TypeEnumerator->getChildCount(); } std::unique_ptr getChildAtIndex(uint32_t Index) const override { return wrap(TypeEnumerator->getChildAtIndex(Index)); } std::unique_ptr getNext() override { return wrap(TypeEnumerator->getNext()); } void reset() override { TypeEnumerator->reset(); } private: std::unique_ptr wrap(std::unique_ptr S) const { if (!S) return nullptr; auto NTFA = std::make_unique(Session, std::move(S)); return PDBSymbol::create(Session, std::move(NTFA)); } NativeSession &Session; std::unique_ptr TypeEnumerator; }; } // namespace NativeTypeFunctionSig::NativeTypeFunctionSig(NativeSession &Session, SymIndexId Id, codeview::TypeIndex Index, codeview::ProcedureRecord Proc) : NativeRawSymbol(Session, PDB_SymType::FunctionSig, Id), Proc(std::move(Proc)), Index(Index), IsMemberFunction(false) {} NativeTypeFunctionSig::NativeTypeFunctionSig( NativeSession &Session, SymIndexId Id, codeview::TypeIndex Index, codeview::MemberFunctionRecord MemberFunc) : NativeRawSymbol(Session, PDB_SymType::FunctionSig, Id), MemberFunc(std::move(MemberFunc)), Index(Index), IsMemberFunction(true) {} void NativeTypeFunctionSig::initialize() { if (IsMemberFunction) { ClassParentId = Session.getSymbolCache().findSymbolByTypeIndex(MemberFunc.ClassType); initializeArgList(MemberFunc.ArgumentList); } else { initializeArgList(Proc.ArgumentList); } } NativeTypeFunctionSig::~NativeTypeFunctionSig() {} void NativeTypeFunctionSig::initializeArgList(codeview::TypeIndex ArgListTI) { TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream()); CVType CVT = Tpi.typeCollection().getType(ArgListTI); cantFail(TypeDeserializer::deserializeAs(CVT, ArgList)); } void NativeTypeFunctionSig::dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, PdbSymbolIdField RecurseIdFields) const { NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session, PdbSymbolIdField::LexicalParent, ShowIdFields, RecurseIdFields); dumpSymbolField(OS, "callingConvention", getCallingConvention(), Indent); dumpSymbolField(OS, "count", getCount(), Indent); dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session, PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields); if (IsMemberFunction) dumpSymbolField(OS, "thisAdjust", getThisAdjust(), Indent); dumpSymbolField(OS, "constructor", hasConstructor(), Indent); dumpSymbolField(OS, "constType", isConstType(), Indent); dumpSymbolField(OS, "isConstructorVirtualBase", isConstructorVirtualBase(), Indent); dumpSymbolField(OS, "isCxxReturnUdt", isCxxReturnUdt(), Indent); dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); } std::unique_ptr NativeTypeFunctionSig::findChildren(PDB_SymType Type) const { if (Type != PDB_SymType::FunctionArg) return std::make_unique>(); auto NET = std::make_unique(Session, /* copy */ ArgList.ArgIndices); return std::unique_ptr( new NativeEnumFunctionArgs(Session, std::move(NET))); } SymIndexId NativeTypeFunctionSig::getClassParentId() const { if (!IsMemberFunction) return 0; return ClassParentId; } PDB_CallingConv NativeTypeFunctionSig::getCallingConvention() const { return IsMemberFunction ? MemberFunc.CallConv : Proc.CallConv; } uint32_t NativeTypeFunctionSig::getCount() const { return IsMemberFunction ? (1 + MemberFunc.getParameterCount()) : Proc.getParameterCount(); } SymIndexId NativeTypeFunctionSig::getTypeId() const { TypeIndex ReturnTI = IsMemberFunction ? MemberFunc.getReturnType() : Proc.getReturnType(); SymIndexId Result = Session.getSymbolCache().findSymbolByTypeIndex(ReturnTI); return Result; } int32_t NativeTypeFunctionSig::getThisAdjust() const { return IsMemberFunction ? MemberFunc.getThisPointerAdjustment() : 0; } bool NativeTypeFunctionSig::hasConstructor() const { if (!IsMemberFunction) return false; return (MemberFunc.getOptions() & FunctionOptions::Constructor) != FunctionOptions::None; } bool NativeTypeFunctionSig::isConstType() const { return false; } bool NativeTypeFunctionSig::isConstructorVirtualBase() const { if (!IsMemberFunction) return false; return (MemberFunc.getOptions() & FunctionOptions::ConstructorWithVirtualBases) != FunctionOptions::None; } bool NativeTypeFunctionSig::isCxxReturnUdt() const { FunctionOptions Options = IsMemberFunction ? MemberFunc.getOptions() : Proc.getOptions(); return (Options & FunctionOptions::CxxReturnUdt) != FunctionOptions::None; } bool NativeTypeFunctionSig::isUnalignedType() const { return false; } bool NativeTypeFunctionSig::isVolatileType() const { return false; }