106c3fb27SDimitry Andric //===-- LVCodeViewVisitor.cpp ---------------------------------------------===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric // 906c3fb27SDimitry Andric // This implements the LVCodeViewVisitor class. 1006c3fb27SDimitry Andric // 1106c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 1206c3fb27SDimitry Andric 1306c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h" 1406c3fb27SDimitry Andric #include "llvm/BinaryFormat/Magic.h" 1506c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/EnumTables.h" 1606c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" 1706c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h" 1806c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" 1906c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" 2006c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVScope.h" 2106c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h" 2206c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVType.h" 2306c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h" 2406c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStream.h" 2506c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InputFile.h" 2606c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 2706c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 2806c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" 2906c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawError.h" 3006c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 3106c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/PDB.h" 3206c3fb27SDimitry Andric #include "llvm/Demangle/Demangle.h" 3306c3fb27SDimitry Andric #include "llvm/Object/COFF.h" 3406c3fb27SDimitry Andric #include "llvm/Support/Error.h" 3506c3fb27SDimitry Andric #include "llvm/Support/FileSystem.h" 3606c3fb27SDimitry Andric #include "llvm/Support/FormatAdapters.h" 3706c3fb27SDimitry Andric #include "llvm/Support/FormatVariadic.h" 3806c3fb27SDimitry Andric 3906c3fb27SDimitry Andric using namespace llvm; 4006c3fb27SDimitry Andric using namespace llvm::codeview; 4106c3fb27SDimitry Andric using namespace llvm::object; 4206c3fb27SDimitry Andric using namespace llvm::pdb; 4306c3fb27SDimitry Andric using namespace llvm::logicalview; 4406c3fb27SDimitry Andric 4506c3fb27SDimitry Andric #define DEBUG_TYPE "CodeViewUtilities" 4606c3fb27SDimitry Andric 4706c3fb27SDimitry Andric namespace llvm { 4806c3fb27SDimitry Andric namespace logicalview { 4906c3fb27SDimitry Andric 5006c3fb27SDimitry Andric static TypeIndex getTrueType(TypeIndex &TI) { 5106c3fb27SDimitry Andric // Dealing with a MSVC generated PDB, we encountered a type index with the 5206c3fb27SDimitry Andric // value of: 0x0280xxxx where xxxx=0000. 5306c3fb27SDimitry Andric // 5406c3fb27SDimitry Andric // There is some documentation about type indices: 5506c3fb27SDimitry Andric // https://llvm.org/docs/PDB/TpiStream.html 5606c3fb27SDimitry Andric // 5706c3fb27SDimitry Andric // A type index is a 32-bit integer that uniquely identifies a type inside 5806c3fb27SDimitry Andric // of an object file’s .debug$T section or a PDB file’s TPI or IPI stream. 5906c3fb27SDimitry Andric // The value of the type index for the first type record from the TPI stream 6006c3fb27SDimitry Andric // is given by the TypeIndexBegin member of the TPI Stream Header although 6106c3fb27SDimitry Andric // in practice this value is always equal to 0x1000 (4096). 6206c3fb27SDimitry Andric // 6306c3fb27SDimitry Andric // Any type index with a high bit set is considered to come from the IPI 6406c3fb27SDimitry Andric // stream, although this appears to be more of a hack, and LLVM does not 6506c3fb27SDimitry Andric // generate type indices of this nature. They can, however, be observed in 6606c3fb27SDimitry Andric // Microsoft PDBs occasionally, so one should be prepared to handle them. 6706c3fb27SDimitry Andric // Note that having the high bit set is not a necessary condition to 6806c3fb27SDimitry Andric // determine whether a type index comes from the IPI stream, it is only 6906c3fb27SDimitry Andric // sufficient. 7006c3fb27SDimitry Andric LLVM_DEBUG( 7106c3fb27SDimitry Andric { dbgs() << "Index before: " << HexNumber(TI.getIndex()) << "\n"; }); 7206c3fb27SDimitry Andric TI.setIndex(TI.getIndex() & 0x0000ffff); 7306c3fb27SDimitry Andric LLVM_DEBUG( 7406c3fb27SDimitry Andric { dbgs() << "Index after: " << HexNumber(TI.getIndex()) << "\n"; }); 7506c3fb27SDimitry Andric return TI; 7606c3fb27SDimitry Andric } 7706c3fb27SDimitry Andric 7806c3fb27SDimitry Andric static const EnumEntry<TypeLeafKind> LeafTypeNames[] = { 7906c3fb27SDimitry Andric #define CV_TYPE(enum, val) {#enum, enum}, 8006c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewTypes.def" 8106c3fb27SDimitry Andric }; 8206c3fb27SDimitry Andric 8306c3fb27SDimitry Andric // Return the type name pointed by the type index. It uses the kind to query 8406c3fb27SDimitry Andric // the associated name for the record type. 8506c3fb27SDimitry Andric static StringRef getRecordName(LazyRandomTypeCollection &Types, TypeIndex TI) { 8606c3fb27SDimitry Andric if (TI.isSimple()) 8706c3fb27SDimitry Andric return {}; 8806c3fb27SDimitry Andric 8906c3fb27SDimitry Andric StringRef RecordName; 9006c3fb27SDimitry Andric CVType CVReference = Types.getType(TI); 9106c3fb27SDimitry Andric auto GetName = [&](auto Record) { 9206c3fb27SDimitry Andric if (Error Err = TypeDeserializer::deserializeAs( 9306c3fb27SDimitry Andric const_cast<CVType &>(CVReference), Record)) 9406c3fb27SDimitry Andric consumeError(std::move(Err)); 9506c3fb27SDimitry Andric else 9606c3fb27SDimitry Andric RecordName = Record.getName(); 9706c3fb27SDimitry Andric }; 9806c3fb27SDimitry Andric 9906c3fb27SDimitry Andric TypeRecordKind RK = static_cast<TypeRecordKind>(CVReference.kind()); 10006c3fb27SDimitry Andric if (RK == TypeRecordKind::Class || RK == TypeRecordKind::Struct) 10106c3fb27SDimitry Andric GetName(ClassRecord(RK)); 10206c3fb27SDimitry Andric else if (RK == TypeRecordKind::Union) 10306c3fb27SDimitry Andric GetName(UnionRecord(RK)); 10406c3fb27SDimitry Andric else if (RK == TypeRecordKind::Enum) 10506c3fb27SDimitry Andric GetName(EnumRecord(RK)); 10606c3fb27SDimitry Andric 10706c3fb27SDimitry Andric return RecordName; 10806c3fb27SDimitry Andric } 10906c3fb27SDimitry Andric 11006c3fb27SDimitry Andric } // namespace logicalview 11106c3fb27SDimitry Andric } // namespace llvm 11206c3fb27SDimitry Andric 11306c3fb27SDimitry Andric #undef DEBUG_TYPE 11406c3fb27SDimitry Andric #define DEBUG_TYPE "CodeViewDataVisitor" 11506c3fb27SDimitry Andric 11606c3fb27SDimitry Andric namespace llvm { 11706c3fb27SDimitry Andric namespace logicalview { 11806c3fb27SDimitry Andric 11906c3fb27SDimitry Andric // Keeps the type indexes with line information. 12006c3fb27SDimitry Andric using LVLineRecords = std::vector<TypeIndex>; 12106c3fb27SDimitry Andric 12206c3fb27SDimitry Andric namespace { 12306c3fb27SDimitry Andric 12406c3fb27SDimitry Andric class LVTypeRecords { 12506c3fb27SDimitry Andric LVShared *Shared = nullptr; 12606c3fb27SDimitry Andric 12706c3fb27SDimitry Andric // Logical elements associated to their CodeView Type Index. 12806c3fb27SDimitry Andric using RecordEntry = std::pair<TypeLeafKind, LVElement *>; 12906c3fb27SDimitry Andric using RecordTable = std::map<TypeIndex, RecordEntry>; 13006c3fb27SDimitry Andric RecordTable RecordFromTypes; 13106c3fb27SDimitry Andric RecordTable RecordFromIds; 13206c3fb27SDimitry Andric 13306c3fb27SDimitry Andric using NameTable = std::map<StringRef, TypeIndex>; 13406c3fb27SDimitry Andric NameTable NameFromTypes; 13506c3fb27SDimitry Andric NameTable NameFromIds; 13606c3fb27SDimitry Andric 13706c3fb27SDimitry Andric public: 13806c3fb27SDimitry Andric LVTypeRecords(LVShared *Shared) : Shared(Shared) {} 13906c3fb27SDimitry Andric 14006c3fb27SDimitry Andric void add(uint32_t StreamIdx, TypeIndex TI, TypeLeafKind Kind, 14106c3fb27SDimitry Andric LVElement *Element = nullptr); 14206c3fb27SDimitry Andric void add(uint32_t StreamIdx, TypeIndex TI, StringRef Name); 14306c3fb27SDimitry Andric LVElement *find(uint32_t StreamIdx, TypeIndex TI, bool Create = true); 14406c3fb27SDimitry Andric TypeIndex find(uint32_t StreamIdx, StringRef Name); 14506c3fb27SDimitry Andric }; 14606c3fb27SDimitry Andric 14706c3fb27SDimitry Andric class LVForwardReferences { 14806c3fb27SDimitry Andric // Forward reference and its definitions (Name as key). 14906c3fb27SDimitry Andric using ForwardEntry = std::pair<TypeIndex, TypeIndex>; 15006c3fb27SDimitry Andric using ForwardTypeNames = std::map<StringRef, ForwardEntry>; 15106c3fb27SDimitry Andric ForwardTypeNames ForwardTypesNames; 15206c3fb27SDimitry Andric 15306c3fb27SDimitry Andric // Forward reference and its definition (TypeIndex as key). 15406c3fb27SDimitry Andric using ForwardType = std::map<TypeIndex, TypeIndex>; 15506c3fb27SDimitry Andric ForwardType ForwardTypes; 15606c3fb27SDimitry Andric 15706c3fb27SDimitry Andric // Forward types and its references. 15806c3fb27SDimitry Andric void add(TypeIndex TIForward, TypeIndex TIReference) { 15906c3fb27SDimitry Andric ForwardTypes.emplace(TIForward, TIReference); 16006c3fb27SDimitry Andric } 16106c3fb27SDimitry Andric 16206c3fb27SDimitry Andric void add(StringRef Name, TypeIndex TIForward) { 16306c3fb27SDimitry Andric if (ForwardTypesNames.find(Name) == ForwardTypesNames.end()) { 16406c3fb27SDimitry Andric ForwardTypesNames.emplace( 16506c3fb27SDimitry Andric std::piecewise_construct, std::forward_as_tuple(Name), 16606c3fb27SDimitry Andric std::forward_as_tuple(TIForward, TypeIndex::None())); 16706c3fb27SDimitry Andric } else { 16806c3fb27SDimitry Andric // Update a recorded definition with its reference. 16906c3fb27SDimitry Andric ForwardTypesNames[Name].first = TIForward; 17006c3fb27SDimitry Andric add(TIForward, ForwardTypesNames[Name].second); 17106c3fb27SDimitry Andric } 17206c3fb27SDimitry Andric } 17306c3fb27SDimitry Andric 17406c3fb27SDimitry Andric // Update a previously recorded forward reference with its definition. 17506c3fb27SDimitry Andric void update(StringRef Name, TypeIndex TIReference) { 17606c3fb27SDimitry Andric if (ForwardTypesNames.find(Name) != ForwardTypesNames.end()) { 17706c3fb27SDimitry Andric // Update the recorded forward reference with its definition. 17806c3fb27SDimitry Andric ForwardTypesNames[Name].second = TIReference; 17906c3fb27SDimitry Andric add(ForwardTypesNames[Name].first, TIReference); 18006c3fb27SDimitry Andric } else { 18106c3fb27SDimitry Andric // We have not seen the forward reference. Insert the definition. 18206c3fb27SDimitry Andric ForwardTypesNames.emplace( 18306c3fb27SDimitry Andric std::piecewise_construct, std::forward_as_tuple(Name), 18406c3fb27SDimitry Andric std::forward_as_tuple(TypeIndex::None(), TIReference)); 18506c3fb27SDimitry Andric } 18606c3fb27SDimitry Andric } 18706c3fb27SDimitry Andric 18806c3fb27SDimitry Andric public: 18906c3fb27SDimitry Andric LVForwardReferences() = default; 19006c3fb27SDimitry Andric 19106c3fb27SDimitry Andric void record(bool IsForwardRef, StringRef Name, TypeIndex TI) { 19206c3fb27SDimitry Andric // We are expecting for the forward references to be first. But that 19306c3fb27SDimitry Andric // is not always the case. A name must be recorded regardless of the 19406c3fb27SDimitry Andric // order in which the forward reference appears. 19506c3fb27SDimitry Andric (IsForwardRef) ? add(Name, TI) : update(Name, TI); 19606c3fb27SDimitry Andric } 19706c3fb27SDimitry Andric 19806c3fb27SDimitry Andric TypeIndex find(TypeIndex TIForward) { 19906c3fb27SDimitry Andric return (ForwardTypes.find(TIForward) != ForwardTypes.end()) 20006c3fb27SDimitry Andric ? ForwardTypes[TIForward] 20106c3fb27SDimitry Andric : TypeIndex::None(); 20206c3fb27SDimitry Andric } 20306c3fb27SDimitry Andric 20406c3fb27SDimitry Andric TypeIndex find(StringRef Name) { 20506c3fb27SDimitry Andric return (ForwardTypesNames.find(Name) != ForwardTypesNames.end()) 20606c3fb27SDimitry Andric ? ForwardTypesNames[Name].second 20706c3fb27SDimitry Andric : TypeIndex::None(); 20806c3fb27SDimitry Andric } 20906c3fb27SDimitry Andric 21006c3fb27SDimitry Andric // If the given TI corresponds to a reference, return the reference. 21106c3fb27SDimitry Andric // Otherwise return the given TI. 21206c3fb27SDimitry Andric TypeIndex remap(TypeIndex TI) { 21306c3fb27SDimitry Andric TypeIndex Forward = find(TI); 21406c3fb27SDimitry Andric return Forward.isNoneType() ? TI : Forward; 21506c3fb27SDimitry Andric } 21606c3fb27SDimitry Andric }; 21706c3fb27SDimitry Andric 21806c3fb27SDimitry Andric // Namespace deduction. 21906c3fb27SDimitry Andric class LVNamespaceDeduction { 22006c3fb27SDimitry Andric LVShared *Shared = nullptr; 22106c3fb27SDimitry Andric 22206c3fb27SDimitry Andric using Names = std::map<StringRef, LVScope *>; 22306c3fb27SDimitry Andric Names NamespaceNames; 22406c3fb27SDimitry Andric 22506c3fb27SDimitry Andric using LookupSet = std::set<StringRef>; 22606c3fb27SDimitry Andric LookupSet DeducedScopes; 22706c3fb27SDimitry Andric LookupSet UnresolvedScopes; 22806c3fb27SDimitry Andric LookupSet IdentifiedNamespaces; 22906c3fb27SDimitry Andric 23006c3fb27SDimitry Andric void add(StringRef Name, LVScope *Namespace) { 23106c3fb27SDimitry Andric if (NamespaceNames.find(Name) == NamespaceNames.end()) 23206c3fb27SDimitry Andric NamespaceNames.emplace(Name, Namespace); 23306c3fb27SDimitry Andric } 23406c3fb27SDimitry Andric 23506c3fb27SDimitry Andric public: 23606c3fb27SDimitry Andric LVNamespaceDeduction(LVShared *Shared) : Shared(Shared) {} 23706c3fb27SDimitry Andric 23806c3fb27SDimitry Andric void init(); 23906c3fb27SDimitry Andric void add(StringRef String); 24006c3fb27SDimitry Andric LVScope *get(LVStringRefs Components); 24106c3fb27SDimitry Andric LVScope *get(StringRef Name, bool CheckScope = true); 24206c3fb27SDimitry Andric 24306c3fb27SDimitry Andric // Find the logical namespace for the 'Name' component. 24406c3fb27SDimitry Andric LVScope *find(StringRef Name) { 24506c3fb27SDimitry Andric LVScope *Namespace = (NamespaceNames.find(Name) != NamespaceNames.end()) 24606c3fb27SDimitry Andric ? NamespaceNames[Name] 24706c3fb27SDimitry Andric : nullptr; 24806c3fb27SDimitry Andric return Namespace; 24906c3fb27SDimitry Andric } 25006c3fb27SDimitry Andric 25106c3fb27SDimitry Andric // For the given lexical components, return a tuple with the first entry 25206c3fb27SDimitry Andric // being the outermost namespace and the second entry being the first 25306c3fb27SDimitry Andric // non-namespace. 25406c3fb27SDimitry Andric LVLexicalIndex find(LVStringRefs Components) { 25506c3fb27SDimitry Andric if (Components.empty()) 25606c3fb27SDimitry Andric return {}; 25706c3fb27SDimitry Andric 25806c3fb27SDimitry Andric LVStringRefs::size_type FirstNamespace = 0; 25906c3fb27SDimitry Andric LVStringRefs::size_type FirstNonNamespace; 26006c3fb27SDimitry Andric for (LVStringRefs::size_type Index = 0; Index < Components.size(); 26106c3fb27SDimitry Andric ++Index) { 26206c3fb27SDimitry Andric FirstNonNamespace = Index; 26306c3fb27SDimitry Andric LookupSet::iterator Iter = IdentifiedNamespaces.find(Components[Index]); 26406c3fb27SDimitry Andric if (Iter == IdentifiedNamespaces.end()) 26506c3fb27SDimitry Andric // The component is not a namespace name. 26606c3fb27SDimitry Andric break; 26706c3fb27SDimitry Andric } 26806c3fb27SDimitry Andric return std::make_tuple(FirstNamespace, FirstNonNamespace); 26906c3fb27SDimitry Andric } 27006c3fb27SDimitry Andric }; 27106c3fb27SDimitry Andric 27206c3fb27SDimitry Andric // Strings. 27306c3fb27SDimitry Andric class LVStringRecords { 27406c3fb27SDimitry Andric using StringEntry = std::tuple<uint32_t, std::string, LVScopeCompileUnit *>; 27506c3fb27SDimitry Andric using StringIds = std::map<TypeIndex, StringEntry>; 27606c3fb27SDimitry Andric StringIds Strings; 27706c3fb27SDimitry Andric 27806c3fb27SDimitry Andric public: 27906c3fb27SDimitry Andric LVStringRecords() = default; 28006c3fb27SDimitry Andric 28106c3fb27SDimitry Andric void add(TypeIndex TI, StringRef String) { 28206c3fb27SDimitry Andric static uint32_t Index = 0; 28306c3fb27SDimitry Andric if (Strings.find(TI) == Strings.end()) 28406c3fb27SDimitry Andric Strings.emplace( 28506c3fb27SDimitry Andric std::piecewise_construct, std::forward_as_tuple(TI), 28606c3fb27SDimitry Andric std::forward_as_tuple(++Index, std::string(String), nullptr)); 28706c3fb27SDimitry Andric } 28806c3fb27SDimitry Andric 28906c3fb27SDimitry Andric StringRef find(TypeIndex TI) { 29006c3fb27SDimitry Andric StringIds::iterator Iter = Strings.find(TI); 29106c3fb27SDimitry Andric return Iter != Strings.end() ? std::get<1>(Iter->second) : StringRef{}; 29206c3fb27SDimitry Andric } 29306c3fb27SDimitry Andric 29406c3fb27SDimitry Andric uint32_t findIndex(TypeIndex TI) { 29506c3fb27SDimitry Andric StringIds::iterator Iter = Strings.find(TI); 29606c3fb27SDimitry Andric return Iter != Strings.end() ? std::get<0>(Iter->second) : 0; 29706c3fb27SDimitry Andric } 29806c3fb27SDimitry Andric 29906c3fb27SDimitry Andric // Move strings representing the filenames to the compile unit. 30006c3fb27SDimitry Andric void addFilenames(); 30106c3fb27SDimitry Andric void addFilenames(LVScopeCompileUnit *Scope); 30206c3fb27SDimitry Andric }; 30306c3fb27SDimitry Andric } // namespace 30406c3fb27SDimitry Andric 30506c3fb27SDimitry Andric using LVTypeKinds = std::set<TypeLeafKind>; 30606c3fb27SDimitry Andric using LVSymbolKinds = std::set<SymbolKind>; 30706c3fb27SDimitry Andric 30806c3fb27SDimitry Andric // The following data keeps forward information, type records, names for 30906c3fb27SDimitry Andric // namespace deduction, strings records, line records. 31006c3fb27SDimitry Andric // It is shared by the type visitor, symbol visitor and logical visitor and 31106c3fb27SDimitry Andric // it is independent from the CodeViewReader. 31206c3fb27SDimitry Andric struct LVShared { 31306c3fb27SDimitry Andric LVCodeViewReader *Reader; 31406c3fb27SDimitry Andric LVLogicalVisitor *Visitor; 31506c3fb27SDimitry Andric LVForwardReferences ForwardReferences; 31606c3fb27SDimitry Andric LVLineRecords LineRecords; 31706c3fb27SDimitry Andric LVNamespaceDeduction NamespaceDeduction; 31806c3fb27SDimitry Andric LVStringRecords StringRecords; 31906c3fb27SDimitry Andric LVTypeRecords TypeRecords; 32006c3fb27SDimitry Andric 32106c3fb27SDimitry Andric // In order to determine which types and/or symbols records should be handled 32206c3fb27SDimitry Andric // by the reader, we record record kinds seen by the type and symbol visitors. 32306c3fb27SDimitry Andric // At the end of the scopes creation, the '--internal=tag' option will allow 32406c3fb27SDimitry Andric // to print the unique record ids collected. 32506c3fb27SDimitry Andric LVTypeKinds TypeKinds; 32606c3fb27SDimitry Andric LVSymbolKinds SymbolKinds; 32706c3fb27SDimitry Andric 32806c3fb27SDimitry Andric LVShared(LVCodeViewReader *Reader, LVLogicalVisitor *Visitor) 32906c3fb27SDimitry Andric : Reader(Reader), Visitor(Visitor), NamespaceDeduction(this), 33006c3fb27SDimitry Andric TypeRecords(this) {} 33106c3fb27SDimitry Andric ~LVShared() = default; 33206c3fb27SDimitry Andric }; 33306c3fb27SDimitry Andric } // namespace logicalview 33406c3fb27SDimitry Andric } // namespace llvm 33506c3fb27SDimitry Andric 33606c3fb27SDimitry Andric void LVTypeRecords::add(uint32_t StreamIdx, TypeIndex TI, TypeLeafKind Kind, 33706c3fb27SDimitry Andric LVElement *Element) { 33806c3fb27SDimitry Andric RecordTable &Target = 33906c3fb27SDimitry Andric (StreamIdx == StreamTPI) ? RecordFromTypes : RecordFromIds; 34006c3fb27SDimitry Andric Target.emplace(std::piecewise_construct, std::forward_as_tuple(TI), 34106c3fb27SDimitry Andric std::forward_as_tuple(Kind, Element)); 34206c3fb27SDimitry Andric } 34306c3fb27SDimitry Andric 34406c3fb27SDimitry Andric void LVTypeRecords::add(uint32_t StreamIdx, TypeIndex TI, StringRef Name) { 34506c3fb27SDimitry Andric NameTable &Target = (StreamIdx == StreamTPI) ? NameFromTypes : NameFromIds; 34606c3fb27SDimitry Andric Target.emplace(Name, TI); 34706c3fb27SDimitry Andric } 34806c3fb27SDimitry Andric 34906c3fb27SDimitry Andric LVElement *LVTypeRecords::find(uint32_t StreamIdx, TypeIndex TI, bool Create) { 35006c3fb27SDimitry Andric RecordTable &Target = 35106c3fb27SDimitry Andric (StreamIdx == StreamTPI) ? RecordFromTypes : RecordFromIds; 35206c3fb27SDimitry Andric 35306c3fb27SDimitry Andric LVElement *Element = nullptr; 35406c3fb27SDimitry Andric RecordTable::iterator Iter = Target.find(TI); 35506c3fb27SDimitry Andric if (Iter != Target.end()) { 35606c3fb27SDimitry Andric Element = Iter->second.second; 35706c3fb27SDimitry Andric if (Element || !Create) 35806c3fb27SDimitry Andric return Element; 35906c3fb27SDimitry Andric 36006c3fb27SDimitry Andric // Create the logical element if not found. 36106c3fb27SDimitry Andric Element = Shared->Visitor->createElement(Iter->second.first); 36206c3fb27SDimitry Andric if (Element) { 36306c3fb27SDimitry Andric Element->setOffset(TI.getIndex()); 36406c3fb27SDimitry Andric Element->setOffsetFromTypeIndex(); 36506c3fb27SDimitry Andric Target[TI].second = Element; 36606c3fb27SDimitry Andric } 36706c3fb27SDimitry Andric } 36806c3fb27SDimitry Andric return Element; 36906c3fb27SDimitry Andric } 37006c3fb27SDimitry Andric 37106c3fb27SDimitry Andric TypeIndex LVTypeRecords::find(uint32_t StreamIdx, StringRef Name) { 37206c3fb27SDimitry Andric NameTable &Target = (StreamIdx == StreamTPI) ? NameFromTypes : NameFromIds; 37306c3fb27SDimitry Andric NameTable::iterator Iter = Target.find(Name); 37406c3fb27SDimitry Andric return Iter != Target.end() ? Iter->second : TypeIndex::None(); 37506c3fb27SDimitry Andric } 37606c3fb27SDimitry Andric 37706c3fb27SDimitry Andric void LVStringRecords::addFilenames() { 37806c3fb27SDimitry Andric for (StringIds::const_reference Entry : Strings) { 37906c3fb27SDimitry Andric StringRef Name = std::get<1>(Entry.second); 38006c3fb27SDimitry Andric LVScopeCompileUnit *Scope = std::get<2>(Entry.second); 38106c3fb27SDimitry Andric Scope->addFilename(transformPath(Name)); 38206c3fb27SDimitry Andric } 38306c3fb27SDimitry Andric Strings.clear(); 38406c3fb27SDimitry Andric } 38506c3fb27SDimitry Andric 38606c3fb27SDimitry Andric void LVStringRecords::addFilenames(LVScopeCompileUnit *Scope) { 38706c3fb27SDimitry Andric for (StringIds::reference Entry : Strings) 38806c3fb27SDimitry Andric if (!std::get<2>(Entry.second)) 38906c3fb27SDimitry Andric std::get<2>(Entry.second) = Scope; 39006c3fb27SDimitry Andric } 39106c3fb27SDimitry Andric 39206c3fb27SDimitry Andric void LVNamespaceDeduction::add(StringRef String) { 39306c3fb27SDimitry Andric StringRef InnerComponent; 39406c3fb27SDimitry Andric StringRef OuterComponent; 39506c3fb27SDimitry Andric std::tie(OuterComponent, InnerComponent) = getInnerComponent(String); 39606c3fb27SDimitry Andric DeducedScopes.insert(InnerComponent); 39706c3fb27SDimitry Andric if (OuterComponent.size()) 39806c3fb27SDimitry Andric UnresolvedScopes.insert(OuterComponent); 39906c3fb27SDimitry Andric } 40006c3fb27SDimitry Andric 40106c3fb27SDimitry Andric void LVNamespaceDeduction::init() { 40206c3fb27SDimitry Andric // We have 2 sets of names: 40306c3fb27SDimitry Andric // - deduced scopes (class, structure, union and enum) and 40406c3fb27SDimitry Andric // - unresolved scopes, that can represent namespaces or any deduced. 40506c3fb27SDimitry Andric // Before creating the namespaces, we have to traverse the unresolved 40606c3fb27SDimitry Andric // and remove any references to already deduced scopes. 40706c3fb27SDimitry Andric LVStringRefs Components; 40806c3fb27SDimitry Andric for (const StringRef &Unresolved : UnresolvedScopes) { 40906c3fb27SDimitry Andric Components = getAllLexicalComponents(Unresolved); 41006c3fb27SDimitry Andric for (const StringRef &Component : Components) { 41106c3fb27SDimitry Andric LookupSet::iterator Iter = DeducedScopes.find(Component); 41206c3fb27SDimitry Andric if (Iter == DeducedScopes.end()) 41306c3fb27SDimitry Andric IdentifiedNamespaces.insert(Component); 41406c3fb27SDimitry Andric } 41506c3fb27SDimitry Andric } 41606c3fb27SDimitry Andric 41706c3fb27SDimitry Andric LLVM_DEBUG({ 41806c3fb27SDimitry Andric auto Print = [&](LookupSet &Container, const char *Title) { 41906c3fb27SDimitry Andric auto Header = [&]() { 42006c3fb27SDimitry Andric dbgs() << formatv("\n{0}\n", fmt_repeat('=', 72)); 42106c3fb27SDimitry Andric dbgs() << formatv("{0}\n", Title); 42206c3fb27SDimitry Andric dbgs() << formatv("{0}\n", fmt_repeat('=', 72)); 42306c3fb27SDimitry Andric }; 42406c3fb27SDimitry Andric Header(); 42506c3fb27SDimitry Andric for (const StringRef &Item : Container) 42606c3fb27SDimitry Andric dbgs() << formatv("'{0}'\n", Item.str().c_str()); 42706c3fb27SDimitry Andric }; 42806c3fb27SDimitry Andric 42906c3fb27SDimitry Andric Print(DeducedScopes, "Deducted Scopes"); 43006c3fb27SDimitry Andric Print(UnresolvedScopes, "Unresolved Scopes"); 43106c3fb27SDimitry Andric Print(IdentifiedNamespaces, "Namespaces"); 43206c3fb27SDimitry Andric }); 43306c3fb27SDimitry Andric } 43406c3fb27SDimitry Andric 43506c3fb27SDimitry Andric LVScope *LVNamespaceDeduction::get(LVStringRefs Components) { 43606c3fb27SDimitry Andric LLVM_DEBUG({ 43706c3fb27SDimitry Andric for (const StringRef &Component : Components) 43806c3fb27SDimitry Andric dbgs() << formatv("'{0}'\n", Component.str().c_str()); 43906c3fb27SDimitry Andric }); 44006c3fb27SDimitry Andric 44106c3fb27SDimitry Andric if (Components.empty()) 44206c3fb27SDimitry Andric return nullptr; 44306c3fb27SDimitry Andric 44406c3fb27SDimitry Andric // Update the namespaces relationship. 44506c3fb27SDimitry Andric LVScope *Namespace = nullptr; 44606c3fb27SDimitry Andric LVScope *Parent = Shared->Reader->getCompileUnit(); 44706c3fb27SDimitry Andric for (const StringRef &Component : Components) { 44806c3fb27SDimitry Andric // Check if we have seen the namespace. 44906c3fb27SDimitry Andric Namespace = find(Component); 45006c3fb27SDimitry Andric if (!Namespace) { 45106c3fb27SDimitry Andric // We have identified namespaces that are generated by MSVC. Mark them 45206c3fb27SDimitry Andric // as 'system' so they will be excluded from the logical view. 45306c3fb27SDimitry Andric Namespace = Shared->Reader->createScopeNamespace(); 45406c3fb27SDimitry Andric Namespace->setTag(dwarf::DW_TAG_namespace); 45506c3fb27SDimitry Andric Namespace->setName(Component); 45606c3fb27SDimitry Andric Parent->addElement(Namespace); 45706c3fb27SDimitry Andric getReader().isSystemEntry(Namespace); 45806c3fb27SDimitry Andric add(Component, Namespace); 45906c3fb27SDimitry Andric } 46006c3fb27SDimitry Andric Parent = Namespace; 46106c3fb27SDimitry Andric } 46206c3fb27SDimitry Andric return Parent; 46306c3fb27SDimitry Andric } 46406c3fb27SDimitry Andric 46506c3fb27SDimitry Andric LVScope *LVNamespaceDeduction::get(StringRef ScopedName, bool CheckScope) { 46606c3fb27SDimitry Andric LVStringRefs Components = getAllLexicalComponents(ScopedName); 46706c3fb27SDimitry Andric if (CheckScope) 4685f757f3fSDimitry Andric llvm::erase_if(Components, [&](StringRef Component) { 4695f757f3fSDimitry Andric LookupSet::iterator Iter = IdentifiedNamespaces.find(Component); 47006c3fb27SDimitry Andric return Iter == IdentifiedNamespaces.end(); 4715f757f3fSDimitry Andric }); 47206c3fb27SDimitry Andric 47306c3fb27SDimitry Andric LLVM_DEBUG( 47406c3fb27SDimitry Andric { dbgs() << formatv("ScopedName: '{0}'\n", ScopedName.str().c_str()); }); 47506c3fb27SDimitry Andric 47606c3fb27SDimitry Andric return get(Components); 47706c3fb27SDimitry Andric } 47806c3fb27SDimitry Andric 47906c3fb27SDimitry Andric #undef DEBUG_TYPE 48006c3fb27SDimitry Andric #define DEBUG_TYPE "CodeViewTypeVisitor" 48106c3fb27SDimitry Andric 48206c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 48306c3fb27SDimitry Andric // TypeRecord traversal. 48406c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 48506c3fb27SDimitry Andric void LVTypeVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI, 48606c3fb27SDimitry Andric uint32_t StreamIdx) const { 48706c3fb27SDimitry Andric codeview::printTypeIndex(W, FieldName, TI, 48806c3fb27SDimitry Andric StreamIdx == StreamTPI ? Types : Ids); 48906c3fb27SDimitry Andric } 49006c3fb27SDimitry Andric 49106c3fb27SDimitry Andric Error LVTypeVisitor::visitTypeBegin(CVType &Record) { 49206c3fb27SDimitry Andric return visitTypeBegin(Record, TypeIndex::fromArrayIndex(Types.size())); 49306c3fb27SDimitry Andric } 49406c3fb27SDimitry Andric 49506c3fb27SDimitry Andric Error LVTypeVisitor::visitTypeBegin(CVType &Record, TypeIndex TI) { 49606c3fb27SDimitry Andric LLVM_DEBUG({ 49706c3fb27SDimitry Andric W.getOStream() << formatTypeLeafKind(Record.kind()); 49806c3fb27SDimitry Andric W.getOStream() << " (" << HexNumber(TI.getIndex()) << ")\n"; 49906c3fb27SDimitry Andric }); 50006c3fb27SDimitry Andric 50106c3fb27SDimitry Andric if (options().getInternalTag()) 50206c3fb27SDimitry Andric Shared->TypeKinds.insert(Record.kind()); 50306c3fb27SDimitry Andric 50406c3fb27SDimitry Andric // The collected type records, will be use to create the logical elements 50506c3fb27SDimitry Andric // during the symbols traversal when a type is referenced. 50606c3fb27SDimitry Andric CurrentTypeIndex = TI; 50706c3fb27SDimitry Andric Shared->TypeRecords.add(StreamIdx, TI, Record.kind()); 50806c3fb27SDimitry Andric return Error::success(); 50906c3fb27SDimitry Andric } 51006c3fb27SDimitry Andric 51106c3fb27SDimitry Andric Error LVTypeVisitor::visitUnknownType(CVType &Record) { 51206c3fb27SDimitry Andric LLVM_DEBUG({ W.printNumber("Length", uint32_t(Record.content().size())); }); 51306c3fb27SDimitry Andric return Error::success(); 51406c3fb27SDimitry Andric } 51506c3fb27SDimitry Andric 51606c3fb27SDimitry Andric Error LVTypeVisitor::visitMemberBegin(CVMemberRecord &Record) { 51706c3fb27SDimitry Andric LLVM_DEBUG({ 51806c3fb27SDimitry Andric W.startLine() << formatTypeLeafKind(Record.Kind); 51906c3fb27SDimitry Andric W.getOStream() << " {\n"; 52006c3fb27SDimitry Andric W.indent(); 52106c3fb27SDimitry Andric }); 52206c3fb27SDimitry Andric return Error::success(); 52306c3fb27SDimitry Andric } 52406c3fb27SDimitry Andric 52506c3fb27SDimitry Andric Error LVTypeVisitor::visitMemberEnd(CVMemberRecord &Record) { 52606c3fb27SDimitry Andric LLVM_DEBUG({ 52706c3fb27SDimitry Andric W.unindent(); 52806c3fb27SDimitry Andric W.startLine() << "}\n"; 52906c3fb27SDimitry Andric }); 53006c3fb27SDimitry Andric return Error::success(); 53106c3fb27SDimitry Andric } 53206c3fb27SDimitry Andric 53306c3fb27SDimitry Andric Error LVTypeVisitor::visitUnknownMember(CVMemberRecord &Record) { 53406c3fb27SDimitry Andric LLVM_DEBUG({ W.printHex("UnknownMember", unsigned(Record.Kind)); }); 53506c3fb27SDimitry Andric return Error::success(); 53606c3fb27SDimitry Andric } 53706c3fb27SDimitry Andric 53806c3fb27SDimitry Andric // LF_BUILDINFO (TPI)/(IPI) 53906c3fb27SDimitry Andric Error LVTypeVisitor::visitKnownRecord(CVType &Record, BuildInfoRecord &Args) { 54006c3fb27SDimitry Andric // All the args are references into the TPI/IPI stream. 54106c3fb27SDimitry Andric LLVM_DEBUG({ 54206c3fb27SDimitry Andric W.printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size())); 54306c3fb27SDimitry Andric ListScope Arguments(W, "Arguments"); 54406c3fb27SDimitry Andric for (TypeIndex Arg : Args.getArgs()) 54506c3fb27SDimitry Andric printTypeIndex("ArgType", Arg, StreamIPI); 54606c3fb27SDimitry Andric }); 54706c3fb27SDimitry Andric 54806c3fb27SDimitry Andric // Only add the strings that hold information about filenames. They will be 54906c3fb27SDimitry Andric // used to complete the line/file information for the logical elements. 55006c3fb27SDimitry Andric // There are other strings holding information about namespaces. 55106c3fb27SDimitry Andric TypeIndex TI; 55206c3fb27SDimitry Andric StringRef String; 55306c3fb27SDimitry Andric 55406c3fb27SDimitry Andric // Absolute CWD path 55506c3fb27SDimitry Andric TI = Args.getArgs()[BuildInfoRecord::BuildInfoArg::CurrentDirectory]; 55606c3fb27SDimitry Andric String = Ids.getTypeName(TI); 55706c3fb27SDimitry Andric if (!String.empty()) 55806c3fb27SDimitry Andric Shared->StringRecords.add(TI, String); 55906c3fb27SDimitry Andric 56006c3fb27SDimitry Andric // Get the compile unit name. 56106c3fb27SDimitry Andric TI = Args.getArgs()[BuildInfoRecord::BuildInfoArg::SourceFile]; 56206c3fb27SDimitry Andric String = Ids.getTypeName(TI); 56306c3fb27SDimitry Andric if (!String.empty()) 56406c3fb27SDimitry Andric Shared->StringRecords.add(TI, String); 56506c3fb27SDimitry Andric LogicalVisitor->setCompileUnitName(std::string(String)); 56606c3fb27SDimitry Andric 56706c3fb27SDimitry Andric return Error::success(); 56806c3fb27SDimitry Andric } 56906c3fb27SDimitry Andric 57006c3fb27SDimitry Andric // LF_CLASS, LF_STRUCTURE, LF_INTERFACE (TPI) 57106c3fb27SDimitry Andric Error LVTypeVisitor::visitKnownRecord(CVType &Record, ClassRecord &Class) { 57206c3fb27SDimitry Andric LLVM_DEBUG({ 57306c3fb27SDimitry Andric printTypeIndex("TypeIndex", CurrentTypeIndex, StreamTPI); 57406c3fb27SDimitry Andric printTypeIndex("FieldListType", Class.getFieldList(), StreamTPI); 57506c3fb27SDimitry Andric W.printString("Name", Class.getName()); 57606c3fb27SDimitry Andric }); 57706c3fb27SDimitry Andric 57806c3fb27SDimitry Andric // Collect class name for scope deduction. 57906c3fb27SDimitry Andric Shared->NamespaceDeduction.add(Class.getName()); 58006c3fb27SDimitry Andric Shared->ForwardReferences.record(Class.isForwardRef(), Class.getName(), 58106c3fb27SDimitry Andric CurrentTypeIndex); 58206c3fb27SDimitry Andric 58306c3fb27SDimitry Andric // Collect class name for contained scopes deduction. 58406c3fb27SDimitry Andric Shared->TypeRecords.add(StreamIdx, CurrentTypeIndex, Class.getName()); 58506c3fb27SDimitry Andric return Error::success(); 58606c3fb27SDimitry Andric } 58706c3fb27SDimitry Andric 58806c3fb27SDimitry Andric // LF_ENUM (TPI) 58906c3fb27SDimitry Andric Error LVTypeVisitor::visitKnownRecord(CVType &Record, EnumRecord &Enum) { 59006c3fb27SDimitry Andric LLVM_DEBUG({ 59106c3fb27SDimitry Andric printTypeIndex("TypeIndex", CurrentTypeIndex, StreamTPI); 59206c3fb27SDimitry Andric printTypeIndex("FieldListType", Enum.getFieldList(), StreamTPI); 59306c3fb27SDimitry Andric W.printString("Name", Enum.getName()); 59406c3fb27SDimitry Andric }); 59506c3fb27SDimitry Andric 59606c3fb27SDimitry Andric // Collect enum name for scope deduction. 59706c3fb27SDimitry Andric Shared->NamespaceDeduction.add(Enum.getName()); 59806c3fb27SDimitry Andric return Error::success(); 59906c3fb27SDimitry Andric } 60006c3fb27SDimitry Andric 60106c3fb27SDimitry Andric // LF_FUNC_ID (TPI)/(IPI) 60206c3fb27SDimitry Andric Error LVTypeVisitor::visitKnownRecord(CVType &Record, FuncIdRecord &Func) { 60306c3fb27SDimitry Andric LLVM_DEBUG({ 60406c3fb27SDimitry Andric printTypeIndex("TypeIndex", CurrentTypeIndex, StreamTPI); 60506c3fb27SDimitry Andric printTypeIndex("Type", Func.getFunctionType(), StreamTPI); 60606c3fb27SDimitry Andric printTypeIndex("Parent", Func.getParentScope(), StreamTPI); 60706c3fb27SDimitry Andric W.printString("Name", Func.getName()); 60806c3fb27SDimitry Andric }); 60906c3fb27SDimitry Andric 61006c3fb27SDimitry Andric // Collect function name for scope deduction. 61106c3fb27SDimitry Andric Shared->NamespaceDeduction.add(Func.getName()); 61206c3fb27SDimitry Andric return Error::success(); 61306c3fb27SDimitry Andric } 61406c3fb27SDimitry Andric 61506c3fb27SDimitry Andric // LF_PROCEDURE (TPI) 61606c3fb27SDimitry Andric Error LVTypeVisitor::visitKnownRecord(CVType &Record, ProcedureRecord &Proc) { 61706c3fb27SDimitry Andric LLVM_DEBUG({ 61806c3fb27SDimitry Andric printTypeIndex("TypeIndex", CurrentTypeIndex, StreamTPI); 61906c3fb27SDimitry Andric printTypeIndex("ReturnType", Proc.getReturnType(), StreamTPI); 62006c3fb27SDimitry Andric W.printNumber("NumParameters", Proc.getParameterCount()); 62106c3fb27SDimitry Andric printTypeIndex("ArgListType", Proc.getArgumentList(), StreamTPI); 62206c3fb27SDimitry Andric }); 62306c3fb27SDimitry Andric 62406c3fb27SDimitry Andric // Collect procedure information as they can be referenced by typedefs. 62506c3fb27SDimitry Andric Shared->TypeRecords.add(StreamTPI, CurrentTypeIndex, {}); 62606c3fb27SDimitry Andric return Error::success(); 62706c3fb27SDimitry Andric } 62806c3fb27SDimitry Andric 62906c3fb27SDimitry Andric // LF_STRING_ID (TPI)/(IPI) 63006c3fb27SDimitry Andric Error LVTypeVisitor::visitKnownRecord(CVType &Record, StringIdRecord &String) { 63106c3fb27SDimitry Andric // No additional references are needed. 63206c3fb27SDimitry Andric LLVM_DEBUG({ 63306c3fb27SDimitry Andric printTypeIndex("Id", String.getId(), StreamIPI); 63406c3fb27SDimitry Andric W.printString("StringData", String.getString()); 63506c3fb27SDimitry Andric }); 63606c3fb27SDimitry Andric return Error::success(); 63706c3fb27SDimitry Andric } 63806c3fb27SDimitry Andric 63906c3fb27SDimitry Andric // LF_UDT_SRC_LINE (TPI)/(IPI) 64006c3fb27SDimitry Andric Error LVTypeVisitor::visitKnownRecord(CVType &Record, 64106c3fb27SDimitry Andric UdtSourceLineRecord &Line) { 64206c3fb27SDimitry Andric // UDT and SourceFile are references into the TPI/IPI stream. 64306c3fb27SDimitry Andric LLVM_DEBUG({ 64406c3fb27SDimitry Andric printTypeIndex("UDT", Line.getUDT(), StreamIPI); 64506c3fb27SDimitry Andric printTypeIndex("SourceFile", Line.getSourceFile(), StreamIPI); 64606c3fb27SDimitry Andric W.printNumber("LineNumber", Line.getLineNumber()); 64706c3fb27SDimitry Andric }); 64806c3fb27SDimitry Andric 64906c3fb27SDimitry Andric Shared->LineRecords.push_back(CurrentTypeIndex); 65006c3fb27SDimitry Andric return Error::success(); 65106c3fb27SDimitry Andric } 65206c3fb27SDimitry Andric 65306c3fb27SDimitry Andric // LF_UNION (TPI) 65406c3fb27SDimitry Andric Error LVTypeVisitor::visitKnownRecord(CVType &Record, UnionRecord &Union) { 65506c3fb27SDimitry Andric LLVM_DEBUG({ 65606c3fb27SDimitry Andric W.printNumber("MemberCount", Union.getMemberCount()); 65706c3fb27SDimitry Andric printTypeIndex("FieldList", Union.getFieldList(), StreamTPI); 65806c3fb27SDimitry Andric W.printNumber("SizeOf", Union.getSize()); 65906c3fb27SDimitry Andric W.printString("Name", Union.getName()); 66006c3fb27SDimitry Andric if (Union.hasUniqueName()) 66106c3fb27SDimitry Andric W.printString("UniqueName", Union.getUniqueName()); 66206c3fb27SDimitry Andric }); 66306c3fb27SDimitry Andric 66406c3fb27SDimitry Andric // Collect union name for scope deduction. 66506c3fb27SDimitry Andric Shared->NamespaceDeduction.add(Union.getName()); 66606c3fb27SDimitry Andric Shared->ForwardReferences.record(Union.isForwardRef(), Union.getName(), 66706c3fb27SDimitry Andric CurrentTypeIndex); 66806c3fb27SDimitry Andric 66906c3fb27SDimitry Andric // Collect class name for contained scopes deduction. 67006c3fb27SDimitry Andric Shared->TypeRecords.add(StreamIdx, CurrentTypeIndex, Union.getName()); 67106c3fb27SDimitry Andric return Error::success(); 67206c3fb27SDimitry Andric } 67306c3fb27SDimitry Andric 67406c3fb27SDimitry Andric #undef DEBUG_TYPE 67506c3fb27SDimitry Andric #define DEBUG_TYPE "CodeViewSymbolVisitor" 67606c3fb27SDimitry Andric 67706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 67806c3fb27SDimitry Andric // SymbolRecord traversal. 67906c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 68006c3fb27SDimitry Andric void LVSymbolVisitorDelegate::printRelocatedField(StringRef Label, 68106c3fb27SDimitry Andric uint32_t RelocOffset, 68206c3fb27SDimitry Andric uint32_t Offset, 68306c3fb27SDimitry Andric StringRef *RelocSym) { 68406c3fb27SDimitry Andric Reader->printRelocatedField(Label, CoffSection, RelocOffset, Offset, 68506c3fb27SDimitry Andric RelocSym); 68606c3fb27SDimitry Andric } 68706c3fb27SDimitry Andric 68806c3fb27SDimitry Andric void LVSymbolVisitorDelegate::getLinkageName(uint32_t RelocOffset, 68906c3fb27SDimitry Andric uint32_t Offset, 69006c3fb27SDimitry Andric StringRef *RelocSym) { 69106c3fb27SDimitry Andric Reader->getLinkageName(CoffSection, RelocOffset, Offset, RelocSym); 69206c3fb27SDimitry Andric } 69306c3fb27SDimitry Andric 69406c3fb27SDimitry Andric StringRef 69506c3fb27SDimitry Andric LVSymbolVisitorDelegate::getFileNameForFileOffset(uint32_t FileOffset) { 69606c3fb27SDimitry Andric Expected<StringRef> Name = Reader->getFileNameForFileOffset(FileOffset); 69706c3fb27SDimitry Andric if (!Name) { 69806c3fb27SDimitry Andric consumeError(Name.takeError()); 69906c3fb27SDimitry Andric return {}; 70006c3fb27SDimitry Andric } 70106c3fb27SDimitry Andric return *Name; 70206c3fb27SDimitry Andric } 70306c3fb27SDimitry Andric 70406c3fb27SDimitry Andric DebugStringTableSubsectionRef LVSymbolVisitorDelegate::getStringTable() { 70506c3fb27SDimitry Andric return Reader->CVStringTable; 70606c3fb27SDimitry Andric } 70706c3fb27SDimitry Andric 70806c3fb27SDimitry Andric void LVSymbolVisitor::printLocalVariableAddrRange( 70906c3fb27SDimitry Andric const LocalVariableAddrRange &Range, uint32_t RelocationOffset) { 71006c3fb27SDimitry Andric DictScope S(W, "LocalVariableAddrRange"); 71106c3fb27SDimitry Andric if (ObjDelegate) 71206c3fb27SDimitry Andric ObjDelegate->printRelocatedField("OffsetStart", RelocationOffset, 71306c3fb27SDimitry Andric Range.OffsetStart); 71406c3fb27SDimitry Andric W.printHex("ISectStart", Range.ISectStart); 71506c3fb27SDimitry Andric W.printHex("Range", Range.Range); 71606c3fb27SDimitry Andric } 71706c3fb27SDimitry Andric 71806c3fb27SDimitry Andric void LVSymbolVisitor::printLocalVariableAddrGap( 71906c3fb27SDimitry Andric ArrayRef<LocalVariableAddrGap> Gaps) { 72006c3fb27SDimitry Andric for (const LocalVariableAddrGap &Gap : Gaps) { 72106c3fb27SDimitry Andric ListScope S(W, "LocalVariableAddrGap"); 72206c3fb27SDimitry Andric W.printHex("GapStartOffset", Gap.GapStartOffset); 72306c3fb27SDimitry Andric W.printHex("Range", Gap.Range); 72406c3fb27SDimitry Andric } 72506c3fb27SDimitry Andric } 72606c3fb27SDimitry Andric 72706c3fb27SDimitry Andric void LVSymbolVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const { 72806c3fb27SDimitry Andric codeview::printTypeIndex(W, FieldName, TI, Types); 72906c3fb27SDimitry Andric } 73006c3fb27SDimitry Andric 73106c3fb27SDimitry Andric Error LVSymbolVisitor::visitSymbolBegin(CVSymbol &Record) { 73206c3fb27SDimitry Andric return visitSymbolBegin(Record, 0); 73306c3fb27SDimitry Andric } 73406c3fb27SDimitry Andric 73506c3fb27SDimitry Andric Error LVSymbolVisitor::visitSymbolBegin(CVSymbol &Record, uint32_t Offset) { 73606c3fb27SDimitry Andric SymbolKind Kind = Record.kind(); 73706c3fb27SDimitry Andric LLVM_DEBUG({ 73806c3fb27SDimitry Andric W.printNumber("Offset", Offset); 73906c3fb27SDimitry Andric W.printEnum("Begin Kind", unsigned(Kind), getSymbolTypeNames()); 74006c3fb27SDimitry Andric }); 74106c3fb27SDimitry Andric 74206c3fb27SDimitry Andric if (options().getInternalTag()) 74306c3fb27SDimitry Andric Shared->SymbolKinds.insert(Kind); 74406c3fb27SDimitry Andric 74506c3fb27SDimitry Andric LogicalVisitor->CurrentElement = LogicalVisitor->createElement(Kind); 74606c3fb27SDimitry Andric if (!LogicalVisitor->CurrentElement) { 74706c3fb27SDimitry Andric LLVM_DEBUG({ 74806c3fb27SDimitry Andric // We have an unsupported Symbol or Type Record. 74906c3fb27SDimitry Andric // W.printEnum("Kind ignored", unsigned(Kind), getSymbolTypeNames()); 75006c3fb27SDimitry Andric }); 75106c3fb27SDimitry Andric return Error::success(); 75206c3fb27SDimitry Andric } 75306c3fb27SDimitry Andric 75406c3fb27SDimitry Andric // Offset carried by the traversal routines when dealing with streams. 75506c3fb27SDimitry Andric CurrentOffset = Offset; 75606c3fb27SDimitry Andric IsCompileUnit = false; 75706c3fb27SDimitry Andric if (!LogicalVisitor->CurrentElement->getOffsetFromTypeIndex()) 75806c3fb27SDimitry Andric LogicalVisitor->CurrentElement->setOffset(Offset); 75906c3fb27SDimitry Andric if (symbolOpensScope(Kind) || (IsCompileUnit = symbolIsCompileUnit(Kind))) { 76006c3fb27SDimitry Andric assert(LogicalVisitor->CurrentScope && "Invalid scope!"); 76106c3fb27SDimitry Andric LogicalVisitor->addElement(LogicalVisitor->CurrentScope, IsCompileUnit); 76206c3fb27SDimitry Andric } else { 76306c3fb27SDimitry Andric if (LogicalVisitor->CurrentSymbol) 76406c3fb27SDimitry Andric LogicalVisitor->addElement(LogicalVisitor->CurrentSymbol); 76506c3fb27SDimitry Andric if (LogicalVisitor->CurrentType) 76606c3fb27SDimitry Andric LogicalVisitor->addElement(LogicalVisitor->CurrentType); 76706c3fb27SDimitry Andric } 76806c3fb27SDimitry Andric 76906c3fb27SDimitry Andric return Error::success(); 77006c3fb27SDimitry Andric } 77106c3fb27SDimitry Andric 77206c3fb27SDimitry Andric Error LVSymbolVisitor::visitSymbolEnd(CVSymbol &Record) { 77306c3fb27SDimitry Andric SymbolKind Kind = Record.kind(); 77406c3fb27SDimitry Andric LLVM_DEBUG( 77506c3fb27SDimitry Andric { W.printEnum("End Kind", unsigned(Kind), getSymbolTypeNames()); }); 77606c3fb27SDimitry Andric 77706c3fb27SDimitry Andric if (symbolEndsScope(Kind)) { 77806c3fb27SDimitry Andric LogicalVisitor->popScope(); 77906c3fb27SDimitry Andric } 78006c3fb27SDimitry Andric 78106c3fb27SDimitry Andric return Error::success(); 78206c3fb27SDimitry Andric } 78306c3fb27SDimitry Andric 78406c3fb27SDimitry Andric Error LVSymbolVisitor::visitUnknownSymbol(CVSymbol &Record) { 78506c3fb27SDimitry Andric LLVM_DEBUG({ W.printNumber("Length", Record.length()); }); 78606c3fb27SDimitry Andric return Error::success(); 78706c3fb27SDimitry Andric } 78806c3fb27SDimitry Andric 78906c3fb27SDimitry Andric // S_BLOCK32 79006c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, BlockSym &Block) { 79106c3fb27SDimitry Andric LLVM_DEBUG({ 79206c3fb27SDimitry Andric W.printHex("CodeSize", Block.CodeSize); 79306c3fb27SDimitry Andric W.printHex("Segment", Block.Segment); 79406c3fb27SDimitry Andric W.printString("BlockName", Block.Name); 79506c3fb27SDimitry Andric }); 79606c3fb27SDimitry Andric 79706c3fb27SDimitry Andric if (LVScope *Scope = LogicalVisitor->CurrentScope) { 79806c3fb27SDimitry Andric StringRef LinkageName; 79906c3fb27SDimitry Andric if (ObjDelegate) 80006c3fb27SDimitry Andric ObjDelegate->getLinkageName(Block.getRelocationOffset(), Block.CodeOffset, 80106c3fb27SDimitry Andric &LinkageName); 80206c3fb27SDimitry Andric Scope->setLinkageName(LinkageName); 80306c3fb27SDimitry Andric 80406c3fb27SDimitry Andric if (options().getGeneralCollectRanges()) { 80506c3fb27SDimitry Andric // Record converted segment::offset addressing for this scope. 80606c3fb27SDimitry Andric LVAddress Addendum = Reader->getSymbolTableAddress(LinkageName); 80706c3fb27SDimitry Andric LVAddress LowPC = 80806c3fb27SDimitry Andric Reader->linearAddress(Block.Segment, Block.CodeOffset, Addendum); 80906c3fb27SDimitry Andric LVAddress HighPC = LowPC + Block.CodeSize - 1; 81006c3fb27SDimitry Andric Scope->addObject(LowPC, HighPC); 81106c3fb27SDimitry Andric } 81206c3fb27SDimitry Andric } 81306c3fb27SDimitry Andric 81406c3fb27SDimitry Andric return Error::success(); 81506c3fb27SDimitry Andric } 81606c3fb27SDimitry Andric 81706c3fb27SDimitry Andric // S_BPREL32 81806c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, 81906c3fb27SDimitry Andric BPRelativeSym &Local) { 82006c3fb27SDimitry Andric LLVM_DEBUG({ 82106c3fb27SDimitry Andric printTypeIndex("Type", Local.Type); 82206c3fb27SDimitry Andric W.printNumber("Offset", Local.Offset); 82306c3fb27SDimitry Andric W.printString("VarName", Local.Name); 82406c3fb27SDimitry Andric }); 82506c3fb27SDimitry Andric 82606c3fb27SDimitry Andric if (LVSymbol *Symbol = LogicalVisitor->CurrentSymbol) { 82706c3fb27SDimitry Andric Symbol->setName(Local.Name); 82806c3fb27SDimitry Andric // From the MS_Symbol_Type.pdf documentation (S_BPREL32): 82906c3fb27SDimitry Andric // This symbol specifies symbols that are allocated on the stack for a 83006c3fb27SDimitry Andric // procedure. For C and C++, these include the actual function parameters 83106c3fb27SDimitry Andric // and the local non-static variables of functions. 83206c3fb27SDimitry Andric // However, the offset for 'this' comes as a negative value. 83306c3fb27SDimitry Andric 83406c3fb27SDimitry Andric // Symbol was created as 'variable'; determine its real kind. 83506c3fb27SDimitry Andric Symbol->resetIsVariable(); 83606c3fb27SDimitry Andric 837*0fca6ea1SDimitry Andric if (Local.Name == "this") { 83806c3fb27SDimitry Andric Symbol->setIsParameter(); 83906c3fb27SDimitry Andric Symbol->setIsArtificial(); 84006c3fb27SDimitry Andric } else { 84106c3fb27SDimitry Andric // Determine symbol kind. 84206c3fb27SDimitry Andric bool(Local.Offset > 0) ? Symbol->setIsParameter() 84306c3fb27SDimitry Andric : Symbol->setIsVariable(); 84406c3fb27SDimitry Andric } 84506c3fb27SDimitry Andric 84606c3fb27SDimitry Andric // Update correct debug information tag. 84706c3fb27SDimitry Andric if (Symbol->getIsParameter()) 84806c3fb27SDimitry Andric Symbol->setTag(dwarf::DW_TAG_formal_parameter); 84906c3fb27SDimitry Andric 85006c3fb27SDimitry Andric LVElement *Element = LogicalVisitor->getElement(StreamTPI, Local.Type); 85106c3fb27SDimitry Andric if (Element && Element->getIsScoped()) { 85206c3fb27SDimitry Andric // We have a local type. Find its parent function. 85306c3fb27SDimitry Andric LVScope *Parent = Symbol->getFunctionParent(); 85406c3fb27SDimitry Andric // The element representing the type has been already finalized. If 85506c3fb27SDimitry Andric // the type is an aggregate type, its members have been already added. 85606c3fb27SDimitry Andric // As the type is local, its level will be changed. 85706c3fb27SDimitry Andric 85806c3fb27SDimitry Andric // FIXME: Currently the algorithm used to scope lambda functions is 85906c3fb27SDimitry Andric // incorrect. Before we allocate the type at this scope, check if is 86006c3fb27SDimitry Andric // already allocated in other scope. 86106c3fb27SDimitry Andric if (!Element->getParentScope()) { 86206c3fb27SDimitry Andric Parent->addElement(Element); 86306c3fb27SDimitry Andric Element->updateLevel(Parent); 86406c3fb27SDimitry Andric } 86506c3fb27SDimitry Andric } 86606c3fb27SDimitry Andric Symbol->setType(Element); 86706c3fb27SDimitry Andric } 86806c3fb27SDimitry Andric 86906c3fb27SDimitry Andric return Error::success(); 87006c3fb27SDimitry Andric } 87106c3fb27SDimitry Andric 87206c3fb27SDimitry Andric // S_REGREL32 87306c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, 87406c3fb27SDimitry Andric RegRelativeSym &Local) { 87506c3fb27SDimitry Andric LLVM_DEBUG({ 87606c3fb27SDimitry Andric printTypeIndex("Type", Local.Type); 87706c3fb27SDimitry Andric W.printNumber("Offset", Local.Offset); 87806c3fb27SDimitry Andric W.printString("VarName", Local.Name); 87906c3fb27SDimitry Andric }); 88006c3fb27SDimitry Andric 88106c3fb27SDimitry Andric if (LVSymbol *Symbol = LogicalVisitor->CurrentSymbol) { 88206c3fb27SDimitry Andric Symbol->setName(Local.Name); 88306c3fb27SDimitry Andric 88406c3fb27SDimitry Andric // Symbol was created as 'variable'; determine its real kind. 88506c3fb27SDimitry Andric Symbol->resetIsVariable(); 88606c3fb27SDimitry Andric 88706c3fb27SDimitry Andric // Check for the 'this' symbol. 888*0fca6ea1SDimitry Andric if (Local.Name == "this") { 88906c3fb27SDimitry Andric Symbol->setIsArtificial(); 89006c3fb27SDimitry Andric Symbol->setIsParameter(); 89106c3fb27SDimitry Andric } else { 89206c3fb27SDimitry Andric // Determine symbol kind. 89306c3fb27SDimitry Andric determineSymbolKind(Symbol, Local.Register); 89406c3fb27SDimitry Andric } 89506c3fb27SDimitry Andric 89606c3fb27SDimitry Andric // Update correct debug information tag. 89706c3fb27SDimitry Andric if (Symbol->getIsParameter()) 89806c3fb27SDimitry Andric Symbol->setTag(dwarf::DW_TAG_formal_parameter); 89906c3fb27SDimitry Andric 90006c3fb27SDimitry Andric LVElement *Element = LogicalVisitor->getElement(StreamTPI, Local.Type); 90106c3fb27SDimitry Andric if (Element && Element->getIsScoped()) { 90206c3fb27SDimitry Andric // We have a local type. Find its parent function. 90306c3fb27SDimitry Andric LVScope *Parent = Symbol->getFunctionParent(); 90406c3fb27SDimitry Andric // The element representing the type has been already finalized. If 90506c3fb27SDimitry Andric // the type is an aggregate type, its members have been already added. 90606c3fb27SDimitry Andric // As the type is local, its level will be changed. 90706c3fb27SDimitry Andric 90806c3fb27SDimitry Andric // FIXME: Currently the algorithm used to scope lambda functions is 90906c3fb27SDimitry Andric // incorrect. Before we allocate the type at this scope, check if is 91006c3fb27SDimitry Andric // already allocated in other scope. 91106c3fb27SDimitry Andric if (!Element->getParentScope()) { 91206c3fb27SDimitry Andric Parent->addElement(Element); 91306c3fb27SDimitry Andric Element->updateLevel(Parent); 91406c3fb27SDimitry Andric } 91506c3fb27SDimitry Andric } 91606c3fb27SDimitry Andric Symbol->setType(Element); 91706c3fb27SDimitry Andric } 91806c3fb27SDimitry Andric 91906c3fb27SDimitry Andric return Error::success(); 92006c3fb27SDimitry Andric } 92106c3fb27SDimitry Andric 92206c3fb27SDimitry Andric // S_BUILDINFO 92306c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &CVR, 92406c3fb27SDimitry Andric BuildInfoSym &BuildInfo) { 92506c3fb27SDimitry Andric LLVM_DEBUG({ printTypeIndex("BuildId", BuildInfo.BuildId); }); 92606c3fb27SDimitry Andric 92706c3fb27SDimitry Andric CVType CVBuildType = Ids.getType(BuildInfo.BuildId); 92806c3fb27SDimitry Andric if (Error Err = LogicalVisitor->finishVisitation( 92906c3fb27SDimitry Andric CVBuildType, BuildInfo.BuildId, Reader->getCompileUnit())) 93006c3fb27SDimitry Andric return Err; 93106c3fb27SDimitry Andric 93206c3fb27SDimitry Andric return Error::success(); 93306c3fb27SDimitry Andric } 93406c3fb27SDimitry Andric 93506c3fb27SDimitry Andric // S_COMPILE2 93606c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, 93706c3fb27SDimitry Andric Compile2Sym &Compile2) { 93806c3fb27SDimitry Andric LLVM_DEBUG({ 93906c3fb27SDimitry Andric W.printEnum("Language", uint8_t(Compile2.getLanguage()), 94006c3fb27SDimitry Andric getSourceLanguageNames()); 94106c3fb27SDimitry Andric W.printFlags("Flags", uint32_t(Compile2.getFlags()), 94206c3fb27SDimitry Andric getCompileSym3FlagNames()); 94306c3fb27SDimitry Andric W.printEnum("Machine", unsigned(Compile2.Machine), getCPUTypeNames()); 94406c3fb27SDimitry Andric W.printString("VersionName", Compile2.Version); 94506c3fb27SDimitry Andric }); 94606c3fb27SDimitry Andric 94706c3fb27SDimitry Andric // MSVC generates the following sequence for a CodeView module: 94806c3fb27SDimitry Andric // S_OBJNAME --> Set 'CurrentObjectName'. 94906c3fb27SDimitry Andric // S_COMPILE2 --> Set the compile unit name using 'CurrentObjectName'. 95006c3fb27SDimitry Andric // ... 95106c3fb27SDimitry Andric // S_BUILDINFO --> Extract the source name. 95206c3fb27SDimitry Andric // 95306c3fb27SDimitry Andric // Clang generates the following sequence for a CodeView module: 95406c3fb27SDimitry Andric // S_COMPILE2 --> Set the compile unit name to empty string. 95506c3fb27SDimitry Andric // ... 95606c3fb27SDimitry Andric // S_BUILDINFO --> Extract the source name. 95706c3fb27SDimitry Andric // 95806c3fb27SDimitry Andric // For both toolchains, update the compile unit name from S_BUILDINFO. 95906c3fb27SDimitry Andric if (LVScope *Scope = LogicalVisitor->CurrentScope) { 96006c3fb27SDimitry Andric // The name of the CU, was extracted from the 'BuildInfo' subsection. 96106c3fb27SDimitry Andric Reader->setCompileUnitCPUType(Compile2.Machine); 96206c3fb27SDimitry Andric Scope->setName(CurrentObjectName); 96306c3fb27SDimitry Andric if (options().getAttributeProducer()) 96406c3fb27SDimitry Andric Scope->setProducer(Compile2.Version); 96506c3fb27SDimitry Andric getReader().isSystemEntry(Scope, CurrentObjectName); 96606c3fb27SDimitry Andric 96706c3fb27SDimitry Andric // The line records in CodeView are recorded per Module ID. Update 96806c3fb27SDimitry Andric // the relationship between the current CU and the Module ID. 96906c3fb27SDimitry Andric Reader->addModule(Scope); 97006c3fb27SDimitry Andric 97106c3fb27SDimitry Andric // Updated the collected strings with their associated compile unit. 97206c3fb27SDimitry Andric Shared->StringRecords.addFilenames(Reader->getCompileUnit()); 97306c3fb27SDimitry Andric } 97406c3fb27SDimitry Andric 97506c3fb27SDimitry Andric // Clear any previous ObjectName. 97606c3fb27SDimitry Andric CurrentObjectName = ""; 97706c3fb27SDimitry Andric return Error::success(); 97806c3fb27SDimitry Andric } 97906c3fb27SDimitry Andric 98006c3fb27SDimitry Andric // S_COMPILE3 98106c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, 98206c3fb27SDimitry Andric Compile3Sym &Compile3) { 98306c3fb27SDimitry Andric LLVM_DEBUG({ 98406c3fb27SDimitry Andric W.printEnum("Language", uint8_t(Compile3.getLanguage()), 98506c3fb27SDimitry Andric getSourceLanguageNames()); 98606c3fb27SDimitry Andric W.printFlags("Flags", uint32_t(Compile3.getFlags()), 98706c3fb27SDimitry Andric getCompileSym3FlagNames()); 98806c3fb27SDimitry Andric W.printEnum("Machine", unsigned(Compile3.Machine), getCPUTypeNames()); 98906c3fb27SDimitry Andric W.printString("VersionName", Compile3.Version); 99006c3fb27SDimitry Andric }); 99106c3fb27SDimitry Andric 99206c3fb27SDimitry Andric // MSVC generates the following sequence for a CodeView module: 99306c3fb27SDimitry Andric // S_OBJNAME --> Set 'CurrentObjectName'. 99406c3fb27SDimitry Andric // S_COMPILE3 --> Set the compile unit name using 'CurrentObjectName'. 99506c3fb27SDimitry Andric // ... 99606c3fb27SDimitry Andric // S_BUILDINFO --> Extract the source name. 99706c3fb27SDimitry Andric // 99806c3fb27SDimitry Andric // Clang generates the following sequence for a CodeView module: 99906c3fb27SDimitry Andric // S_COMPILE3 --> Set the compile unit name to empty string. 100006c3fb27SDimitry Andric // ... 100106c3fb27SDimitry Andric // S_BUILDINFO --> Extract the source name. 100206c3fb27SDimitry Andric // 100306c3fb27SDimitry Andric // For both toolchains, update the compile unit name from S_BUILDINFO. 100406c3fb27SDimitry Andric if (LVScope *Scope = LogicalVisitor->CurrentScope) { 100506c3fb27SDimitry Andric // The name of the CU, was extracted from the 'BuildInfo' subsection. 100606c3fb27SDimitry Andric Reader->setCompileUnitCPUType(Compile3.Machine); 100706c3fb27SDimitry Andric Scope->setName(CurrentObjectName); 100806c3fb27SDimitry Andric if (options().getAttributeProducer()) 100906c3fb27SDimitry Andric Scope->setProducer(Compile3.Version); 101006c3fb27SDimitry Andric getReader().isSystemEntry(Scope, CurrentObjectName); 101106c3fb27SDimitry Andric 101206c3fb27SDimitry Andric // The line records in CodeView are recorded per Module ID. Update 101306c3fb27SDimitry Andric // the relationship between the current CU and the Module ID. 101406c3fb27SDimitry Andric Reader->addModule(Scope); 101506c3fb27SDimitry Andric 101606c3fb27SDimitry Andric // Updated the collected strings with their associated compile unit. 101706c3fb27SDimitry Andric Shared->StringRecords.addFilenames(Reader->getCompileUnit()); 101806c3fb27SDimitry Andric } 101906c3fb27SDimitry Andric 102006c3fb27SDimitry Andric // Clear any previous ObjectName. 102106c3fb27SDimitry Andric CurrentObjectName = ""; 102206c3fb27SDimitry Andric return Error::success(); 102306c3fb27SDimitry Andric } 102406c3fb27SDimitry Andric 102506c3fb27SDimitry Andric // S_CONSTANT, S_MANCONSTANT 102606c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, 102706c3fb27SDimitry Andric ConstantSym &Constant) { 102806c3fb27SDimitry Andric LLVM_DEBUG({ 102906c3fb27SDimitry Andric printTypeIndex("Type", Constant.Type); 103006c3fb27SDimitry Andric W.printNumber("Value", Constant.Value); 103106c3fb27SDimitry Andric W.printString("Name", Constant.Name); 103206c3fb27SDimitry Andric }); 103306c3fb27SDimitry Andric 103406c3fb27SDimitry Andric if (LVSymbol *Symbol = LogicalVisitor->CurrentSymbol) { 103506c3fb27SDimitry Andric Symbol->setName(Constant.Name); 103606c3fb27SDimitry Andric Symbol->setType(LogicalVisitor->getElement(StreamTPI, Constant.Type)); 103706c3fb27SDimitry Andric Symbol->resetIncludeInPrint(); 103806c3fb27SDimitry Andric } 103906c3fb27SDimitry Andric 104006c3fb27SDimitry Andric return Error::success(); 104106c3fb27SDimitry Andric } 104206c3fb27SDimitry Andric 104306c3fb27SDimitry Andric // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE 104406c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord( 104506c3fb27SDimitry Andric CVSymbol &Record, 104606c3fb27SDimitry Andric DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) { 104706c3fb27SDimitry Andric // DefRanges don't have types, just registers and code offsets. 104806c3fb27SDimitry Andric LLVM_DEBUG({ 104906c3fb27SDimitry Andric if (LocalSymbol) 105006c3fb27SDimitry Andric W.getOStream() << formatv("Symbol: {0}, ", LocalSymbol->getName()); 105106c3fb27SDimitry Andric 105206c3fb27SDimitry Andric W.printNumber("Offset", DefRangeFramePointerRelFullScope.Offset); 105306c3fb27SDimitry Andric }); 105406c3fb27SDimitry Andric 105506c3fb27SDimitry Andric if (LVSymbol *Symbol = LocalSymbol) { 105606c3fb27SDimitry Andric Symbol->setHasCodeViewLocation(); 105706c3fb27SDimitry Andric LocalSymbol = nullptr; 105806c3fb27SDimitry Andric 105906c3fb27SDimitry Andric // Add location debug location. Operands: [Offset, 0]. 106006c3fb27SDimitry Andric dwarf::Attribute Attr = 106106c3fb27SDimitry Andric dwarf::Attribute(SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE); 106206c3fb27SDimitry Andric 106306c3fb27SDimitry Andric uint64_t Operand1 = DefRangeFramePointerRelFullScope.Offset; 106406c3fb27SDimitry Andric Symbol->addLocation(Attr, 0, 0, 0, 0); 106506c3fb27SDimitry Andric Symbol->addLocationOperands(LVSmall(Attr), {Operand1}); 106606c3fb27SDimitry Andric } 106706c3fb27SDimitry Andric 106806c3fb27SDimitry Andric return Error::success(); 106906c3fb27SDimitry Andric } 107006c3fb27SDimitry Andric 107106c3fb27SDimitry Andric // S_DEFRANGE_FRAMEPOINTER_REL 107206c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord( 107306c3fb27SDimitry Andric CVSymbol &Record, DefRangeFramePointerRelSym &DefRangeFramePointerRel) { 107406c3fb27SDimitry Andric // DefRanges don't have types, just registers and code offsets. 107506c3fb27SDimitry Andric LLVM_DEBUG({ 107606c3fb27SDimitry Andric if (LocalSymbol) 107706c3fb27SDimitry Andric W.getOStream() << formatv("Symbol: {0}, ", LocalSymbol->getName()); 107806c3fb27SDimitry Andric 107906c3fb27SDimitry Andric W.printNumber("Offset", DefRangeFramePointerRel.Hdr.Offset); 108006c3fb27SDimitry Andric printLocalVariableAddrRange(DefRangeFramePointerRel.Range, 108106c3fb27SDimitry Andric DefRangeFramePointerRel.getRelocationOffset()); 108206c3fb27SDimitry Andric printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps); 108306c3fb27SDimitry Andric }); 108406c3fb27SDimitry Andric 108506c3fb27SDimitry Andric // We are expecting the following sequence: 108606c3fb27SDimitry Andric // 128 | S_LOCAL [size = 20] `ParamBar` 108706c3fb27SDimitry Andric // ... 108806c3fb27SDimitry Andric // 148 | S_DEFRANGE_FRAMEPOINTER_REL [size = 16] 108906c3fb27SDimitry Andric if (LVSymbol *Symbol = LocalSymbol) { 109006c3fb27SDimitry Andric Symbol->setHasCodeViewLocation(); 109106c3fb27SDimitry Andric LocalSymbol = nullptr; 109206c3fb27SDimitry Andric 109306c3fb27SDimitry Andric // Add location debug location. Operands: [Offset, 0]. 109406c3fb27SDimitry Andric dwarf::Attribute Attr = 109506c3fb27SDimitry Andric dwarf::Attribute(SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL); 109606c3fb27SDimitry Andric uint64_t Operand1 = DefRangeFramePointerRel.Hdr.Offset; 109706c3fb27SDimitry Andric 109806c3fb27SDimitry Andric LocalVariableAddrRange Range = DefRangeFramePointerRel.Range; 109906c3fb27SDimitry Andric LVAddress Address = 110006c3fb27SDimitry Andric Reader->linearAddress(Range.ISectStart, Range.OffsetStart); 110106c3fb27SDimitry Andric 110206c3fb27SDimitry Andric Symbol->addLocation(Attr, Address, Address + Range.Range, 0, 0); 110306c3fb27SDimitry Andric Symbol->addLocationOperands(LVSmall(Attr), {Operand1}); 110406c3fb27SDimitry Andric } 110506c3fb27SDimitry Andric 110606c3fb27SDimitry Andric return Error::success(); 110706c3fb27SDimitry Andric } 110806c3fb27SDimitry Andric 110906c3fb27SDimitry Andric // S_DEFRANGE_REGISTER_REL 111006c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord( 111106c3fb27SDimitry Andric CVSymbol &Record, DefRangeRegisterRelSym &DefRangeRegisterRel) { 111206c3fb27SDimitry Andric // DefRanges don't have types, just registers and code offsets. 111306c3fb27SDimitry Andric LLVM_DEBUG({ 111406c3fb27SDimitry Andric if (LocalSymbol) 111506c3fb27SDimitry Andric W.getOStream() << formatv("Symbol: {0}, ", LocalSymbol->getName()); 111606c3fb27SDimitry Andric 111706c3fb27SDimitry Andric W.printBoolean("HasSpilledUDTMember", 111806c3fb27SDimitry Andric DefRangeRegisterRel.hasSpilledUDTMember()); 111906c3fb27SDimitry Andric W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent()); 112006c3fb27SDimitry Andric W.printNumber("BasePointerOffset", 112106c3fb27SDimitry Andric DefRangeRegisterRel.Hdr.BasePointerOffset); 112206c3fb27SDimitry Andric printLocalVariableAddrRange(DefRangeRegisterRel.Range, 112306c3fb27SDimitry Andric DefRangeRegisterRel.getRelocationOffset()); 112406c3fb27SDimitry Andric printLocalVariableAddrGap(DefRangeRegisterRel.Gaps); 112506c3fb27SDimitry Andric }); 112606c3fb27SDimitry Andric 112706c3fb27SDimitry Andric if (LVSymbol *Symbol = LocalSymbol) { 112806c3fb27SDimitry Andric Symbol->setHasCodeViewLocation(); 112906c3fb27SDimitry Andric LocalSymbol = nullptr; 113006c3fb27SDimitry Andric 113106c3fb27SDimitry Andric // Add location debug location. Operands: [Register, Offset]. 113206c3fb27SDimitry Andric dwarf::Attribute Attr = 113306c3fb27SDimitry Andric dwarf::Attribute(SymbolKind::S_DEFRANGE_REGISTER_REL); 113406c3fb27SDimitry Andric uint64_t Operand1 = DefRangeRegisterRel.Hdr.Register; 113506c3fb27SDimitry Andric uint64_t Operand2 = DefRangeRegisterRel.Hdr.BasePointerOffset; 113606c3fb27SDimitry Andric 113706c3fb27SDimitry Andric LocalVariableAddrRange Range = DefRangeRegisterRel.Range; 113806c3fb27SDimitry Andric LVAddress Address = 113906c3fb27SDimitry Andric Reader->linearAddress(Range.ISectStart, Range.OffsetStart); 114006c3fb27SDimitry Andric 114106c3fb27SDimitry Andric Symbol->addLocation(Attr, Address, Address + Range.Range, 0, 0); 114206c3fb27SDimitry Andric Symbol->addLocationOperands(LVSmall(Attr), {Operand1, Operand2}); 114306c3fb27SDimitry Andric } 114406c3fb27SDimitry Andric 114506c3fb27SDimitry Andric return Error::success(); 114606c3fb27SDimitry Andric } 114706c3fb27SDimitry Andric 114806c3fb27SDimitry Andric // S_DEFRANGE_REGISTER 114906c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, 115006c3fb27SDimitry Andric DefRangeRegisterSym &DefRangeRegister) { 115106c3fb27SDimitry Andric // DefRanges don't have types, just registers and code offsets. 115206c3fb27SDimitry Andric LLVM_DEBUG({ 115306c3fb27SDimitry Andric if (LocalSymbol) 115406c3fb27SDimitry Andric W.getOStream() << formatv("Symbol: {0}, ", LocalSymbol->getName()); 115506c3fb27SDimitry Andric 115606c3fb27SDimitry Andric W.printEnum("Register", uint16_t(DefRangeRegister.Hdr.Register), 115706c3fb27SDimitry Andric getRegisterNames(Reader->getCompileUnitCPUType())); 115806c3fb27SDimitry Andric W.printNumber("MayHaveNoName", DefRangeRegister.Hdr.MayHaveNoName); 115906c3fb27SDimitry Andric printLocalVariableAddrRange(DefRangeRegister.Range, 116006c3fb27SDimitry Andric DefRangeRegister.getRelocationOffset()); 116106c3fb27SDimitry Andric printLocalVariableAddrGap(DefRangeRegister.Gaps); 116206c3fb27SDimitry Andric }); 116306c3fb27SDimitry Andric 116406c3fb27SDimitry Andric if (LVSymbol *Symbol = LocalSymbol) { 116506c3fb27SDimitry Andric Symbol->setHasCodeViewLocation(); 116606c3fb27SDimitry Andric LocalSymbol = nullptr; 116706c3fb27SDimitry Andric 116806c3fb27SDimitry Andric // Add location debug location. Operands: [Register, 0]. 116906c3fb27SDimitry Andric dwarf::Attribute Attr = dwarf::Attribute(SymbolKind::S_DEFRANGE_REGISTER); 117006c3fb27SDimitry Andric uint64_t Operand1 = DefRangeRegister.Hdr.Register; 117106c3fb27SDimitry Andric 117206c3fb27SDimitry Andric LocalVariableAddrRange Range = DefRangeRegister.Range; 117306c3fb27SDimitry Andric LVAddress Address = 117406c3fb27SDimitry Andric Reader->linearAddress(Range.ISectStart, Range.OffsetStart); 117506c3fb27SDimitry Andric 117606c3fb27SDimitry Andric Symbol->addLocation(Attr, Address, Address + Range.Range, 0, 0); 117706c3fb27SDimitry Andric Symbol->addLocationOperands(LVSmall(Attr), {Operand1}); 117806c3fb27SDimitry Andric } 117906c3fb27SDimitry Andric 118006c3fb27SDimitry Andric return Error::success(); 118106c3fb27SDimitry Andric } 118206c3fb27SDimitry Andric 118306c3fb27SDimitry Andric // S_DEFRANGE_SUBFIELD_REGISTER 118406c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord( 118506c3fb27SDimitry Andric CVSymbol &Record, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) { 118606c3fb27SDimitry Andric // DefRanges don't have types, just registers and code offsets. 118706c3fb27SDimitry Andric LLVM_DEBUG({ 118806c3fb27SDimitry Andric if (LocalSymbol) 118906c3fb27SDimitry Andric W.getOStream() << formatv("Symbol: {0}, ", LocalSymbol->getName()); 119006c3fb27SDimitry Andric 119106c3fb27SDimitry Andric W.printEnum("Register", uint16_t(DefRangeSubfieldRegister.Hdr.Register), 119206c3fb27SDimitry Andric getRegisterNames(Reader->getCompileUnitCPUType())); 119306c3fb27SDimitry Andric W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Hdr.MayHaveNoName); 119406c3fb27SDimitry Andric W.printNumber("OffsetInParent", 119506c3fb27SDimitry Andric DefRangeSubfieldRegister.Hdr.OffsetInParent); 119606c3fb27SDimitry Andric printLocalVariableAddrRange(DefRangeSubfieldRegister.Range, 119706c3fb27SDimitry Andric DefRangeSubfieldRegister.getRelocationOffset()); 119806c3fb27SDimitry Andric printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps); 119906c3fb27SDimitry Andric }); 120006c3fb27SDimitry Andric 120106c3fb27SDimitry Andric if (LVSymbol *Symbol = LocalSymbol) { 120206c3fb27SDimitry Andric Symbol->setHasCodeViewLocation(); 120306c3fb27SDimitry Andric LocalSymbol = nullptr; 120406c3fb27SDimitry Andric 120506c3fb27SDimitry Andric // Add location debug location. Operands: [Register, 0]. 120606c3fb27SDimitry Andric dwarf::Attribute Attr = 120706c3fb27SDimitry Andric dwarf::Attribute(SymbolKind::S_DEFRANGE_SUBFIELD_REGISTER); 120806c3fb27SDimitry Andric uint64_t Operand1 = DefRangeSubfieldRegister.Hdr.Register; 120906c3fb27SDimitry Andric 121006c3fb27SDimitry Andric LocalVariableAddrRange Range = DefRangeSubfieldRegister.Range; 121106c3fb27SDimitry Andric LVAddress Address = 121206c3fb27SDimitry Andric Reader->linearAddress(Range.ISectStart, Range.OffsetStart); 121306c3fb27SDimitry Andric 121406c3fb27SDimitry Andric Symbol->addLocation(Attr, Address, Address + Range.Range, 0, 0); 121506c3fb27SDimitry Andric Symbol->addLocationOperands(LVSmall(Attr), {Operand1}); 121606c3fb27SDimitry Andric } 121706c3fb27SDimitry Andric 121806c3fb27SDimitry Andric return Error::success(); 121906c3fb27SDimitry Andric } 122006c3fb27SDimitry Andric 122106c3fb27SDimitry Andric // S_DEFRANGE_SUBFIELD 122206c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, 122306c3fb27SDimitry Andric DefRangeSubfieldSym &DefRangeSubfield) { 122406c3fb27SDimitry Andric // DefRanges don't have types, just registers and code offsets. 122506c3fb27SDimitry Andric LLVM_DEBUG({ 122606c3fb27SDimitry Andric if (LocalSymbol) 122706c3fb27SDimitry Andric W.getOStream() << formatv("Symbol: {0}, ", LocalSymbol->getName()); 122806c3fb27SDimitry Andric 122906c3fb27SDimitry Andric if (ObjDelegate) { 123006c3fb27SDimitry Andric DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable(); 123106c3fb27SDimitry Andric auto ExpectedProgram = Strings.getString(DefRangeSubfield.Program); 123206c3fb27SDimitry Andric if (!ExpectedProgram) { 123306c3fb27SDimitry Andric consumeError(ExpectedProgram.takeError()); 123406c3fb27SDimitry Andric return llvm::make_error<CodeViewError>( 123506c3fb27SDimitry Andric "String table offset outside of bounds of String Table!"); 123606c3fb27SDimitry Andric } 123706c3fb27SDimitry Andric W.printString("Program", *ExpectedProgram); 123806c3fb27SDimitry Andric } 123906c3fb27SDimitry Andric W.printNumber("OffsetInParent", DefRangeSubfield.OffsetInParent); 124006c3fb27SDimitry Andric printLocalVariableAddrRange(DefRangeSubfield.Range, 124106c3fb27SDimitry Andric DefRangeSubfield.getRelocationOffset()); 124206c3fb27SDimitry Andric printLocalVariableAddrGap(DefRangeSubfield.Gaps); 124306c3fb27SDimitry Andric }); 124406c3fb27SDimitry Andric 124506c3fb27SDimitry Andric if (LVSymbol *Symbol = LocalSymbol) { 124606c3fb27SDimitry Andric Symbol->setHasCodeViewLocation(); 124706c3fb27SDimitry Andric LocalSymbol = nullptr; 124806c3fb27SDimitry Andric 124906c3fb27SDimitry Andric // Add location debug location. Operands: [Program, 0]. 125006c3fb27SDimitry Andric dwarf::Attribute Attr = dwarf::Attribute(SymbolKind::S_DEFRANGE_SUBFIELD); 125106c3fb27SDimitry Andric uint64_t Operand1 = DefRangeSubfield.Program; 125206c3fb27SDimitry Andric 125306c3fb27SDimitry Andric LocalVariableAddrRange Range = DefRangeSubfield.Range; 125406c3fb27SDimitry Andric LVAddress Address = 125506c3fb27SDimitry Andric Reader->linearAddress(Range.ISectStart, Range.OffsetStart); 125606c3fb27SDimitry Andric 125706c3fb27SDimitry Andric Symbol->addLocation(Attr, Address, Address + Range.Range, 0, 0); 125806c3fb27SDimitry Andric Symbol->addLocationOperands(LVSmall(Attr), {Operand1, /*Operand2=*/0}); 125906c3fb27SDimitry Andric } 126006c3fb27SDimitry Andric 126106c3fb27SDimitry Andric return Error::success(); 126206c3fb27SDimitry Andric } 126306c3fb27SDimitry Andric 126406c3fb27SDimitry Andric // S_DEFRANGE 126506c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, 126606c3fb27SDimitry Andric DefRangeSym &DefRange) { 126706c3fb27SDimitry Andric // DefRanges don't have types, just registers and code offsets. 126806c3fb27SDimitry Andric LLVM_DEBUG({ 126906c3fb27SDimitry Andric if (LocalSymbol) 127006c3fb27SDimitry Andric W.getOStream() << formatv("Symbol: {0}, ", LocalSymbol->getName()); 127106c3fb27SDimitry Andric 127206c3fb27SDimitry Andric if (ObjDelegate) { 127306c3fb27SDimitry Andric DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable(); 127406c3fb27SDimitry Andric auto ExpectedProgram = Strings.getString(DefRange.Program); 127506c3fb27SDimitry Andric if (!ExpectedProgram) { 127606c3fb27SDimitry Andric consumeError(ExpectedProgram.takeError()); 127706c3fb27SDimitry Andric return llvm::make_error<CodeViewError>( 127806c3fb27SDimitry Andric "String table offset outside of bounds of String Table!"); 127906c3fb27SDimitry Andric } 128006c3fb27SDimitry Andric W.printString("Program", *ExpectedProgram); 128106c3fb27SDimitry Andric } 128206c3fb27SDimitry Andric printLocalVariableAddrRange(DefRange.Range, DefRange.getRelocationOffset()); 128306c3fb27SDimitry Andric printLocalVariableAddrGap(DefRange.Gaps); 128406c3fb27SDimitry Andric }); 128506c3fb27SDimitry Andric 128606c3fb27SDimitry Andric if (LVSymbol *Symbol = LocalSymbol) { 128706c3fb27SDimitry Andric Symbol->setHasCodeViewLocation(); 128806c3fb27SDimitry Andric LocalSymbol = nullptr; 128906c3fb27SDimitry Andric 129006c3fb27SDimitry Andric // Add location debug location. Operands: [Program, 0]. 129106c3fb27SDimitry Andric dwarf::Attribute Attr = dwarf::Attribute(SymbolKind::S_DEFRANGE); 129206c3fb27SDimitry Andric uint64_t Operand1 = DefRange.Program; 129306c3fb27SDimitry Andric 129406c3fb27SDimitry Andric LocalVariableAddrRange Range = DefRange.Range; 129506c3fb27SDimitry Andric LVAddress Address = 129606c3fb27SDimitry Andric Reader->linearAddress(Range.ISectStart, Range.OffsetStart); 129706c3fb27SDimitry Andric 129806c3fb27SDimitry Andric Symbol->addLocation(Attr, Address, Address + Range.Range, 0, 0); 129906c3fb27SDimitry Andric Symbol->addLocationOperands(LVSmall(Attr), {Operand1, /*Operand2=*/0}); 130006c3fb27SDimitry Andric } 130106c3fb27SDimitry Andric 130206c3fb27SDimitry Andric return Error::success(); 130306c3fb27SDimitry Andric } 130406c3fb27SDimitry Andric 130506c3fb27SDimitry Andric // S_FRAMEPROC 130606c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, 130706c3fb27SDimitry Andric FrameProcSym &FrameProc) { 130806c3fb27SDimitry Andric if (LVScope *Function = LogicalVisitor->getReaderScope()) { 130906c3fb27SDimitry Andric // S_FRAMEPROC contains extra information for the function described 131006c3fb27SDimitry Andric // by any of the previous generated records: 131106c3fb27SDimitry Andric // S_GPROC32, S_LPROC32, S_LPROC32_ID, S_GPROC32_ID. 131206c3fb27SDimitry Andric 131306c3fb27SDimitry Andric // The generated sequence is: 131406c3fb27SDimitry Andric // S_GPROC32_ID ... 131506c3fb27SDimitry Andric // S_FRAMEPROC ... 131606c3fb27SDimitry Andric 131706c3fb27SDimitry Andric // Collect additional inline flags for the current scope function. 131806c3fb27SDimitry Andric FrameProcedureOptions Flags = FrameProc.Flags; 131906c3fb27SDimitry Andric if (FrameProcedureOptions::MarkedInline == 132006c3fb27SDimitry Andric (Flags & FrameProcedureOptions::MarkedInline)) 132106c3fb27SDimitry Andric Function->setInlineCode(dwarf::DW_INL_declared_inlined); 132206c3fb27SDimitry Andric if (FrameProcedureOptions::Inlined == 132306c3fb27SDimitry Andric (Flags & FrameProcedureOptions::Inlined)) 132406c3fb27SDimitry Andric Function->setInlineCode(dwarf::DW_INL_inlined); 132506c3fb27SDimitry Andric 132606c3fb27SDimitry Andric // To determine the symbol kind for any symbol declared in that function, 132706c3fb27SDimitry Andric // we can access the S_FRAMEPROC for the parent scope function. It contains 132806c3fb27SDimitry Andric // information about the local fp and param fp registers and compare with 132906c3fb27SDimitry Andric // the register in the S_REGREL32 to get a match. 133006c3fb27SDimitry Andric codeview::CPUType CPU = Reader->getCompileUnitCPUType(); 133106c3fb27SDimitry Andric LocalFrameRegister = FrameProc.getLocalFramePtrReg(CPU); 133206c3fb27SDimitry Andric ParamFrameRegister = FrameProc.getParamFramePtrReg(CPU); 133306c3fb27SDimitry Andric } 133406c3fb27SDimitry Andric 133506c3fb27SDimitry Andric return Error::success(); 133606c3fb27SDimitry Andric } 133706c3fb27SDimitry Andric 133806c3fb27SDimitry Andric // S_GDATA32, S_LDATA32, S_LMANDATA, S_GMANDATA 133906c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, DataSym &Data) { 134006c3fb27SDimitry Andric LLVM_DEBUG({ 134106c3fb27SDimitry Andric printTypeIndex("Type", Data.Type); 134206c3fb27SDimitry Andric W.printString("DisplayName", Data.Name); 134306c3fb27SDimitry Andric }); 134406c3fb27SDimitry Andric 134506c3fb27SDimitry Andric if (LVSymbol *Symbol = LogicalVisitor->CurrentSymbol) { 134606c3fb27SDimitry Andric StringRef LinkageName; 134706c3fb27SDimitry Andric if (ObjDelegate) 134806c3fb27SDimitry Andric ObjDelegate->getLinkageName(Data.getRelocationOffset(), Data.DataOffset, 134906c3fb27SDimitry Andric &LinkageName); 135006c3fb27SDimitry Andric 135106c3fb27SDimitry Andric Symbol->setName(Data.Name); 135206c3fb27SDimitry Andric Symbol->setLinkageName(LinkageName); 135306c3fb27SDimitry Andric 135406c3fb27SDimitry Andric // The MSVC generates local data as initialization for aggregates. It 135506c3fb27SDimitry Andric // contains the address for an initialization function. 135606c3fb27SDimitry Andric // The symbols contains the '$initializer$' pattern. Allow them only if 135706c3fb27SDimitry Andric // the '--internal=system' option is given. 135806c3fb27SDimitry Andric // 0 | S_LDATA32 `Struct$initializer$` 135906c3fb27SDimitry Andric // type = 0x1040 (void ()*) 136006c3fb27SDimitry Andric if (getReader().isSystemEntry(Symbol) && !options().getAttributeSystem()) { 136106c3fb27SDimitry Andric Symbol->resetIncludeInPrint(); 136206c3fb27SDimitry Andric return Error::success(); 136306c3fb27SDimitry Andric } 136406c3fb27SDimitry Andric 136506c3fb27SDimitry Andric if (LVScope *Namespace = Shared->NamespaceDeduction.get(Data.Name)) { 136606c3fb27SDimitry Andric // The variable is already at different scope. In order to reflect 136706c3fb27SDimitry Andric // the correct parent, move it to the namespace. 136806c3fb27SDimitry Andric if (Symbol->getParentScope()->removeElement(Symbol)) 136906c3fb27SDimitry Andric Namespace->addElement(Symbol); 137006c3fb27SDimitry Andric } 137106c3fb27SDimitry Andric 137206c3fb27SDimitry Andric Symbol->setType(LogicalVisitor->getElement(StreamTPI, Data.Type)); 137306c3fb27SDimitry Andric if (Record.kind() == SymbolKind::S_GDATA32) 137406c3fb27SDimitry Andric Symbol->setIsExternal(); 137506c3fb27SDimitry Andric } 137606c3fb27SDimitry Andric 137706c3fb27SDimitry Andric return Error::success(); 137806c3fb27SDimitry Andric } 137906c3fb27SDimitry Andric 138006c3fb27SDimitry Andric // S_INLINESITE 138106c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, 138206c3fb27SDimitry Andric InlineSiteSym &InlineSite) { 138306c3fb27SDimitry Andric LLVM_DEBUG({ printTypeIndex("Inlinee", InlineSite.Inlinee); }); 138406c3fb27SDimitry Andric 138506c3fb27SDimitry Andric if (LVScope *InlinedFunction = LogicalVisitor->CurrentScope) { 138606c3fb27SDimitry Andric LVScope *AbstractFunction = Reader->createScopeFunction(); 138706c3fb27SDimitry Andric AbstractFunction->setIsSubprogram(); 138806c3fb27SDimitry Andric AbstractFunction->setTag(dwarf::DW_TAG_subprogram); 138906c3fb27SDimitry Andric AbstractFunction->setInlineCode(dwarf::DW_INL_inlined); 139006c3fb27SDimitry Andric AbstractFunction->setIsInlinedAbstract(); 139106c3fb27SDimitry Andric InlinedFunction->setReference(AbstractFunction); 139206c3fb27SDimitry Andric 139306c3fb27SDimitry Andric LogicalVisitor->startProcessArgumentList(); 139406c3fb27SDimitry Andric // 'Inlinee' is a Type ID. 139506c3fb27SDimitry Andric CVType CVFunctionType = Ids.getType(InlineSite.Inlinee); 139606c3fb27SDimitry Andric if (Error Err = LogicalVisitor->finishVisitation( 139706c3fb27SDimitry Andric CVFunctionType, InlineSite.Inlinee, AbstractFunction)) 139806c3fb27SDimitry Andric return Err; 139906c3fb27SDimitry Andric LogicalVisitor->stopProcessArgumentList(); 140006c3fb27SDimitry Andric 140106c3fb27SDimitry Andric // For inlined functions set the linkage name to be the same as 140206c3fb27SDimitry Andric // the name. It used to find their lines and ranges. 140306c3fb27SDimitry Andric StringRef Name = AbstractFunction->getName(); 140406c3fb27SDimitry Andric InlinedFunction->setName(Name); 140506c3fb27SDimitry Andric InlinedFunction->setLinkageName(Name); 140606c3fb27SDimitry Andric 140706c3fb27SDimitry Andric // Process annotation bytes to calculate code and line offsets. 140806c3fb27SDimitry Andric if (Error Err = LogicalVisitor->inlineSiteAnnotation( 140906c3fb27SDimitry Andric AbstractFunction, InlinedFunction, InlineSite)) 141006c3fb27SDimitry Andric return Err; 141106c3fb27SDimitry Andric } 141206c3fb27SDimitry Andric 141306c3fb27SDimitry Andric return Error::success(); 141406c3fb27SDimitry Andric } 141506c3fb27SDimitry Andric 141606c3fb27SDimitry Andric // S_LOCAL 141706c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, LocalSym &Local) { 141806c3fb27SDimitry Andric LLVM_DEBUG({ 141906c3fb27SDimitry Andric printTypeIndex("Type", Local.Type); 142006c3fb27SDimitry Andric W.printFlags("Flags", uint16_t(Local.Flags), getLocalFlagNames()); 142106c3fb27SDimitry Andric W.printString("VarName", Local.Name); 142206c3fb27SDimitry Andric }); 142306c3fb27SDimitry Andric 142406c3fb27SDimitry Andric if (LVSymbol *Symbol = LogicalVisitor->CurrentSymbol) { 142506c3fb27SDimitry Andric Symbol->setName(Local.Name); 142606c3fb27SDimitry Andric 142706c3fb27SDimitry Andric // Symbol was created as 'variable'; determine its real kind. 142806c3fb27SDimitry Andric Symbol->resetIsVariable(); 142906c3fb27SDimitry Andric 143006c3fb27SDimitry Andric // Be sure the 'this' symbol is marked as 'compiler generated'. 143106c3fb27SDimitry Andric if (bool(Local.Flags & LocalSymFlags::IsCompilerGenerated) || 1432*0fca6ea1SDimitry Andric Local.Name == "this") { 143306c3fb27SDimitry Andric Symbol->setIsArtificial(); 143406c3fb27SDimitry Andric Symbol->setIsParameter(); 143506c3fb27SDimitry Andric } else { 143606c3fb27SDimitry Andric bool(Local.Flags & LocalSymFlags::IsParameter) ? Symbol->setIsParameter() 143706c3fb27SDimitry Andric : Symbol->setIsVariable(); 143806c3fb27SDimitry Andric } 143906c3fb27SDimitry Andric 144006c3fb27SDimitry Andric // Update correct debug information tag. 144106c3fb27SDimitry Andric if (Symbol->getIsParameter()) 144206c3fb27SDimitry Andric Symbol->setTag(dwarf::DW_TAG_formal_parameter); 144306c3fb27SDimitry Andric 144406c3fb27SDimitry Andric LVElement *Element = LogicalVisitor->getElement(StreamTPI, Local.Type); 144506c3fb27SDimitry Andric if (Element && Element->getIsScoped()) { 144606c3fb27SDimitry Andric // We have a local type. Find its parent function. 144706c3fb27SDimitry Andric LVScope *Parent = Symbol->getFunctionParent(); 144806c3fb27SDimitry Andric // The element representing the type has been already finalized. If 144906c3fb27SDimitry Andric // the type is an aggregate type, its members have been already added. 145006c3fb27SDimitry Andric // As the type is local, its level will be changed. 145106c3fb27SDimitry Andric Parent->addElement(Element); 145206c3fb27SDimitry Andric Element->updateLevel(Parent); 145306c3fb27SDimitry Andric } 145406c3fb27SDimitry Andric Symbol->setType(Element); 145506c3fb27SDimitry Andric 145606c3fb27SDimitry Andric // The CodeView records (S_DEFFRAME_*) describing debug location for 145706c3fb27SDimitry Andric // this symbol, do not have any direct reference to it. Those records 145806c3fb27SDimitry Andric // are emitted after this symbol. Record the current symbol. 145906c3fb27SDimitry Andric LocalSymbol = Symbol; 146006c3fb27SDimitry Andric } 146106c3fb27SDimitry Andric 146206c3fb27SDimitry Andric return Error::success(); 146306c3fb27SDimitry Andric } 146406c3fb27SDimitry Andric 146506c3fb27SDimitry Andric // S_OBJNAME 146606c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, ObjNameSym &ObjName) { 146706c3fb27SDimitry Andric LLVM_DEBUG({ 146806c3fb27SDimitry Andric W.printHex("Signature", ObjName.Signature); 146906c3fb27SDimitry Andric W.printString("ObjectName", ObjName.Name); 147006c3fb27SDimitry Andric }); 147106c3fb27SDimitry Andric 147206c3fb27SDimitry Andric CurrentObjectName = ObjName.Name; 147306c3fb27SDimitry Andric return Error::success(); 147406c3fb27SDimitry Andric } 147506c3fb27SDimitry Andric 147606c3fb27SDimitry Andric // S_GPROC32, S_LPROC32, S_LPROC32_ID, S_GPROC32_ID 147706c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, ProcSym &Proc) { 147806c3fb27SDimitry Andric if (InFunctionScope) 147906c3fb27SDimitry Andric return llvm::make_error<CodeViewError>("Visiting a ProcSym while inside " 148006c3fb27SDimitry Andric "function scope!"); 148106c3fb27SDimitry Andric 148206c3fb27SDimitry Andric InFunctionScope = true; 148306c3fb27SDimitry Andric 148406c3fb27SDimitry Andric LLVM_DEBUG({ 148506c3fb27SDimitry Andric printTypeIndex("FunctionType", Proc.FunctionType); 148606c3fb27SDimitry Andric W.printHex("Segment", Proc.Segment); 148706c3fb27SDimitry Andric W.printFlags("Flags", static_cast<uint8_t>(Proc.Flags), 148806c3fb27SDimitry Andric getProcSymFlagNames()); 148906c3fb27SDimitry Andric W.printString("DisplayName", Proc.Name); 149006c3fb27SDimitry Andric }); 149106c3fb27SDimitry Andric 149206c3fb27SDimitry Andric // Clang and Microsoft generated different debug information records: 149306c3fb27SDimitry Andric // For functions definitions: 149406c3fb27SDimitry Andric // Clang: S_GPROC32 -> LF_FUNC_ID -> LF_PROCEDURE 149506c3fb27SDimitry Andric // Microsoft: S_GPROC32 -> LF_PROCEDURE 149606c3fb27SDimitry Andric 149706c3fb27SDimitry Andric // For member function definition: 149806c3fb27SDimitry Andric // Clang: S_GPROC32 -> LF_MFUNC_ID -> LF_MFUNCTION 149906c3fb27SDimitry Andric // Microsoft: S_GPROC32 -> LF_MFUNCTION 150006c3fb27SDimitry Andric // In order to support both sequences, if we found LF_FUNCTION_ID, just 150106c3fb27SDimitry Andric // get the TypeIndex for LF_PROCEDURE. 150206c3fb27SDimitry Andric 150306c3fb27SDimitry Andric // For the given test case, we have the sequence: 150406c3fb27SDimitry Andric // namespace NSP_local { 150506c3fb27SDimitry Andric // void foo_local() { 150606c3fb27SDimitry Andric // } 150706c3fb27SDimitry Andric // } 150806c3fb27SDimitry Andric // 150906c3fb27SDimitry Andric // 0x1000 | LF_STRING_ID String: NSP_local 151006c3fb27SDimitry Andric // 0x1002 | LF_PROCEDURE 151106c3fb27SDimitry Andric // return type = 0x0003 (void), # args = 0, param list = 0x1001 151206c3fb27SDimitry Andric // calling conv = cdecl, options = None 151306c3fb27SDimitry Andric // 0x1003 | LF_FUNC_ID 151406c3fb27SDimitry Andric // name = foo_local, type = 0x1002, parent scope = 0x1000 151506c3fb27SDimitry Andric // 0 | S_GPROC32_ID `NSP_local::foo_local` 151606c3fb27SDimitry Andric // type = `0x1003 (foo_local)` 151706c3fb27SDimitry Andric // 0x1004 | LF_STRING_ID String: suite 151806c3fb27SDimitry Andric // 0x1005 | LF_STRING_ID String: suite_local.cpp 151906c3fb27SDimitry Andric // 152006c3fb27SDimitry Andric // The LF_STRING_ID can hold different information: 152106c3fb27SDimitry Andric // 0x1000 - The enclosing namespace. 152206c3fb27SDimitry Andric // 0x1004 - The compile unit directory name. 152306c3fb27SDimitry Andric // 0x1005 - The compile unit name. 152406c3fb27SDimitry Andric // 152506c3fb27SDimitry Andric // Before deducting its scope, we need to evaluate its type and create any 152606c3fb27SDimitry Andric // associated namespaces. 152706c3fb27SDimitry Andric if (LVScope *Function = LogicalVisitor->CurrentScope) { 152806c3fb27SDimitry Andric StringRef LinkageName; 152906c3fb27SDimitry Andric if (ObjDelegate) 153006c3fb27SDimitry Andric ObjDelegate->getLinkageName(Proc.getRelocationOffset(), Proc.CodeOffset, 153106c3fb27SDimitry Andric &LinkageName); 153206c3fb27SDimitry Andric 153306c3fb27SDimitry Andric // The line table can be accessed using the linkage name. 153406c3fb27SDimitry Andric Reader->addToSymbolTable(LinkageName, Function); 153506c3fb27SDimitry Andric Function->setName(Proc.Name); 153606c3fb27SDimitry Andric Function->setLinkageName(LinkageName); 153706c3fb27SDimitry Andric 153806c3fb27SDimitry Andric if (options().getGeneralCollectRanges()) { 153906c3fb27SDimitry Andric // Record converted segment::offset addressing for this scope. 154006c3fb27SDimitry Andric LVAddress Addendum = Reader->getSymbolTableAddress(LinkageName); 154106c3fb27SDimitry Andric LVAddress LowPC = 154206c3fb27SDimitry Andric Reader->linearAddress(Proc.Segment, Proc.CodeOffset, Addendum); 154306c3fb27SDimitry Andric LVAddress HighPC = LowPC + Proc.CodeSize - 1; 154406c3fb27SDimitry Andric Function->addObject(LowPC, HighPC); 154506c3fb27SDimitry Andric 154606c3fb27SDimitry Andric // If the scope is a function, add it to the public names. 154706c3fb27SDimitry Andric if ((options().getAttributePublics() || options().getPrintAnyLine()) && 154806c3fb27SDimitry Andric !Function->getIsInlinedFunction()) 154906c3fb27SDimitry Andric Reader->getCompileUnit()->addPublicName(Function, LowPC, HighPC); 155006c3fb27SDimitry Andric } 155106c3fb27SDimitry Andric 155206c3fb27SDimitry Andric if (Function->getIsSystem() && !options().getAttributeSystem()) { 155306c3fb27SDimitry Andric Function->resetIncludeInPrint(); 155406c3fb27SDimitry Andric return Error::success(); 155506c3fb27SDimitry Andric } 155606c3fb27SDimitry Andric 155706c3fb27SDimitry Andric TypeIndex TIFunctionType = Proc.FunctionType; 155806c3fb27SDimitry Andric if (TIFunctionType.isSimple()) 155906c3fb27SDimitry Andric Function->setType(LogicalVisitor->getElement(StreamTPI, TIFunctionType)); 156006c3fb27SDimitry Andric else { 156106c3fb27SDimitry Andric // We have to detect the correct stream, using the lexical parent 156206c3fb27SDimitry Andric // name, as there is not other obvious way to get the stream. 156306c3fb27SDimitry Andric // Normal function: LF_FUNC_ID (TPI)/(IPI) 156406c3fb27SDimitry Andric // LF_PROCEDURE (TPI) 156506c3fb27SDimitry Andric // Lambda function: LF_MFUNCTION (TPI) 156606c3fb27SDimitry Andric // Member function: LF_MFUNC_ID (TPI)/(IPI) 156706c3fb27SDimitry Andric 156806c3fb27SDimitry Andric StringRef OuterComponent; 156906c3fb27SDimitry Andric std::tie(OuterComponent, std::ignore) = getInnerComponent(Proc.Name); 157006c3fb27SDimitry Andric TypeIndex TI = Shared->ForwardReferences.find(OuterComponent); 157106c3fb27SDimitry Andric 157206c3fb27SDimitry Andric std::optional<CVType> CVFunctionType; 157306c3fb27SDimitry Andric auto GetRecordType = [&]() -> bool { 157406c3fb27SDimitry Andric CVFunctionType = Ids.tryGetType(TIFunctionType); 157506c3fb27SDimitry Andric if (!CVFunctionType) 157606c3fb27SDimitry Andric return false; 157706c3fb27SDimitry Andric 157806c3fb27SDimitry Andric if (TI.isNoneType()) 157906c3fb27SDimitry Andric // Normal function. 158006c3fb27SDimitry Andric if (CVFunctionType->kind() == LF_FUNC_ID) 158106c3fb27SDimitry Andric return true; 158206c3fb27SDimitry Andric 158306c3fb27SDimitry Andric // Member function. 158406c3fb27SDimitry Andric return (CVFunctionType->kind() == LF_MFUNC_ID); 158506c3fb27SDimitry Andric }; 158606c3fb27SDimitry Andric 158706c3fb27SDimitry Andric // We can have a LF_FUNC_ID, LF_PROCEDURE or LF_MFUNCTION. 158806c3fb27SDimitry Andric if (!GetRecordType()) { 158906c3fb27SDimitry Andric CVFunctionType = Types.tryGetType(TIFunctionType); 159006c3fb27SDimitry Andric if (!CVFunctionType) 159106c3fb27SDimitry Andric return llvm::make_error<CodeViewError>("Invalid type index"); 159206c3fb27SDimitry Andric } 159306c3fb27SDimitry Andric 159406c3fb27SDimitry Andric if (Error Err = LogicalVisitor->finishVisitation( 159506c3fb27SDimitry Andric *CVFunctionType, TIFunctionType, Function)) 159606c3fb27SDimitry Andric return Err; 159706c3fb27SDimitry Andric } 159806c3fb27SDimitry Andric 159906c3fb27SDimitry Andric if (Record.kind() == SymbolKind::S_GPROC32 || 160006c3fb27SDimitry Andric Record.kind() == SymbolKind::S_GPROC32_ID) 160106c3fb27SDimitry Andric Function->setIsExternal(); 160206c3fb27SDimitry Andric 160306c3fb27SDimitry Andric // We don't have a way to see if the symbol is compiler generated. Use 160406c3fb27SDimitry Andric // the linkage name, to detect `scalar deleting destructor' functions. 160506c3fb27SDimitry Andric std::string DemangledSymbol = demangle(LinkageName); 160606c3fb27SDimitry Andric if (DemangledSymbol.find("scalar deleting dtor") != std::string::npos) { 160706c3fb27SDimitry Andric Function->setIsArtificial(); 160806c3fb27SDimitry Andric } else { 160906c3fb27SDimitry Andric // Clang generates global ctor and dtor names containing the substrings: 161006c3fb27SDimitry Andric // 'dynamic initializer for' and 'dynamic atexit destructor for'. 161106c3fb27SDimitry Andric if (DemangledSymbol.find("dynamic atexit destructor for") != 161206c3fb27SDimitry Andric std::string::npos) 161306c3fb27SDimitry Andric Function->setIsArtificial(); 161406c3fb27SDimitry Andric } 161506c3fb27SDimitry Andric } 161606c3fb27SDimitry Andric 161706c3fb27SDimitry Andric return Error::success(); 161806c3fb27SDimitry Andric } 161906c3fb27SDimitry Andric 162006c3fb27SDimitry Andric // S_END 162106c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, 162206c3fb27SDimitry Andric ScopeEndSym &ScopeEnd) { 162306c3fb27SDimitry Andric InFunctionScope = false; 162406c3fb27SDimitry Andric return Error::success(); 162506c3fb27SDimitry Andric } 162606c3fb27SDimitry Andric 162706c3fb27SDimitry Andric // S_THUNK32 162806c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, Thunk32Sym &Thunk) { 162906c3fb27SDimitry Andric if (InFunctionScope) 163006c3fb27SDimitry Andric return llvm::make_error<CodeViewError>("Visiting a Thunk32Sym while inside " 163106c3fb27SDimitry Andric "function scope!"); 163206c3fb27SDimitry Andric 163306c3fb27SDimitry Andric InFunctionScope = true; 163406c3fb27SDimitry Andric 163506c3fb27SDimitry Andric LLVM_DEBUG({ 163606c3fb27SDimitry Andric W.printHex("Segment", Thunk.Segment); 163706c3fb27SDimitry Andric W.printString("Name", Thunk.Name); 163806c3fb27SDimitry Andric }); 163906c3fb27SDimitry Andric 164006c3fb27SDimitry Andric if (LVScope *Function = LogicalVisitor->CurrentScope) 164106c3fb27SDimitry Andric Function->setName(Thunk.Name); 164206c3fb27SDimitry Andric 164306c3fb27SDimitry Andric return Error::success(); 164406c3fb27SDimitry Andric } 164506c3fb27SDimitry Andric 164606c3fb27SDimitry Andric // S_UDT, S_COBOLUDT 164706c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, UDTSym &UDT) { 164806c3fb27SDimitry Andric LLVM_DEBUG({ 164906c3fb27SDimitry Andric printTypeIndex("Type", UDT.Type); 165006c3fb27SDimitry Andric W.printString("UDTName", UDT.Name); 165106c3fb27SDimitry Andric }); 165206c3fb27SDimitry Andric 165306c3fb27SDimitry Andric if (LVType *Type = LogicalVisitor->CurrentType) { 165406c3fb27SDimitry Andric if (LVScope *Namespace = Shared->NamespaceDeduction.get(UDT.Name)) { 165506c3fb27SDimitry Andric if (Type->getParentScope()->removeElement(Type)) 165606c3fb27SDimitry Andric Namespace->addElement(Type); 165706c3fb27SDimitry Andric } 165806c3fb27SDimitry Andric 165906c3fb27SDimitry Andric Type->setName(UDT.Name); 166006c3fb27SDimitry Andric 166106c3fb27SDimitry Andric // We have to determine if the typedef is a real C/C++ definition or is 166206c3fb27SDimitry Andric // the S_UDT record that describe all the user defined types. 166306c3fb27SDimitry Andric // 0 | S_UDT `Name` original type = 0x1009 166406c3fb27SDimitry Andric // 0x1009 | LF_STRUCTURE `Name` 166506c3fb27SDimitry Andric // Ignore type definitions for RTTI types: 166606c3fb27SDimitry Andric // _s__RTTIBaseClassArray, _s__RTTIBaseClassDescriptor, 166706c3fb27SDimitry Andric // _s__RTTICompleteObjectLocator, _s__RTTIClassHierarchyDescriptor. 166806c3fb27SDimitry Andric if (getReader().isSystemEntry(Type)) 166906c3fb27SDimitry Andric Type->resetIncludeInPrint(); 167006c3fb27SDimitry Andric else { 167106c3fb27SDimitry Andric StringRef RecordName = getRecordName(Types, UDT.Type); 1672*0fca6ea1SDimitry Andric if (UDT.Name == RecordName) 167306c3fb27SDimitry Andric Type->resetIncludeInPrint(); 167406c3fb27SDimitry Andric Type->setType(LogicalVisitor->getElement(StreamTPI, UDT.Type)); 167506c3fb27SDimitry Andric } 167606c3fb27SDimitry Andric } 167706c3fb27SDimitry Andric 167806c3fb27SDimitry Andric return Error::success(); 167906c3fb27SDimitry Andric } 168006c3fb27SDimitry Andric 168106c3fb27SDimitry Andric // S_UNAMESPACE 168206c3fb27SDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, 168306c3fb27SDimitry Andric UsingNamespaceSym &UN) { 168406c3fb27SDimitry Andric LLVM_DEBUG({ W.printString("Namespace", UN.Name); }); 168506c3fb27SDimitry Andric return Error::success(); 168606c3fb27SDimitry Andric } 168706c3fb27SDimitry Andric 16885f757f3fSDimitry Andric // S_ARMSWITCHTABLE 16895f757f3fSDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &CVR, 16905f757f3fSDimitry Andric JumpTableSym &JumpTable) { 16915f757f3fSDimitry Andric LLVM_DEBUG({ 16925f757f3fSDimitry Andric W.printHex("BaseOffset", JumpTable.BaseOffset); 16935f757f3fSDimitry Andric W.printNumber("BaseSegment", JumpTable.BaseSegment); 16945f757f3fSDimitry Andric W.printFlags("SwitchType", static_cast<uint16_t>(JumpTable.SwitchType), 16955f757f3fSDimitry Andric getJumpTableEntrySizeNames()); 16965f757f3fSDimitry Andric W.printHex("BranchOffset", JumpTable.BranchOffset); 16975f757f3fSDimitry Andric W.printHex("TableOffset", JumpTable.TableOffset); 16985f757f3fSDimitry Andric W.printNumber("BranchSegment", JumpTable.BranchSegment); 16995f757f3fSDimitry Andric W.printNumber("TableSegment", JumpTable.TableSegment); 17005f757f3fSDimitry Andric W.printNumber("EntriesCount", JumpTable.EntriesCount); 17015f757f3fSDimitry Andric }); 17025f757f3fSDimitry Andric return Error::success(); 17035f757f3fSDimitry Andric } 17045f757f3fSDimitry Andric 17055f757f3fSDimitry Andric // S_CALLERS, S_CALLEES, S_INLINEES 17065f757f3fSDimitry Andric Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, CallerSym &Caller) { 17075f757f3fSDimitry Andric LLVM_DEBUG({ 17085f757f3fSDimitry Andric llvm::StringRef FieldName; 17095f757f3fSDimitry Andric switch (Caller.getKind()) { 17105f757f3fSDimitry Andric case SymbolRecordKind::CallerSym: 17115f757f3fSDimitry Andric FieldName = "Callee"; 17125f757f3fSDimitry Andric break; 17135f757f3fSDimitry Andric case SymbolRecordKind::CalleeSym: 17145f757f3fSDimitry Andric FieldName = "Caller"; 17155f757f3fSDimitry Andric break; 17165f757f3fSDimitry Andric case SymbolRecordKind::InlineesSym: 17175f757f3fSDimitry Andric FieldName = "Inlinee"; 17185f757f3fSDimitry Andric break; 17195f757f3fSDimitry Andric default: 17205f757f3fSDimitry Andric return llvm::make_error<CodeViewError>( 17215f757f3fSDimitry Andric "Unknown CV Record type for a CallerSym object!"); 17225f757f3fSDimitry Andric } 17235f757f3fSDimitry Andric for (auto FuncID : Caller.Indices) { 17245f757f3fSDimitry Andric printTypeIndex(FieldName, FuncID); 17255f757f3fSDimitry Andric } 17265f757f3fSDimitry Andric }); 17275f757f3fSDimitry Andric return Error::success(); 17285f757f3fSDimitry Andric } 17295f757f3fSDimitry Andric 173006c3fb27SDimitry Andric #undef DEBUG_TYPE 173106c3fb27SDimitry Andric #define DEBUG_TYPE "CodeViewLogicalVisitor" 173206c3fb27SDimitry Andric 173306c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 173406c3fb27SDimitry Andric // Logical visitor. 173506c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 173606c3fb27SDimitry Andric LVLogicalVisitor::LVLogicalVisitor(LVCodeViewReader *Reader, ScopedPrinter &W, 173706c3fb27SDimitry Andric InputFile &Input) 173806c3fb27SDimitry Andric : Reader(Reader), W(W), Input(Input) { 173906c3fb27SDimitry Andric // The LogicalVisitor connects the CodeViewReader with the visitors that 174006c3fb27SDimitry Andric // traverse the types, symbols, etc. Do any initialization that is needed. 174106c3fb27SDimitry Andric Shared = std::make_shared<LVShared>(Reader, this); 174206c3fb27SDimitry Andric } 174306c3fb27SDimitry Andric 174406c3fb27SDimitry Andric void LVLogicalVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI, 174506c3fb27SDimitry Andric uint32_t StreamIdx) { 174606c3fb27SDimitry Andric codeview::printTypeIndex(W, FieldName, TI, 174706c3fb27SDimitry Andric StreamIdx == StreamTPI ? types() : ids()); 174806c3fb27SDimitry Andric } 174906c3fb27SDimitry Andric 175006c3fb27SDimitry Andric void LVLogicalVisitor::printTypeBegin(CVType &Record, TypeIndex TI, 175106c3fb27SDimitry Andric LVElement *Element, uint32_t StreamIdx) { 175206c3fb27SDimitry Andric W.getOStream() << "\n"; 175306c3fb27SDimitry Andric W.startLine() << formatTypeLeafKind(Record.kind()); 175406c3fb27SDimitry Andric W.getOStream() << " (" << HexNumber(TI.getIndex()) << ")"; 175506c3fb27SDimitry Andric W.getOStream() << " {\n"; 175606c3fb27SDimitry Andric W.indent(); 175706c3fb27SDimitry Andric W.printEnum("TypeLeafKind", unsigned(Record.kind()), ArrayRef(LeafTypeNames)); 175806c3fb27SDimitry Andric printTypeIndex("TI", TI, StreamIdx); 175906c3fb27SDimitry Andric W.startLine() << "Element: " << HexNumber(Element->getOffset()) << " " 176006c3fb27SDimitry Andric << Element->getName() << "\n"; 176106c3fb27SDimitry Andric } 176206c3fb27SDimitry Andric 176306c3fb27SDimitry Andric void LVLogicalVisitor::printTypeEnd(CVType &Record) { 176406c3fb27SDimitry Andric W.unindent(); 176506c3fb27SDimitry Andric W.startLine() << "}\n"; 176606c3fb27SDimitry Andric } 176706c3fb27SDimitry Andric 176806c3fb27SDimitry Andric void LVLogicalVisitor::printMemberBegin(CVMemberRecord &Record, TypeIndex TI, 176906c3fb27SDimitry Andric LVElement *Element, 177006c3fb27SDimitry Andric uint32_t StreamIdx) { 177106c3fb27SDimitry Andric W.getOStream() << "\n"; 177206c3fb27SDimitry Andric W.startLine() << formatTypeLeafKind(Record.Kind); 177306c3fb27SDimitry Andric W.getOStream() << " (" << HexNumber(TI.getIndex()) << ")"; 177406c3fb27SDimitry Andric W.getOStream() << " {\n"; 177506c3fb27SDimitry Andric W.indent(); 177606c3fb27SDimitry Andric W.printEnum("TypeLeafKind", unsigned(Record.Kind), ArrayRef(LeafTypeNames)); 177706c3fb27SDimitry Andric printTypeIndex("TI", TI, StreamIdx); 177806c3fb27SDimitry Andric W.startLine() << "Element: " << HexNumber(Element->getOffset()) << " " 177906c3fb27SDimitry Andric << Element->getName() << "\n"; 178006c3fb27SDimitry Andric } 178106c3fb27SDimitry Andric 178206c3fb27SDimitry Andric void LVLogicalVisitor::printMemberEnd(CVMemberRecord &Record) { 178306c3fb27SDimitry Andric W.unindent(); 178406c3fb27SDimitry Andric W.startLine() << "}\n"; 178506c3fb27SDimitry Andric } 178606c3fb27SDimitry Andric 178706c3fb27SDimitry Andric Error LVLogicalVisitor::visitUnknownType(CVType &Record, TypeIndex TI) { 178806c3fb27SDimitry Andric LLVM_DEBUG({ 178906c3fb27SDimitry Andric printTypeIndex("\nTI", TI, StreamTPI); 179006c3fb27SDimitry Andric W.printNumber("Length", uint32_t(Record.content().size())); 179106c3fb27SDimitry Andric }); 179206c3fb27SDimitry Andric return Error::success(); 179306c3fb27SDimitry Andric } 179406c3fb27SDimitry Andric 179506c3fb27SDimitry Andric // LF_ARGLIST (TPI) 179606c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ArgListRecord &Args, 179706c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 179806c3fb27SDimitry Andric ArrayRef<TypeIndex> Indices = Args.getIndices(); 179906c3fb27SDimitry Andric uint32_t Size = Indices.size(); 180006c3fb27SDimitry Andric LLVM_DEBUG({ 180106c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 180206c3fb27SDimitry Andric W.printNumber("NumArgs", Size); 180306c3fb27SDimitry Andric ListScope Arguments(W, "Arguments"); 180406c3fb27SDimitry Andric for (uint32_t I = 0; I < Size; ++I) 180506c3fb27SDimitry Andric printTypeIndex("ArgType", Indices[I], StreamTPI); 180606c3fb27SDimitry Andric printTypeEnd(Record); 180706c3fb27SDimitry Andric }); 180806c3fb27SDimitry Andric 180906c3fb27SDimitry Andric LVScope *Function = static_cast<LVScope *>(Element); 181006c3fb27SDimitry Andric for (uint32_t Index = 0; Index < Size; ++Index) { 181106c3fb27SDimitry Andric TypeIndex ParameterType = Indices[Index]; 181206c3fb27SDimitry Andric createParameter(ParameterType, StringRef(), Function); 181306c3fb27SDimitry Andric } 181406c3fb27SDimitry Andric 181506c3fb27SDimitry Andric return Error::success(); 181606c3fb27SDimitry Andric } 181706c3fb27SDimitry Andric 181806c3fb27SDimitry Andric // LF_ARRAY (TPI) 181906c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ArrayRecord &AT, 182006c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 182106c3fb27SDimitry Andric LLVM_DEBUG({ 182206c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 182306c3fb27SDimitry Andric printTypeIndex("ElementType", AT.getElementType(), StreamTPI); 182406c3fb27SDimitry Andric printTypeIndex("IndexType", AT.getIndexType(), StreamTPI); 182506c3fb27SDimitry Andric W.printNumber("SizeOf", AT.getSize()); 182606c3fb27SDimitry Andric W.printString("Name", AT.getName()); 182706c3fb27SDimitry Andric printTypeEnd(Record); 182806c3fb27SDimitry Andric }); 182906c3fb27SDimitry Andric 183006c3fb27SDimitry Andric if (Element->getIsFinalized()) 183106c3fb27SDimitry Andric return Error::success(); 183206c3fb27SDimitry Andric Element->setIsFinalized(); 183306c3fb27SDimitry Andric 183406c3fb27SDimitry Andric LVScopeArray *Array = static_cast<LVScopeArray *>(Element); 183506c3fb27SDimitry Andric if (!Array) 183606c3fb27SDimitry Andric return Error::success(); 183706c3fb27SDimitry Andric 183806c3fb27SDimitry Andric Reader->getCompileUnit()->addElement(Array); 183906c3fb27SDimitry Andric TypeIndex TIElementType = AT.getElementType(); 184006c3fb27SDimitry Andric 184106c3fb27SDimitry Andric LVType *PrevSubrange = nullptr; 184206c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types(); 184306c3fb27SDimitry Andric 184406c3fb27SDimitry Andric // As the logical view is modeled on DWARF, for each dimension we have to 184506c3fb27SDimitry Andric // create a DW_TAG_subrange_type, with dimension size. 184606c3fb27SDimitry Andric // The subrange type can be: unsigned __int32 or unsigned __int64. 184706c3fb27SDimitry Andric auto AddSubrangeType = [&](ArrayRecord &AR) { 184806c3fb27SDimitry Andric LVType *Subrange = Reader->createTypeSubrange(); 184906c3fb27SDimitry Andric Subrange->setTag(dwarf::DW_TAG_subrange_type); 185006c3fb27SDimitry Andric Subrange->setType(getElement(StreamTPI, AR.getIndexType())); 185106c3fb27SDimitry Andric Subrange->setCount(AR.getSize()); 185206c3fb27SDimitry Andric Subrange->setOffset( 185306c3fb27SDimitry Andric TIElementType.isSimple() 185406c3fb27SDimitry Andric ? (uint32_t)(TypeLeafKind)TIElementType.getSimpleKind() 185506c3fb27SDimitry Andric : TIElementType.getIndex()); 185606c3fb27SDimitry Andric Array->addElement(Subrange); 185706c3fb27SDimitry Andric 185806c3fb27SDimitry Andric if (PrevSubrange) 185906c3fb27SDimitry Andric if (int64_t Count = Subrange->getCount()) 186006c3fb27SDimitry Andric PrevSubrange->setCount(PrevSubrange->getCount() / Count); 186106c3fb27SDimitry Andric PrevSubrange = Subrange; 186206c3fb27SDimitry Andric }; 186306c3fb27SDimitry Andric 186406c3fb27SDimitry Andric // Preserve the original TypeIndex; it would be updated in the case of: 186506c3fb27SDimitry Andric // - The array type contains qualifiers. 186606c3fb27SDimitry Andric // - In multidimensional arrays, the last LF_ARRAY entry contains the type. 186706c3fb27SDimitry Andric TypeIndex TIArrayType; 186806c3fb27SDimitry Andric 186906c3fb27SDimitry Andric // For each dimension in the array, there is a LF_ARRAY entry. The last 187006c3fb27SDimitry Andric // entry contains the array type, which can be a LF_MODIFIER in the case 187106c3fb27SDimitry Andric // of the type being modified by a qualifier (const, etc). 187206c3fb27SDimitry Andric ArrayRecord AR(AT); 187306c3fb27SDimitry Andric CVType CVEntry = Record; 187406c3fb27SDimitry Andric while (CVEntry.kind() == LF_ARRAY) { 187506c3fb27SDimitry Andric // Create the subrange information, required by the logical view. Once 187606c3fb27SDimitry Andric // the array has been processed, the dimension sizes will updated, as 187706c3fb27SDimitry Andric // the sizes are a progression. For instance: 187806c3fb27SDimitry Andric // sizeof(int) = 4 187906c3fb27SDimitry Andric // int Array[2]; Sizes: 8 Dim: 8 / 4 -> [2] 188006c3fb27SDimitry Andric // int Array[2][3]; Sizes: 24, 12 Dim: 24 / 12 -> [2] 188106c3fb27SDimitry Andric // Dim: 12 / 4 -> [3] 188206c3fb27SDimitry Andric // int Array[2][3][4]; sizes: 96, 48, 16 Dim: 96 / 48 -> [2] 188306c3fb27SDimitry Andric // Dim: 48 / 16 -> [3] 188406c3fb27SDimitry Andric // Dim: 16 / 4 -> [4] 188506c3fb27SDimitry Andric AddSubrangeType(AR); 188606c3fb27SDimitry Andric TIArrayType = TIElementType; 188706c3fb27SDimitry Andric 188806c3fb27SDimitry Andric // The current ElementType can be a modifier, in which case we need to 188906c3fb27SDimitry Andric // get the type being modified. 189006c3fb27SDimitry Andric // If TypeIndex is not a simple type, check if we have a qualified type. 189106c3fb27SDimitry Andric if (!TIElementType.isSimple()) { 189206c3fb27SDimitry Andric CVType CVElementType = Types.getType(TIElementType); 189306c3fb27SDimitry Andric if (CVElementType.kind() == LF_MODIFIER) { 189406c3fb27SDimitry Andric LVElement *QualifiedType = 189506c3fb27SDimitry Andric Shared->TypeRecords.find(StreamTPI, TIElementType); 189606c3fb27SDimitry Andric if (Error Err = 189706c3fb27SDimitry Andric finishVisitation(CVElementType, TIElementType, QualifiedType)) 189806c3fb27SDimitry Andric return Err; 189906c3fb27SDimitry Andric // Get the TypeIndex of the type that the LF_MODIFIER modifies. 190006c3fb27SDimitry Andric TIElementType = getModifiedType(CVElementType); 190106c3fb27SDimitry Andric } 190206c3fb27SDimitry Andric } 190306c3fb27SDimitry Andric // Ends the traversal, as we have reached a simple type (int, char, etc). 190406c3fb27SDimitry Andric if (TIElementType.isSimple()) 190506c3fb27SDimitry Andric break; 190606c3fb27SDimitry Andric 190706c3fb27SDimitry Andric // Read next dimension linked entry, if any. 190806c3fb27SDimitry Andric CVEntry = Types.getType(TIElementType); 190906c3fb27SDimitry Andric if (Error Err = TypeDeserializer::deserializeAs( 191006c3fb27SDimitry Andric const_cast<CVType &>(CVEntry), AR)) { 191106c3fb27SDimitry Andric consumeError(std::move(Err)); 191206c3fb27SDimitry Andric break; 191306c3fb27SDimitry Andric } 191406c3fb27SDimitry Andric TIElementType = AR.getElementType(); 191506c3fb27SDimitry Andric // NOTE: The typeindex has a value of: 0x0280.0000 191606c3fb27SDimitry Andric getTrueType(TIElementType); 191706c3fb27SDimitry Andric } 191806c3fb27SDimitry Andric 191906c3fb27SDimitry Andric Array->setName(AT.getName()); 192006c3fb27SDimitry Andric TIArrayType = Shared->ForwardReferences.remap(TIArrayType); 192106c3fb27SDimitry Andric Array->setType(getElement(StreamTPI, TIArrayType)); 192206c3fb27SDimitry Andric 192306c3fb27SDimitry Andric if (PrevSubrange) 192406c3fb27SDimitry Andric // In the case of an aggregate type (class, struct, union, interface), 192506c3fb27SDimitry Andric // get the aggregate size. As the original record is pointing to its 192606c3fb27SDimitry Andric // reference, we have to update it. 192706c3fb27SDimitry Andric if (uint64_t Size = 192806c3fb27SDimitry Andric isAggregate(CVEntry) 192906c3fb27SDimitry Andric ? getSizeInBytesForTypeRecord(Types.getType(TIArrayType)) 193006c3fb27SDimitry Andric : getSizeInBytesForTypeIndex(TIElementType)) 193106c3fb27SDimitry Andric PrevSubrange->setCount(PrevSubrange->getCount() / Size); 193206c3fb27SDimitry Andric 193306c3fb27SDimitry Andric return Error::success(); 193406c3fb27SDimitry Andric } 193506c3fb27SDimitry Andric 193606c3fb27SDimitry Andric // LF_BITFIELD (TPI) 193706c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, BitFieldRecord &BF, 193806c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 193906c3fb27SDimitry Andric LLVM_DEBUG({ 194006c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 194106c3fb27SDimitry Andric printTypeIndex("Type", TI, StreamTPI); 194206c3fb27SDimitry Andric W.printNumber("BitSize", BF.getBitSize()); 194306c3fb27SDimitry Andric W.printNumber("BitOffset", BF.getBitOffset()); 194406c3fb27SDimitry Andric printTypeEnd(Record); 194506c3fb27SDimitry Andric }); 194606c3fb27SDimitry Andric 194706c3fb27SDimitry Andric Element->setType(getElement(StreamTPI, BF.getType())); 194806c3fb27SDimitry Andric Element->setBitSize(BF.getBitSize()); 194906c3fb27SDimitry Andric return Error::success(); 195006c3fb27SDimitry Andric } 195106c3fb27SDimitry Andric 195206c3fb27SDimitry Andric // LF_BUILDINFO (TPI)/(IPI) 195306c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, BuildInfoRecord &BI, 195406c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 195506c3fb27SDimitry Andric LLVM_DEBUG({ 195606c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamIPI); 195706c3fb27SDimitry Andric W.printNumber("NumArgs", static_cast<uint32_t>(BI.getArgs().size())); 195806c3fb27SDimitry Andric ListScope Arguments(W, "Arguments"); 195906c3fb27SDimitry Andric for (TypeIndex Arg : BI.getArgs()) 196006c3fb27SDimitry Andric printTypeIndex("ArgType", Arg, StreamIPI); 196106c3fb27SDimitry Andric printTypeEnd(Record); 196206c3fb27SDimitry Andric }); 196306c3fb27SDimitry Andric 196406c3fb27SDimitry Andric // The given 'Element' refers to the current compilation unit. 196506c3fb27SDimitry Andric // All the args are references into the TPI/IPI stream. 196606c3fb27SDimitry Andric TypeIndex TIName = BI.getArgs()[BuildInfoRecord::BuildInfoArg::SourceFile]; 196706c3fb27SDimitry Andric std::string Name = std::string(ids().getTypeName(TIName)); 196806c3fb27SDimitry Andric 196906c3fb27SDimitry Andric // There are cases where LF_BUILDINFO fields are empty. 197006c3fb27SDimitry Andric if (!Name.empty()) 197106c3fb27SDimitry Andric Element->setName(Name); 197206c3fb27SDimitry Andric 197306c3fb27SDimitry Andric return Error::success(); 197406c3fb27SDimitry Andric } 197506c3fb27SDimitry Andric 197606c3fb27SDimitry Andric // LF_CLASS, LF_STRUCTURE, LF_INTERFACE (TPI) 197706c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ClassRecord &Class, 197806c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 197906c3fb27SDimitry Andric LLVM_DEBUG({ 198006c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 198106c3fb27SDimitry Andric W.printNumber("MemberCount", Class.getMemberCount()); 198206c3fb27SDimitry Andric printTypeIndex("FieldList", Class.getFieldList(), StreamTPI); 198306c3fb27SDimitry Andric printTypeIndex("DerivedFrom", Class.getDerivationList(), StreamTPI); 198406c3fb27SDimitry Andric printTypeIndex("VShape", Class.getVTableShape(), StreamTPI); 198506c3fb27SDimitry Andric W.printNumber("SizeOf", Class.getSize()); 198606c3fb27SDimitry Andric W.printString("Name", Class.getName()); 198706c3fb27SDimitry Andric if (Class.hasUniqueName()) 198806c3fb27SDimitry Andric W.printString("UniqueName", Class.getUniqueName()); 198906c3fb27SDimitry Andric printTypeEnd(Record); 199006c3fb27SDimitry Andric }); 199106c3fb27SDimitry Andric 199206c3fb27SDimitry Andric if (Element->getIsFinalized()) 199306c3fb27SDimitry Andric return Error::success(); 199406c3fb27SDimitry Andric Element->setIsFinalized(); 199506c3fb27SDimitry Andric 199606c3fb27SDimitry Andric LVScopeAggregate *Scope = static_cast<LVScopeAggregate *>(Element); 199706c3fb27SDimitry Andric if (!Scope) 199806c3fb27SDimitry Andric return Error::success(); 199906c3fb27SDimitry Andric 200006c3fb27SDimitry Andric Scope->setName(Class.getName()); 200106c3fb27SDimitry Andric if (Class.hasUniqueName()) 200206c3fb27SDimitry Andric Scope->setLinkageName(Class.getUniqueName()); 200306c3fb27SDimitry Andric 200406c3fb27SDimitry Andric if (Class.isNested()) { 200506c3fb27SDimitry Andric Scope->setIsNested(); 200606c3fb27SDimitry Andric createParents(Class.getName(), Scope); 200706c3fb27SDimitry Andric } 200806c3fb27SDimitry Andric 200906c3fb27SDimitry Andric if (Class.isScoped()) 201006c3fb27SDimitry Andric Scope->setIsScoped(); 201106c3fb27SDimitry Andric 201206c3fb27SDimitry Andric // Nested types will be added to their parents at creation. The forward 201306c3fb27SDimitry Andric // references are only processed to finish the referenced element creation. 201406c3fb27SDimitry Andric if (!(Class.isNested() || Class.isScoped())) { 201506c3fb27SDimitry Andric if (LVScope *Namespace = Shared->NamespaceDeduction.get(Class.getName())) 201606c3fb27SDimitry Andric Namespace->addElement(Scope); 201706c3fb27SDimitry Andric else 201806c3fb27SDimitry Andric Reader->getCompileUnit()->addElement(Scope); 201906c3fb27SDimitry Andric } 202006c3fb27SDimitry Andric 202106c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types(); 202206c3fb27SDimitry Andric TypeIndex TIFieldList = Class.getFieldList(); 202306c3fb27SDimitry Andric if (TIFieldList.isNoneType()) { 202406c3fb27SDimitry Andric TypeIndex ForwardType = Shared->ForwardReferences.find(Class.getName()); 202506c3fb27SDimitry Andric if (!ForwardType.isNoneType()) { 202606c3fb27SDimitry Andric CVType CVReference = Types.getType(ForwardType); 202706c3fb27SDimitry Andric TypeRecordKind RK = static_cast<TypeRecordKind>(CVReference.kind()); 202806c3fb27SDimitry Andric ClassRecord ReferenceRecord(RK); 202906c3fb27SDimitry Andric if (Error Err = TypeDeserializer::deserializeAs( 203006c3fb27SDimitry Andric const_cast<CVType &>(CVReference), ReferenceRecord)) 203106c3fb27SDimitry Andric return Err; 203206c3fb27SDimitry Andric TIFieldList = ReferenceRecord.getFieldList(); 203306c3fb27SDimitry Andric } 203406c3fb27SDimitry Andric } 203506c3fb27SDimitry Andric 203606c3fb27SDimitry Andric if (!TIFieldList.isNoneType()) { 203706c3fb27SDimitry Andric // Pass down the TypeIndex 'TI' for the aggregate containing the field list. 203806c3fb27SDimitry Andric CVType CVFieldList = Types.getType(TIFieldList); 203906c3fb27SDimitry Andric if (Error Err = finishVisitation(CVFieldList, TI, Scope)) 204006c3fb27SDimitry Andric return Err; 204106c3fb27SDimitry Andric } 204206c3fb27SDimitry Andric 204306c3fb27SDimitry Andric return Error::success(); 204406c3fb27SDimitry Andric } 204506c3fb27SDimitry Andric 204606c3fb27SDimitry Andric // LF_ENUM (TPI) 204706c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, EnumRecord &Enum, 204806c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 204906c3fb27SDimitry Andric LLVM_DEBUG({ 205006c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 205106c3fb27SDimitry Andric W.printNumber("NumEnumerators", Enum.getMemberCount()); 205206c3fb27SDimitry Andric printTypeIndex("UnderlyingType", Enum.getUnderlyingType(), StreamTPI); 205306c3fb27SDimitry Andric printTypeIndex("FieldListType", Enum.getFieldList(), StreamTPI); 205406c3fb27SDimitry Andric W.printString("Name", Enum.getName()); 205506c3fb27SDimitry Andric printTypeEnd(Record); 205606c3fb27SDimitry Andric }); 205706c3fb27SDimitry Andric 205806c3fb27SDimitry Andric LVScopeEnumeration *Scope = static_cast<LVScopeEnumeration *>(Element); 205906c3fb27SDimitry Andric if (!Scope) 206006c3fb27SDimitry Andric return Error::success(); 206106c3fb27SDimitry Andric 206206c3fb27SDimitry Andric if (Scope->getIsFinalized()) 206306c3fb27SDimitry Andric return Error::success(); 206406c3fb27SDimitry Andric Scope->setIsFinalized(); 206506c3fb27SDimitry Andric 206606c3fb27SDimitry Andric // Set the name, as in the case of nested, it would determine the relation 206706c3fb27SDimitry Andric // to any potential parent, via the LF_NESTTYPE record. 206806c3fb27SDimitry Andric Scope->setName(Enum.getName()); 206906c3fb27SDimitry Andric if (Enum.hasUniqueName()) 207006c3fb27SDimitry Andric Scope->setLinkageName(Enum.getUniqueName()); 207106c3fb27SDimitry Andric 207206c3fb27SDimitry Andric Scope->setType(getElement(StreamTPI, Enum.getUnderlyingType())); 207306c3fb27SDimitry Andric 207406c3fb27SDimitry Andric if (Enum.isNested()) { 207506c3fb27SDimitry Andric Scope->setIsNested(); 207606c3fb27SDimitry Andric createParents(Enum.getName(), Scope); 207706c3fb27SDimitry Andric } 207806c3fb27SDimitry Andric 207906c3fb27SDimitry Andric if (Enum.isScoped()) { 208006c3fb27SDimitry Andric Scope->setIsScoped(); 208106c3fb27SDimitry Andric Scope->setIsEnumClass(); 208206c3fb27SDimitry Andric } 208306c3fb27SDimitry Andric 208406c3fb27SDimitry Andric // Nested types will be added to their parents at creation. 208506c3fb27SDimitry Andric if (!(Enum.isNested() || Enum.isScoped())) { 208606c3fb27SDimitry Andric if (LVScope *Namespace = Shared->NamespaceDeduction.get(Enum.getName())) 208706c3fb27SDimitry Andric Namespace->addElement(Scope); 208806c3fb27SDimitry Andric else 208906c3fb27SDimitry Andric Reader->getCompileUnit()->addElement(Scope); 209006c3fb27SDimitry Andric } 209106c3fb27SDimitry Andric 209206c3fb27SDimitry Andric TypeIndex TIFieldList = Enum.getFieldList(); 209306c3fb27SDimitry Andric if (!TIFieldList.isNoneType()) { 209406c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types(); 209506c3fb27SDimitry Andric CVType CVFieldList = Types.getType(TIFieldList); 209606c3fb27SDimitry Andric if (Error Err = finishVisitation(CVFieldList, TIFieldList, Scope)) 209706c3fb27SDimitry Andric return Err; 209806c3fb27SDimitry Andric } 209906c3fb27SDimitry Andric 210006c3fb27SDimitry Andric return Error::success(); 210106c3fb27SDimitry Andric } 210206c3fb27SDimitry Andric 210306c3fb27SDimitry Andric // LF_FIELDLIST (TPI) 210406c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, 210506c3fb27SDimitry Andric FieldListRecord &FieldList, 210606c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 210706c3fb27SDimitry Andric LLVM_DEBUG({ 210806c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 210906c3fb27SDimitry Andric printTypeEnd(Record); 211006c3fb27SDimitry Andric }); 211106c3fb27SDimitry Andric 211206c3fb27SDimitry Andric if (Error Err = visitFieldListMemberStream(TI, Element, FieldList.Data)) 211306c3fb27SDimitry Andric return Err; 211406c3fb27SDimitry Andric 211506c3fb27SDimitry Andric return Error::success(); 211606c3fb27SDimitry Andric } 211706c3fb27SDimitry Andric 211806c3fb27SDimitry Andric // LF_FUNC_ID (TPI)/(IPI) 211906c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, FuncIdRecord &Func, 212006c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 212106c3fb27SDimitry Andric // ParentScope and FunctionType are references into the TPI stream. 212206c3fb27SDimitry Andric LLVM_DEBUG({ 212306c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamIPI); 212406c3fb27SDimitry Andric printTypeIndex("ParentScope", Func.getParentScope(), StreamTPI); 212506c3fb27SDimitry Andric printTypeIndex("FunctionType", Func.getFunctionType(), StreamTPI); 212606c3fb27SDimitry Andric W.printString("Name", Func.getName()); 212706c3fb27SDimitry Andric printTypeEnd(Record); 212806c3fb27SDimitry Andric }); 212906c3fb27SDimitry Andric 213006c3fb27SDimitry Andric // The TypeIndex (LF_PROCEDURE) returned by 'getFunctionType' is the 213106c3fb27SDimitry Andric // function propotype, we need to use the function definition. 213206c3fb27SDimitry Andric if (LVScope *FunctionDcl = static_cast<LVScope *>(Element)) { 213306c3fb27SDimitry Andric // For inlined functions, the inlined instance has been already processed 213406c3fb27SDimitry Andric // (all its information is contained in the Symbols section). 213506c3fb27SDimitry Andric // 'Element' points to the created 'abstract' (out-of-line) function. 213606c3fb27SDimitry Andric // Use the parent scope information to allocate it to the correct scope. 213706c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types(); 213806c3fb27SDimitry Andric TypeIndex TIParent = Func.getParentScope(); 213906c3fb27SDimitry Andric if (FunctionDcl->getIsInlinedAbstract()) { 214006c3fb27SDimitry Andric FunctionDcl->setName(Func.getName()); 214106c3fb27SDimitry Andric if (TIParent.isNoneType()) 214206c3fb27SDimitry Andric Reader->getCompileUnit()->addElement(FunctionDcl); 214306c3fb27SDimitry Andric } 214406c3fb27SDimitry Andric 214506c3fb27SDimitry Andric if (!TIParent.isNoneType()) { 214606c3fb27SDimitry Andric CVType CVParentScope = ids().getType(TIParent); 214706c3fb27SDimitry Andric if (Error Err = finishVisitation(CVParentScope, TIParent, FunctionDcl)) 214806c3fb27SDimitry Andric return Err; 214906c3fb27SDimitry Andric } 215006c3fb27SDimitry Andric 215106c3fb27SDimitry Andric TypeIndex TIFunctionType = Func.getFunctionType(); 215206c3fb27SDimitry Andric CVType CVFunctionType = Types.getType(TIFunctionType); 215306c3fb27SDimitry Andric if (Error Err = 215406c3fb27SDimitry Andric finishVisitation(CVFunctionType, TIFunctionType, FunctionDcl)) 215506c3fb27SDimitry Andric return Err; 215606c3fb27SDimitry Andric 215706c3fb27SDimitry Andric FunctionDcl->setIsFinalized(); 215806c3fb27SDimitry Andric } 215906c3fb27SDimitry Andric 216006c3fb27SDimitry Andric return Error::success(); 216106c3fb27SDimitry Andric } 216206c3fb27SDimitry Andric 216306c3fb27SDimitry Andric // LF_LABEL (TPI) 216406c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, LabelRecord &LR, 216506c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 216606c3fb27SDimitry Andric LLVM_DEBUG({ 216706c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 216806c3fb27SDimitry Andric printTypeEnd(Record); 216906c3fb27SDimitry Andric }); 217006c3fb27SDimitry Andric return Error::success(); 217106c3fb27SDimitry Andric } 217206c3fb27SDimitry Andric 217306c3fb27SDimitry Andric // LF_MFUNC_ID (TPI)/(IPI) 217406c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, MemberFuncIdRecord &Id, 217506c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 217606c3fb27SDimitry Andric // ClassType and FunctionType are references into the TPI stream. 217706c3fb27SDimitry Andric LLVM_DEBUG({ 217806c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamIPI); 217906c3fb27SDimitry Andric printTypeIndex("ClassType", Id.getClassType(), StreamTPI); 218006c3fb27SDimitry Andric printTypeIndex("FunctionType", Id.getFunctionType(), StreamTPI); 218106c3fb27SDimitry Andric W.printString("Name", Id.getName()); 218206c3fb27SDimitry Andric printTypeEnd(Record); 218306c3fb27SDimitry Andric }); 218406c3fb27SDimitry Andric 218506c3fb27SDimitry Andric LVScope *FunctionDcl = static_cast<LVScope *>(Element); 218606c3fb27SDimitry Andric if (FunctionDcl->getIsInlinedAbstract()) { 218706c3fb27SDimitry Andric // For inlined functions, the inlined instance has been already processed 218806c3fb27SDimitry Andric // (all its information is contained in the Symbols section). 218906c3fb27SDimitry Andric // 'Element' points to the created 'abstract' (out-of-line) function. 219006c3fb27SDimitry Andric // Use the parent scope information to allocate it to the correct scope. 219106c3fb27SDimitry Andric if (LVScope *Class = static_cast<LVScope *>( 219206c3fb27SDimitry Andric Shared->TypeRecords.find(StreamTPI, Id.getClassType()))) 219306c3fb27SDimitry Andric Class->addElement(FunctionDcl); 219406c3fb27SDimitry Andric } 219506c3fb27SDimitry Andric 219606c3fb27SDimitry Andric TypeIndex TIFunctionType = Id.getFunctionType(); 219706c3fb27SDimitry Andric CVType CVFunction = types().getType(TIFunctionType); 219806c3fb27SDimitry Andric if (Error Err = finishVisitation(CVFunction, TIFunctionType, Element)) 219906c3fb27SDimitry Andric return Err; 220006c3fb27SDimitry Andric 220106c3fb27SDimitry Andric return Error::success(); 220206c3fb27SDimitry Andric } 220306c3fb27SDimitry Andric 220406c3fb27SDimitry Andric // LF_MFUNCTION (TPI) 220506c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, 220606c3fb27SDimitry Andric MemberFunctionRecord &MF, TypeIndex TI, 220706c3fb27SDimitry Andric LVElement *Element) { 220806c3fb27SDimitry Andric LLVM_DEBUG({ 220906c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 221006c3fb27SDimitry Andric printTypeIndex("ReturnType", MF.getReturnType(), StreamTPI); 221106c3fb27SDimitry Andric printTypeIndex("ClassType", MF.getClassType(), StreamTPI); 221206c3fb27SDimitry Andric printTypeIndex("ThisType", MF.getThisType(), StreamTPI); 221306c3fb27SDimitry Andric W.printNumber("NumParameters", MF.getParameterCount()); 221406c3fb27SDimitry Andric printTypeIndex("ArgListType", MF.getArgumentList(), StreamTPI); 221506c3fb27SDimitry Andric W.printNumber("ThisAdjustment", MF.getThisPointerAdjustment()); 221606c3fb27SDimitry Andric printTypeEnd(Record); 221706c3fb27SDimitry Andric }); 221806c3fb27SDimitry Andric 221906c3fb27SDimitry Andric if (LVScope *MemberFunction = static_cast<LVScope *>(Element)) { 222006c3fb27SDimitry Andric LVElement *Class = getElement(StreamTPI, MF.getClassType()); 222106c3fb27SDimitry Andric 222206c3fb27SDimitry Andric MemberFunction->setIsFinalized(); 222306c3fb27SDimitry Andric MemberFunction->setType(getElement(StreamTPI, MF.getReturnType())); 222406c3fb27SDimitry Andric MemberFunction->setOffset(TI.getIndex()); 222506c3fb27SDimitry Andric MemberFunction->setOffsetFromTypeIndex(); 222606c3fb27SDimitry Andric 222706c3fb27SDimitry Andric if (ProcessArgumentList) { 222806c3fb27SDimitry Andric ProcessArgumentList = false; 222906c3fb27SDimitry Andric 223006c3fb27SDimitry Andric if (!MemberFunction->getIsStatic()) { 223106c3fb27SDimitry Andric LVElement *ThisPointer = getElement(StreamTPI, MF.getThisType()); 223206c3fb27SDimitry Andric // When creating the 'this' pointer, check if it points to a reference. 223306c3fb27SDimitry Andric ThisPointer->setType(Class); 223406c3fb27SDimitry Andric LVSymbol *This = 223506c3fb27SDimitry Andric createParameter(ThisPointer, StringRef(), MemberFunction); 223606c3fb27SDimitry Andric This->setIsArtificial(); 223706c3fb27SDimitry Andric } 223806c3fb27SDimitry Andric 223906c3fb27SDimitry Andric // Create formal parameters. 224006c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types(); 224106c3fb27SDimitry Andric CVType CVArguments = Types.getType(MF.getArgumentList()); 224206c3fb27SDimitry Andric if (Error Err = finishVisitation(CVArguments, MF.getArgumentList(), 224306c3fb27SDimitry Andric MemberFunction)) 224406c3fb27SDimitry Andric return Err; 224506c3fb27SDimitry Andric } 224606c3fb27SDimitry Andric } 224706c3fb27SDimitry Andric 224806c3fb27SDimitry Andric return Error::success(); 224906c3fb27SDimitry Andric } 225006c3fb27SDimitry Andric 225106c3fb27SDimitry Andric // LF_METHODLIST (TPI) 225206c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, 225306c3fb27SDimitry Andric MethodOverloadListRecord &Overloads, 225406c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 225506c3fb27SDimitry Andric LLVM_DEBUG({ 225606c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 225706c3fb27SDimitry Andric printTypeEnd(Record); 225806c3fb27SDimitry Andric }); 225906c3fb27SDimitry Andric 226006c3fb27SDimitry Andric for (OneMethodRecord &Method : Overloads.Methods) { 226106c3fb27SDimitry Andric CVMemberRecord Record; 226206c3fb27SDimitry Andric Record.Kind = LF_METHOD; 226306c3fb27SDimitry Andric Method.Name = OverloadedMethodName; 226406c3fb27SDimitry Andric if (Error Err = visitKnownMember(Record, Method, TI, Element)) 226506c3fb27SDimitry Andric return Err; 226606c3fb27SDimitry Andric } 226706c3fb27SDimitry Andric 226806c3fb27SDimitry Andric return Error::success(); 226906c3fb27SDimitry Andric } 227006c3fb27SDimitry Andric 227106c3fb27SDimitry Andric // LF_MODIFIER (TPI) 227206c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ModifierRecord &Mod, 227306c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 227406c3fb27SDimitry Andric LLVM_DEBUG({ 227506c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 227606c3fb27SDimitry Andric printTypeIndex("ModifiedType", Mod.getModifiedType(), StreamTPI); 227706c3fb27SDimitry Andric printTypeEnd(Record); 227806c3fb27SDimitry Andric }); 227906c3fb27SDimitry Andric 228006c3fb27SDimitry Andric // Create the modified type, which will be attached to the type(s) that 228106c3fb27SDimitry Andric // contains the modifiers. 228206c3fb27SDimitry Andric LVElement *ModifiedType = getElement(StreamTPI, Mod.getModifiedType()); 228306c3fb27SDimitry Andric 228406c3fb27SDimitry Andric // At this point the types recording the qualifiers do not have a 228506c3fb27SDimitry Andric // scope parent. They must be assigned to the current compile unit. 228606c3fb27SDimitry Andric LVScopeCompileUnit *CompileUnit = Reader->getCompileUnit(); 228706c3fb27SDimitry Andric 228806c3fb27SDimitry Andric // The incoming element does not have a defined kind. Use the given 228906c3fb27SDimitry Andric // modifiers to complete its type. A type can have more than one modifier; 229006c3fb27SDimitry Andric // in that case, we have to create an extra type to have the other modifier. 229106c3fb27SDimitry Andric LVType *LastLink = static_cast<LVType *>(Element); 229206c3fb27SDimitry Andric if (!LastLink->getParentScope()) 229306c3fb27SDimitry Andric CompileUnit->addElement(LastLink); 229406c3fb27SDimitry Andric 229506c3fb27SDimitry Andric bool SeenModifier = false; 229606c3fb27SDimitry Andric uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers()); 229706c3fb27SDimitry Andric if (Mods & uint16_t(ModifierOptions::Const)) { 229806c3fb27SDimitry Andric SeenModifier = true; 229906c3fb27SDimitry Andric LastLink->setTag(dwarf::DW_TAG_const_type); 230006c3fb27SDimitry Andric LastLink->setIsConst(); 230106c3fb27SDimitry Andric LastLink->setName("const"); 230206c3fb27SDimitry Andric } 230306c3fb27SDimitry Andric if (Mods & uint16_t(ModifierOptions::Volatile)) { 230406c3fb27SDimitry Andric if (SeenModifier) { 230506c3fb27SDimitry Andric LVType *Volatile = Reader->createType(); 230606c3fb27SDimitry Andric Volatile->setIsModifier(); 230706c3fb27SDimitry Andric LastLink->setType(Volatile); 230806c3fb27SDimitry Andric LastLink = Volatile; 230906c3fb27SDimitry Andric CompileUnit->addElement(LastLink); 231006c3fb27SDimitry Andric } 231106c3fb27SDimitry Andric LastLink->setTag(dwarf::DW_TAG_volatile_type); 231206c3fb27SDimitry Andric LastLink->setIsVolatile(); 231306c3fb27SDimitry Andric LastLink->setName("volatile"); 231406c3fb27SDimitry Andric } 231506c3fb27SDimitry Andric if (Mods & uint16_t(ModifierOptions::Unaligned)) { 231606c3fb27SDimitry Andric if (SeenModifier) { 231706c3fb27SDimitry Andric LVType *Unaligned = Reader->createType(); 231806c3fb27SDimitry Andric Unaligned->setIsModifier(); 231906c3fb27SDimitry Andric LastLink->setType(Unaligned); 232006c3fb27SDimitry Andric LastLink = Unaligned; 232106c3fb27SDimitry Andric CompileUnit->addElement(LastLink); 232206c3fb27SDimitry Andric } 232306c3fb27SDimitry Andric LastLink->setTag(dwarf::DW_TAG_unaligned); 232406c3fb27SDimitry Andric LastLink->setIsUnaligned(); 232506c3fb27SDimitry Andric LastLink->setName("unaligned"); 232606c3fb27SDimitry Andric } 232706c3fb27SDimitry Andric 232806c3fb27SDimitry Andric LastLink->setType(ModifiedType); 232906c3fb27SDimitry Andric return Error::success(); 233006c3fb27SDimitry Andric } 233106c3fb27SDimitry Andric 233206c3fb27SDimitry Andric // LF_POINTER (TPI) 233306c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, PointerRecord &Ptr, 233406c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 233506c3fb27SDimitry Andric LLVM_DEBUG({ 233606c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 233706c3fb27SDimitry Andric printTypeIndex("PointeeType", Ptr.getReferentType(), StreamTPI); 233806c3fb27SDimitry Andric W.printNumber("IsFlat", Ptr.isFlat()); 233906c3fb27SDimitry Andric W.printNumber("IsConst", Ptr.isConst()); 234006c3fb27SDimitry Andric W.printNumber("IsVolatile", Ptr.isVolatile()); 234106c3fb27SDimitry Andric W.printNumber("IsUnaligned", Ptr.isUnaligned()); 234206c3fb27SDimitry Andric W.printNumber("IsRestrict", Ptr.isRestrict()); 234306c3fb27SDimitry Andric W.printNumber("IsThisPtr&", Ptr.isLValueReferenceThisPtr()); 234406c3fb27SDimitry Andric W.printNumber("IsThisPtr&&", Ptr.isRValueReferenceThisPtr()); 234506c3fb27SDimitry Andric W.printNumber("SizeOf", Ptr.getSize()); 234606c3fb27SDimitry Andric 234706c3fb27SDimitry Andric if (Ptr.isPointerToMember()) { 234806c3fb27SDimitry Andric const MemberPointerInfo &MI = Ptr.getMemberInfo(); 234906c3fb27SDimitry Andric printTypeIndex("ClassType", MI.getContainingType(), StreamTPI); 235006c3fb27SDimitry Andric } 235106c3fb27SDimitry Andric printTypeEnd(Record); 235206c3fb27SDimitry Andric }); 235306c3fb27SDimitry Andric 235406c3fb27SDimitry Andric // Find the pointed-to type. 235506c3fb27SDimitry Andric LVType *Pointer = static_cast<LVType *>(Element); 235606c3fb27SDimitry Andric LVElement *Pointee = nullptr; 235706c3fb27SDimitry Andric 235806c3fb27SDimitry Andric PointerMode Mode = Ptr.getMode(); 235906c3fb27SDimitry Andric Pointee = Ptr.isPointerToMember() 236006c3fb27SDimitry Andric ? Shared->TypeRecords.find(StreamTPI, Ptr.getReferentType()) 236106c3fb27SDimitry Andric : getElement(StreamTPI, Ptr.getReferentType()); 236206c3fb27SDimitry Andric 236306c3fb27SDimitry Andric // At this point the types recording the qualifiers do not have a 236406c3fb27SDimitry Andric // scope parent. They must be assigned to the current compile unit. 236506c3fb27SDimitry Andric LVScopeCompileUnit *CompileUnit = Reader->getCompileUnit(); 236606c3fb27SDimitry Andric 236706c3fb27SDimitry Andric // Order for the different modifiers: 236806c3fb27SDimitry Andric // <restrict> <pointer, Reference, ValueReference> <const, volatile> 236906c3fb27SDimitry Andric // Const and volatile already processed. 237006c3fb27SDimitry Andric bool SeenModifier = false; 237106c3fb27SDimitry Andric LVType *LastLink = Pointer; 237206c3fb27SDimitry Andric if (!LastLink->getParentScope()) 237306c3fb27SDimitry Andric CompileUnit->addElement(LastLink); 237406c3fb27SDimitry Andric 237506c3fb27SDimitry Andric if (Ptr.isRestrict()) { 237606c3fb27SDimitry Andric SeenModifier = true; 237706c3fb27SDimitry Andric LVType *Restrict = Reader->createType(); 237806c3fb27SDimitry Andric Restrict->setTag(dwarf::DW_TAG_restrict_type); 237906c3fb27SDimitry Andric Restrict->setIsRestrict(); 238006c3fb27SDimitry Andric Restrict->setName("restrict"); 238106c3fb27SDimitry Andric LastLink->setType(Restrict); 238206c3fb27SDimitry Andric LastLink = Restrict; 238306c3fb27SDimitry Andric CompileUnit->addElement(LastLink); 238406c3fb27SDimitry Andric } 238506c3fb27SDimitry Andric if (Mode == PointerMode::LValueReference) { 238606c3fb27SDimitry Andric if (SeenModifier) { 238706c3fb27SDimitry Andric LVType *LReference = Reader->createType(); 238806c3fb27SDimitry Andric LReference->setIsModifier(); 238906c3fb27SDimitry Andric LastLink->setType(LReference); 239006c3fb27SDimitry Andric LastLink = LReference; 239106c3fb27SDimitry Andric CompileUnit->addElement(LastLink); 239206c3fb27SDimitry Andric } 239306c3fb27SDimitry Andric LastLink->setTag(dwarf::DW_TAG_reference_type); 239406c3fb27SDimitry Andric LastLink->setIsReference(); 239506c3fb27SDimitry Andric LastLink->setName("&"); 239606c3fb27SDimitry Andric } 239706c3fb27SDimitry Andric if (Mode == PointerMode::RValueReference) { 239806c3fb27SDimitry Andric if (SeenModifier) { 239906c3fb27SDimitry Andric LVType *RReference = Reader->createType(); 240006c3fb27SDimitry Andric RReference->setIsModifier(); 240106c3fb27SDimitry Andric LastLink->setType(RReference); 240206c3fb27SDimitry Andric LastLink = RReference; 240306c3fb27SDimitry Andric CompileUnit->addElement(LastLink); 240406c3fb27SDimitry Andric } 240506c3fb27SDimitry Andric LastLink->setTag(dwarf::DW_TAG_rvalue_reference_type); 240606c3fb27SDimitry Andric LastLink->setIsRvalueReference(); 240706c3fb27SDimitry Andric LastLink->setName("&&"); 240806c3fb27SDimitry Andric } 240906c3fb27SDimitry Andric 241006c3fb27SDimitry Andric // When creating the pointer, check if it points to a reference. 241106c3fb27SDimitry Andric LastLink->setType(Pointee); 241206c3fb27SDimitry Andric return Error::success(); 241306c3fb27SDimitry Andric } 241406c3fb27SDimitry Andric 241506c3fb27SDimitry Andric // LF_PROCEDURE (TPI) 241606c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ProcedureRecord &Proc, 241706c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 241806c3fb27SDimitry Andric LLVM_DEBUG({ 241906c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 242006c3fb27SDimitry Andric printTypeIndex("ReturnType", Proc.getReturnType(), StreamTPI); 242106c3fb27SDimitry Andric W.printNumber("NumParameters", Proc.getParameterCount()); 242206c3fb27SDimitry Andric printTypeIndex("ArgListType", Proc.getArgumentList(), StreamTPI); 242306c3fb27SDimitry Andric printTypeEnd(Record); 242406c3fb27SDimitry Andric }); 242506c3fb27SDimitry Andric 242606c3fb27SDimitry Andric // There is no need to traverse the argument list, as the CodeView format 242706c3fb27SDimitry Andric // declares the parameters as a 'S_LOCAL' symbol tagged as parameter. 242806c3fb27SDimitry Andric // Only process parameters when dealing with inline functions. 242906c3fb27SDimitry Andric if (LVScope *FunctionDcl = static_cast<LVScope *>(Element)) { 243006c3fb27SDimitry Andric FunctionDcl->setType(getElement(StreamTPI, Proc.getReturnType())); 243106c3fb27SDimitry Andric 243206c3fb27SDimitry Andric if (ProcessArgumentList) { 243306c3fb27SDimitry Andric ProcessArgumentList = false; 243406c3fb27SDimitry Andric // Create formal parameters. 243506c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types(); 243606c3fb27SDimitry Andric CVType CVArguments = Types.getType(Proc.getArgumentList()); 243706c3fb27SDimitry Andric if (Error Err = finishVisitation(CVArguments, Proc.getArgumentList(), 243806c3fb27SDimitry Andric FunctionDcl)) 243906c3fb27SDimitry Andric return Err; 244006c3fb27SDimitry Andric } 244106c3fb27SDimitry Andric } 244206c3fb27SDimitry Andric 244306c3fb27SDimitry Andric return Error::success(); 244406c3fb27SDimitry Andric } 244506c3fb27SDimitry Andric 244606c3fb27SDimitry Andric // LF_UNION (TPI) 244706c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, UnionRecord &Union, 244806c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 244906c3fb27SDimitry Andric LLVM_DEBUG({ 245006c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 245106c3fb27SDimitry Andric W.printNumber("MemberCount", Union.getMemberCount()); 245206c3fb27SDimitry Andric printTypeIndex("FieldList", Union.getFieldList(), StreamTPI); 245306c3fb27SDimitry Andric W.printNumber("SizeOf", Union.getSize()); 245406c3fb27SDimitry Andric W.printString("Name", Union.getName()); 245506c3fb27SDimitry Andric if (Union.hasUniqueName()) 245606c3fb27SDimitry Andric W.printString("UniqueName", Union.getUniqueName()); 245706c3fb27SDimitry Andric printTypeEnd(Record); 245806c3fb27SDimitry Andric }); 245906c3fb27SDimitry Andric 246006c3fb27SDimitry Andric LVScopeAggregate *Scope = static_cast<LVScopeAggregate *>(Element); 246106c3fb27SDimitry Andric if (!Scope) 246206c3fb27SDimitry Andric return Error::success(); 246306c3fb27SDimitry Andric 246406c3fb27SDimitry Andric if (Scope->getIsFinalized()) 246506c3fb27SDimitry Andric return Error::success(); 246606c3fb27SDimitry Andric Scope->setIsFinalized(); 246706c3fb27SDimitry Andric 246806c3fb27SDimitry Andric Scope->setName(Union.getName()); 246906c3fb27SDimitry Andric if (Union.hasUniqueName()) 247006c3fb27SDimitry Andric Scope->setLinkageName(Union.getUniqueName()); 247106c3fb27SDimitry Andric 247206c3fb27SDimitry Andric if (Union.isNested()) { 247306c3fb27SDimitry Andric Scope->setIsNested(); 247406c3fb27SDimitry Andric createParents(Union.getName(), Scope); 247506c3fb27SDimitry Andric } else { 247606c3fb27SDimitry Andric if (LVScope *Namespace = Shared->NamespaceDeduction.get(Union.getName())) 247706c3fb27SDimitry Andric Namespace->addElement(Scope); 247806c3fb27SDimitry Andric else 247906c3fb27SDimitry Andric Reader->getCompileUnit()->addElement(Scope); 248006c3fb27SDimitry Andric } 248106c3fb27SDimitry Andric 248206c3fb27SDimitry Andric if (!Union.getFieldList().isNoneType()) { 248306c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types(); 248406c3fb27SDimitry Andric // Pass down the TypeIndex 'TI' for the aggregate containing the field list. 248506c3fb27SDimitry Andric CVType CVFieldList = Types.getType(Union.getFieldList()); 248606c3fb27SDimitry Andric if (Error Err = finishVisitation(CVFieldList, TI, Scope)) 248706c3fb27SDimitry Andric return Err; 248806c3fb27SDimitry Andric } 248906c3fb27SDimitry Andric 249006c3fb27SDimitry Andric return Error::success(); 249106c3fb27SDimitry Andric } 249206c3fb27SDimitry Andric 249306c3fb27SDimitry Andric // LF_TYPESERVER2 (TPI) 249406c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, TypeServer2Record &TS, 249506c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 249606c3fb27SDimitry Andric LLVM_DEBUG({ 249706c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 249806c3fb27SDimitry Andric W.printString("Guid", formatv("{0}", TS.getGuid()).str()); 249906c3fb27SDimitry Andric W.printNumber("Age", TS.getAge()); 250006c3fb27SDimitry Andric W.printString("Name", TS.getName()); 250106c3fb27SDimitry Andric printTypeEnd(Record); 250206c3fb27SDimitry Andric }); 250306c3fb27SDimitry Andric return Error::success(); 250406c3fb27SDimitry Andric } 250506c3fb27SDimitry Andric 250606c3fb27SDimitry Andric // LF_VFTABLE (TPI) 250706c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, VFTableRecord &VFT, 250806c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 250906c3fb27SDimitry Andric LLVM_DEBUG({ 251006c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 251106c3fb27SDimitry Andric printTypeIndex("CompleteClass", VFT.getCompleteClass(), StreamTPI); 251206c3fb27SDimitry Andric printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable(), StreamTPI); 251306c3fb27SDimitry Andric W.printHex("VFPtrOffset", VFT.getVFPtrOffset()); 251406c3fb27SDimitry Andric W.printString("VFTableName", VFT.getName()); 251506c3fb27SDimitry Andric for (const StringRef &N : VFT.getMethodNames()) 251606c3fb27SDimitry Andric W.printString("MethodName", N); 251706c3fb27SDimitry Andric printTypeEnd(Record); 251806c3fb27SDimitry Andric }); 251906c3fb27SDimitry Andric return Error::success(); 252006c3fb27SDimitry Andric } 252106c3fb27SDimitry Andric 252206c3fb27SDimitry Andric // LF_VTSHAPE (TPI) 252306c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, 252406c3fb27SDimitry Andric VFTableShapeRecord &Shape, 252506c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 252606c3fb27SDimitry Andric LLVM_DEBUG({ 252706c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 252806c3fb27SDimitry Andric W.printNumber("VFEntryCount", Shape.getEntryCount()); 252906c3fb27SDimitry Andric printTypeEnd(Record); 253006c3fb27SDimitry Andric }); 253106c3fb27SDimitry Andric return Error::success(); 253206c3fb27SDimitry Andric } 253306c3fb27SDimitry Andric 253406c3fb27SDimitry Andric // LF_SUBSTR_LIST (TPI)/(IPI) 253506c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, 253606c3fb27SDimitry Andric StringListRecord &Strings, 253706c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 253806c3fb27SDimitry Andric // All the indices are references into the TPI/IPI stream. 253906c3fb27SDimitry Andric LLVM_DEBUG({ 254006c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamIPI); 254106c3fb27SDimitry Andric ArrayRef<TypeIndex> Indices = Strings.getIndices(); 254206c3fb27SDimitry Andric uint32_t Size = Indices.size(); 254306c3fb27SDimitry Andric W.printNumber("NumStrings", Size); 254406c3fb27SDimitry Andric ListScope Arguments(W, "Strings"); 254506c3fb27SDimitry Andric for (uint32_t I = 0; I < Size; ++I) 254606c3fb27SDimitry Andric printTypeIndex("String", Indices[I], StreamIPI); 254706c3fb27SDimitry Andric printTypeEnd(Record); 254806c3fb27SDimitry Andric }); 254906c3fb27SDimitry Andric return Error::success(); 255006c3fb27SDimitry Andric } 255106c3fb27SDimitry Andric 255206c3fb27SDimitry Andric // LF_STRING_ID (TPI)/(IPI) 255306c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, StringIdRecord &String, 255406c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 255506c3fb27SDimitry Andric // All args are references into the TPI/IPI stream. 255606c3fb27SDimitry Andric LLVM_DEBUG({ 255706c3fb27SDimitry Andric printTypeIndex("\nTI", TI, StreamIPI); 255806c3fb27SDimitry Andric printTypeIndex("Id", String.getId(), StreamIPI); 255906c3fb27SDimitry Andric W.printString("StringData", String.getString()); 256006c3fb27SDimitry Andric }); 256106c3fb27SDimitry Andric 256206c3fb27SDimitry Andric if (LVScope *Namespace = Shared->NamespaceDeduction.get( 256306c3fb27SDimitry Andric String.getString(), /*CheckScope=*/false)) { 256406c3fb27SDimitry Andric // The function is already at different scope. In order to reflect 256506c3fb27SDimitry Andric // the correct parent, move it to the namespace. 256606c3fb27SDimitry Andric if (LVScope *Scope = Element->getParentScope()) 256706c3fb27SDimitry Andric Scope->removeElement(Element); 256806c3fb27SDimitry Andric Namespace->addElement(Element); 256906c3fb27SDimitry Andric } 257006c3fb27SDimitry Andric 257106c3fb27SDimitry Andric return Error::success(); 257206c3fb27SDimitry Andric } 257306c3fb27SDimitry Andric 257406c3fb27SDimitry Andric // LF_UDT_SRC_LINE (TPI)/(IPI) 257506c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, 257606c3fb27SDimitry Andric UdtSourceLineRecord &SourceLine, 257706c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 257806c3fb27SDimitry Andric // All args are references into the TPI/IPI stream. 257906c3fb27SDimitry Andric LLVM_DEBUG({ 258006c3fb27SDimitry Andric printTypeIndex("\nTI", TI, StreamIPI); 258106c3fb27SDimitry Andric printTypeIndex("UDT", SourceLine.getUDT(), StreamIPI); 258206c3fb27SDimitry Andric printTypeIndex("SourceFile", SourceLine.getSourceFile(), StreamIPI); 258306c3fb27SDimitry Andric W.printNumber("LineNumber", SourceLine.getLineNumber()); 258406c3fb27SDimitry Andric }); 258506c3fb27SDimitry Andric return Error::success(); 258606c3fb27SDimitry Andric } 258706c3fb27SDimitry Andric 258806c3fb27SDimitry Andric // LF_UDT_MOD_SRC_LINE (TPI)/(IPI) 258906c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, 259006c3fb27SDimitry Andric UdtModSourceLineRecord &ModSourceLine, 259106c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 259206c3fb27SDimitry Andric // All args are references into the TPI/IPI stream. 259306c3fb27SDimitry Andric LLVM_DEBUG({ 259406c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamIPI); 259506c3fb27SDimitry Andric printTypeIndex("\nTI", TI, StreamIPI); 259606c3fb27SDimitry Andric printTypeIndex("UDT", ModSourceLine.getUDT(), StreamIPI); 259706c3fb27SDimitry Andric printTypeIndex("SourceFile", ModSourceLine.getSourceFile(), StreamIPI); 259806c3fb27SDimitry Andric W.printNumber("LineNumber", ModSourceLine.getLineNumber()); 259906c3fb27SDimitry Andric W.printNumber("Module", ModSourceLine.getModule()); 260006c3fb27SDimitry Andric printTypeEnd(Record); 260106c3fb27SDimitry Andric }); 260206c3fb27SDimitry Andric return Error::success(); 260306c3fb27SDimitry Andric } 260406c3fb27SDimitry Andric 260506c3fb27SDimitry Andric // LF_PRECOMP (TPI) 260606c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, PrecompRecord &Precomp, 260706c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 260806c3fb27SDimitry Andric LLVM_DEBUG({ 260906c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 261006c3fb27SDimitry Andric W.printHex("StartIndex", Precomp.getStartTypeIndex()); 261106c3fb27SDimitry Andric W.printHex("Count", Precomp.getTypesCount()); 261206c3fb27SDimitry Andric W.printHex("Signature", Precomp.getSignature()); 261306c3fb27SDimitry Andric W.printString("PrecompFile", Precomp.getPrecompFilePath()); 261406c3fb27SDimitry Andric printTypeEnd(Record); 261506c3fb27SDimitry Andric }); 261606c3fb27SDimitry Andric return Error::success(); 261706c3fb27SDimitry Andric } 261806c3fb27SDimitry Andric 261906c3fb27SDimitry Andric // LF_ENDPRECOMP (TPI) 262006c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownRecord(CVType &Record, 262106c3fb27SDimitry Andric EndPrecompRecord &EndPrecomp, 262206c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 262306c3fb27SDimitry Andric LLVM_DEBUG({ 262406c3fb27SDimitry Andric printTypeBegin(Record, TI, Element, StreamTPI); 262506c3fb27SDimitry Andric W.printHex("Signature", EndPrecomp.getSignature()); 262606c3fb27SDimitry Andric printTypeEnd(Record); 262706c3fb27SDimitry Andric }); 262806c3fb27SDimitry Andric return Error::success(); 262906c3fb27SDimitry Andric } 263006c3fb27SDimitry Andric 263106c3fb27SDimitry Andric Error LVLogicalVisitor::visitUnknownMember(CVMemberRecord &Record, 263206c3fb27SDimitry Andric TypeIndex TI) { 263306c3fb27SDimitry Andric LLVM_DEBUG({ W.printHex("UnknownMember", unsigned(Record.Kind)); }); 263406c3fb27SDimitry Andric return Error::success(); 263506c3fb27SDimitry Andric } 263606c3fb27SDimitry Andric 263706c3fb27SDimitry Andric // LF_BCLASS, LF_BINTERFACE 263806c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, 263906c3fb27SDimitry Andric BaseClassRecord &Base, TypeIndex TI, 264006c3fb27SDimitry Andric LVElement *Element) { 264106c3fb27SDimitry Andric LLVM_DEBUG({ 264206c3fb27SDimitry Andric printMemberBegin(Record, TI, Element, StreamTPI); 264306c3fb27SDimitry Andric printTypeIndex("BaseType", Base.getBaseType(), StreamTPI); 264406c3fb27SDimitry Andric W.printHex("BaseOffset", Base.getBaseOffset()); 264506c3fb27SDimitry Andric printMemberEnd(Record); 264606c3fb27SDimitry Andric }); 264706c3fb27SDimitry Andric 264806c3fb27SDimitry Andric createElement(Record.Kind); 264906c3fb27SDimitry Andric if (LVSymbol *Symbol = CurrentSymbol) { 265006c3fb27SDimitry Andric LVElement *BaseClass = getElement(StreamTPI, Base.getBaseType()); 265106c3fb27SDimitry Andric Symbol->setName(BaseClass->getName()); 265206c3fb27SDimitry Andric Symbol->setType(BaseClass); 265306c3fb27SDimitry Andric Symbol->setAccessibilityCode(Base.getAccess()); 265406c3fb27SDimitry Andric static_cast<LVScope *>(Element)->addElement(Symbol); 265506c3fb27SDimitry Andric } 265606c3fb27SDimitry Andric 265706c3fb27SDimitry Andric return Error::success(); 265806c3fb27SDimitry Andric } 265906c3fb27SDimitry Andric 266006c3fb27SDimitry Andric // LF_MEMBER 266106c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, 266206c3fb27SDimitry Andric DataMemberRecord &Field, TypeIndex TI, 266306c3fb27SDimitry Andric LVElement *Element) { 266406c3fb27SDimitry Andric LLVM_DEBUG({ 266506c3fb27SDimitry Andric printMemberBegin(Record, TI, Element, StreamTPI); 266606c3fb27SDimitry Andric printTypeIndex("Type", Field.getType(), StreamTPI); 266706c3fb27SDimitry Andric W.printHex("FieldOffset", Field.getFieldOffset()); 266806c3fb27SDimitry Andric W.printString("Name", Field.getName()); 266906c3fb27SDimitry Andric printMemberEnd(Record); 267006c3fb27SDimitry Andric }); 267106c3fb27SDimitry Andric 267206c3fb27SDimitry Andric // Create the data member. 267306c3fb27SDimitry Andric createDataMember(Record, static_cast<LVScope *>(Element), Field.getName(), 267406c3fb27SDimitry Andric Field.getType(), Field.getAccess()); 267506c3fb27SDimitry Andric return Error::success(); 267606c3fb27SDimitry Andric } 267706c3fb27SDimitry Andric 267806c3fb27SDimitry Andric // LF_ENUMERATE 267906c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, 268006c3fb27SDimitry Andric EnumeratorRecord &Enum, TypeIndex TI, 268106c3fb27SDimitry Andric LVElement *Element) { 268206c3fb27SDimitry Andric LLVM_DEBUG({ 268306c3fb27SDimitry Andric printMemberBegin(Record, TI, Element, StreamTPI); 268406c3fb27SDimitry Andric W.printNumber("EnumValue", Enum.getValue()); 268506c3fb27SDimitry Andric W.printString("Name", Enum.getName()); 268606c3fb27SDimitry Andric printMemberEnd(Record); 268706c3fb27SDimitry Andric }); 268806c3fb27SDimitry Andric 268906c3fb27SDimitry Andric createElement(Record.Kind); 269006c3fb27SDimitry Andric if (LVType *Type = CurrentType) { 269106c3fb27SDimitry Andric Type->setName(Enum.getName()); 269206c3fb27SDimitry Andric SmallString<16> Value; 269306c3fb27SDimitry Andric Enum.getValue().toString(Value, 16, true, true); 269406c3fb27SDimitry Andric Type->setValue(Value); 269506c3fb27SDimitry Andric static_cast<LVScope *>(Element)->addElement(CurrentType); 269606c3fb27SDimitry Andric } 269706c3fb27SDimitry Andric 269806c3fb27SDimitry Andric return Error::success(); 269906c3fb27SDimitry Andric } 270006c3fb27SDimitry Andric 270106c3fb27SDimitry Andric // LF_INDEX 270206c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, 270306c3fb27SDimitry Andric ListContinuationRecord &Cont, 270406c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 270506c3fb27SDimitry Andric LLVM_DEBUG({ 270606c3fb27SDimitry Andric printMemberBegin(Record, TI, Element, StreamTPI); 270706c3fb27SDimitry Andric printTypeIndex("ContinuationIndex", Cont.getContinuationIndex(), StreamTPI); 270806c3fb27SDimitry Andric printMemberEnd(Record); 270906c3fb27SDimitry Andric }); 271006c3fb27SDimitry Andric return Error::success(); 271106c3fb27SDimitry Andric } 271206c3fb27SDimitry Andric 271306c3fb27SDimitry Andric // LF_NESTTYPE 271406c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, 271506c3fb27SDimitry Andric NestedTypeRecord &Nested, TypeIndex TI, 271606c3fb27SDimitry Andric LVElement *Element) { 271706c3fb27SDimitry Andric LLVM_DEBUG({ 271806c3fb27SDimitry Andric printMemberBegin(Record, TI, Element, StreamTPI); 271906c3fb27SDimitry Andric printTypeIndex("Type", Nested.getNestedType(), StreamTPI); 272006c3fb27SDimitry Andric W.printString("Name", Nested.getName()); 272106c3fb27SDimitry Andric printMemberEnd(Record); 272206c3fb27SDimitry Andric }); 272306c3fb27SDimitry Andric 272406c3fb27SDimitry Andric if (LVElement *Typedef = createElement(SymbolKind::S_UDT)) { 272506c3fb27SDimitry Andric Typedef->setName(Nested.getName()); 272606c3fb27SDimitry Andric LVElement *NestedType = getElement(StreamTPI, Nested.getNestedType()); 272706c3fb27SDimitry Andric Typedef->setType(NestedType); 272806c3fb27SDimitry Andric LVScope *Scope = static_cast<LVScope *>(Element); 272906c3fb27SDimitry Andric Scope->addElement(Typedef); 273006c3fb27SDimitry Andric 273106c3fb27SDimitry Andric if (NestedType && NestedType->getIsNested()) { 273206c3fb27SDimitry Andric // 'Element' is an aggregate type that may contains this nested type 273306c3fb27SDimitry Andric // definition. Used their scoped names, to decide on their relationship. 273406c3fb27SDimitry Andric StringRef RecordName = getRecordName(types(), TI); 273506c3fb27SDimitry Andric 273606c3fb27SDimitry Andric StringRef NestedTypeName = NestedType->getName(); 273706c3fb27SDimitry Andric if (NestedTypeName.size() && RecordName.size()) { 273806c3fb27SDimitry Andric StringRef OuterComponent; 273906c3fb27SDimitry Andric std::tie(OuterComponent, std::ignore) = 274006c3fb27SDimitry Andric getInnerComponent(NestedTypeName); 274106c3fb27SDimitry Andric // We have an already created nested type. Add it to the current scope 274206c3fb27SDimitry Andric // and update all its children if any. 2743*0fca6ea1SDimitry Andric if (OuterComponent.size() && OuterComponent == RecordName) { 274406c3fb27SDimitry Andric if (!NestedType->getIsScopedAlready()) { 274506c3fb27SDimitry Andric Scope->addElement(NestedType); 274606c3fb27SDimitry Andric NestedType->setIsScopedAlready(); 274706c3fb27SDimitry Andric NestedType->updateLevel(Scope); 274806c3fb27SDimitry Andric } 274906c3fb27SDimitry Andric Typedef->resetIncludeInPrint(); 275006c3fb27SDimitry Andric } 275106c3fb27SDimitry Andric } 275206c3fb27SDimitry Andric } 275306c3fb27SDimitry Andric } 275406c3fb27SDimitry Andric 275506c3fb27SDimitry Andric return Error::success(); 275606c3fb27SDimitry Andric } 275706c3fb27SDimitry Andric 275806c3fb27SDimitry Andric // LF_ONEMETHOD 275906c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, 276006c3fb27SDimitry Andric OneMethodRecord &Method, TypeIndex TI, 276106c3fb27SDimitry Andric LVElement *Element) { 276206c3fb27SDimitry Andric LLVM_DEBUG({ 276306c3fb27SDimitry Andric printMemberBegin(Record, TI, Element, StreamTPI); 276406c3fb27SDimitry Andric printTypeIndex("Type", Method.getType(), StreamTPI); 276506c3fb27SDimitry Andric // If virtual, then read the vftable offset. 276606c3fb27SDimitry Andric if (Method.isIntroducingVirtual()) 276706c3fb27SDimitry Andric W.printHex("VFTableOffset", Method.getVFTableOffset()); 276806c3fb27SDimitry Andric W.printString("Name", Method.getName()); 276906c3fb27SDimitry Andric printMemberEnd(Record); 277006c3fb27SDimitry Andric }); 277106c3fb27SDimitry Andric 277206c3fb27SDimitry Andric // All the LF_ONEMETHOD objects share the same type description. 277306c3fb27SDimitry Andric // We have to create a scope object for each one and get the required 277406c3fb27SDimitry Andric // information from the LF_MFUNCTION object. 277506c3fb27SDimitry Andric ProcessArgumentList = true; 277606c3fb27SDimitry Andric if (LVElement *MemberFunction = createElement(TypeLeafKind::LF_ONEMETHOD)) { 277706c3fb27SDimitry Andric MemberFunction->setIsFinalized(); 277806c3fb27SDimitry Andric static_cast<LVScope *>(Element)->addElement(MemberFunction); 277906c3fb27SDimitry Andric 278006c3fb27SDimitry Andric MemberFunction->setName(Method.getName()); 278106c3fb27SDimitry Andric MemberFunction->setAccessibilityCode(Method.getAccess()); 278206c3fb27SDimitry Andric 278306c3fb27SDimitry Andric MethodKind Kind = Method.getMethodKind(); 278406c3fb27SDimitry Andric if (Kind == MethodKind::Static) 278506c3fb27SDimitry Andric MemberFunction->setIsStatic(); 278606c3fb27SDimitry Andric MemberFunction->setVirtualityCode(Kind); 278706c3fb27SDimitry Andric 278806c3fb27SDimitry Andric MethodOptions Flags = Method.Attrs.getFlags(); 278906c3fb27SDimitry Andric if (MethodOptions::CompilerGenerated == 279006c3fb27SDimitry Andric (Flags & MethodOptions::CompilerGenerated)) 279106c3fb27SDimitry Andric MemberFunction->setIsArtificial(); 279206c3fb27SDimitry Andric 279306c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types(); 279406c3fb27SDimitry Andric CVType CVMethodType = Types.getType(Method.getType()); 279506c3fb27SDimitry Andric if (Error Err = 279606c3fb27SDimitry Andric finishVisitation(CVMethodType, Method.getType(), MemberFunction)) 279706c3fb27SDimitry Andric return Err; 279806c3fb27SDimitry Andric } 279906c3fb27SDimitry Andric ProcessArgumentList = false; 280006c3fb27SDimitry Andric 280106c3fb27SDimitry Andric return Error::success(); 280206c3fb27SDimitry Andric } 280306c3fb27SDimitry Andric 280406c3fb27SDimitry Andric // LF_METHOD 280506c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, 280606c3fb27SDimitry Andric OverloadedMethodRecord &Method, 280706c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 280806c3fb27SDimitry Andric LLVM_DEBUG({ 280906c3fb27SDimitry Andric printMemberBegin(Record, TI, Element, StreamTPI); 281006c3fb27SDimitry Andric W.printHex("MethodCount", Method.getNumOverloads()); 281106c3fb27SDimitry Andric printTypeIndex("MethodListIndex", Method.getMethodList(), StreamTPI); 281206c3fb27SDimitry Andric W.printString("Name", Method.getName()); 281306c3fb27SDimitry Andric printMemberEnd(Record); 281406c3fb27SDimitry Andric }); 281506c3fb27SDimitry Andric 281606c3fb27SDimitry Andric // Record the overloaded method name, which will be used during the 281706c3fb27SDimitry Andric // traversal of the method list. 281806c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types(); 281906c3fb27SDimitry Andric OverloadedMethodName = Method.getName(); 282006c3fb27SDimitry Andric CVType CVMethods = Types.getType(Method.getMethodList()); 282106c3fb27SDimitry Andric if (Error Err = finishVisitation(CVMethods, Method.getMethodList(), Element)) 282206c3fb27SDimitry Andric return Err; 282306c3fb27SDimitry Andric 282406c3fb27SDimitry Andric return Error::success(); 282506c3fb27SDimitry Andric } 282606c3fb27SDimitry Andric 282706c3fb27SDimitry Andric // LF_STMEMBER 282806c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, 282906c3fb27SDimitry Andric StaticDataMemberRecord &Field, 283006c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 283106c3fb27SDimitry Andric LLVM_DEBUG({ 283206c3fb27SDimitry Andric printMemberBegin(Record, TI, Element, StreamTPI); 283306c3fb27SDimitry Andric printTypeIndex("Type", Field.getType(), StreamTPI); 283406c3fb27SDimitry Andric W.printString("Name", Field.getName()); 283506c3fb27SDimitry Andric printMemberEnd(Record); 283606c3fb27SDimitry Andric }); 283706c3fb27SDimitry Andric 283806c3fb27SDimitry Andric // Create the data member. 283906c3fb27SDimitry Andric createDataMember(Record, static_cast<LVScope *>(Element), Field.getName(), 284006c3fb27SDimitry Andric Field.getType(), Field.getAccess()); 284106c3fb27SDimitry Andric return Error::success(); 284206c3fb27SDimitry Andric } 284306c3fb27SDimitry Andric 284406c3fb27SDimitry Andric // LF_VFUNCTAB 284506c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, 284606c3fb27SDimitry Andric VFPtrRecord &VFTable, TypeIndex TI, 284706c3fb27SDimitry Andric LVElement *Element) { 284806c3fb27SDimitry Andric LLVM_DEBUG({ 284906c3fb27SDimitry Andric printMemberBegin(Record, TI, Element, StreamTPI); 285006c3fb27SDimitry Andric printTypeIndex("Type", VFTable.getType(), StreamTPI); 285106c3fb27SDimitry Andric printMemberEnd(Record); 285206c3fb27SDimitry Andric }); 285306c3fb27SDimitry Andric return Error::success(); 285406c3fb27SDimitry Andric } 285506c3fb27SDimitry Andric 285606c3fb27SDimitry Andric // LF_VBCLASS, LF_IVBCLASS 285706c3fb27SDimitry Andric Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record, 285806c3fb27SDimitry Andric VirtualBaseClassRecord &Base, 285906c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 286006c3fb27SDimitry Andric LLVM_DEBUG({ 286106c3fb27SDimitry Andric printMemberBegin(Record, TI, Element, StreamTPI); 286206c3fb27SDimitry Andric printTypeIndex("BaseType", Base.getBaseType(), StreamTPI); 286306c3fb27SDimitry Andric printTypeIndex("VBPtrType", Base.getVBPtrType(), StreamTPI); 286406c3fb27SDimitry Andric W.printHex("VBPtrOffset", Base.getVBPtrOffset()); 286506c3fb27SDimitry Andric W.printHex("VBTableIndex", Base.getVTableIndex()); 286606c3fb27SDimitry Andric printMemberEnd(Record); 286706c3fb27SDimitry Andric }); 286806c3fb27SDimitry Andric 286906c3fb27SDimitry Andric createElement(Record.Kind); 287006c3fb27SDimitry Andric if (LVSymbol *Symbol = CurrentSymbol) { 287106c3fb27SDimitry Andric LVElement *BaseClass = getElement(StreamTPI, Base.getBaseType()); 287206c3fb27SDimitry Andric Symbol->setName(BaseClass->getName()); 287306c3fb27SDimitry Andric Symbol->setType(BaseClass); 287406c3fb27SDimitry Andric Symbol->setAccessibilityCode(Base.getAccess()); 287506c3fb27SDimitry Andric Symbol->setVirtualityCode(MethodKind::Virtual); 287606c3fb27SDimitry Andric static_cast<LVScope *>(Element)->addElement(Symbol); 287706c3fb27SDimitry Andric } 287806c3fb27SDimitry Andric 287906c3fb27SDimitry Andric return Error::success(); 288006c3fb27SDimitry Andric } 288106c3fb27SDimitry Andric 288206c3fb27SDimitry Andric Error LVLogicalVisitor::visitMemberRecord(CVMemberRecord &Record, 288306c3fb27SDimitry Andric TypeVisitorCallbacks &Callbacks, 288406c3fb27SDimitry Andric TypeIndex TI, LVElement *Element) { 288506c3fb27SDimitry Andric if (Error Err = Callbacks.visitMemberBegin(Record)) 288606c3fb27SDimitry Andric return Err; 288706c3fb27SDimitry Andric 288806c3fb27SDimitry Andric switch (Record.Kind) { 288906c3fb27SDimitry Andric default: 289006c3fb27SDimitry Andric if (Error Err = Callbacks.visitUnknownMember(Record)) 289106c3fb27SDimitry Andric return Err; 289206c3fb27SDimitry Andric break; 289306c3fb27SDimitry Andric #define MEMBER_RECORD(EnumName, EnumVal, Name) \ 289406c3fb27SDimitry Andric case EnumName: { \ 289506c3fb27SDimitry Andric if (Error Err = \ 289606c3fb27SDimitry Andric visitKnownMember<Name##Record>(Record, Callbacks, TI, Element)) \ 289706c3fb27SDimitry Andric return Err; \ 289806c3fb27SDimitry Andric break; \ 289906c3fb27SDimitry Andric } 290006c3fb27SDimitry Andric #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ 290106c3fb27SDimitry Andric MEMBER_RECORD(EnumVal, EnumVal, AliasName) 290206c3fb27SDimitry Andric #define TYPE_RECORD(EnumName, EnumVal, Name) 290306c3fb27SDimitry Andric #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) 290406c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewTypes.def" 290506c3fb27SDimitry Andric } 290606c3fb27SDimitry Andric 290706c3fb27SDimitry Andric if (Error Err = Callbacks.visitMemberEnd(Record)) 290806c3fb27SDimitry Andric return Err; 290906c3fb27SDimitry Andric 291006c3fb27SDimitry Andric return Error::success(); 291106c3fb27SDimitry Andric } 291206c3fb27SDimitry Andric 291306c3fb27SDimitry Andric Error LVLogicalVisitor::finishVisitation(CVType &Record, TypeIndex TI, 291406c3fb27SDimitry Andric LVElement *Element) { 291506c3fb27SDimitry Andric switch (Record.kind()) { 291606c3fb27SDimitry Andric default: 291706c3fb27SDimitry Andric if (Error Err = visitUnknownType(Record, TI)) 291806c3fb27SDimitry Andric return Err; 291906c3fb27SDimitry Andric break; 292006c3fb27SDimitry Andric #define TYPE_RECORD(EnumName, EnumVal, Name) \ 292106c3fb27SDimitry Andric case EnumName: { \ 292206c3fb27SDimitry Andric if (Error Err = visitKnownRecord<Name##Record>(Record, TI, Element)) \ 292306c3fb27SDimitry Andric return Err; \ 292406c3fb27SDimitry Andric break; \ 292506c3fb27SDimitry Andric } 292606c3fb27SDimitry Andric #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ 292706c3fb27SDimitry Andric TYPE_RECORD(EnumVal, EnumVal, AliasName) 292806c3fb27SDimitry Andric #define MEMBER_RECORD(EnumName, EnumVal, Name) 292906c3fb27SDimitry Andric #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) 293006c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewTypes.def" 293106c3fb27SDimitry Andric } 293206c3fb27SDimitry Andric 293306c3fb27SDimitry Andric return Error::success(); 293406c3fb27SDimitry Andric } 293506c3fb27SDimitry Andric 293606c3fb27SDimitry Andric // Customized version of 'FieldListVisitHelper'. 293706c3fb27SDimitry Andric Error LVLogicalVisitor::visitFieldListMemberStream( 293806c3fb27SDimitry Andric TypeIndex TI, LVElement *Element, ArrayRef<uint8_t> FieldList) { 29395f757f3fSDimitry Andric BinaryByteStream Stream(FieldList, llvm::endianness::little); 294006c3fb27SDimitry Andric BinaryStreamReader Reader(Stream); 294106c3fb27SDimitry Andric FieldListDeserializer Deserializer(Reader); 294206c3fb27SDimitry Andric TypeVisitorCallbackPipeline Pipeline; 294306c3fb27SDimitry Andric Pipeline.addCallbackToPipeline(Deserializer); 294406c3fb27SDimitry Andric 294506c3fb27SDimitry Andric TypeLeafKind Leaf; 294606c3fb27SDimitry Andric while (!Reader.empty()) { 294706c3fb27SDimitry Andric if (Error Err = Reader.readEnum(Leaf)) 294806c3fb27SDimitry Andric return Err; 294906c3fb27SDimitry Andric 295006c3fb27SDimitry Andric CVMemberRecord Record; 295106c3fb27SDimitry Andric Record.Kind = Leaf; 295206c3fb27SDimitry Andric if (Error Err = visitMemberRecord(Record, Pipeline, TI, Element)) 295306c3fb27SDimitry Andric return Err; 295406c3fb27SDimitry Andric } 295506c3fb27SDimitry Andric 295606c3fb27SDimitry Andric return Error::success(); 295706c3fb27SDimitry Andric } 295806c3fb27SDimitry Andric 295906c3fb27SDimitry Andric void LVLogicalVisitor::addElement(LVScope *Scope, bool IsCompileUnit) { 296006c3fb27SDimitry Andric // The CodeView specifications does not treat S_COMPILE2 and S_COMPILE3 296106c3fb27SDimitry Andric // as symbols that open a scope. The CodeView reader, treat them in a 296206c3fb27SDimitry Andric // similar way as DWARF. As there is no a symbole S_END to close the 296306c3fb27SDimitry Andric // compile unit, we need to check for the next compile unit. 296406c3fb27SDimitry Andric if (IsCompileUnit) { 296506c3fb27SDimitry Andric if (!ScopeStack.empty()) 296606c3fb27SDimitry Andric popScope(); 296706c3fb27SDimitry Andric InCompileUnitScope = true; 296806c3fb27SDimitry Andric } 296906c3fb27SDimitry Andric 297006c3fb27SDimitry Andric pushScope(Scope); 297106c3fb27SDimitry Andric ReaderParent->addElement(Scope); 297206c3fb27SDimitry Andric } 297306c3fb27SDimitry Andric 297406c3fb27SDimitry Andric void LVLogicalVisitor::addElement(LVSymbol *Symbol) { 297506c3fb27SDimitry Andric ReaderScope->addElement(Symbol); 297606c3fb27SDimitry Andric } 297706c3fb27SDimitry Andric 297806c3fb27SDimitry Andric void LVLogicalVisitor::addElement(LVType *Type) { 297906c3fb27SDimitry Andric ReaderScope->addElement(Type); 298006c3fb27SDimitry Andric } 298106c3fb27SDimitry Andric 298206c3fb27SDimitry Andric LVElement *LVLogicalVisitor::createElement(TypeLeafKind Kind) { 298306c3fb27SDimitry Andric CurrentScope = nullptr; 298406c3fb27SDimitry Andric CurrentSymbol = nullptr; 298506c3fb27SDimitry Andric CurrentType = nullptr; 298606c3fb27SDimitry Andric 298706c3fb27SDimitry Andric if (Kind < TypeIndex::FirstNonSimpleIndex) { 298806c3fb27SDimitry Andric CurrentType = Reader->createType(); 298906c3fb27SDimitry Andric CurrentType->setIsBase(); 299006c3fb27SDimitry Andric CurrentType->setTag(dwarf::DW_TAG_base_type); 299106c3fb27SDimitry Andric if (options().getAttributeBase()) 299206c3fb27SDimitry Andric CurrentType->setIncludeInPrint(); 299306c3fb27SDimitry Andric return CurrentType; 299406c3fb27SDimitry Andric } 299506c3fb27SDimitry Andric 299606c3fb27SDimitry Andric switch (Kind) { 299706c3fb27SDimitry Andric // Types. 299806c3fb27SDimitry Andric case TypeLeafKind::LF_ENUMERATE: 299906c3fb27SDimitry Andric CurrentType = Reader->createTypeEnumerator(); 300006c3fb27SDimitry Andric CurrentType->setTag(dwarf::DW_TAG_enumerator); 300106c3fb27SDimitry Andric return CurrentType; 300206c3fb27SDimitry Andric case TypeLeafKind::LF_MODIFIER: 300306c3fb27SDimitry Andric CurrentType = Reader->createType(); 300406c3fb27SDimitry Andric CurrentType->setIsModifier(); 300506c3fb27SDimitry Andric return CurrentType; 300606c3fb27SDimitry Andric case TypeLeafKind::LF_POINTER: 300706c3fb27SDimitry Andric CurrentType = Reader->createType(); 300806c3fb27SDimitry Andric CurrentType->setIsPointer(); 300906c3fb27SDimitry Andric CurrentType->setName("*"); 301006c3fb27SDimitry Andric CurrentType->setTag(dwarf::DW_TAG_pointer_type); 301106c3fb27SDimitry Andric return CurrentType; 301206c3fb27SDimitry Andric 301306c3fb27SDimitry Andric // Symbols. 301406c3fb27SDimitry Andric case TypeLeafKind::LF_BCLASS: 301506c3fb27SDimitry Andric case TypeLeafKind::LF_IVBCLASS: 301606c3fb27SDimitry Andric case TypeLeafKind::LF_VBCLASS: 301706c3fb27SDimitry Andric CurrentSymbol = Reader->createSymbol(); 301806c3fb27SDimitry Andric CurrentSymbol->setTag(dwarf::DW_TAG_inheritance); 301906c3fb27SDimitry Andric CurrentSymbol->setIsInheritance(); 302006c3fb27SDimitry Andric return CurrentSymbol; 302106c3fb27SDimitry Andric case TypeLeafKind::LF_MEMBER: 302206c3fb27SDimitry Andric case TypeLeafKind::LF_STMEMBER: 302306c3fb27SDimitry Andric CurrentSymbol = Reader->createSymbol(); 302406c3fb27SDimitry Andric CurrentSymbol->setIsMember(); 302506c3fb27SDimitry Andric CurrentSymbol->setTag(dwarf::DW_TAG_member); 302606c3fb27SDimitry Andric return CurrentSymbol; 302706c3fb27SDimitry Andric 302806c3fb27SDimitry Andric // Scopes. 302906c3fb27SDimitry Andric case TypeLeafKind::LF_ARRAY: 303006c3fb27SDimitry Andric CurrentScope = Reader->createScopeArray(); 303106c3fb27SDimitry Andric CurrentScope->setTag(dwarf::DW_TAG_array_type); 303206c3fb27SDimitry Andric return CurrentScope; 303306c3fb27SDimitry Andric case TypeLeafKind::LF_CLASS: 303406c3fb27SDimitry Andric CurrentScope = Reader->createScopeAggregate(); 303506c3fb27SDimitry Andric CurrentScope->setTag(dwarf::DW_TAG_class_type); 303606c3fb27SDimitry Andric CurrentScope->setIsClass(); 303706c3fb27SDimitry Andric return CurrentScope; 303806c3fb27SDimitry Andric case TypeLeafKind::LF_ENUM: 303906c3fb27SDimitry Andric CurrentScope = Reader->createScopeEnumeration(); 304006c3fb27SDimitry Andric CurrentScope->setTag(dwarf::DW_TAG_enumeration_type); 304106c3fb27SDimitry Andric return CurrentScope; 304206c3fb27SDimitry Andric case TypeLeafKind::LF_METHOD: 304306c3fb27SDimitry Andric case TypeLeafKind::LF_ONEMETHOD: 304406c3fb27SDimitry Andric case TypeLeafKind::LF_PROCEDURE: 304506c3fb27SDimitry Andric CurrentScope = Reader->createScopeFunction(); 304606c3fb27SDimitry Andric CurrentScope->setIsSubprogram(); 304706c3fb27SDimitry Andric CurrentScope->setTag(dwarf::DW_TAG_subprogram); 304806c3fb27SDimitry Andric return CurrentScope; 304906c3fb27SDimitry Andric case TypeLeafKind::LF_STRUCTURE: 305006c3fb27SDimitry Andric CurrentScope = Reader->createScopeAggregate(); 305106c3fb27SDimitry Andric CurrentScope->setIsStructure(); 305206c3fb27SDimitry Andric CurrentScope->setTag(dwarf::DW_TAG_structure_type); 305306c3fb27SDimitry Andric return CurrentScope; 305406c3fb27SDimitry Andric case TypeLeafKind::LF_UNION: 305506c3fb27SDimitry Andric CurrentScope = Reader->createScopeAggregate(); 305606c3fb27SDimitry Andric CurrentScope->setIsUnion(); 305706c3fb27SDimitry Andric CurrentScope->setTag(dwarf::DW_TAG_union_type); 305806c3fb27SDimitry Andric return CurrentScope; 305906c3fb27SDimitry Andric default: 306006c3fb27SDimitry Andric // If '--internal=tag' and '--print=warning' are specified in the command 306106c3fb27SDimitry Andric // line, we record and print each seen 'TypeLeafKind'. 306206c3fb27SDimitry Andric break; 306306c3fb27SDimitry Andric } 306406c3fb27SDimitry Andric return nullptr; 306506c3fb27SDimitry Andric } 306606c3fb27SDimitry Andric 306706c3fb27SDimitry Andric LVElement *LVLogicalVisitor::createElement(SymbolKind Kind) { 306806c3fb27SDimitry Andric CurrentScope = nullptr; 306906c3fb27SDimitry Andric CurrentSymbol = nullptr; 307006c3fb27SDimitry Andric CurrentType = nullptr; 307106c3fb27SDimitry Andric switch (Kind) { 307206c3fb27SDimitry Andric // Types. 307306c3fb27SDimitry Andric case SymbolKind::S_UDT: 307406c3fb27SDimitry Andric CurrentType = Reader->createTypeDefinition(); 307506c3fb27SDimitry Andric CurrentType->setTag(dwarf::DW_TAG_typedef); 307606c3fb27SDimitry Andric return CurrentType; 307706c3fb27SDimitry Andric 307806c3fb27SDimitry Andric // Symbols. 307906c3fb27SDimitry Andric case SymbolKind::S_CONSTANT: 308006c3fb27SDimitry Andric CurrentSymbol = Reader->createSymbol(); 308106c3fb27SDimitry Andric CurrentSymbol->setIsConstant(); 308206c3fb27SDimitry Andric CurrentSymbol->setTag(dwarf::DW_TAG_constant); 308306c3fb27SDimitry Andric return CurrentSymbol; 308406c3fb27SDimitry Andric 308506c3fb27SDimitry Andric case SymbolKind::S_BPREL32: 308606c3fb27SDimitry Andric case SymbolKind::S_REGREL32: 308706c3fb27SDimitry Andric case SymbolKind::S_GDATA32: 308806c3fb27SDimitry Andric case SymbolKind::S_LDATA32: 308906c3fb27SDimitry Andric case SymbolKind::S_LOCAL: 309006c3fb27SDimitry Andric // During the symbol traversal more information is available to 309106c3fb27SDimitry Andric // determine if the symbol is a parameter or a variable. At this 309206c3fb27SDimitry Andric // stage mark it as variable. 309306c3fb27SDimitry Andric CurrentSymbol = Reader->createSymbol(); 309406c3fb27SDimitry Andric CurrentSymbol->setIsVariable(); 309506c3fb27SDimitry Andric CurrentSymbol->setTag(dwarf::DW_TAG_variable); 309606c3fb27SDimitry Andric return CurrentSymbol; 309706c3fb27SDimitry Andric 309806c3fb27SDimitry Andric // Scopes. 309906c3fb27SDimitry Andric case SymbolKind::S_BLOCK32: 310006c3fb27SDimitry Andric CurrentScope = Reader->createScope(); 310106c3fb27SDimitry Andric CurrentScope->setIsLexicalBlock(); 310206c3fb27SDimitry Andric CurrentScope->setTag(dwarf::DW_TAG_lexical_block); 310306c3fb27SDimitry Andric return CurrentScope; 310406c3fb27SDimitry Andric case SymbolKind::S_COMPILE2: 310506c3fb27SDimitry Andric case SymbolKind::S_COMPILE3: 310606c3fb27SDimitry Andric CurrentScope = Reader->createScopeCompileUnit(); 310706c3fb27SDimitry Andric CurrentScope->setTag(dwarf::DW_TAG_compile_unit); 310806c3fb27SDimitry Andric Reader->setCompileUnit(static_cast<LVScopeCompileUnit *>(CurrentScope)); 310906c3fb27SDimitry Andric return CurrentScope; 311006c3fb27SDimitry Andric case SymbolKind::S_INLINESITE: 311106c3fb27SDimitry Andric case SymbolKind::S_INLINESITE2: 311206c3fb27SDimitry Andric CurrentScope = Reader->createScopeFunctionInlined(); 311306c3fb27SDimitry Andric CurrentScope->setIsInlinedFunction(); 311406c3fb27SDimitry Andric CurrentScope->setTag(dwarf::DW_TAG_inlined_subroutine); 311506c3fb27SDimitry Andric return CurrentScope; 311606c3fb27SDimitry Andric case SymbolKind::S_LPROC32: 311706c3fb27SDimitry Andric case SymbolKind::S_GPROC32: 311806c3fb27SDimitry Andric case SymbolKind::S_LPROC32_ID: 311906c3fb27SDimitry Andric case SymbolKind::S_GPROC32_ID: 312006c3fb27SDimitry Andric case SymbolKind::S_SEPCODE: 312106c3fb27SDimitry Andric case SymbolKind::S_THUNK32: 312206c3fb27SDimitry Andric CurrentScope = Reader->createScopeFunction(); 312306c3fb27SDimitry Andric CurrentScope->setIsSubprogram(); 312406c3fb27SDimitry Andric CurrentScope->setTag(dwarf::DW_TAG_subprogram); 312506c3fb27SDimitry Andric return CurrentScope; 312606c3fb27SDimitry Andric default: 312706c3fb27SDimitry Andric // If '--internal=tag' and '--print=warning' are specified in the command 312806c3fb27SDimitry Andric // line, we record and print each seen 'SymbolKind'. 312906c3fb27SDimitry Andric break; 313006c3fb27SDimitry Andric } 313106c3fb27SDimitry Andric return nullptr; 313206c3fb27SDimitry Andric } 313306c3fb27SDimitry Andric 313406c3fb27SDimitry Andric LVElement *LVLogicalVisitor::createElement(TypeIndex TI, TypeLeafKind Kind) { 313506c3fb27SDimitry Andric LVElement *Element = Shared->TypeRecords.find(StreamTPI, TI); 313606c3fb27SDimitry Andric if (!Element) { 313706c3fb27SDimitry Andric // We are dealing with a base type or pointer to a base type, which are 313806c3fb27SDimitry Andric // not included explicitly in the CodeView format. 313906c3fb27SDimitry Andric if (Kind < TypeIndex::FirstNonSimpleIndex) { 314006c3fb27SDimitry Andric Element = createElement(Kind); 314106c3fb27SDimitry Andric Element->setIsFinalized(); 314206c3fb27SDimitry Andric Shared->TypeRecords.add(StreamTPI, (TypeIndex)Kind, Kind, Element); 314306c3fb27SDimitry Andric Element->setOffset(Kind); 314406c3fb27SDimitry Andric return Element; 314506c3fb27SDimitry Andric } 314606c3fb27SDimitry Andric // We are dealing with a pointer to a base type. 314706c3fb27SDimitry Andric if (TI.getIndex() < TypeIndex::FirstNonSimpleIndex) { 314806c3fb27SDimitry Andric Element = createElement(Kind); 314906c3fb27SDimitry Andric Shared->TypeRecords.add(StreamTPI, TI, Kind, Element); 315006c3fb27SDimitry Andric Element->setOffset(TI.getIndex()); 315106c3fb27SDimitry Andric Element->setOffsetFromTypeIndex(); 315206c3fb27SDimitry Andric return Element; 315306c3fb27SDimitry Andric } 315406c3fb27SDimitry Andric 315506c3fb27SDimitry Andric W.printString("** Not implemented. **"); 315606c3fb27SDimitry Andric printTypeIndex("TypeIndex", TI, StreamTPI); 315706c3fb27SDimitry Andric W.printString("TypeLeafKind", formatTypeLeafKind(Kind)); 315806c3fb27SDimitry Andric return nullptr; 315906c3fb27SDimitry Andric } 316006c3fb27SDimitry Andric 316106c3fb27SDimitry Andric Element->setOffset(TI.getIndex()); 316206c3fb27SDimitry Andric Element->setOffsetFromTypeIndex(); 316306c3fb27SDimitry Andric return Element; 316406c3fb27SDimitry Andric } 316506c3fb27SDimitry Andric 316606c3fb27SDimitry Andric void LVLogicalVisitor::createDataMember(CVMemberRecord &Record, LVScope *Parent, 316706c3fb27SDimitry Andric StringRef Name, TypeIndex TI, 316806c3fb27SDimitry Andric MemberAccess Access) { 316906c3fb27SDimitry Andric LLVM_DEBUG({ 317006c3fb27SDimitry Andric printTypeIndex("TypeIndex", TI, StreamTPI); 317106c3fb27SDimitry Andric W.printString("TypeName", Name); 317206c3fb27SDimitry Andric }); 317306c3fb27SDimitry Andric 317406c3fb27SDimitry Andric createElement(Record.Kind); 317506c3fb27SDimitry Andric if (LVSymbol *Symbol = CurrentSymbol) { 317606c3fb27SDimitry Andric Symbol->setName(Name); 317706c3fb27SDimitry Andric if (TI.isNoneType() || TI.isSimple()) 317806c3fb27SDimitry Andric Symbol->setType(getElement(StreamTPI, TI)); 317906c3fb27SDimitry Andric else { 318006c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types(); 318106c3fb27SDimitry Andric CVType CVMemberType = Types.getType(TI); 318206c3fb27SDimitry Andric if (CVMemberType.kind() == LF_BITFIELD) { 318306c3fb27SDimitry Andric if (Error Err = finishVisitation(CVMemberType, TI, Symbol)) { 318406c3fb27SDimitry Andric consumeError(std::move(Err)); 318506c3fb27SDimitry Andric return; 318606c3fb27SDimitry Andric } 318706c3fb27SDimitry Andric } else 318806c3fb27SDimitry Andric Symbol->setType(getElement(StreamTPI, TI)); 318906c3fb27SDimitry Andric } 319006c3fb27SDimitry Andric Symbol->setAccessibilityCode(Access); 319106c3fb27SDimitry Andric Parent->addElement(Symbol); 319206c3fb27SDimitry Andric } 319306c3fb27SDimitry Andric } 319406c3fb27SDimitry Andric 319506c3fb27SDimitry Andric LVSymbol *LVLogicalVisitor::createParameter(LVElement *Element, StringRef Name, 319606c3fb27SDimitry Andric LVScope *Parent) { 319706c3fb27SDimitry Andric LVSymbol *Parameter = Reader->createSymbol(); 319806c3fb27SDimitry Andric Parent->addElement(Parameter); 319906c3fb27SDimitry Andric Parameter->setIsParameter(); 320006c3fb27SDimitry Andric Parameter->setTag(dwarf::DW_TAG_formal_parameter); 320106c3fb27SDimitry Andric Parameter->setName(Name); 320206c3fb27SDimitry Andric Parameter->setType(Element); 320306c3fb27SDimitry Andric return Parameter; 320406c3fb27SDimitry Andric } 320506c3fb27SDimitry Andric 320606c3fb27SDimitry Andric LVSymbol *LVLogicalVisitor::createParameter(TypeIndex TI, StringRef Name, 320706c3fb27SDimitry Andric LVScope *Parent) { 320806c3fb27SDimitry Andric return createParameter(getElement(StreamTPI, TI), Name, Parent); 320906c3fb27SDimitry Andric } 321006c3fb27SDimitry Andric 321106c3fb27SDimitry Andric LVType *LVLogicalVisitor::createBaseType(TypeIndex TI, StringRef TypeName) { 321206c3fb27SDimitry Andric TypeLeafKind SimpleKind = (TypeLeafKind)TI.getSimpleKind(); 321306c3fb27SDimitry Andric TypeIndex TIR = (TypeIndex)SimpleKind; 321406c3fb27SDimitry Andric LLVM_DEBUG({ 321506c3fb27SDimitry Andric printTypeIndex("TypeIndex", TIR, StreamTPI); 321606c3fb27SDimitry Andric W.printString("TypeName", TypeName); 321706c3fb27SDimitry Andric }); 321806c3fb27SDimitry Andric 321906c3fb27SDimitry Andric if (LVElement *Element = Shared->TypeRecords.find(StreamTPI, TIR)) 322006c3fb27SDimitry Andric return static_cast<LVType *>(Element); 322106c3fb27SDimitry Andric 322206c3fb27SDimitry Andric if (createElement(TIR, SimpleKind)) { 322306c3fb27SDimitry Andric CurrentType->setName(TypeName); 322406c3fb27SDimitry Andric Reader->getCompileUnit()->addElement(CurrentType); 322506c3fb27SDimitry Andric } 322606c3fb27SDimitry Andric return CurrentType; 322706c3fb27SDimitry Andric } 322806c3fb27SDimitry Andric 322906c3fb27SDimitry Andric LVType *LVLogicalVisitor::createPointerType(TypeIndex TI, StringRef TypeName) { 323006c3fb27SDimitry Andric LLVM_DEBUG({ 323106c3fb27SDimitry Andric printTypeIndex("TypeIndex", TI, StreamTPI); 323206c3fb27SDimitry Andric W.printString("TypeName", TypeName); 323306c3fb27SDimitry Andric }); 323406c3fb27SDimitry Andric 323506c3fb27SDimitry Andric if (LVElement *Element = Shared->TypeRecords.find(StreamTPI, TI)) 323606c3fb27SDimitry Andric return static_cast<LVType *>(Element); 323706c3fb27SDimitry Andric 323806c3fb27SDimitry Andric LVType *Pointee = createBaseType(TI, TypeName.drop_back(1)); 323906c3fb27SDimitry Andric if (createElement(TI, TypeLeafKind::LF_POINTER)) { 324006c3fb27SDimitry Andric CurrentType->setIsFinalized(); 324106c3fb27SDimitry Andric CurrentType->setType(Pointee); 324206c3fb27SDimitry Andric Reader->getCompileUnit()->addElement(CurrentType); 324306c3fb27SDimitry Andric } 324406c3fb27SDimitry Andric return CurrentType; 324506c3fb27SDimitry Andric } 324606c3fb27SDimitry Andric 324706c3fb27SDimitry Andric void LVLogicalVisitor::createParents(StringRef ScopedName, LVElement *Element) { 324806c3fb27SDimitry Andric // For the given test case: 324906c3fb27SDimitry Andric // 325006c3fb27SDimitry Andric // struct S { enum E { ... }; }; 325106c3fb27SDimitry Andric // S::E V; 325206c3fb27SDimitry Andric // 325306c3fb27SDimitry Andric // 0 | S_LOCAL `V` 325406c3fb27SDimitry Andric // type=0x1004 (S::E), flags = none 325506c3fb27SDimitry Andric // 0x1004 | LF_ENUM `S::E` 325606c3fb27SDimitry Andric // options: has unique name | is nested 325706c3fb27SDimitry Andric // 0x1009 | LF_STRUCTURE `S` 325806c3fb27SDimitry Andric // options: contains nested class 325906c3fb27SDimitry Andric // 326006c3fb27SDimitry Andric // When the local 'V' is processed, its type 'E' is created. But There is 326106c3fb27SDimitry Andric // no direct reference to its parent 'S'. We use the scoped name for 'E', 326206c3fb27SDimitry Andric // to create its parents. 326306c3fb27SDimitry Andric 326406c3fb27SDimitry Andric // The input scoped name must have at least parent and nested names. 326506c3fb27SDimitry Andric // Drop the last element name, as it corresponds to the nested type. 326606c3fb27SDimitry Andric LVStringRefs Components = getAllLexicalComponents(ScopedName); 326706c3fb27SDimitry Andric if (Components.size() < 2) 326806c3fb27SDimitry Andric return; 326906c3fb27SDimitry Andric Components.pop_back(); 327006c3fb27SDimitry Andric 327106c3fb27SDimitry Andric LVStringRefs::size_type FirstNamespace; 327206c3fb27SDimitry Andric LVStringRefs::size_type FirstAggregate; 327306c3fb27SDimitry Andric std::tie(FirstNamespace, FirstAggregate) = 327406c3fb27SDimitry Andric Shared->NamespaceDeduction.find(Components); 327506c3fb27SDimitry Andric 327606c3fb27SDimitry Andric LLVM_DEBUG({ 327706c3fb27SDimitry Andric W.printString("First Namespace", Components[FirstNamespace]); 327806c3fb27SDimitry Andric W.printString("First NonNamespace", Components[FirstAggregate]); 327906c3fb27SDimitry Andric }); 328006c3fb27SDimitry Andric 328106c3fb27SDimitry Andric // Create any referenced namespaces. 328206c3fb27SDimitry Andric if (FirstNamespace < FirstAggregate) { 328306c3fb27SDimitry Andric Shared->NamespaceDeduction.get( 328406c3fb27SDimitry Andric LVStringRefs(Components.begin() + FirstNamespace, 328506c3fb27SDimitry Andric Components.begin() + FirstAggregate)); 328606c3fb27SDimitry Andric } 328706c3fb27SDimitry Andric 328806c3fb27SDimitry Andric // Traverse the enclosing scopes (aggregates) and create them. In the 328906c3fb27SDimitry Andric // case of nested empty aggregates, MSVC does not emit a full record 329006c3fb27SDimitry Andric // description. It emits only the reference record. 329106c3fb27SDimitry Andric LVScope *Aggregate = nullptr; 329206c3fb27SDimitry Andric TypeIndex TIAggregate; 329306c3fb27SDimitry Andric std::string AggregateName = getScopedName( 329406c3fb27SDimitry Andric LVStringRefs(Components.begin(), Components.begin() + FirstAggregate)); 329506c3fb27SDimitry Andric 329606c3fb27SDimitry Andric // This traversal is executed at least once. 329706c3fb27SDimitry Andric for (LVStringRefs::size_type Index = FirstAggregate; 329806c3fb27SDimitry Andric Index < Components.size(); ++Index) { 329906c3fb27SDimitry Andric AggregateName = getScopedName(LVStringRefs(Components.begin() + Index, 330006c3fb27SDimitry Andric Components.begin() + Index + 1), 330106c3fb27SDimitry Andric AggregateName); 330206c3fb27SDimitry Andric TIAggregate = Shared->ForwardReferences.remap( 330306c3fb27SDimitry Andric Shared->TypeRecords.find(StreamTPI, AggregateName)); 330406c3fb27SDimitry Andric Aggregate = 330506c3fb27SDimitry Andric TIAggregate.isNoneType() 330606c3fb27SDimitry Andric ? nullptr 330706c3fb27SDimitry Andric : static_cast<LVScope *>(getElement(StreamTPI, TIAggregate)); 330806c3fb27SDimitry Andric } 330906c3fb27SDimitry Andric 331006c3fb27SDimitry Andric // Workaround for cases where LF_NESTTYPE is missing for nested templates. 331106c3fb27SDimitry Andric // If we manage to get parent information from the scoped name, we can add 331206c3fb27SDimitry Andric // the nested type without relying on the LF_NESTTYPE. 331306c3fb27SDimitry Andric if (Aggregate && !Element->getIsScopedAlready()) { 331406c3fb27SDimitry Andric Aggregate->addElement(Element); 331506c3fb27SDimitry Andric Element->setIsScopedAlready(); 331606c3fb27SDimitry Andric } 331706c3fb27SDimitry Andric } 331806c3fb27SDimitry Andric 331906c3fb27SDimitry Andric LVElement *LVLogicalVisitor::getElement(uint32_t StreamIdx, TypeIndex TI, 332006c3fb27SDimitry Andric LVScope *Parent) { 332106c3fb27SDimitry Andric LLVM_DEBUG({ printTypeIndex("TypeIndex", TI, StreamTPI); }); 332206c3fb27SDimitry Andric TI = Shared->ForwardReferences.remap(TI); 332306c3fb27SDimitry Andric LLVM_DEBUG({ printTypeIndex("TypeIndex Remap", TI, StreamTPI); }); 332406c3fb27SDimitry Andric 332506c3fb27SDimitry Andric LVElement *Element = Shared->TypeRecords.find(StreamIdx, TI); 332606c3fb27SDimitry Andric if (!Element) { 332706c3fb27SDimitry Andric if (TI.isNoneType() || TI.isSimple()) { 332806c3fb27SDimitry Andric StringRef TypeName = TypeIndex::simpleTypeName(TI); 332906c3fb27SDimitry Andric // If the name ends with "*", create 2 logical types: a pointer and a 333006c3fb27SDimitry Andric // pointee type. TypeIndex is composed of a SympleTypeMode byte followed 333106c3fb27SDimitry Andric // by a SimpleTypeKind byte. The logical pointer will be identified by 333206c3fb27SDimitry Andric // the full TypeIndex value and the pointee by the SimpleTypeKind. 333306c3fb27SDimitry Andric return (TypeName.back() == '*') ? createPointerType(TI, TypeName) 333406c3fb27SDimitry Andric : createBaseType(TI, TypeName); 333506c3fb27SDimitry Andric } 333606c3fb27SDimitry Andric 333706c3fb27SDimitry Andric LLVM_DEBUG({ W.printHex("TypeIndex not implemented: ", TI.getIndex()); }); 333806c3fb27SDimitry Andric return nullptr; 333906c3fb27SDimitry Andric } 334006c3fb27SDimitry Andric 334106c3fb27SDimitry Andric // The element has been finalized. 334206c3fb27SDimitry Andric if (Element->getIsFinalized()) 334306c3fb27SDimitry Andric return Element; 334406c3fb27SDimitry Andric 334506c3fb27SDimitry Andric // Add the element in case of a given parent. 334606c3fb27SDimitry Andric if (Parent) 334706c3fb27SDimitry Andric Parent->addElement(Element); 334806c3fb27SDimitry Andric 334906c3fb27SDimitry Andric // Check for a composite type. 335006c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types(); 335106c3fb27SDimitry Andric CVType CVRecord = Types.getType(TI); 335206c3fb27SDimitry Andric if (Error Err = finishVisitation(CVRecord, TI, Element)) { 335306c3fb27SDimitry Andric consumeError(std::move(Err)); 335406c3fb27SDimitry Andric return nullptr; 335506c3fb27SDimitry Andric } 335606c3fb27SDimitry Andric Element->setIsFinalized(); 335706c3fb27SDimitry Andric return Element; 335806c3fb27SDimitry Andric } 335906c3fb27SDimitry Andric 336006c3fb27SDimitry Andric void LVLogicalVisitor::processLines() { 336106c3fb27SDimitry Andric // Traverse the collected LF_UDT_SRC_LINE records and add the source line 336206c3fb27SDimitry Andric // information to the logical elements. 336306c3fb27SDimitry Andric for (const TypeIndex &Entry : Shared->LineRecords) { 336406c3fb27SDimitry Andric CVType CVRecord = ids().getType(Entry); 336506c3fb27SDimitry Andric UdtSourceLineRecord Line; 336606c3fb27SDimitry Andric if (Error Err = TypeDeserializer::deserializeAs( 336706c3fb27SDimitry Andric const_cast<CVType &>(CVRecord), Line)) 336806c3fb27SDimitry Andric consumeError(std::move(Err)); 336906c3fb27SDimitry Andric else { 337006c3fb27SDimitry Andric LLVM_DEBUG({ 337106c3fb27SDimitry Andric printTypeIndex("UDT", Line.getUDT(), StreamIPI); 337206c3fb27SDimitry Andric printTypeIndex("SourceFile", Line.getSourceFile(), StreamIPI); 337306c3fb27SDimitry Andric W.printNumber("LineNumber", Line.getLineNumber()); 337406c3fb27SDimitry Andric }); 337506c3fb27SDimitry Andric 337606c3fb27SDimitry Andric // The TypeIndex returned by 'getUDT()' must point to an already 337706c3fb27SDimitry Andric // created logical element. If no logical element is found, it means 337806c3fb27SDimitry Andric // the LF_UDT_SRC_LINE is associated with a system TypeIndex. 337906c3fb27SDimitry Andric if (LVElement *Element = Shared->TypeRecords.find( 338006c3fb27SDimitry Andric StreamTPI, Line.getUDT(), /*Create=*/false)) { 338106c3fb27SDimitry Andric Element->setLineNumber(Line.getLineNumber()); 338206c3fb27SDimitry Andric Element->setFilenameIndex( 338306c3fb27SDimitry Andric Shared->StringRecords.findIndex(Line.getSourceFile())); 338406c3fb27SDimitry Andric } 338506c3fb27SDimitry Andric } 338606c3fb27SDimitry Andric } 338706c3fb27SDimitry Andric } 338806c3fb27SDimitry Andric 338906c3fb27SDimitry Andric void LVLogicalVisitor::processNamespaces() { 339006c3fb27SDimitry Andric // Create namespaces. 339106c3fb27SDimitry Andric Shared->NamespaceDeduction.init(); 339206c3fb27SDimitry Andric } 339306c3fb27SDimitry Andric 339406c3fb27SDimitry Andric void LVLogicalVisitor::processFiles() { Shared->StringRecords.addFilenames(); } 339506c3fb27SDimitry Andric 339606c3fb27SDimitry Andric void LVLogicalVisitor::printRecords(raw_ostream &OS) const { 339706c3fb27SDimitry Andric if (!options().getInternalTag()) 339806c3fb27SDimitry Andric return; 339906c3fb27SDimitry Andric 340006c3fb27SDimitry Andric unsigned Count = 0; 340106c3fb27SDimitry Andric auto PrintItem = [&](StringRef Name) { 340206c3fb27SDimitry Andric auto NewLine = [&]() { 340306c3fb27SDimitry Andric if (++Count == 4) { 340406c3fb27SDimitry Andric Count = 0; 340506c3fb27SDimitry Andric OS << "\n"; 340606c3fb27SDimitry Andric } 340706c3fb27SDimitry Andric }; 340806c3fb27SDimitry Andric OS << format("%20s", Name.str().c_str()); 340906c3fb27SDimitry Andric NewLine(); 341006c3fb27SDimitry Andric }; 341106c3fb27SDimitry Andric 341206c3fb27SDimitry Andric OS << "\nTypes:\n"; 341306c3fb27SDimitry Andric for (const TypeLeafKind &Kind : Shared->TypeKinds) 341406c3fb27SDimitry Andric PrintItem(formatTypeLeafKind(Kind)); 341506c3fb27SDimitry Andric Shared->TypeKinds.clear(); 341606c3fb27SDimitry Andric 341706c3fb27SDimitry Andric Count = 0; 341806c3fb27SDimitry Andric OS << "\nSymbols:\n"; 341906c3fb27SDimitry Andric for (const SymbolKind &Kind : Shared->SymbolKinds) 342006c3fb27SDimitry Andric PrintItem(LVCodeViewReader::getSymbolKindName(Kind)); 342106c3fb27SDimitry Andric Shared->SymbolKinds.clear(); 342206c3fb27SDimitry Andric 342306c3fb27SDimitry Andric OS << "\n"; 342406c3fb27SDimitry Andric } 342506c3fb27SDimitry Andric 342606c3fb27SDimitry Andric Error LVLogicalVisitor::inlineSiteAnnotation(LVScope *AbstractFunction, 342706c3fb27SDimitry Andric LVScope *InlinedFunction, 342806c3fb27SDimitry Andric InlineSiteSym &InlineSite) { 342906c3fb27SDimitry Andric // Get the parent scope to update the address ranges of the nested 343006c3fb27SDimitry Andric // scope representing the inlined function. 343106c3fb27SDimitry Andric LVAddress ParentLowPC = 0; 343206c3fb27SDimitry Andric LVScope *Parent = InlinedFunction->getParentScope(); 343306c3fb27SDimitry Andric if (const LVLocations *Locations = Parent->getRanges()) { 343406c3fb27SDimitry Andric if (!Locations->empty()) 343506c3fb27SDimitry Andric ParentLowPC = (*Locations->begin())->getLowerAddress(); 343606c3fb27SDimitry Andric } 343706c3fb27SDimitry Andric 343806c3fb27SDimitry Andric // For the given inlinesite, get the initial line number and its 343906c3fb27SDimitry Andric // source filename. Update the logical scope representing it. 344006c3fb27SDimitry Andric uint32_t LineNumber = 0; 344106c3fb27SDimitry Andric StringRef Filename; 344206c3fb27SDimitry Andric LVInlineeInfo::iterator Iter = InlineeInfo.find(InlineSite.Inlinee); 344306c3fb27SDimitry Andric if (Iter != InlineeInfo.end()) { 344406c3fb27SDimitry Andric LineNumber = Iter->second.first; 344506c3fb27SDimitry Andric Filename = Iter->second.second; 344606c3fb27SDimitry Andric AbstractFunction->setLineNumber(LineNumber); 344706c3fb27SDimitry Andric // TODO: This part needs additional work in order to set properly the 344806c3fb27SDimitry Andric // correct filename in order to detect changes between filenames. 344906c3fb27SDimitry Andric // AbstractFunction->setFilename(Filename); 345006c3fb27SDimitry Andric } 345106c3fb27SDimitry Andric 345206c3fb27SDimitry Andric LLVM_DEBUG({ 345306c3fb27SDimitry Andric dbgs() << "inlineSiteAnnotation\n" 345406c3fb27SDimitry Andric << "Abstract: " << AbstractFunction->getName() << "\n" 345506c3fb27SDimitry Andric << "Inlined: " << InlinedFunction->getName() << "\n" 345606c3fb27SDimitry Andric << "Parent: " << Parent->getName() << "\n" 345706c3fb27SDimitry Andric << "Low PC: " << hexValue(ParentLowPC) << "\n"; 345806c3fb27SDimitry Andric }); 345906c3fb27SDimitry Andric 346006c3fb27SDimitry Andric // Get the source lines if requested by command line option. 346106c3fb27SDimitry Andric if (!options().getPrintLines()) 346206c3fb27SDimitry Andric return Error::success(); 346306c3fb27SDimitry Andric 346406c3fb27SDimitry Andric // Limitation: Currently we don't track changes in the FileOffset. The 346506c3fb27SDimitry Andric // side effects are the caller that it is unable to differentiate the 346606c3fb27SDimitry Andric // source filename for the inlined code. 346706c3fb27SDimitry Andric uint64_t CodeOffset = ParentLowPC; 346806c3fb27SDimitry Andric int32_t LineOffset = LineNumber; 346906c3fb27SDimitry Andric uint32_t FileOffset = 0; 347006c3fb27SDimitry Andric 347106c3fb27SDimitry Andric auto UpdateClose = [&]() { LLVM_DEBUG({ dbgs() << ("\n"); }); }; 347206c3fb27SDimitry Andric auto UpdateCodeOffset = [&](uint32_t Delta) { 347306c3fb27SDimitry Andric CodeOffset += Delta; 347406c3fb27SDimitry Andric LLVM_DEBUG({ 347506c3fb27SDimitry Andric dbgs() << formatv(" code 0x{0} (+0x{1})", utohexstr(CodeOffset), 347606c3fb27SDimitry Andric utohexstr(Delta)); 347706c3fb27SDimitry Andric }); 347806c3fb27SDimitry Andric }; 347906c3fb27SDimitry Andric auto UpdateLineOffset = [&](int32_t Delta) { 348006c3fb27SDimitry Andric LineOffset += Delta; 348106c3fb27SDimitry Andric LLVM_DEBUG({ 348206c3fb27SDimitry Andric char Sign = Delta > 0 ? '+' : '-'; 348306c3fb27SDimitry Andric dbgs() << formatv(" line {0} ({1}{2})", LineOffset, Sign, 348406c3fb27SDimitry Andric std::abs(Delta)); 348506c3fb27SDimitry Andric }); 348606c3fb27SDimitry Andric }; 348706c3fb27SDimitry Andric auto UpdateFileOffset = [&](int32_t Offset) { 348806c3fb27SDimitry Andric FileOffset = Offset; 348906c3fb27SDimitry Andric LLVM_DEBUG({ dbgs() << formatv(" file {0}", FileOffset); }); 349006c3fb27SDimitry Andric }; 349106c3fb27SDimitry Andric 349206c3fb27SDimitry Andric LVLines InlineeLines; 349306c3fb27SDimitry Andric auto CreateLine = [&]() { 349406c3fb27SDimitry Andric // Create the logical line record. 349506c3fb27SDimitry Andric LVLineDebug *Line = Reader->createLineDebug(); 349606c3fb27SDimitry Andric Line->setAddress(CodeOffset); 349706c3fb27SDimitry Andric Line->setLineNumber(LineOffset); 349806c3fb27SDimitry Andric // TODO: This part needs additional work in order to set properly the 349906c3fb27SDimitry Andric // correct filename in order to detect changes between filenames. 350006c3fb27SDimitry Andric // Line->setFilename(Filename); 350106c3fb27SDimitry Andric InlineeLines.push_back(Line); 350206c3fb27SDimitry Andric }; 350306c3fb27SDimitry Andric 350406c3fb27SDimitry Andric bool SeenLowAddress = false; 350506c3fb27SDimitry Andric bool SeenHighAddress = false; 350606c3fb27SDimitry Andric uint64_t LowPC = 0; 350706c3fb27SDimitry Andric uint64_t HighPC = 0; 350806c3fb27SDimitry Andric 350906c3fb27SDimitry Andric for (auto &Annot : InlineSite.annotations()) { 351006c3fb27SDimitry Andric LLVM_DEBUG({ 351106c3fb27SDimitry Andric dbgs() << formatv(" {0}", 351206c3fb27SDimitry Andric fmt_align(toHex(Annot.Bytes), AlignStyle::Left, 9)); 351306c3fb27SDimitry Andric }); 351406c3fb27SDimitry Andric 351506c3fb27SDimitry Andric // Use the opcode to interpret the integer values. 351606c3fb27SDimitry Andric switch (Annot.OpCode) { 351706c3fb27SDimitry Andric case BinaryAnnotationsOpCode::ChangeCodeOffset: 351806c3fb27SDimitry Andric case BinaryAnnotationsOpCode::CodeOffset: 351906c3fb27SDimitry Andric case BinaryAnnotationsOpCode::ChangeCodeLength: 352006c3fb27SDimitry Andric UpdateCodeOffset(Annot.U1); 352106c3fb27SDimitry Andric UpdateClose(); 352206c3fb27SDimitry Andric if (Annot.OpCode == BinaryAnnotationsOpCode::ChangeCodeOffset) { 352306c3fb27SDimitry Andric CreateLine(); 352406c3fb27SDimitry Andric LowPC = CodeOffset; 352506c3fb27SDimitry Andric SeenLowAddress = true; 352606c3fb27SDimitry Andric break; 352706c3fb27SDimitry Andric } 352806c3fb27SDimitry Andric if (Annot.OpCode == BinaryAnnotationsOpCode::ChangeCodeLength) { 352906c3fb27SDimitry Andric HighPC = CodeOffset - 1; 353006c3fb27SDimitry Andric SeenHighAddress = true; 353106c3fb27SDimitry Andric } 353206c3fb27SDimitry Andric break; 353306c3fb27SDimitry Andric case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: 353406c3fb27SDimitry Andric UpdateCodeOffset(Annot.U2); 353506c3fb27SDimitry Andric UpdateClose(); 353606c3fb27SDimitry Andric break; 353706c3fb27SDimitry Andric case BinaryAnnotationsOpCode::ChangeLineOffset: 353806c3fb27SDimitry Andric case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: 353906c3fb27SDimitry Andric UpdateCodeOffset(Annot.U1); 354006c3fb27SDimitry Andric UpdateLineOffset(Annot.S1); 354106c3fb27SDimitry Andric UpdateClose(); 354206c3fb27SDimitry Andric if (Annot.OpCode == 354306c3fb27SDimitry Andric BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset) 354406c3fb27SDimitry Andric CreateLine(); 354506c3fb27SDimitry Andric break; 354606c3fb27SDimitry Andric case BinaryAnnotationsOpCode::ChangeFile: 354706c3fb27SDimitry Andric UpdateFileOffset(Annot.U1); 354806c3fb27SDimitry Andric UpdateClose(); 354906c3fb27SDimitry Andric break; 355006c3fb27SDimitry Andric default: 355106c3fb27SDimitry Andric break; 355206c3fb27SDimitry Andric } 355306c3fb27SDimitry Andric if (SeenLowAddress && SeenHighAddress) { 355406c3fb27SDimitry Andric SeenLowAddress = false; 355506c3fb27SDimitry Andric SeenHighAddress = false; 355606c3fb27SDimitry Andric InlinedFunction->addObject(LowPC, HighPC); 355706c3fb27SDimitry Andric } 355806c3fb27SDimitry Andric } 355906c3fb27SDimitry Andric 356006c3fb27SDimitry Andric Reader->addInlineeLines(InlinedFunction, InlineeLines); 356106c3fb27SDimitry Andric UpdateClose(); 356206c3fb27SDimitry Andric 356306c3fb27SDimitry Andric return Error::success(); 356406c3fb27SDimitry Andric } 3565