//===-- LVCodeViewVisitor.cpp ---------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This implements the LVCodeViewVisitor class.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewVisitor.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
#include "llvm/DebugInfo/LogicalView/Core/LVType.h"
#include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/InputFile.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/PDB.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/FormatVariadic.h"

using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::object;
using namespace llvm::pdb;
using namespace llvm::logicalview;

#define DEBUG_TYPE "CodeViewUtilities"

namespace llvm {
namespace logicalview {

static TypeIndex getTrueType(TypeIndex &TI) {
  // Dealing with a MSVC generated PDB, we encountered a type index with the
  // value of: 0x0280xxxx where xxxx=0000.
  //
  // There is some documentation about type indices:
  // https://llvm.org/docs/PDB/TpiStream.html
  //
  // A type index is a 32-bit integer that uniquely identifies a type inside
  // of an object file’s .debug$T section or a PDB file’s TPI or IPI stream.
  // The value of the type index for the first type record from the TPI stream
  // is given by the TypeIndexBegin member of the TPI Stream Header although
  // in practice this value is always equal to 0x1000 (4096).
  //
  // Any type index with a high bit set is considered to come from the IPI
  // stream, although this appears to be more of a hack, and LLVM does not
  // generate type indices of this nature. They can, however, be observed in
  // Microsoft PDBs occasionally, so one should be prepared to handle them.
  // Note that having the high bit set is not a necessary condition to
  // determine whether a type index comes from the IPI stream, it is only
  // sufficient.
  LLVM_DEBUG(
      { dbgs() << "Index before: " << HexNumber(TI.getIndex()) << "\n"; });
  TI.setIndex(TI.getIndex() & 0x0000ffff);
  LLVM_DEBUG(
      { dbgs() << "Index after: " << HexNumber(TI.getIndex()) << "\n"; });
  return TI;
}

static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
#define CV_TYPE(enum, val) {#enum, enum},
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
};

// Return the type name pointed by the type index. It uses the kind to query
// the associated name for the record type.
static StringRef getRecordName(LazyRandomTypeCollection &Types, TypeIndex TI) {
  if (TI.isSimple())
    return {};

  StringRef RecordName;
  CVType CVReference = Types.getType(TI);
  auto GetName = [&](auto Record) {
    if (Error Err = TypeDeserializer::deserializeAs(
            const_cast<CVType &>(CVReference), Record))
      consumeError(std::move(Err));
    else
      RecordName = Record.getName();
  };

  TypeRecordKind RK = static_cast<TypeRecordKind>(CVReference.kind());
  if (RK == TypeRecordKind::Class || RK == TypeRecordKind::Struct)
    GetName(ClassRecord(RK));
  else if (RK == TypeRecordKind::Union)
    GetName(UnionRecord(RK));
  else if (RK == TypeRecordKind::Enum)
    GetName(EnumRecord(RK));

  return RecordName;
}

} // namespace logicalview
} // namespace llvm

#undef DEBUG_TYPE
#define DEBUG_TYPE "CodeViewDataVisitor"

namespace llvm {
namespace logicalview {

// Keeps the type indexes with line information.
using LVLineRecords = std::vector<TypeIndex>;

namespace {

class LVTypeRecords {
  LVShared *Shared = nullptr;

  // Logical elements associated to their CodeView Type Index.
  using RecordEntry = std::pair<TypeLeafKind, LVElement *>;
  using RecordTable = std::map<TypeIndex, RecordEntry>;
  RecordTable RecordFromTypes;
  RecordTable RecordFromIds;

  using NameTable = std::map<StringRef, TypeIndex>;
  NameTable NameFromTypes;
  NameTable NameFromIds;

public:
  LVTypeRecords(LVShared *Shared) : Shared(Shared) {}

  void add(uint32_t StreamIdx, TypeIndex TI, TypeLeafKind Kind,
           LVElement *Element = nullptr);
  void add(uint32_t StreamIdx, TypeIndex TI, StringRef Name);
  LVElement *find(uint32_t StreamIdx, TypeIndex TI, bool Create = true);
  TypeIndex find(uint32_t StreamIdx, StringRef Name);
};

class LVForwardReferences {
  // Forward reference and its definitions (Name as key).
  using ForwardEntry = std::pair<TypeIndex, TypeIndex>;
  using ForwardTypeNames = std::map<StringRef, ForwardEntry>;
  ForwardTypeNames ForwardTypesNames;

  // Forward reference and its definition (TypeIndex as key).
  using ForwardType = std::map<TypeIndex, TypeIndex>;
  ForwardType ForwardTypes;

  // Forward types and its references.
  void add(TypeIndex TIForward, TypeIndex TIReference) {
    ForwardTypes.emplace(TIForward, TIReference);
  }

  void add(StringRef Name, TypeIndex TIForward) {
    if (ForwardTypesNames.find(Name) == ForwardTypesNames.end()) {
      ForwardTypesNames.emplace(
          std::piecewise_construct, std::forward_as_tuple(Name),
          std::forward_as_tuple(TIForward, TypeIndex::None()));
    } else {
      // Update a recorded definition with its reference.
      ForwardTypesNames[Name].first = TIForward;
      add(TIForward, ForwardTypesNames[Name].second);
    }
  }

  // Update a previously recorded forward reference with its definition.
  void update(StringRef Name, TypeIndex TIReference) {
    if (ForwardTypesNames.find(Name) != ForwardTypesNames.end()) {
      // Update the recorded forward reference with its definition.
      ForwardTypesNames[Name].second = TIReference;
      add(ForwardTypesNames[Name].first, TIReference);
    } else {
      // We have not seen the forward reference. Insert the definition.
      ForwardTypesNames.emplace(
          std::piecewise_construct, std::forward_as_tuple(Name),
          std::forward_as_tuple(TypeIndex::None(), TIReference));
    }
  }

public:
  LVForwardReferences() = default;

  void record(bool IsForwardRef, StringRef Name, TypeIndex TI) {
    // We are expecting for the forward references to be first. But that
    // is not always the case. A name must be recorded regardless of the
    // order in which the forward reference appears.
    (IsForwardRef) ? add(Name, TI) : update(Name, TI);
  }

  TypeIndex find(TypeIndex TIForward) {
    return (ForwardTypes.find(TIForward) != ForwardTypes.end())
               ? ForwardTypes[TIForward]
               : TypeIndex::None();
  }

  TypeIndex find(StringRef Name) {
    return (ForwardTypesNames.find(Name) != ForwardTypesNames.end())
               ? ForwardTypesNames[Name].second
               : TypeIndex::None();
  }

  // If the given TI corresponds to a reference, return the reference.
  // Otherwise return the given TI.
  TypeIndex remap(TypeIndex TI) {
    TypeIndex Forward = find(TI);
    return Forward.isNoneType() ? TI : Forward;
  }
};

// Namespace deduction.
class LVNamespaceDeduction {
  LVShared *Shared = nullptr;

  using Names = std::map<StringRef, LVScope *>;
  Names NamespaceNames;

  using LookupSet = std::set<StringRef>;
  LookupSet DeducedScopes;
  LookupSet UnresolvedScopes;
  LookupSet IdentifiedNamespaces;

  void add(StringRef Name, LVScope *Namespace) {
    if (NamespaceNames.find(Name) == NamespaceNames.end())
      NamespaceNames.emplace(Name, Namespace);
  }

public:
  LVNamespaceDeduction(LVShared *Shared) : Shared(Shared) {}

  void init();
  void add(StringRef String);
  LVScope *get(LVStringRefs Components);
  LVScope *get(StringRef Name, bool CheckScope = true);

  // Find the logical namespace for the 'Name' component.
  LVScope *find(StringRef Name) {
    LVScope *Namespace = (NamespaceNames.find(Name) != NamespaceNames.end())
                             ? NamespaceNames[Name]
                             : nullptr;
    return Namespace;
  }

  // For the given lexical components, return a tuple with the first entry
  // being the outermost namespace and the second entry being the first
  // non-namespace.
  LVLexicalIndex find(LVStringRefs Components) {
    if (Components.empty())
      return {};

    LVStringRefs::size_type FirstNamespace = 0;
    LVStringRefs::size_type FirstNonNamespace;
    for (LVStringRefs::size_type Index = 0; Index < Components.size();
         ++Index) {
      FirstNonNamespace = Index;
      LookupSet::iterator Iter = IdentifiedNamespaces.find(Components[Index]);
      if (Iter == IdentifiedNamespaces.end())
        // The component is not a namespace name.
        break;
    }
    return std::make_tuple(FirstNamespace, FirstNonNamespace);
  }
};

// Strings.
class LVStringRecords {
  using StringEntry = std::tuple<uint32_t, std::string, LVScopeCompileUnit *>;
  using StringIds = std::map<TypeIndex, StringEntry>;
  StringIds Strings;

public:
  LVStringRecords() = default;

  void add(TypeIndex TI, StringRef String) {
    static uint32_t Index = 0;
    if (Strings.find(TI) == Strings.end())
      Strings.emplace(
          std::piecewise_construct, std::forward_as_tuple(TI),
          std::forward_as_tuple(++Index, std::string(String), nullptr));
  }

  StringRef find(TypeIndex TI) {
    StringIds::iterator Iter = Strings.find(TI);
    return Iter != Strings.end() ? std::get<1>(Iter->second) : StringRef{};
  }

  uint32_t findIndex(TypeIndex TI) {
    StringIds::iterator Iter = Strings.find(TI);
    return Iter != Strings.end() ? std::get<0>(Iter->second) : 0;
  }

  // Move strings representing the filenames to the compile unit.
  void addFilenames();
  void addFilenames(LVScopeCompileUnit *Scope);
};
} // namespace

using LVTypeKinds = std::set<TypeLeafKind>;
using LVSymbolKinds = std::set<SymbolKind>;

// The following data keeps forward information, type records, names for
// namespace deduction, strings records, line records.
// It is shared by the type visitor, symbol visitor and logical visitor and
// it is independent from the CodeViewReader.
struct LVShared {
  LVCodeViewReader *Reader;
  LVLogicalVisitor *Visitor;
  LVForwardReferences ForwardReferences;
  LVLineRecords LineRecords;
  LVNamespaceDeduction NamespaceDeduction;
  LVStringRecords StringRecords;
  LVTypeRecords TypeRecords;

  // In order to determine which types and/or symbols records should be handled
  // by the reader, we record record kinds seen by the type and symbol visitors.
  // At the end of the scopes creation, the '--internal=tag' option will allow
  // to print the unique record ids collected.
  LVTypeKinds TypeKinds;
  LVSymbolKinds SymbolKinds;

  LVShared(LVCodeViewReader *Reader, LVLogicalVisitor *Visitor)
      : Reader(Reader), Visitor(Visitor), NamespaceDeduction(this),
        TypeRecords(this) {}
  ~LVShared() = default;
};
} // namespace logicalview
} // namespace llvm

void LVTypeRecords::add(uint32_t StreamIdx, TypeIndex TI, TypeLeafKind Kind,
                        LVElement *Element) {
  RecordTable &Target =
      (StreamIdx == StreamTPI) ? RecordFromTypes : RecordFromIds;
  Target.emplace(std::piecewise_construct, std::forward_as_tuple(TI),
                 std::forward_as_tuple(Kind, Element));
}

void LVTypeRecords::add(uint32_t StreamIdx, TypeIndex TI, StringRef Name) {
  NameTable &Target = (StreamIdx == StreamTPI) ? NameFromTypes : NameFromIds;
  Target.emplace(Name, TI);
}

LVElement *LVTypeRecords::find(uint32_t StreamIdx, TypeIndex TI, bool Create) {
  RecordTable &Target =
      (StreamIdx == StreamTPI) ? RecordFromTypes : RecordFromIds;

  LVElement *Element = nullptr;
  RecordTable::iterator Iter = Target.find(TI);
  if (Iter != Target.end()) {
    Element = Iter->second.second;
    if (Element || !Create)
      return Element;

    // Create the logical element if not found.
    Element = Shared->Visitor->createElement(Iter->second.first);
    if (Element) {
      Element->setOffset(TI.getIndex());
      Element->setOffsetFromTypeIndex();
      Target[TI].second = Element;
    }
  }
  return Element;
}

TypeIndex LVTypeRecords::find(uint32_t StreamIdx, StringRef Name) {
  NameTable &Target = (StreamIdx == StreamTPI) ? NameFromTypes : NameFromIds;
  NameTable::iterator Iter = Target.find(Name);
  return Iter != Target.end() ? Iter->second : TypeIndex::None();
}

void LVStringRecords::addFilenames() {
  for (StringIds::const_reference Entry : Strings) {
    StringRef Name = std::get<1>(Entry.second);
    LVScopeCompileUnit *Scope = std::get<2>(Entry.second);
    Scope->addFilename(transformPath(Name));
  }
  Strings.clear();
}

void LVStringRecords::addFilenames(LVScopeCompileUnit *Scope) {
  for (StringIds::reference Entry : Strings)
    if (!std::get<2>(Entry.second))
      std::get<2>(Entry.second) = Scope;
}

void LVNamespaceDeduction::add(StringRef String) {
  StringRef InnerComponent;
  StringRef OuterComponent;
  std::tie(OuterComponent, InnerComponent) = getInnerComponent(String);
  DeducedScopes.insert(InnerComponent);
  if (OuterComponent.size())
    UnresolvedScopes.insert(OuterComponent);
}

void LVNamespaceDeduction::init() {
  // We have 2 sets of names:
  // - deduced scopes (class, structure, union and enum) and
  // - unresolved scopes, that can represent namespaces or any deduced.
  // Before creating the namespaces, we have to traverse the unresolved
  // and remove any references to already deduced scopes.
  LVStringRefs Components;
  for (const StringRef &Unresolved : UnresolvedScopes) {
    Components = getAllLexicalComponents(Unresolved);
    for (const StringRef &Component : Components) {
      LookupSet::iterator Iter = DeducedScopes.find(Component);
      if (Iter == DeducedScopes.end())
        IdentifiedNamespaces.insert(Component);
    }
  }

  LLVM_DEBUG({
    auto Print = [&](LookupSet &Container, const char *Title) {
      auto Header = [&]() {
        dbgs() << formatv("\n{0}\n", fmt_repeat('=', 72));
        dbgs() << formatv("{0}\n", Title);
        dbgs() << formatv("{0}\n", fmt_repeat('=', 72));
      };
      Header();
      for (const StringRef &Item : Container)
        dbgs() << formatv("'{0}'\n", Item.str().c_str());
    };

    Print(DeducedScopes, "Deducted Scopes");
    Print(UnresolvedScopes, "Unresolved Scopes");
    Print(IdentifiedNamespaces, "Namespaces");
  });
}

LVScope *LVNamespaceDeduction::get(LVStringRefs Components) {
  LLVM_DEBUG({
    for (const StringRef &Component : Components)
      dbgs() << formatv("'{0}'\n", Component.str().c_str());
  });

  if (Components.empty())
    return nullptr;

  // Update the namespaces relationship.
  LVScope *Namespace = nullptr;
  LVScope *Parent = Shared->Reader->getCompileUnit();
  for (const StringRef &Component : Components) {
    // Check if we have seen the namespace.
    Namespace = find(Component);
    if (!Namespace) {
      // We have identified namespaces that are generated by MSVC. Mark them
      // as 'system' so they will be excluded from the logical view.
      Namespace = Shared->Reader->createScopeNamespace();
      Namespace->setTag(dwarf::DW_TAG_namespace);
      Namespace->setName(Component);
      Parent->addElement(Namespace);
      getReader().isSystemEntry(Namespace);
      add(Component, Namespace);
    }
    Parent = Namespace;
  }
  return Parent;
}

LVScope *LVNamespaceDeduction::get(StringRef ScopedName, bool CheckScope) {
  LVStringRefs Components = getAllLexicalComponents(ScopedName);
  if (CheckScope)
    llvm::erase_if(Components, [&](StringRef Component) {
      LookupSet::iterator Iter = IdentifiedNamespaces.find(Component);
      return Iter == IdentifiedNamespaces.end();
    });

  LLVM_DEBUG(
      { dbgs() << formatv("ScopedName: '{0}'\n", ScopedName.str().c_str()); });

  return get(Components);
}

#undef DEBUG_TYPE
#define DEBUG_TYPE "CodeViewTypeVisitor"

//===----------------------------------------------------------------------===//
// TypeRecord traversal.
//===----------------------------------------------------------------------===//
void LVTypeVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI,
                                   uint32_t StreamIdx) const {
  codeview::printTypeIndex(W, FieldName, TI,
                           StreamIdx == StreamTPI ? Types : Ids);
}

Error LVTypeVisitor::visitTypeBegin(CVType &Record) {
  return visitTypeBegin(Record, TypeIndex::fromArrayIndex(Types.size()));
}

Error LVTypeVisitor::visitTypeBegin(CVType &Record, TypeIndex TI) {
  LLVM_DEBUG({
    W.getOStream() << formatTypeLeafKind(Record.kind());
    W.getOStream() << " (" << HexNumber(TI.getIndex()) << ")\n";
  });

  if (options().getInternalTag())
    Shared->TypeKinds.insert(Record.kind());

  // The collected type records, will be use to create the logical elements
  // during the symbols traversal when a type is referenced.
  CurrentTypeIndex = TI;
  Shared->TypeRecords.add(StreamIdx, TI, Record.kind());
  return Error::success();
}

Error LVTypeVisitor::visitUnknownType(CVType &Record) {
  LLVM_DEBUG({ W.printNumber("Length", uint32_t(Record.content().size())); });
  return Error::success();
}

Error LVTypeVisitor::visitMemberBegin(CVMemberRecord &Record) {
  LLVM_DEBUG({
    W.startLine() << formatTypeLeafKind(Record.Kind);
    W.getOStream() << " {\n";
    W.indent();
  });
  return Error::success();
}

Error LVTypeVisitor::visitMemberEnd(CVMemberRecord &Record) {
  LLVM_DEBUG({
    W.unindent();
    W.startLine() << "}\n";
  });
  return Error::success();
}

Error LVTypeVisitor::visitUnknownMember(CVMemberRecord &Record) {
  LLVM_DEBUG({ W.printHex("UnknownMember", unsigned(Record.Kind)); });
  return Error::success();
}

// LF_BUILDINFO (TPI)/(IPI)
Error LVTypeVisitor::visitKnownRecord(CVType &Record, BuildInfoRecord &Args) {
  // All the args are references into the TPI/IPI stream.
  LLVM_DEBUG({
    W.printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size()));
    ListScope Arguments(W, "Arguments");
    for (TypeIndex Arg : Args.getArgs())
      printTypeIndex("ArgType", Arg, StreamIPI);
  });

  // Only add the strings that hold information about filenames. They will be
  // used to complete the line/file information for the logical elements.
  // There are other strings holding information about namespaces.
  TypeIndex TI;
  StringRef String;

  // Absolute CWD path
  TI = Args.getArgs()[BuildInfoRecord::BuildInfoArg::CurrentDirectory];
  String = Ids.getTypeName(TI);
  if (!String.empty())
    Shared->StringRecords.add(TI, String);

  // Get the compile unit name.
  TI = Args.getArgs()[BuildInfoRecord::BuildInfoArg::SourceFile];
  String = Ids.getTypeName(TI);
  if (!String.empty())
    Shared->StringRecords.add(TI, String);
  LogicalVisitor->setCompileUnitName(std::string(String));

  return Error::success();
}

// LF_CLASS, LF_STRUCTURE, LF_INTERFACE (TPI)
Error LVTypeVisitor::visitKnownRecord(CVType &Record, ClassRecord &Class) {
  LLVM_DEBUG({
    printTypeIndex("TypeIndex", CurrentTypeIndex, StreamTPI);
    printTypeIndex("FieldListType", Class.getFieldList(), StreamTPI);
    W.printString("Name", Class.getName());
  });

  // Collect class name for scope deduction.
  Shared->NamespaceDeduction.add(Class.getName());
  Shared->ForwardReferences.record(Class.isForwardRef(), Class.getName(),
                                   CurrentTypeIndex);

  // Collect class name for contained scopes deduction.
  Shared->TypeRecords.add(StreamIdx, CurrentTypeIndex, Class.getName());
  return Error::success();
}

// LF_ENUM (TPI)
Error LVTypeVisitor::visitKnownRecord(CVType &Record, EnumRecord &Enum) {
  LLVM_DEBUG({
    printTypeIndex("TypeIndex", CurrentTypeIndex, StreamTPI);
    printTypeIndex("FieldListType", Enum.getFieldList(), StreamTPI);
    W.printString("Name", Enum.getName());
  });

  // Collect enum name for scope deduction.
  Shared->NamespaceDeduction.add(Enum.getName());
  return Error::success();
}

// LF_FUNC_ID (TPI)/(IPI)
Error LVTypeVisitor::visitKnownRecord(CVType &Record, FuncIdRecord &Func) {
  LLVM_DEBUG({
    printTypeIndex("TypeIndex", CurrentTypeIndex, StreamTPI);
    printTypeIndex("Type", Func.getFunctionType(), StreamTPI);
    printTypeIndex("Parent", Func.getParentScope(), StreamTPI);
    W.printString("Name", Func.getName());
  });

  // Collect function name for scope deduction.
  Shared->NamespaceDeduction.add(Func.getName());
  return Error::success();
}

// LF_PROCEDURE (TPI)
Error LVTypeVisitor::visitKnownRecord(CVType &Record, ProcedureRecord &Proc) {
  LLVM_DEBUG({
    printTypeIndex("TypeIndex", CurrentTypeIndex, StreamTPI);
    printTypeIndex("ReturnType", Proc.getReturnType(), StreamTPI);
    W.printNumber("NumParameters", Proc.getParameterCount());
    printTypeIndex("ArgListType", Proc.getArgumentList(), StreamTPI);
  });

  // Collect procedure information as they can be referenced by typedefs.
  Shared->TypeRecords.add(StreamTPI, CurrentTypeIndex, {});
  return Error::success();
}

// LF_STRING_ID (TPI)/(IPI)
Error LVTypeVisitor::visitKnownRecord(CVType &Record, StringIdRecord &String) {
  // No additional references are needed.
  LLVM_DEBUG({
    printTypeIndex("Id", String.getId(), StreamIPI);
    W.printString("StringData", String.getString());
  });
  return Error::success();
}

// LF_UDT_SRC_LINE (TPI)/(IPI)
Error LVTypeVisitor::visitKnownRecord(CVType &Record,
                                      UdtSourceLineRecord &Line) {
  // UDT and SourceFile are references into the TPI/IPI stream.
  LLVM_DEBUG({
    printTypeIndex("UDT", Line.getUDT(), StreamIPI);
    printTypeIndex("SourceFile", Line.getSourceFile(), StreamIPI);
    W.printNumber("LineNumber", Line.getLineNumber());
  });

  Shared->LineRecords.push_back(CurrentTypeIndex);
  return Error::success();
}

// LF_UNION (TPI)
Error LVTypeVisitor::visitKnownRecord(CVType &Record, UnionRecord &Union) {
  LLVM_DEBUG({
    W.printNumber("MemberCount", Union.getMemberCount());
    printTypeIndex("FieldList", Union.getFieldList(), StreamTPI);
    W.printNumber("SizeOf", Union.getSize());
    W.printString("Name", Union.getName());
    if (Union.hasUniqueName())
      W.printString("UniqueName", Union.getUniqueName());
  });

  // Collect union name for scope deduction.
  Shared->NamespaceDeduction.add(Union.getName());
  Shared->ForwardReferences.record(Union.isForwardRef(), Union.getName(),
                                   CurrentTypeIndex);

  // Collect class name for contained scopes deduction.
  Shared->TypeRecords.add(StreamIdx, CurrentTypeIndex, Union.getName());
  return Error::success();
}

#undef DEBUG_TYPE
#define DEBUG_TYPE "CodeViewSymbolVisitor"

//===----------------------------------------------------------------------===//
// SymbolRecord traversal.
//===----------------------------------------------------------------------===//
void LVSymbolVisitorDelegate::printRelocatedField(StringRef Label,
                                                  uint32_t RelocOffset,
                                                  uint32_t Offset,
                                                  StringRef *RelocSym) {
  Reader->printRelocatedField(Label, CoffSection, RelocOffset, Offset,
                              RelocSym);
}

void LVSymbolVisitorDelegate::getLinkageName(uint32_t RelocOffset,
                                             uint32_t Offset,
                                             StringRef *RelocSym) {
  Reader->getLinkageName(CoffSection, RelocOffset, Offset, RelocSym);
}

StringRef
LVSymbolVisitorDelegate::getFileNameForFileOffset(uint32_t FileOffset) {
  Expected<StringRef> Name = Reader->getFileNameForFileOffset(FileOffset);
  if (!Name) {
    consumeError(Name.takeError());
    return {};
  }
  return *Name;
}

DebugStringTableSubsectionRef LVSymbolVisitorDelegate::getStringTable() {
  return Reader->CVStringTable;
}

void LVSymbolVisitor::printLocalVariableAddrRange(
    const LocalVariableAddrRange &Range, uint32_t RelocationOffset) {
  DictScope S(W, "LocalVariableAddrRange");
  if (ObjDelegate)
    ObjDelegate->printRelocatedField("OffsetStart", RelocationOffset,
                                     Range.OffsetStart);
  W.printHex("ISectStart", Range.ISectStart);
  W.printHex("Range", Range.Range);
}

void LVSymbolVisitor::printLocalVariableAddrGap(
    ArrayRef<LocalVariableAddrGap> Gaps) {
  for (const LocalVariableAddrGap &Gap : Gaps) {
    ListScope S(W, "LocalVariableAddrGap");
    W.printHex("GapStartOffset", Gap.GapStartOffset);
    W.printHex("Range", Gap.Range);
  }
}

void LVSymbolVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const {
  codeview::printTypeIndex(W, FieldName, TI, Types);
}

Error LVSymbolVisitor::visitSymbolBegin(CVSymbol &Record) {
  return visitSymbolBegin(Record, 0);
}

Error LVSymbolVisitor::visitSymbolBegin(CVSymbol &Record, uint32_t Offset) {
  SymbolKind Kind = Record.kind();
  LLVM_DEBUG({
    W.printNumber("Offset", Offset);
    W.printEnum("Begin Kind", unsigned(Kind), getSymbolTypeNames());
  });

  if (options().getInternalTag())
    Shared->SymbolKinds.insert(Kind);

  LogicalVisitor->CurrentElement = LogicalVisitor->createElement(Kind);
  if (!LogicalVisitor->CurrentElement) {
    LLVM_DEBUG({
        // We have an unsupported Symbol or Type Record.
        // W.printEnum("Kind ignored", unsigned(Kind), getSymbolTypeNames());
    });
    return Error::success();
  }

  // Offset carried by the traversal routines when dealing with streams.
  CurrentOffset = Offset;
  IsCompileUnit = false;
  if (!LogicalVisitor->CurrentElement->getOffsetFromTypeIndex())
    LogicalVisitor->CurrentElement->setOffset(Offset);
  if (symbolOpensScope(Kind) || (IsCompileUnit = symbolIsCompileUnit(Kind))) {
    assert(LogicalVisitor->CurrentScope && "Invalid scope!");
    LogicalVisitor->addElement(LogicalVisitor->CurrentScope, IsCompileUnit);
  } else {
    if (LogicalVisitor->CurrentSymbol)
      LogicalVisitor->addElement(LogicalVisitor->CurrentSymbol);
    if (LogicalVisitor->CurrentType)
      LogicalVisitor->addElement(LogicalVisitor->CurrentType);
  }

  return Error::success();
}

Error LVSymbolVisitor::visitSymbolEnd(CVSymbol &Record) {
  SymbolKind Kind = Record.kind();
  LLVM_DEBUG(
      { W.printEnum("End Kind", unsigned(Kind), getSymbolTypeNames()); });

  if (symbolEndsScope(Kind)) {
    LogicalVisitor->popScope();
  }

  return Error::success();
}

Error LVSymbolVisitor::visitUnknownSymbol(CVSymbol &Record) {
  LLVM_DEBUG({ W.printNumber("Length", Record.length()); });
  return Error::success();
}

// S_BLOCK32
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, BlockSym &Block) {
  LLVM_DEBUG({
    W.printHex("CodeSize", Block.CodeSize);
    W.printHex("Segment", Block.Segment);
    W.printString("BlockName", Block.Name);
  });

  if (LVScope *Scope = LogicalVisitor->CurrentScope) {
    StringRef LinkageName;
    if (ObjDelegate)
      ObjDelegate->getLinkageName(Block.getRelocationOffset(), Block.CodeOffset,
                                  &LinkageName);
    Scope->setLinkageName(LinkageName);

    if (options().getGeneralCollectRanges()) {
      // Record converted segment::offset addressing for this scope.
      LVAddress Addendum = Reader->getSymbolTableAddress(LinkageName);
      LVAddress LowPC =
          Reader->linearAddress(Block.Segment, Block.CodeOffset, Addendum);
      LVAddress HighPC = LowPC + Block.CodeSize - 1;
      Scope->addObject(LowPC, HighPC);
    }
  }

  return Error::success();
}

// S_BPREL32
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record,
                                        BPRelativeSym &Local) {
  LLVM_DEBUG({
    printTypeIndex("Type", Local.Type);
    W.printNumber("Offset", Local.Offset);
    W.printString("VarName", Local.Name);
  });

  if (LVSymbol *Symbol = LogicalVisitor->CurrentSymbol) {
    Symbol->setName(Local.Name);
    // From the MS_Symbol_Type.pdf documentation (S_BPREL32):
    // This symbol specifies symbols that are allocated on the stack for a
    // procedure. For C and C++, these include the actual function parameters
    // and the local non-static variables of functions.
    // However, the offset for 'this' comes as a negative value.

    // Symbol was created as 'variable'; determine its real kind.
    Symbol->resetIsVariable();

    if (Local.Name.equals("this")) {
      Symbol->setIsParameter();
      Symbol->setIsArtificial();
    } else {
      // Determine symbol kind.
      bool(Local.Offset > 0) ? Symbol->setIsParameter()
                             : Symbol->setIsVariable();
    }

    // Update correct debug information tag.
    if (Symbol->getIsParameter())
      Symbol->setTag(dwarf::DW_TAG_formal_parameter);

    LVElement *Element = LogicalVisitor->getElement(StreamTPI, Local.Type);
    if (Element && Element->getIsScoped()) {
      // We have a local type. Find its parent function.
      LVScope *Parent = Symbol->getFunctionParent();
      // The element representing the type has been already finalized. If
      // the type is an aggregate type, its members have been already added.
      // As the type is local, its level will be changed.

      // FIXME: Currently the algorithm used to scope lambda functions is
      // incorrect. Before we allocate the type at this scope, check if is
      // already allocated in other scope.
      if (!Element->getParentScope()) {
        Parent->addElement(Element);
        Element->updateLevel(Parent);
      }
    }
    Symbol->setType(Element);
  }

  return Error::success();
}

// S_REGREL32
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record,
                                        RegRelativeSym &Local) {
  LLVM_DEBUG({
    printTypeIndex("Type", Local.Type);
    W.printNumber("Offset", Local.Offset);
    W.printString("VarName", Local.Name);
  });

  if (LVSymbol *Symbol = LogicalVisitor->CurrentSymbol) {
    Symbol->setName(Local.Name);

    // Symbol was created as 'variable'; determine its real kind.
    Symbol->resetIsVariable();

    // Check for the 'this' symbol.
    if (Local.Name.equals("this")) {
      Symbol->setIsArtificial();
      Symbol->setIsParameter();
    } else {
      // Determine symbol kind.
      determineSymbolKind(Symbol, Local.Register);
    }

    // Update correct debug information tag.
    if (Symbol->getIsParameter())
      Symbol->setTag(dwarf::DW_TAG_formal_parameter);

    LVElement *Element = LogicalVisitor->getElement(StreamTPI, Local.Type);
    if (Element && Element->getIsScoped()) {
      // We have a local type. Find its parent function.
      LVScope *Parent = Symbol->getFunctionParent();
      // The element representing the type has been already finalized. If
      // the type is an aggregate type, its members have been already added.
      // As the type is local, its level will be changed.

      // FIXME: Currently the algorithm used to scope lambda functions is
      // incorrect. Before we allocate the type at this scope, check if is
      // already allocated in other scope.
      if (!Element->getParentScope()) {
        Parent->addElement(Element);
        Element->updateLevel(Parent);
      }
    }
    Symbol->setType(Element);
  }

  return Error::success();
}

// S_BUILDINFO
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &CVR,
                                        BuildInfoSym &BuildInfo) {
  LLVM_DEBUG({ printTypeIndex("BuildId", BuildInfo.BuildId); });

  CVType CVBuildType = Ids.getType(BuildInfo.BuildId);
  if (Error Err = LogicalVisitor->finishVisitation(
          CVBuildType, BuildInfo.BuildId, Reader->getCompileUnit()))
    return Err;

  return Error::success();
}

// S_COMPILE2
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record,
                                        Compile2Sym &Compile2) {
  LLVM_DEBUG({
    W.printEnum("Language", uint8_t(Compile2.getLanguage()),
                getSourceLanguageNames());
    W.printFlags("Flags", uint32_t(Compile2.getFlags()),
                 getCompileSym3FlagNames());
    W.printEnum("Machine", unsigned(Compile2.Machine), getCPUTypeNames());
    W.printString("VersionName", Compile2.Version);
  });

  // MSVC generates the following sequence for a CodeView module:
  //   S_OBJNAME    --> Set 'CurrentObjectName'.
  //   S_COMPILE2   --> Set the compile unit name using 'CurrentObjectName'.
  //   ...
  //   S_BUILDINFO  --> Extract the source name.
  //
  // Clang generates the following sequence for a CodeView module:
  //   S_COMPILE2   --> Set the compile unit name to empty string.
  //   ...
  //   S_BUILDINFO  --> Extract the source name.
  //
  // For both toolchains, update the compile unit name from S_BUILDINFO.
  if (LVScope *Scope = LogicalVisitor->CurrentScope) {
    // The name of the CU, was extracted from the 'BuildInfo' subsection.
    Reader->setCompileUnitCPUType(Compile2.Machine);
    Scope->setName(CurrentObjectName);
    if (options().getAttributeProducer())
      Scope->setProducer(Compile2.Version);
    getReader().isSystemEntry(Scope, CurrentObjectName);

    // The line records in CodeView are recorded per Module ID. Update
    // the relationship between the current CU and the Module ID.
    Reader->addModule(Scope);

    // Updated the collected strings with their associated compile unit.
    Shared->StringRecords.addFilenames(Reader->getCompileUnit());
  }

  // Clear any previous ObjectName.
  CurrentObjectName = "";
  return Error::success();
}

// S_COMPILE3
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record,
                                        Compile3Sym &Compile3) {
  LLVM_DEBUG({
    W.printEnum("Language", uint8_t(Compile3.getLanguage()),
                getSourceLanguageNames());
    W.printFlags("Flags", uint32_t(Compile3.getFlags()),
                 getCompileSym3FlagNames());
    W.printEnum("Machine", unsigned(Compile3.Machine), getCPUTypeNames());
    W.printString("VersionName", Compile3.Version);
  });

  // MSVC generates the following sequence for a CodeView module:
  //   S_OBJNAME    --> Set 'CurrentObjectName'.
  //   S_COMPILE3   --> Set the compile unit name using 'CurrentObjectName'.
  //   ...
  //   S_BUILDINFO  --> Extract the source name.
  //
  // Clang generates the following sequence for a CodeView module:
  //   S_COMPILE3   --> Set the compile unit name to empty string.
  //   ...
  //   S_BUILDINFO  --> Extract the source name.
  //
  // For both toolchains, update the compile unit name from S_BUILDINFO.
  if (LVScope *Scope = LogicalVisitor->CurrentScope) {
    // The name of the CU, was extracted from the 'BuildInfo' subsection.
    Reader->setCompileUnitCPUType(Compile3.Machine);
    Scope->setName(CurrentObjectName);
    if (options().getAttributeProducer())
      Scope->setProducer(Compile3.Version);
    getReader().isSystemEntry(Scope, CurrentObjectName);

    // The line records in CodeView are recorded per Module ID. Update
    // the relationship between the current CU and the Module ID.
    Reader->addModule(Scope);

    // Updated the collected strings with their associated compile unit.
    Shared->StringRecords.addFilenames(Reader->getCompileUnit());
  }

  // Clear any previous ObjectName.
  CurrentObjectName = "";
  return Error::success();
}

// S_CONSTANT, S_MANCONSTANT
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record,
                                        ConstantSym &Constant) {
  LLVM_DEBUG({
    printTypeIndex("Type", Constant.Type);
    W.printNumber("Value", Constant.Value);
    W.printString("Name", Constant.Name);
  });

  if (LVSymbol *Symbol = LogicalVisitor->CurrentSymbol) {
    Symbol->setName(Constant.Name);
    Symbol->setType(LogicalVisitor->getElement(StreamTPI, Constant.Type));
    Symbol->resetIncludeInPrint();
  }

  return Error::success();
}

// S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
Error LVSymbolVisitor::visitKnownRecord(
    CVSymbol &Record,
    DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
  // DefRanges don't have types, just registers and code offsets.
  LLVM_DEBUG({
    if (LocalSymbol)
      W.getOStream() << formatv("Symbol: {0}, ", LocalSymbol->getName());

    W.printNumber("Offset", DefRangeFramePointerRelFullScope.Offset);
  });

  if (LVSymbol *Symbol = LocalSymbol) {
    Symbol->setHasCodeViewLocation();
    LocalSymbol = nullptr;

    // Add location debug location. Operands: [Offset, 0].
    dwarf::Attribute Attr =
        dwarf::Attribute(SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE);

    uint64_t Operand1 = DefRangeFramePointerRelFullScope.Offset;
    Symbol->addLocation(Attr, 0, 0, 0, 0);
    Symbol->addLocationOperands(LVSmall(Attr), {Operand1});
  }

  return Error::success();
}

// S_DEFRANGE_FRAMEPOINTER_REL
Error LVSymbolVisitor::visitKnownRecord(
    CVSymbol &Record, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
  // DefRanges don't have types, just registers and code offsets.
  LLVM_DEBUG({
    if (LocalSymbol)
      W.getOStream() << formatv("Symbol: {0}, ", LocalSymbol->getName());

    W.printNumber("Offset", DefRangeFramePointerRel.Hdr.Offset);
    printLocalVariableAddrRange(DefRangeFramePointerRel.Range,
                                DefRangeFramePointerRel.getRelocationOffset());
    printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
  });

  // We are expecting the following sequence:
  //   128 | S_LOCAL [size = 20] `ParamBar`
  //         ...
  //   148 | S_DEFRANGE_FRAMEPOINTER_REL [size = 16]
  if (LVSymbol *Symbol = LocalSymbol) {
    Symbol->setHasCodeViewLocation();
    LocalSymbol = nullptr;

    // Add location debug location. Operands: [Offset, 0].
    dwarf::Attribute Attr =
        dwarf::Attribute(SymbolKind::S_DEFRANGE_FRAMEPOINTER_REL);
    uint64_t Operand1 = DefRangeFramePointerRel.Hdr.Offset;

    LocalVariableAddrRange Range = DefRangeFramePointerRel.Range;
    LVAddress Address =
        Reader->linearAddress(Range.ISectStart, Range.OffsetStart);

    Symbol->addLocation(Attr, Address, Address + Range.Range, 0, 0);
    Symbol->addLocationOperands(LVSmall(Attr), {Operand1});
  }

  return Error::success();
}

// S_DEFRANGE_REGISTER_REL
Error LVSymbolVisitor::visitKnownRecord(
    CVSymbol &Record, DefRangeRegisterRelSym &DefRangeRegisterRel) {
  // DefRanges don't have types, just registers and code offsets.
  LLVM_DEBUG({
    if (LocalSymbol)
      W.getOStream() << formatv("Symbol: {0}, ", LocalSymbol->getName());

    W.printBoolean("HasSpilledUDTMember",
                   DefRangeRegisterRel.hasSpilledUDTMember());
    W.printNumber("OffsetInParent", DefRangeRegisterRel.offsetInParent());
    W.printNumber("BasePointerOffset",
                  DefRangeRegisterRel.Hdr.BasePointerOffset);
    printLocalVariableAddrRange(DefRangeRegisterRel.Range,
                                DefRangeRegisterRel.getRelocationOffset());
    printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
  });

  if (LVSymbol *Symbol = LocalSymbol) {
    Symbol->setHasCodeViewLocation();
    LocalSymbol = nullptr;

    // Add location debug location. Operands: [Register, Offset].
    dwarf::Attribute Attr =
        dwarf::Attribute(SymbolKind::S_DEFRANGE_REGISTER_REL);
    uint64_t Operand1 = DefRangeRegisterRel.Hdr.Register;
    uint64_t Operand2 = DefRangeRegisterRel.Hdr.BasePointerOffset;

    LocalVariableAddrRange Range = DefRangeRegisterRel.Range;
    LVAddress Address =
        Reader->linearAddress(Range.ISectStart, Range.OffsetStart);

    Symbol->addLocation(Attr, Address, Address + Range.Range, 0, 0);
    Symbol->addLocationOperands(LVSmall(Attr), {Operand1, Operand2});
  }

  return Error::success();
}

// S_DEFRANGE_REGISTER
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record,
                                        DefRangeRegisterSym &DefRangeRegister) {
  // DefRanges don't have types, just registers and code offsets.
  LLVM_DEBUG({
    if (LocalSymbol)
      W.getOStream() << formatv("Symbol: {0}, ", LocalSymbol->getName());

    W.printEnum("Register", uint16_t(DefRangeRegister.Hdr.Register),
                getRegisterNames(Reader->getCompileUnitCPUType()));
    W.printNumber("MayHaveNoName", DefRangeRegister.Hdr.MayHaveNoName);
    printLocalVariableAddrRange(DefRangeRegister.Range,
                                DefRangeRegister.getRelocationOffset());
    printLocalVariableAddrGap(DefRangeRegister.Gaps);
  });

  if (LVSymbol *Symbol = LocalSymbol) {
    Symbol->setHasCodeViewLocation();
    LocalSymbol = nullptr;

    // Add location debug location. Operands: [Register, 0].
    dwarf::Attribute Attr = dwarf::Attribute(SymbolKind::S_DEFRANGE_REGISTER);
    uint64_t Operand1 = DefRangeRegister.Hdr.Register;

    LocalVariableAddrRange Range = DefRangeRegister.Range;
    LVAddress Address =
        Reader->linearAddress(Range.ISectStart, Range.OffsetStart);

    Symbol->addLocation(Attr, Address, Address + Range.Range, 0, 0);
    Symbol->addLocationOperands(LVSmall(Attr), {Operand1});
  }

  return Error::success();
}

// S_DEFRANGE_SUBFIELD_REGISTER
Error LVSymbolVisitor::visitKnownRecord(
    CVSymbol &Record, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
  // DefRanges don't have types, just registers and code offsets.
  LLVM_DEBUG({
    if (LocalSymbol)
      W.getOStream() << formatv("Symbol: {0}, ", LocalSymbol->getName());

    W.printEnum("Register", uint16_t(DefRangeSubfieldRegister.Hdr.Register),
                getRegisterNames(Reader->getCompileUnitCPUType()));
    W.printNumber("MayHaveNoName", DefRangeSubfieldRegister.Hdr.MayHaveNoName);
    W.printNumber("OffsetInParent",
                  DefRangeSubfieldRegister.Hdr.OffsetInParent);
    printLocalVariableAddrRange(DefRangeSubfieldRegister.Range,
                                DefRangeSubfieldRegister.getRelocationOffset());
    printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
  });

  if (LVSymbol *Symbol = LocalSymbol) {
    Symbol->setHasCodeViewLocation();
    LocalSymbol = nullptr;

    // Add location debug location.  Operands: [Register, 0].
    dwarf::Attribute Attr =
        dwarf::Attribute(SymbolKind::S_DEFRANGE_SUBFIELD_REGISTER);
    uint64_t Operand1 = DefRangeSubfieldRegister.Hdr.Register;

    LocalVariableAddrRange Range = DefRangeSubfieldRegister.Range;
    LVAddress Address =
        Reader->linearAddress(Range.ISectStart, Range.OffsetStart);

    Symbol->addLocation(Attr, Address, Address + Range.Range, 0, 0);
    Symbol->addLocationOperands(LVSmall(Attr), {Operand1});
  }

  return Error::success();
}

// S_DEFRANGE_SUBFIELD
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record,
                                        DefRangeSubfieldSym &DefRangeSubfield) {
  // DefRanges don't have types, just registers and code offsets.
  LLVM_DEBUG({
    if (LocalSymbol)
      W.getOStream() << formatv("Symbol: {0}, ", LocalSymbol->getName());

    if (ObjDelegate) {
      DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable();
      auto ExpectedProgram = Strings.getString(DefRangeSubfield.Program);
      if (!ExpectedProgram) {
        consumeError(ExpectedProgram.takeError());
        return llvm::make_error<CodeViewError>(
            "String table offset outside of bounds of String Table!");
      }
      W.printString("Program", *ExpectedProgram);
    }
    W.printNumber("OffsetInParent", DefRangeSubfield.OffsetInParent);
    printLocalVariableAddrRange(DefRangeSubfield.Range,
                                DefRangeSubfield.getRelocationOffset());
    printLocalVariableAddrGap(DefRangeSubfield.Gaps);
  });

  if (LVSymbol *Symbol = LocalSymbol) {
    Symbol->setHasCodeViewLocation();
    LocalSymbol = nullptr;

    // Add location debug location. Operands: [Program, 0].
    dwarf::Attribute Attr = dwarf::Attribute(SymbolKind::S_DEFRANGE_SUBFIELD);
    uint64_t Operand1 = DefRangeSubfield.Program;

    LocalVariableAddrRange Range = DefRangeSubfield.Range;
    LVAddress Address =
        Reader->linearAddress(Range.ISectStart, Range.OffsetStart);

    Symbol->addLocation(Attr, Address, Address + Range.Range, 0, 0);
    Symbol->addLocationOperands(LVSmall(Attr), {Operand1, /*Operand2=*/0});
  }

  return Error::success();
}

// S_DEFRANGE
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record,
                                        DefRangeSym &DefRange) {
  // DefRanges don't have types, just registers and code offsets.
  LLVM_DEBUG({
    if (LocalSymbol)
      W.getOStream() << formatv("Symbol: {0}, ", LocalSymbol->getName());

    if (ObjDelegate) {
      DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable();
      auto ExpectedProgram = Strings.getString(DefRange.Program);
      if (!ExpectedProgram) {
        consumeError(ExpectedProgram.takeError());
        return llvm::make_error<CodeViewError>(
            "String table offset outside of bounds of String Table!");
      }
      W.printString("Program", *ExpectedProgram);
    }
    printLocalVariableAddrRange(DefRange.Range, DefRange.getRelocationOffset());
    printLocalVariableAddrGap(DefRange.Gaps);
  });

  if (LVSymbol *Symbol = LocalSymbol) {
    Symbol->setHasCodeViewLocation();
    LocalSymbol = nullptr;

    // Add location debug location. Operands: [Program, 0].
    dwarf::Attribute Attr = dwarf::Attribute(SymbolKind::S_DEFRANGE);
    uint64_t Operand1 = DefRange.Program;

    LocalVariableAddrRange Range = DefRange.Range;
    LVAddress Address =
        Reader->linearAddress(Range.ISectStart, Range.OffsetStart);

    Symbol->addLocation(Attr, Address, Address + Range.Range, 0, 0);
    Symbol->addLocationOperands(LVSmall(Attr), {Operand1, /*Operand2=*/0});
  }

  return Error::success();
}

// S_FRAMEPROC
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record,
                                        FrameProcSym &FrameProc) {
  if (LVScope *Function = LogicalVisitor->getReaderScope()) {
    // S_FRAMEPROC contains extra information for the function described
    // by any of the previous generated records:
    // S_GPROC32, S_LPROC32, S_LPROC32_ID, S_GPROC32_ID.

    // The generated sequence is:
    //   S_GPROC32_ID ...
    //   S_FRAMEPROC ...

    // Collect additional inline flags for the current scope function.
    FrameProcedureOptions Flags = FrameProc.Flags;
    if (FrameProcedureOptions::MarkedInline ==
        (Flags & FrameProcedureOptions::MarkedInline))
      Function->setInlineCode(dwarf::DW_INL_declared_inlined);
    if (FrameProcedureOptions::Inlined ==
        (Flags & FrameProcedureOptions::Inlined))
      Function->setInlineCode(dwarf::DW_INL_inlined);

    // To determine the symbol kind for any symbol declared in that function,
    // we can access the S_FRAMEPROC for the parent scope function. It contains
    // information about the local fp and param fp registers and compare with
    // the register in the S_REGREL32 to get a match.
    codeview::CPUType CPU = Reader->getCompileUnitCPUType();
    LocalFrameRegister = FrameProc.getLocalFramePtrReg(CPU);
    ParamFrameRegister = FrameProc.getParamFramePtrReg(CPU);
  }

  return Error::success();
}

// S_GDATA32, S_LDATA32, S_LMANDATA, S_GMANDATA
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, DataSym &Data) {
  LLVM_DEBUG({
    printTypeIndex("Type", Data.Type);
    W.printString("DisplayName", Data.Name);
  });

  if (LVSymbol *Symbol = LogicalVisitor->CurrentSymbol) {
    StringRef LinkageName;
    if (ObjDelegate)
      ObjDelegate->getLinkageName(Data.getRelocationOffset(), Data.DataOffset,
                                  &LinkageName);

    Symbol->setName(Data.Name);
    Symbol->setLinkageName(LinkageName);

    // The MSVC generates local data as initialization for aggregates. It
    // contains the address for an initialization function.
    // The symbols contains the '$initializer$' pattern. Allow them only if
    // the '--internal=system' option is given.
    //   0 | S_LDATA32 `Struct$initializer$`
    //       type = 0x1040 (void ()*)
    if (getReader().isSystemEntry(Symbol) && !options().getAttributeSystem()) {
      Symbol->resetIncludeInPrint();
      return Error::success();
    }

    if (LVScope *Namespace = Shared->NamespaceDeduction.get(Data.Name)) {
      // The variable is already at different scope. In order to reflect
      // the correct parent, move it to the namespace.
      if (Symbol->getParentScope()->removeElement(Symbol))
        Namespace->addElement(Symbol);
    }

    Symbol->setType(LogicalVisitor->getElement(StreamTPI, Data.Type));
    if (Record.kind() == SymbolKind::S_GDATA32)
      Symbol->setIsExternal();
  }

  return Error::success();
}

// S_INLINESITE
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record,
                                        InlineSiteSym &InlineSite) {
  LLVM_DEBUG({ printTypeIndex("Inlinee", InlineSite.Inlinee); });

  if (LVScope *InlinedFunction = LogicalVisitor->CurrentScope) {
    LVScope *AbstractFunction = Reader->createScopeFunction();
    AbstractFunction->setIsSubprogram();
    AbstractFunction->setTag(dwarf::DW_TAG_subprogram);
    AbstractFunction->setInlineCode(dwarf::DW_INL_inlined);
    AbstractFunction->setIsInlinedAbstract();
    InlinedFunction->setReference(AbstractFunction);

    LogicalVisitor->startProcessArgumentList();
    // 'Inlinee' is a Type ID.
    CVType CVFunctionType = Ids.getType(InlineSite.Inlinee);
    if (Error Err = LogicalVisitor->finishVisitation(
            CVFunctionType, InlineSite.Inlinee, AbstractFunction))
      return Err;
    LogicalVisitor->stopProcessArgumentList();

    // For inlined functions set the linkage name to be the same as
    // the name. It used to find their lines and ranges.
    StringRef Name = AbstractFunction->getName();
    InlinedFunction->setName(Name);
    InlinedFunction->setLinkageName(Name);

    // Process annotation bytes to calculate code and line offsets.
    if (Error Err = LogicalVisitor->inlineSiteAnnotation(
            AbstractFunction, InlinedFunction, InlineSite))
      return Err;
  }

  return Error::success();
}

// S_LOCAL
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, LocalSym &Local) {
  LLVM_DEBUG({
    printTypeIndex("Type", Local.Type);
    W.printFlags("Flags", uint16_t(Local.Flags), getLocalFlagNames());
    W.printString("VarName", Local.Name);
  });

  if (LVSymbol *Symbol = LogicalVisitor->CurrentSymbol) {
    Symbol->setName(Local.Name);

    // Symbol was created as 'variable'; determine its real kind.
    Symbol->resetIsVariable();

    // Be sure the 'this' symbol is marked as 'compiler generated'.
    if (bool(Local.Flags & LocalSymFlags::IsCompilerGenerated) ||
        Local.Name.equals("this")) {
      Symbol->setIsArtificial();
      Symbol->setIsParameter();
    } else {
      bool(Local.Flags & LocalSymFlags::IsParameter) ? Symbol->setIsParameter()
                                                     : Symbol->setIsVariable();
    }

    // Update correct debug information tag.
    if (Symbol->getIsParameter())
      Symbol->setTag(dwarf::DW_TAG_formal_parameter);

    LVElement *Element = LogicalVisitor->getElement(StreamTPI, Local.Type);
    if (Element && Element->getIsScoped()) {
      // We have a local type. Find its parent function.
      LVScope *Parent = Symbol->getFunctionParent();
      // The element representing the type has been already finalized. If
      // the type is an aggregate type, its members have been already added.
      // As the type is local, its level will be changed.
      Parent->addElement(Element);
      Element->updateLevel(Parent);
    }
    Symbol->setType(Element);

    // The CodeView records (S_DEFFRAME_*) describing debug location for
    // this symbol, do not have any direct reference to it. Those records
    // are emitted after this symbol. Record the current symbol.
    LocalSymbol = Symbol;
  }

  return Error::success();
}

// S_OBJNAME
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, ObjNameSym &ObjName) {
  LLVM_DEBUG({
    W.printHex("Signature", ObjName.Signature);
    W.printString("ObjectName", ObjName.Name);
  });

  CurrentObjectName = ObjName.Name;
  return Error::success();
}

// S_GPROC32, S_LPROC32, S_LPROC32_ID, S_GPROC32_ID
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, ProcSym &Proc) {
  if (InFunctionScope)
    return llvm::make_error<CodeViewError>("Visiting a ProcSym while inside "
                                           "function scope!");

  InFunctionScope = true;

  LLVM_DEBUG({
    printTypeIndex("FunctionType", Proc.FunctionType);
    W.printHex("Segment", Proc.Segment);
    W.printFlags("Flags", static_cast<uint8_t>(Proc.Flags),
                 getProcSymFlagNames());
    W.printString("DisplayName", Proc.Name);
  });

  // Clang and Microsoft generated different debug information records:
  // For functions definitions:
  // Clang:     S_GPROC32 -> LF_FUNC_ID -> LF_PROCEDURE
  // Microsoft: S_GPROC32 ->               LF_PROCEDURE

  // For member function definition:
  // Clang:     S_GPROC32 -> LF_MFUNC_ID -> LF_MFUNCTION
  // Microsoft: S_GPROC32 ->                LF_MFUNCTION
  // In order to support both sequences, if we found LF_FUNCTION_ID, just
  // get the TypeIndex for LF_PROCEDURE.

  // For the given test case, we have the sequence:
  // namespace NSP_local {
  //   void foo_local() {
  //   }
  // }
  //
  // 0x1000 | LF_STRING_ID String: NSP_local
  // 0x1002 | LF_PROCEDURE
  //          return type = 0x0003 (void), # args = 0, param list = 0x1001
  //          calling conv = cdecl, options = None
  // 0x1003 | LF_FUNC_ID
  //          name = foo_local, type = 0x1002, parent scope = 0x1000
  //      0 | S_GPROC32_ID `NSP_local::foo_local`
  //          type = `0x1003 (foo_local)`
  // 0x1004 | LF_STRING_ID String: suite
  // 0x1005 | LF_STRING_ID String: suite_local.cpp
  //
  // The LF_STRING_ID can hold different information:
  // 0x1000 - The enclosing namespace.
  // 0x1004 - The compile unit directory name.
  // 0x1005 - The compile unit name.
  //
  // Before deducting its scope, we need to evaluate its type and create any
  // associated namespaces.
  if (LVScope *Function = LogicalVisitor->CurrentScope) {
    StringRef LinkageName;
    if (ObjDelegate)
      ObjDelegate->getLinkageName(Proc.getRelocationOffset(), Proc.CodeOffset,
                                  &LinkageName);

    // The line table can be accessed using the linkage name.
    Reader->addToSymbolTable(LinkageName, Function);
    Function->setName(Proc.Name);
    Function->setLinkageName(LinkageName);

    if (options().getGeneralCollectRanges()) {
      // Record converted segment::offset addressing for this scope.
      LVAddress Addendum = Reader->getSymbolTableAddress(LinkageName);
      LVAddress LowPC =
          Reader->linearAddress(Proc.Segment, Proc.CodeOffset, Addendum);
      LVAddress HighPC = LowPC + Proc.CodeSize - 1;
      Function->addObject(LowPC, HighPC);

      // If the scope is a function, add it to the public names.
      if ((options().getAttributePublics() || options().getPrintAnyLine()) &&
          !Function->getIsInlinedFunction())
        Reader->getCompileUnit()->addPublicName(Function, LowPC, HighPC);
    }

    if (Function->getIsSystem() && !options().getAttributeSystem()) {
      Function->resetIncludeInPrint();
      return Error::success();
    }

    TypeIndex TIFunctionType = Proc.FunctionType;
    if (TIFunctionType.isSimple())
      Function->setType(LogicalVisitor->getElement(StreamTPI, TIFunctionType));
    else {
      // We have to detect the correct stream, using the lexical parent
      // name, as there is not other obvious way to get the stream.
      //   Normal function: LF_FUNC_ID (TPI)/(IPI)
      //                    LF_PROCEDURE (TPI)
      //   Lambda function: LF_MFUNCTION (TPI)
      //   Member function: LF_MFUNC_ID (TPI)/(IPI)

      StringRef OuterComponent;
      std::tie(OuterComponent, std::ignore) = getInnerComponent(Proc.Name);
      TypeIndex TI = Shared->ForwardReferences.find(OuterComponent);

      std::optional<CVType> CVFunctionType;
      auto GetRecordType = [&]() -> bool {
        CVFunctionType = Ids.tryGetType(TIFunctionType);
        if (!CVFunctionType)
          return false;

        if (TI.isNoneType())
          // Normal function.
          if (CVFunctionType->kind() == LF_FUNC_ID)
            return true;

        // Member function.
        return (CVFunctionType->kind() == LF_MFUNC_ID);
      };

      // We can have a LF_FUNC_ID, LF_PROCEDURE or LF_MFUNCTION.
      if (!GetRecordType()) {
        CVFunctionType = Types.tryGetType(TIFunctionType);
        if (!CVFunctionType)
          return llvm::make_error<CodeViewError>("Invalid type index");
      }

      if (Error Err = LogicalVisitor->finishVisitation(
              *CVFunctionType, TIFunctionType, Function))
        return Err;
    }

    if (Record.kind() == SymbolKind::S_GPROC32 ||
        Record.kind() == SymbolKind::S_GPROC32_ID)
      Function->setIsExternal();

    // We don't have a way to see if the symbol is compiler generated. Use
    // the linkage name, to detect `scalar deleting destructor' functions.
    std::string DemangledSymbol = demangle(LinkageName);
    if (DemangledSymbol.find("scalar deleting dtor") != std::string::npos) {
      Function->setIsArtificial();
    } else {
      // Clang generates global ctor and dtor names containing the substrings:
      // 'dynamic initializer for' and 'dynamic atexit destructor for'.
      if (DemangledSymbol.find("dynamic atexit destructor for") !=
          std::string::npos)
        Function->setIsArtificial();
    }
  }

  return Error::success();
}

// S_END
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record,
                                        ScopeEndSym &ScopeEnd) {
  InFunctionScope = false;
  return Error::success();
}

// S_THUNK32
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, Thunk32Sym &Thunk) {
  if (InFunctionScope)
    return llvm::make_error<CodeViewError>("Visiting a Thunk32Sym while inside "
                                           "function scope!");

  InFunctionScope = true;

  LLVM_DEBUG({
    W.printHex("Segment", Thunk.Segment);
    W.printString("Name", Thunk.Name);
  });

  if (LVScope *Function = LogicalVisitor->CurrentScope)
    Function->setName(Thunk.Name);

  return Error::success();
}

// S_UDT, S_COBOLUDT
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, UDTSym &UDT) {
  LLVM_DEBUG({
    printTypeIndex("Type", UDT.Type);
    W.printString("UDTName", UDT.Name);
  });

  if (LVType *Type = LogicalVisitor->CurrentType) {
    if (LVScope *Namespace = Shared->NamespaceDeduction.get(UDT.Name)) {
      if (Type->getParentScope()->removeElement(Type))
        Namespace->addElement(Type);
    }

    Type->setName(UDT.Name);

    // We have to determine if the typedef is a real C/C++ definition or is
    // the S_UDT record that describe all the user defined types.
    //      0 | S_UDT `Name` original type = 0x1009
    // 0x1009 | LF_STRUCTURE `Name`
    // Ignore type definitions for RTTI types:
    // _s__RTTIBaseClassArray, _s__RTTIBaseClassDescriptor,
    // _s__RTTICompleteObjectLocator, _s__RTTIClassHierarchyDescriptor.
    if (getReader().isSystemEntry(Type))
      Type->resetIncludeInPrint();
    else {
      StringRef RecordName = getRecordName(Types, UDT.Type);
      if (UDT.Name.equals(RecordName))
        Type->resetIncludeInPrint();
      Type->setType(LogicalVisitor->getElement(StreamTPI, UDT.Type));
    }
  }

  return Error::success();
}

// S_UNAMESPACE
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record,
                                        UsingNamespaceSym &UN) {
  LLVM_DEBUG({ W.printString("Namespace", UN.Name); });
  return Error::success();
}

// S_ARMSWITCHTABLE
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &CVR,
                                        JumpTableSym &JumpTable) {
  LLVM_DEBUG({
    W.printHex("BaseOffset", JumpTable.BaseOffset);
    W.printNumber("BaseSegment", JumpTable.BaseSegment);
    W.printFlags("SwitchType", static_cast<uint16_t>(JumpTable.SwitchType),
                 getJumpTableEntrySizeNames());
    W.printHex("BranchOffset", JumpTable.BranchOffset);
    W.printHex("TableOffset", JumpTable.TableOffset);
    W.printNumber("BranchSegment", JumpTable.BranchSegment);
    W.printNumber("TableSegment", JumpTable.TableSegment);
    W.printNumber("EntriesCount", JumpTable.EntriesCount);
  });
  return Error::success();
}

// S_CALLERS, S_CALLEES, S_INLINEES
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record, CallerSym &Caller) {
  LLVM_DEBUG({
    llvm::StringRef FieldName;
    switch (Caller.getKind()) {
    case SymbolRecordKind::CallerSym:
      FieldName = "Callee";
      break;
    case SymbolRecordKind::CalleeSym:
      FieldName = "Caller";
      break;
    case SymbolRecordKind::InlineesSym:
      FieldName = "Inlinee";
      break;
    default:
      return llvm::make_error<CodeViewError>(
          "Unknown CV Record type for a CallerSym object!");
    }
    for (auto FuncID : Caller.Indices) {
      printTypeIndex(FieldName, FuncID);
    }
  });
  return Error::success();
}

#undef DEBUG_TYPE
#define DEBUG_TYPE "CodeViewLogicalVisitor"

//===----------------------------------------------------------------------===//
// Logical visitor.
//===----------------------------------------------------------------------===//
LVLogicalVisitor::LVLogicalVisitor(LVCodeViewReader *Reader, ScopedPrinter &W,
                                   InputFile &Input)
    : Reader(Reader), W(W), Input(Input) {
  // The LogicalVisitor connects the CodeViewReader with the visitors that
  // traverse the types, symbols, etc. Do any initialization that is needed.
  Shared = std::make_shared<LVShared>(Reader, this);
}

void LVLogicalVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI,
                                      uint32_t StreamIdx) {
  codeview::printTypeIndex(W, FieldName, TI,
                           StreamIdx == StreamTPI ? types() : ids());
}

void LVLogicalVisitor::printTypeBegin(CVType &Record, TypeIndex TI,
                                      LVElement *Element, uint32_t StreamIdx) {
  W.getOStream() << "\n";
  W.startLine() << formatTypeLeafKind(Record.kind());
  W.getOStream() << " (" << HexNumber(TI.getIndex()) << ")";
  W.getOStream() << " {\n";
  W.indent();
  W.printEnum("TypeLeafKind", unsigned(Record.kind()), ArrayRef(LeafTypeNames));
  printTypeIndex("TI", TI, StreamIdx);
  W.startLine() << "Element: " << HexNumber(Element->getOffset()) << " "
                << Element->getName() << "\n";
}

void LVLogicalVisitor::printTypeEnd(CVType &Record) {
  W.unindent();
  W.startLine() << "}\n";
}

void LVLogicalVisitor::printMemberBegin(CVMemberRecord &Record, TypeIndex TI,
                                        LVElement *Element,
                                        uint32_t StreamIdx) {
  W.getOStream() << "\n";
  W.startLine() << formatTypeLeafKind(Record.Kind);
  W.getOStream() << " (" << HexNumber(TI.getIndex()) << ")";
  W.getOStream() << " {\n";
  W.indent();
  W.printEnum("TypeLeafKind", unsigned(Record.Kind), ArrayRef(LeafTypeNames));
  printTypeIndex("TI", TI, StreamIdx);
  W.startLine() << "Element: " << HexNumber(Element->getOffset()) << " "
                << Element->getName() << "\n";
}

void LVLogicalVisitor::printMemberEnd(CVMemberRecord &Record) {
  W.unindent();
  W.startLine() << "}\n";
}

Error LVLogicalVisitor::visitUnknownType(CVType &Record, TypeIndex TI) {
  LLVM_DEBUG({
    printTypeIndex("\nTI", TI, StreamTPI);
    W.printNumber("Length", uint32_t(Record.content().size()));
  });
  return Error::success();
}

// LF_ARGLIST (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ArgListRecord &Args,
                                         TypeIndex TI, LVElement *Element) {
  ArrayRef<TypeIndex> Indices = Args.getIndices();
  uint32_t Size = Indices.size();
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    W.printNumber("NumArgs", Size);
    ListScope Arguments(W, "Arguments");
    for (uint32_t I = 0; I < Size; ++I)
      printTypeIndex("ArgType", Indices[I], StreamTPI);
    printTypeEnd(Record);
  });

  LVScope *Function = static_cast<LVScope *>(Element);
  for (uint32_t Index = 0; Index < Size; ++Index) {
    TypeIndex ParameterType = Indices[Index];
    createParameter(ParameterType, StringRef(), Function);
  }

  return Error::success();
}

// LF_ARRAY (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ArrayRecord &AT,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    printTypeIndex("ElementType", AT.getElementType(), StreamTPI);
    printTypeIndex("IndexType", AT.getIndexType(), StreamTPI);
    W.printNumber("SizeOf", AT.getSize());
    W.printString("Name", AT.getName());
    printTypeEnd(Record);
  });

  if (Element->getIsFinalized())
    return Error::success();
  Element->setIsFinalized();

  LVScopeArray *Array = static_cast<LVScopeArray *>(Element);
  if (!Array)
    return Error::success();

  Reader->getCompileUnit()->addElement(Array);
  TypeIndex TIElementType = AT.getElementType();

  LVType *PrevSubrange = nullptr;
  LazyRandomTypeCollection &Types = types();

  // As the logical view is modeled on DWARF, for each dimension we have to
  // create a DW_TAG_subrange_type, with dimension size.
  // The subrange type can be: unsigned __int32 or unsigned __int64.
  auto AddSubrangeType = [&](ArrayRecord &AR) {
    LVType *Subrange = Reader->createTypeSubrange();
    Subrange->setTag(dwarf::DW_TAG_subrange_type);
    Subrange->setType(getElement(StreamTPI, AR.getIndexType()));
    Subrange->setCount(AR.getSize());
    Subrange->setOffset(
        TIElementType.isSimple()
            ? (uint32_t)(TypeLeafKind)TIElementType.getSimpleKind()
            : TIElementType.getIndex());
    Array->addElement(Subrange);

    if (PrevSubrange)
      if (int64_t Count = Subrange->getCount())
        PrevSubrange->setCount(PrevSubrange->getCount() / Count);
    PrevSubrange = Subrange;
  };

  // Preserve the original TypeIndex; it would be updated in the case of:
  // - The array type contains qualifiers.
  // - In multidimensional arrays, the last LF_ARRAY entry contains the type.
  TypeIndex TIArrayType;

  // For each dimension in the array, there is a LF_ARRAY entry. The last
  // entry contains the array type, which can be a LF_MODIFIER in the case
  // of the type being modified by a qualifier (const, etc).
  ArrayRecord AR(AT);
  CVType CVEntry = Record;
  while (CVEntry.kind() == LF_ARRAY) {
    // Create the subrange information, required by the logical view. Once
    // the array has been processed, the dimension sizes will updated, as
    // the sizes are a progression. For instance:
    // sizeof(int) = 4
    // int Array[2];        Sizes:  8          Dim: 8  /  4 -> [2]
    // int Array[2][3];     Sizes: 24, 12      Dim: 24 / 12 -> [2]
    //                                         Dim: 12 /  4 ->    [3]
    // int Array[2][3][4];  sizes: 96, 48, 16  Dim: 96 / 48 -> [2]
    //                                         Dim: 48 / 16 ->    [3]
    //                                         Dim: 16 /  4 ->       [4]
    AddSubrangeType(AR);
    TIArrayType = TIElementType;

    // The current ElementType can be a modifier, in which case we need to
    // get the type being modified.
    // If TypeIndex is not a simple type, check if we have a qualified type.
    if (!TIElementType.isSimple()) {
      CVType CVElementType = Types.getType(TIElementType);
      if (CVElementType.kind() == LF_MODIFIER) {
        LVElement *QualifiedType =
            Shared->TypeRecords.find(StreamTPI, TIElementType);
        if (Error Err =
                finishVisitation(CVElementType, TIElementType, QualifiedType))
          return Err;
        // Get the TypeIndex of the type that the LF_MODIFIER modifies.
        TIElementType = getModifiedType(CVElementType);
      }
    }
    // Ends the traversal, as we have reached a simple type (int, char, etc).
    if (TIElementType.isSimple())
      break;

    // Read next dimension linked entry, if any.
    CVEntry = Types.getType(TIElementType);
    if (Error Err = TypeDeserializer::deserializeAs(
            const_cast<CVType &>(CVEntry), AR)) {
      consumeError(std::move(Err));
      break;
    }
    TIElementType = AR.getElementType();
    // NOTE: The typeindex has a value of: 0x0280.0000
    getTrueType(TIElementType);
  }

  Array->setName(AT.getName());
  TIArrayType = Shared->ForwardReferences.remap(TIArrayType);
  Array->setType(getElement(StreamTPI, TIArrayType));

  if (PrevSubrange)
    // In the case of an aggregate type (class, struct, union, interface),
    // get the aggregate size. As the original record is pointing to its
    // reference, we have to update it.
    if (uint64_t Size =
            isAggregate(CVEntry)
                ? getSizeInBytesForTypeRecord(Types.getType(TIArrayType))
                : getSizeInBytesForTypeIndex(TIElementType))
      PrevSubrange->setCount(PrevSubrange->getCount() / Size);

  return Error::success();
}

// LF_BITFIELD (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, BitFieldRecord &BF,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    printTypeIndex("Type", TI, StreamTPI);
    W.printNumber("BitSize", BF.getBitSize());
    W.printNumber("BitOffset", BF.getBitOffset());
    printTypeEnd(Record);
  });

  Element->setType(getElement(StreamTPI, BF.getType()));
  Element->setBitSize(BF.getBitSize());
  return Error::success();
}

// LF_BUILDINFO (TPI)/(IPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, BuildInfoRecord &BI,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamIPI);
    W.printNumber("NumArgs", static_cast<uint32_t>(BI.getArgs().size()));
    ListScope Arguments(W, "Arguments");
    for (TypeIndex Arg : BI.getArgs())
      printTypeIndex("ArgType", Arg, StreamIPI);
    printTypeEnd(Record);
  });

  // The given 'Element' refers to the current compilation unit.
  // All the args are references into the TPI/IPI stream.
  TypeIndex TIName = BI.getArgs()[BuildInfoRecord::BuildInfoArg::SourceFile];
  std::string Name = std::string(ids().getTypeName(TIName));

  // There are cases where LF_BUILDINFO fields are empty.
  if (!Name.empty())
    Element->setName(Name);

  return Error::success();
}

// LF_CLASS, LF_STRUCTURE, LF_INTERFACE (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ClassRecord &Class,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    W.printNumber("MemberCount", Class.getMemberCount());
    printTypeIndex("FieldList", Class.getFieldList(), StreamTPI);
    printTypeIndex("DerivedFrom", Class.getDerivationList(), StreamTPI);
    printTypeIndex("VShape", Class.getVTableShape(), StreamTPI);
    W.printNumber("SizeOf", Class.getSize());
    W.printString("Name", Class.getName());
    if (Class.hasUniqueName())
      W.printString("UniqueName", Class.getUniqueName());
    printTypeEnd(Record);
  });

  if (Element->getIsFinalized())
    return Error::success();
  Element->setIsFinalized();

  LVScopeAggregate *Scope = static_cast<LVScopeAggregate *>(Element);
  if (!Scope)
    return Error::success();

  Scope->setName(Class.getName());
  if (Class.hasUniqueName())
    Scope->setLinkageName(Class.getUniqueName());

  if (Class.isNested()) {
    Scope->setIsNested();
    createParents(Class.getName(), Scope);
  }

  if (Class.isScoped())
    Scope->setIsScoped();

  // Nested types will be added to their parents at creation. The forward
  // references are only processed to finish the referenced element creation.
  if (!(Class.isNested() || Class.isScoped())) {
    if (LVScope *Namespace = Shared->NamespaceDeduction.get(Class.getName()))
      Namespace->addElement(Scope);
    else
      Reader->getCompileUnit()->addElement(Scope);
  }

  LazyRandomTypeCollection &Types = types();
  TypeIndex TIFieldList = Class.getFieldList();
  if (TIFieldList.isNoneType()) {
    TypeIndex ForwardType = Shared->ForwardReferences.find(Class.getName());
    if (!ForwardType.isNoneType()) {
      CVType CVReference = Types.getType(ForwardType);
      TypeRecordKind RK = static_cast<TypeRecordKind>(CVReference.kind());
      ClassRecord ReferenceRecord(RK);
      if (Error Err = TypeDeserializer::deserializeAs(
              const_cast<CVType &>(CVReference), ReferenceRecord))
        return Err;
      TIFieldList = ReferenceRecord.getFieldList();
    }
  }

  if (!TIFieldList.isNoneType()) {
    // Pass down the TypeIndex 'TI' for the aggregate containing the field list.
    CVType CVFieldList = Types.getType(TIFieldList);
    if (Error Err = finishVisitation(CVFieldList, TI, Scope))
      return Err;
  }

  return Error::success();
}

// LF_ENUM (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, EnumRecord &Enum,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    W.printNumber("NumEnumerators", Enum.getMemberCount());
    printTypeIndex("UnderlyingType", Enum.getUnderlyingType(), StreamTPI);
    printTypeIndex("FieldListType", Enum.getFieldList(), StreamTPI);
    W.printString("Name", Enum.getName());
    printTypeEnd(Record);
  });

  LVScopeEnumeration *Scope = static_cast<LVScopeEnumeration *>(Element);
  if (!Scope)
    return Error::success();

  if (Scope->getIsFinalized())
    return Error::success();
  Scope->setIsFinalized();

  // Set the name, as in the case of nested, it would determine the relation
  // to any potential parent, via the LF_NESTTYPE record.
  Scope->setName(Enum.getName());
  if (Enum.hasUniqueName())
    Scope->setLinkageName(Enum.getUniqueName());

  Scope->setType(getElement(StreamTPI, Enum.getUnderlyingType()));

  if (Enum.isNested()) {
    Scope->setIsNested();
    createParents(Enum.getName(), Scope);
  }

  if (Enum.isScoped()) {
    Scope->setIsScoped();
    Scope->setIsEnumClass();
  }

  // Nested types will be added to their parents at creation.
  if (!(Enum.isNested() || Enum.isScoped())) {
    if (LVScope *Namespace = Shared->NamespaceDeduction.get(Enum.getName()))
      Namespace->addElement(Scope);
    else
      Reader->getCompileUnit()->addElement(Scope);
  }

  TypeIndex TIFieldList = Enum.getFieldList();
  if (!TIFieldList.isNoneType()) {
    LazyRandomTypeCollection &Types = types();
    CVType CVFieldList = Types.getType(TIFieldList);
    if (Error Err = finishVisitation(CVFieldList, TIFieldList, Scope))
      return Err;
  }

  return Error::success();
}

// LF_FIELDLIST (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record,
                                         FieldListRecord &FieldList,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    printTypeEnd(Record);
  });

  if (Error Err = visitFieldListMemberStream(TI, Element, FieldList.Data))
    return Err;

  return Error::success();
}

// LF_FUNC_ID (TPI)/(IPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, FuncIdRecord &Func,
                                         TypeIndex TI, LVElement *Element) {
  // ParentScope and FunctionType are references into the TPI stream.
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamIPI);
    printTypeIndex("ParentScope", Func.getParentScope(), StreamTPI);
    printTypeIndex("FunctionType", Func.getFunctionType(), StreamTPI);
    W.printString("Name", Func.getName());
    printTypeEnd(Record);
  });

  // The TypeIndex (LF_PROCEDURE) returned by 'getFunctionType' is the
  // function propotype, we need to use the function definition.
  if (LVScope *FunctionDcl = static_cast<LVScope *>(Element)) {
    // For inlined functions, the inlined instance has been already processed
    // (all its information is contained in the Symbols section).
    // 'Element' points to the created 'abstract' (out-of-line) function.
    // Use the parent scope information to allocate it to the correct scope.
    LazyRandomTypeCollection &Types = types();
    TypeIndex TIParent = Func.getParentScope();
    if (FunctionDcl->getIsInlinedAbstract()) {
      FunctionDcl->setName(Func.getName());
      if (TIParent.isNoneType())
        Reader->getCompileUnit()->addElement(FunctionDcl);
    }

    if (!TIParent.isNoneType()) {
      CVType CVParentScope = ids().getType(TIParent);
      if (Error Err = finishVisitation(CVParentScope, TIParent, FunctionDcl))
        return Err;
    }

    TypeIndex TIFunctionType = Func.getFunctionType();
    CVType CVFunctionType = Types.getType(TIFunctionType);
    if (Error Err =
            finishVisitation(CVFunctionType, TIFunctionType, FunctionDcl))
      return Err;

    FunctionDcl->setIsFinalized();
  }

  return Error::success();
}

// LF_LABEL (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, LabelRecord &LR,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    printTypeEnd(Record);
  });
  return Error::success();
}

// LF_MFUNC_ID (TPI)/(IPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, MemberFuncIdRecord &Id,
                                         TypeIndex TI, LVElement *Element) {
  // ClassType and FunctionType are references into the TPI stream.
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamIPI);
    printTypeIndex("ClassType", Id.getClassType(), StreamTPI);
    printTypeIndex("FunctionType", Id.getFunctionType(), StreamTPI);
    W.printString("Name", Id.getName());
    printTypeEnd(Record);
  });

  LVScope *FunctionDcl = static_cast<LVScope *>(Element);
  if (FunctionDcl->getIsInlinedAbstract()) {
    // For inlined functions, the inlined instance has been already processed
    // (all its information is contained in the Symbols section).
    // 'Element' points to the created 'abstract' (out-of-line) function.
    // Use the parent scope information to allocate it to the correct scope.
    if (LVScope *Class = static_cast<LVScope *>(
            Shared->TypeRecords.find(StreamTPI, Id.getClassType())))
      Class->addElement(FunctionDcl);
  }

  TypeIndex TIFunctionType = Id.getFunctionType();
  CVType CVFunction = types().getType(TIFunctionType);
  if (Error Err = finishVisitation(CVFunction, TIFunctionType, Element))
    return Err;

  return Error::success();
}

// LF_MFUNCTION (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record,
                                         MemberFunctionRecord &MF, TypeIndex TI,
                                         LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    printTypeIndex("ReturnType", MF.getReturnType(), StreamTPI);
    printTypeIndex("ClassType", MF.getClassType(), StreamTPI);
    printTypeIndex("ThisType", MF.getThisType(), StreamTPI);
    W.printNumber("NumParameters", MF.getParameterCount());
    printTypeIndex("ArgListType", MF.getArgumentList(), StreamTPI);
    W.printNumber("ThisAdjustment", MF.getThisPointerAdjustment());
    printTypeEnd(Record);
  });

  if (LVScope *MemberFunction = static_cast<LVScope *>(Element)) {
    LVElement *Class = getElement(StreamTPI, MF.getClassType());

    MemberFunction->setIsFinalized();
    MemberFunction->setType(getElement(StreamTPI, MF.getReturnType()));
    MemberFunction->setOffset(TI.getIndex());
    MemberFunction->setOffsetFromTypeIndex();

    if (ProcessArgumentList) {
      ProcessArgumentList = false;

      if (!MemberFunction->getIsStatic()) {
        LVElement *ThisPointer = getElement(StreamTPI, MF.getThisType());
        // When creating the 'this' pointer, check if it points to a reference.
        ThisPointer->setType(Class);
        LVSymbol *This =
            createParameter(ThisPointer, StringRef(), MemberFunction);
        This->setIsArtificial();
      }

      // Create formal parameters.
      LazyRandomTypeCollection &Types = types();
      CVType CVArguments = Types.getType(MF.getArgumentList());
      if (Error Err = finishVisitation(CVArguments, MF.getArgumentList(),
                                       MemberFunction))
        return Err;
    }
  }

  return Error::success();
}

// LF_METHODLIST (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record,
                                         MethodOverloadListRecord &Overloads,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    printTypeEnd(Record);
  });

  for (OneMethodRecord &Method : Overloads.Methods) {
    CVMemberRecord Record;
    Record.Kind = LF_METHOD;
    Method.Name = OverloadedMethodName;
    if (Error Err = visitKnownMember(Record, Method, TI, Element))
      return Err;
  }

  return Error::success();
}

// LF_MODIFIER (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ModifierRecord &Mod,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    printTypeIndex("ModifiedType", Mod.getModifiedType(), StreamTPI);
    printTypeEnd(Record);
  });

  // Create the modified type, which will be attached to the type(s) that
  // contains the modifiers.
  LVElement *ModifiedType = getElement(StreamTPI, Mod.getModifiedType());

  // At this point the types recording the qualifiers do not have a
  // scope parent. They must be assigned to the current compile unit.
  LVScopeCompileUnit *CompileUnit = Reader->getCompileUnit();

  // The incoming element does not have a defined kind. Use the given
  // modifiers to complete its type. A type can have more than one modifier;
  // in that case, we have to create an extra type to have the other modifier.
  LVType *LastLink = static_cast<LVType *>(Element);
  if (!LastLink->getParentScope())
    CompileUnit->addElement(LastLink);

  bool SeenModifier = false;
  uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
  if (Mods & uint16_t(ModifierOptions::Const)) {
    SeenModifier = true;
    LastLink->setTag(dwarf::DW_TAG_const_type);
    LastLink->setIsConst();
    LastLink->setName("const");
  }
  if (Mods & uint16_t(ModifierOptions::Volatile)) {
    if (SeenModifier) {
      LVType *Volatile = Reader->createType();
      Volatile->setIsModifier();
      LastLink->setType(Volatile);
      LastLink = Volatile;
      CompileUnit->addElement(LastLink);
    }
    LastLink->setTag(dwarf::DW_TAG_volatile_type);
    LastLink->setIsVolatile();
    LastLink->setName("volatile");
  }
  if (Mods & uint16_t(ModifierOptions::Unaligned)) {
    if (SeenModifier) {
      LVType *Unaligned = Reader->createType();
      Unaligned->setIsModifier();
      LastLink->setType(Unaligned);
      LastLink = Unaligned;
      CompileUnit->addElement(LastLink);
    }
    LastLink->setTag(dwarf::DW_TAG_unaligned);
    LastLink->setIsUnaligned();
    LastLink->setName("unaligned");
  }

  LastLink->setType(ModifiedType);
  return Error::success();
}

// LF_POINTER (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, PointerRecord &Ptr,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    printTypeIndex("PointeeType", Ptr.getReferentType(), StreamTPI);
    W.printNumber("IsFlat", Ptr.isFlat());
    W.printNumber("IsConst", Ptr.isConst());
    W.printNumber("IsVolatile", Ptr.isVolatile());
    W.printNumber("IsUnaligned", Ptr.isUnaligned());
    W.printNumber("IsRestrict", Ptr.isRestrict());
    W.printNumber("IsThisPtr&", Ptr.isLValueReferenceThisPtr());
    W.printNumber("IsThisPtr&&", Ptr.isRValueReferenceThisPtr());
    W.printNumber("SizeOf", Ptr.getSize());

    if (Ptr.isPointerToMember()) {
      const MemberPointerInfo &MI = Ptr.getMemberInfo();
      printTypeIndex("ClassType", MI.getContainingType(), StreamTPI);
    }
    printTypeEnd(Record);
  });

  // Find the pointed-to type.
  LVType *Pointer = static_cast<LVType *>(Element);
  LVElement *Pointee = nullptr;

  PointerMode Mode = Ptr.getMode();
  Pointee = Ptr.isPointerToMember()
                ? Shared->TypeRecords.find(StreamTPI, Ptr.getReferentType())
                : getElement(StreamTPI, Ptr.getReferentType());

  // At this point the types recording the qualifiers do not have a
  // scope parent. They must be assigned to the current compile unit.
  LVScopeCompileUnit *CompileUnit = Reader->getCompileUnit();

  // Order for the different modifiers:
  // <restrict> <pointer, Reference, ValueReference> <const, volatile>
  // Const and volatile already processed.
  bool SeenModifier = false;
  LVType *LastLink = Pointer;
  if (!LastLink->getParentScope())
    CompileUnit->addElement(LastLink);

  if (Ptr.isRestrict()) {
    SeenModifier = true;
    LVType *Restrict = Reader->createType();
    Restrict->setTag(dwarf::DW_TAG_restrict_type);
    Restrict->setIsRestrict();
    Restrict->setName("restrict");
    LastLink->setType(Restrict);
    LastLink = Restrict;
    CompileUnit->addElement(LastLink);
  }
  if (Mode == PointerMode::LValueReference) {
    if (SeenModifier) {
      LVType *LReference = Reader->createType();
      LReference->setIsModifier();
      LastLink->setType(LReference);
      LastLink = LReference;
      CompileUnit->addElement(LastLink);
    }
    LastLink->setTag(dwarf::DW_TAG_reference_type);
    LastLink->setIsReference();
    LastLink->setName("&");
  }
  if (Mode == PointerMode::RValueReference) {
    if (SeenModifier) {
      LVType *RReference = Reader->createType();
      RReference->setIsModifier();
      LastLink->setType(RReference);
      LastLink = RReference;
      CompileUnit->addElement(LastLink);
    }
    LastLink->setTag(dwarf::DW_TAG_rvalue_reference_type);
    LastLink->setIsRvalueReference();
    LastLink->setName("&&");
  }

  // When creating the pointer, check if it points to a reference.
  LastLink->setType(Pointee);
  return Error::success();
}

// LF_PROCEDURE (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, ProcedureRecord &Proc,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    printTypeIndex("ReturnType", Proc.getReturnType(), StreamTPI);
    W.printNumber("NumParameters", Proc.getParameterCount());
    printTypeIndex("ArgListType", Proc.getArgumentList(), StreamTPI);
    printTypeEnd(Record);
  });

  // There is no need to traverse the argument list, as the CodeView format
  // declares the parameters as a 'S_LOCAL' symbol tagged as parameter.
  // Only process parameters when dealing with inline functions.
  if (LVScope *FunctionDcl = static_cast<LVScope *>(Element)) {
    FunctionDcl->setType(getElement(StreamTPI, Proc.getReturnType()));

    if (ProcessArgumentList) {
      ProcessArgumentList = false;
      // Create formal parameters.
      LazyRandomTypeCollection &Types = types();
      CVType CVArguments = Types.getType(Proc.getArgumentList());
      if (Error Err = finishVisitation(CVArguments, Proc.getArgumentList(),
                                       FunctionDcl))
        return Err;
    }
  }

  return Error::success();
}

// LF_UNION (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, UnionRecord &Union,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    W.printNumber("MemberCount", Union.getMemberCount());
    printTypeIndex("FieldList", Union.getFieldList(), StreamTPI);
    W.printNumber("SizeOf", Union.getSize());
    W.printString("Name", Union.getName());
    if (Union.hasUniqueName())
      W.printString("UniqueName", Union.getUniqueName());
    printTypeEnd(Record);
  });

  LVScopeAggregate *Scope = static_cast<LVScopeAggregate *>(Element);
  if (!Scope)
    return Error::success();

  if (Scope->getIsFinalized())
    return Error::success();
  Scope->setIsFinalized();

  Scope->setName(Union.getName());
  if (Union.hasUniqueName())
    Scope->setLinkageName(Union.getUniqueName());

  if (Union.isNested()) {
    Scope->setIsNested();
    createParents(Union.getName(), Scope);
  } else {
    if (LVScope *Namespace = Shared->NamespaceDeduction.get(Union.getName()))
      Namespace->addElement(Scope);
    else
      Reader->getCompileUnit()->addElement(Scope);
  }

  if (!Union.getFieldList().isNoneType()) {
    LazyRandomTypeCollection &Types = types();
    // Pass down the TypeIndex 'TI' for the aggregate containing the field list.
    CVType CVFieldList = Types.getType(Union.getFieldList());
    if (Error Err = finishVisitation(CVFieldList, TI, Scope))
      return Err;
  }

  return Error::success();
}

// LF_TYPESERVER2 (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, TypeServer2Record &TS,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    W.printString("Guid", formatv("{0}", TS.getGuid()).str());
    W.printNumber("Age", TS.getAge());
    W.printString("Name", TS.getName());
    printTypeEnd(Record);
  });
  return Error::success();
}

// LF_VFTABLE (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, VFTableRecord &VFT,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    printTypeIndex("CompleteClass", VFT.getCompleteClass(), StreamTPI);
    printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable(), StreamTPI);
    W.printHex("VFPtrOffset", VFT.getVFPtrOffset());
    W.printString("VFTableName", VFT.getName());
    for (const StringRef &N : VFT.getMethodNames())
      W.printString("MethodName", N);
    printTypeEnd(Record);
  });
  return Error::success();
}

// LF_VTSHAPE (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record,
                                         VFTableShapeRecord &Shape,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    W.printNumber("VFEntryCount", Shape.getEntryCount());
    printTypeEnd(Record);
  });
  return Error::success();
}

// LF_SUBSTR_LIST (TPI)/(IPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record,
                                         StringListRecord &Strings,
                                         TypeIndex TI, LVElement *Element) {
  // All the indices are references into the TPI/IPI stream.
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamIPI);
    ArrayRef<TypeIndex> Indices = Strings.getIndices();
    uint32_t Size = Indices.size();
    W.printNumber("NumStrings", Size);
    ListScope Arguments(W, "Strings");
    for (uint32_t I = 0; I < Size; ++I)
      printTypeIndex("String", Indices[I], StreamIPI);
    printTypeEnd(Record);
  });
  return Error::success();
}

// LF_STRING_ID (TPI)/(IPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, StringIdRecord &String,
                                         TypeIndex TI, LVElement *Element) {
  // All args are references into the TPI/IPI stream.
  LLVM_DEBUG({
    printTypeIndex("\nTI", TI, StreamIPI);
    printTypeIndex("Id", String.getId(), StreamIPI);
    W.printString("StringData", String.getString());
  });

  if (LVScope *Namespace = Shared->NamespaceDeduction.get(
          String.getString(), /*CheckScope=*/false)) {
    // The function is already at different scope. In order to reflect
    // the correct parent, move it to the namespace.
    if (LVScope *Scope = Element->getParentScope())
      Scope->removeElement(Element);
    Namespace->addElement(Element);
  }

  return Error::success();
}

// LF_UDT_SRC_LINE (TPI)/(IPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record,
                                         UdtSourceLineRecord &SourceLine,
                                         TypeIndex TI, LVElement *Element) {
  // All args are references into the TPI/IPI stream.
  LLVM_DEBUG({
    printTypeIndex("\nTI", TI, StreamIPI);
    printTypeIndex("UDT", SourceLine.getUDT(), StreamIPI);
    printTypeIndex("SourceFile", SourceLine.getSourceFile(), StreamIPI);
    W.printNumber("LineNumber", SourceLine.getLineNumber());
  });
  return Error::success();
}

// LF_UDT_MOD_SRC_LINE (TPI)/(IPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record,
                                         UdtModSourceLineRecord &ModSourceLine,
                                         TypeIndex TI, LVElement *Element) {
  // All args are references into the TPI/IPI stream.
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamIPI);
    printTypeIndex("\nTI", TI, StreamIPI);
    printTypeIndex("UDT", ModSourceLine.getUDT(), StreamIPI);
    printTypeIndex("SourceFile", ModSourceLine.getSourceFile(), StreamIPI);
    W.printNumber("LineNumber", ModSourceLine.getLineNumber());
    W.printNumber("Module", ModSourceLine.getModule());
    printTypeEnd(Record);
  });
  return Error::success();
}

// LF_PRECOMP (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record, PrecompRecord &Precomp,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    W.printHex("StartIndex", Precomp.getStartTypeIndex());
    W.printHex("Count", Precomp.getTypesCount());
    W.printHex("Signature", Precomp.getSignature());
    W.printString("PrecompFile", Precomp.getPrecompFilePath());
    printTypeEnd(Record);
  });
  return Error::success();
}

// LF_ENDPRECOMP (TPI)
Error LVLogicalVisitor::visitKnownRecord(CVType &Record,
                                         EndPrecompRecord &EndPrecomp,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printTypeBegin(Record, TI, Element, StreamTPI);
    W.printHex("Signature", EndPrecomp.getSignature());
    printTypeEnd(Record);
  });
  return Error::success();
}

Error LVLogicalVisitor::visitUnknownMember(CVMemberRecord &Record,
                                           TypeIndex TI) {
  LLVM_DEBUG({ W.printHex("UnknownMember", unsigned(Record.Kind)); });
  return Error::success();
}

// LF_BCLASS, LF_BINTERFACE
Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record,
                                         BaseClassRecord &Base, TypeIndex TI,
                                         LVElement *Element) {
  LLVM_DEBUG({
    printMemberBegin(Record, TI, Element, StreamTPI);
    printTypeIndex("BaseType", Base.getBaseType(), StreamTPI);
    W.printHex("BaseOffset", Base.getBaseOffset());
    printMemberEnd(Record);
  });

  createElement(Record.Kind);
  if (LVSymbol *Symbol = CurrentSymbol) {
    LVElement *BaseClass = getElement(StreamTPI, Base.getBaseType());
    Symbol->setName(BaseClass->getName());
    Symbol->setType(BaseClass);
    Symbol->setAccessibilityCode(Base.getAccess());
    static_cast<LVScope *>(Element)->addElement(Symbol);
  }

  return Error::success();
}

// LF_MEMBER
Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record,
                                         DataMemberRecord &Field, TypeIndex TI,
                                         LVElement *Element) {
  LLVM_DEBUG({
    printMemberBegin(Record, TI, Element, StreamTPI);
    printTypeIndex("Type", Field.getType(), StreamTPI);
    W.printHex("FieldOffset", Field.getFieldOffset());
    W.printString("Name", Field.getName());
    printMemberEnd(Record);
  });

  // Create the data member.
  createDataMember(Record, static_cast<LVScope *>(Element), Field.getName(),
                   Field.getType(), Field.getAccess());
  return Error::success();
}

// LF_ENUMERATE
Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record,
                                         EnumeratorRecord &Enum, TypeIndex TI,
                                         LVElement *Element) {
  LLVM_DEBUG({
    printMemberBegin(Record, TI, Element, StreamTPI);
    W.printNumber("EnumValue", Enum.getValue());
    W.printString("Name", Enum.getName());
    printMemberEnd(Record);
  });

  createElement(Record.Kind);
  if (LVType *Type = CurrentType) {
    Type->setName(Enum.getName());
    SmallString<16> Value;
    Enum.getValue().toString(Value, 16, true, true);
    Type->setValue(Value);
    static_cast<LVScope *>(Element)->addElement(CurrentType);
  }

  return Error::success();
}

// LF_INDEX
Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record,
                                         ListContinuationRecord &Cont,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printMemberBegin(Record, TI, Element, StreamTPI);
    printTypeIndex("ContinuationIndex", Cont.getContinuationIndex(), StreamTPI);
    printMemberEnd(Record);
  });
  return Error::success();
}

// LF_NESTTYPE
Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record,
                                         NestedTypeRecord &Nested, TypeIndex TI,
                                         LVElement *Element) {
  LLVM_DEBUG({
    printMemberBegin(Record, TI, Element, StreamTPI);
    printTypeIndex("Type", Nested.getNestedType(), StreamTPI);
    W.printString("Name", Nested.getName());
    printMemberEnd(Record);
  });

  if (LVElement *Typedef = createElement(SymbolKind::S_UDT)) {
    Typedef->setName(Nested.getName());
    LVElement *NestedType = getElement(StreamTPI, Nested.getNestedType());
    Typedef->setType(NestedType);
    LVScope *Scope = static_cast<LVScope *>(Element);
    Scope->addElement(Typedef);

    if (NestedType && NestedType->getIsNested()) {
      // 'Element' is an aggregate type that may contains this nested type
      // definition. Used their scoped names, to decide on their relationship.
      StringRef RecordName = getRecordName(types(), TI);

      StringRef NestedTypeName = NestedType->getName();
      if (NestedTypeName.size() && RecordName.size()) {
        StringRef OuterComponent;
        std::tie(OuterComponent, std::ignore) =
            getInnerComponent(NestedTypeName);
        // We have an already created nested type. Add it to the current scope
        // and update all its children if any.
        if (OuterComponent.size() && OuterComponent.equals(RecordName)) {
          if (!NestedType->getIsScopedAlready()) {
            Scope->addElement(NestedType);
            NestedType->setIsScopedAlready();
            NestedType->updateLevel(Scope);
          }
          Typedef->resetIncludeInPrint();
        }
      }
    }
  }

  return Error::success();
}

// LF_ONEMETHOD
Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record,
                                         OneMethodRecord &Method, TypeIndex TI,
                                         LVElement *Element) {
  LLVM_DEBUG({
    printMemberBegin(Record, TI, Element, StreamTPI);
    printTypeIndex("Type", Method.getType(), StreamTPI);
    // If virtual, then read the vftable offset.
    if (Method.isIntroducingVirtual())
      W.printHex("VFTableOffset", Method.getVFTableOffset());
    W.printString("Name", Method.getName());
    printMemberEnd(Record);
  });

  // All the LF_ONEMETHOD objects share the same type description.
  // We have to create a scope object for each one and get the required
  // information from the LF_MFUNCTION object.
  ProcessArgumentList = true;
  if (LVElement *MemberFunction = createElement(TypeLeafKind::LF_ONEMETHOD)) {
    MemberFunction->setIsFinalized();
    static_cast<LVScope *>(Element)->addElement(MemberFunction);

    MemberFunction->setName(Method.getName());
    MemberFunction->setAccessibilityCode(Method.getAccess());

    MethodKind Kind = Method.getMethodKind();
    if (Kind == MethodKind::Static)
      MemberFunction->setIsStatic();
    MemberFunction->setVirtualityCode(Kind);

    MethodOptions Flags = Method.Attrs.getFlags();
    if (MethodOptions::CompilerGenerated ==
        (Flags & MethodOptions::CompilerGenerated))
      MemberFunction->setIsArtificial();

    LazyRandomTypeCollection &Types = types();
    CVType CVMethodType = Types.getType(Method.getType());
    if (Error Err =
            finishVisitation(CVMethodType, Method.getType(), MemberFunction))
      return Err;
  }
  ProcessArgumentList = false;

  return Error::success();
}

// LF_METHOD
Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record,
                                         OverloadedMethodRecord &Method,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printMemberBegin(Record, TI, Element, StreamTPI);
    W.printHex("MethodCount", Method.getNumOverloads());
    printTypeIndex("MethodListIndex", Method.getMethodList(), StreamTPI);
    W.printString("Name", Method.getName());
    printMemberEnd(Record);
  });

  // Record the overloaded method name, which will be used during the
  // traversal of the method list.
  LazyRandomTypeCollection &Types = types();
  OverloadedMethodName = Method.getName();
  CVType CVMethods = Types.getType(Method.getMethodList());
  if (Error Err = finishVisitation(CVMethods, Method.getMethodList(), Element))
    return Err;

  return Error::success();
}

// LF_STMEMBER
Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record,
                                         StaticDataMemberRecord &Field,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printMemberBegin(Record, TI, Element, StreamTPI);
    printTypeIndex("Type", Field.getType(), StreamTPI);
    W.printString("Name", Field.getName());
    printMemberEnd(Record);
  });

  // Create the data member.
  createDataMember(Record, static_cast<LVScope *>(Element), Field.getName(),
                   Field.getType(), Field.getAccess());
  return Error::success();
}

// LF_VFUNCTAB
Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record,
                                         VFPtrRecord &VFTable, TypeIndex TI,
                                         LVElement *Element) {
  LLVM_DEBUG({
    printMemberBegin(Record, TI, Element, StreamTPI);
    printTypeIndex("Type", VFTable.getType(), StreamTPI);
    printMemberEnd(Record);
  });
  return Error::success();
}

// LF_VBCLASS, LF_IVBCLASS
Error LVLogicalVisitor::visitKnownMember(CVMemberRecord &Record,
                                         VirtualBaseClassRecord &Base,
                                         TypeIndex TI, LVElement *Element) {
  LLVM_DEBUG({
    printMemberBegin(Record, TI, Element, StreamTPI);
    printTypeIndex("BaseType", Base.getBaseType(), StreamTPI);
    printTypeIndex("VBPtrType", Base.getVBPtrType(), StreamTPI);
    W.printHex("VBPtrOffset", Base.getVBPtrOffset());
    W.printHex("VBTableIndex", Base.getVTableIndex());
    printMemberEnd(Record);
  });

  createElement(Record.Kind);
  if (LVSymbol *Symbol = CurrentSymbol) {
    LVElement *BaseClass = getElement(StreamTPI, Base.getBaseType());
    Symbol->setName(BaseClass->getName());
    Symbol->setType(BaseClass);
    Symbol->setAccessibilityCode(Base.getAccess());
    Symbol->setVirtualityCode(MethodKind::Virtual);
    static_cast<LVScope *>(Element)->addElement(Symbol);
  }

  return Error::success();
}

Error LVLogicalVisitor::visitMemberRecord(CVMemberRecord &Record,
                                          TypeVisitorCallbacks &Callbacks,
                                          TypeIndex TI, LVElement *Element) {
  if (Error Err = Callbacks.visitMemberBegin(Record))
    return Err;

  switch (Record.Kind) {
  default:
    if (Error Err = Callbacks.visitUnknownMember(Record))
      return Err;
    break;
#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
  case EnumName: {                                                             \
    if (Error Err =                                                            \
            visitKnownMember<Name##Record>(Record, Callbacks, TI, Element))    \
      return Err;                                                              \
    break;                                                                     \
  }
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
  MEMBER_RECORD(EnumVal, EnumVal, AliasName)
#define TYPE_RECORD(EnumName, EnumVal, Name)
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
  }

  if (Error Err = Callbacks.visitMemberEnd(Record))
    return Err;

  return Error::success();
}

Error LVLogicalVisitor::finishVisitation(CVType &Record, TypeIndex TI,
                                         LVElement *Element) {
  switch (Record.kind()) {
  default:
    if (Error Err = visitUnknownType(Record, TI))
      return Err;
    break;
#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
  case EnumName: {                                                             \
    if (Error Err = visitKnownRecord<Name##Record>(Record, TI, Element))       \
      return Err;                                                              \
    break;                                                                     \
  }
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                  \
  TYPE_RECORD(EnumVal, EnumVal, AliasName)
#define MEMBER_RECORD(EnumName, EnumVal, Name)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
  }

  return Error::success();
}

// Customized version of 'FieldListVisitHelper'.
Error LVLogicalVisitor::visitFieldListMemberStream(
    TypeIndex TI, LVElement *Element, ArrayRef<uint8_t> FieldList) {
  BinaryByteStream Stream(FieldList, llvm::endianness::little);
  BinaryStreamReader Reader(Stream);
  FieldListDeserializer Deserializer(Reader);
  TypeVisitorCallbackPipeline Pipeline;
  Pipeline.addCallbackToPipeline(Deserializer);

  TypeLeafKind Leaf;
  while (!Reader.empty()) {
    if (Error Err = Reader.readEnum(Leaf))
      return Err;

    CVMemberRecord Record;
    Record.Kind = Leaf;
    if (Error Err = visitMemberRecord(Record, Pipeline, TI, Element))
      return Err;
  }

  return Error::success();
}

void LVLogicalVisitor::addElement(LVScope *Scope, bool IsCompileUnit) {
  // The CodeView specifications does not treat S_COMPILE2 and S_COMPILE3
  // as symbols that open a scope. The CodeView reader, treat them in a
  // similar way as DWARF. As there is no a symbole S_END to close the
  // compile unit, we need to check for the next compile unit.
  if (IsCompileUnit) {
    if (!ScopeStack.empty())
      popScope();
    InCompileUnitScope = true;
  }

  pushScope(Scope);
  ReaderParent->addElement(Scope);
}

void LVLogicalVisitor::addElement(LVSymbol *Symbol) {
  ReaderScope->addElement(Symbol);
}

void LVLogicalVisitor::addElement(LVType *Type) {
  ReaderScope->addElement(Type);
}

LVElement *LVLogicalVisitor::createElement(TypeLeafKind Kind) {
  CurrentScope = nullptr;
  CurrentSymbol = nullptr;
  CurrentType = nullptr;

  if (Kind < TypeIndex::FirstNonSimpleIndex) {
    CurrentType = Reader->createType();
    CurrentType->setIsBase();
    CurrentType->setTag(dwarf::DW_TAG_base_type);
    if (options().getAttributeBase())
      CurrentType->setIncludeInPrint();
    return CurrentType;
  }

  switch (Kind) {
  // Types.
  case TypeLeafKind::LF_ENUMERATE:
    CurrentType = Reader->createTypeEnumerator();
    CurrentType->setTag(dwarf::DW_TAG_enumerator);
    return CurrentType;
  case TypeLeafKind::LF_MODIFIER:
    CurrentType = Reader->createType();
    CurrentType->setIsModifier();
    return CurrentType;
  case TypeLeafKind::LF_POINTER:
    CurrentType = Reader->createType();
    CurrentType->setIsPointer();
    CurrentType->setName("*");
    CurrentType->setTag(dwarf::DW_TAG_pointer_type);
    return CurrentType;

    // Symbols.
  case TypeLeafKind::LF_BCLASS:
  case TypeLeafKind::LF_IVBCLASS:
  case TypeLeafKind::LF_VBCLASS:
    CurrentSymbol = Reader->createSymbol();
    CurrentSymbol->setTag(dwarf::DW_TAG_inheritance);
    CurrentSymbol->setIsInheritance();
    return CurrentSymbol;
  case TypeLeafKind::LF_MEMBER:
  case TypeLeafKind::LF_STMEMBER:
    CurrentSymbol = Reader->createSymbol();
    CurrentSymbol->setIsMember();
    CurrentSymbol->setTag(dwarf::DW_TAG_member);
    return CurrentSymbol;

  // Scopes.
  case TypeLeafKind::LF_ARRAY:
    CurrentScope = Reader->createScopeArray();
    CurrentScope->setTag(dwarf::DW_TAG_array_type);
    return CurrentScope;
  case TypeLeafKind::LF_CLASS:
    CurrentScope = Reader->createScopeAggregate();
    CurrentScope->setTag(dwarf::DW_TAG_class_type);
    CurrentScope->setIsClass();
    return CurrentScope;
  case TypeLeafKind::LF_ENUM:
    CurrentScope = Reader->createScopeEnumeration();
    CurrentScope->setTag(dwarf::DW_TAG_enumeration_type);
    return CurrentScope;
  case TypeLeafKind::LF_METHOD:
  case TypeLeafKind::LF_ONEMETHOD:
  case TypeLeafKind::LF_PROCEDURE:
    CurrentScope = Reader->createScopeFunction();
    CurrentScope->setIsSubprogram();
    CurrentScope->setTag(dwarf::DW_TAG_subprogram);
    return CurrentScope;
  case TypeLeafKind::LF_STRUCTURE:
    CurrentScope = Reader->createScopeAggregate();
    CurrentScope->setIsStructure();
    CurrentScope->setTag(dwarf::DW_TAG_structure_type);
    return CurrentScope;
  case TypeLeafKind::LF_UNION:
    CurrentScope = Reader->createScopeAggregate();
    CurrentScope->setIsUnion();
    CurrentScope->setTag(dwarf::DW_TAG_union_type);
    return CurrentScope;
  default:
    // If '--internal=tag' and '--print=warning' are specified in the command
    // line, we record and print each seen 'TypeLeafKind'.
    break;
  }
  return nullptr;
}

LVElement *LVLogicalVisitor::createElement(SymbolKind Kind) {
  CurrentScope = nullptr;
  CurrentSymbol = nullptr;
  CurrentType = nullptr;
  switch (Kind) {
  // Types.
  case SymbolKind::S_UDT:
    CurrentType = Reader->createTypeDefinition();
    CurrentType->setTag(dwarf::DW_TAG_typedef);
    return CurrentType;

  // Symbols.
  case SymbolKind::S_CONSTANT:
    CurrentSymbol = Reader->createSymbol();
    CurrentSymbol->setIsConstant();
    CurrentSymbol->setTag(dwarf::DW_TAG_constant);
    return CurrentSymbol;

  case SymbolKind::S_BPREL32:
  case SymbolKind::S_REGREL32:
  case SymbolKind::S_GDATA32:
  case SymbolKind::S_LDATA32:
  case SymbolKind::S_LOCAL:
    // During the symbol traversal more information is available to
    // determine if the symbol is a parameter or a variable. At this
    // stage mark it as variable.
    CurrentSymbol = Reader->createSymbol();
    CurrentSymbol->setIsVariable();
    CurrentSymbol->setTag(dwarf::DW_TAG_variable);
    return CurrentSymbol;

  // Scopes.
  case SymbolKind::S_BLOCK32:
    CurrentScope = Reader->createScope();
    CurrentScope->setIsLexicalBlock();
    CurrentScope->setTag(dwarf::DW_TAG_lexical_block);
    return CurrentScope;
  case SymbolKind::S_COMPILE2:
  case SymbolKind::S_COMPILE3:
    CurrentScope = Reader->createScopeCompileUnit();
    CurrentScope->setTag(dwarf::DW_TAG_compile_unit);
    Reader->setCompileUnit(static_cast<LVScopeCompileUnit *>(CurrentScope));
    return CurrentScope;
  case SymbolKind::S_INLINESITE:
  case SymbolKind::S_INLINESITE2:
    CurrentScope = Reader->createScopeFunctionInlined();
    CurrentScope->setIsInlinedFunction();
    CurrentScope->setTag(dwarf::DW_TAG_inlined_subroutine);
    return CurrentScope;
  case SymbolKind::S_LPROC32:
  case SymbolKind::S_GPROC32:
  case SymbolKind::S_LPROC32_ID:
  case SymbolKind::S_GPROC32_ID:
  case SymbolKind::S_SEPCODE:
  case SymbolKind::S_THUNK32:
    CurrentScope = Reader->createScopeFunction();
    CurrentScope->setIsSubprogram();
    CurrentScope->setTag(dwarf::DW_TAG_subprogram);
    return CurrentScope;
  default:
    // If '--internal=tag' and '--print=warning' are specified in the command
    // line, we record and print each seen 'SymbolKind'.
    break;
  }
  return nullptr;
}

LVElement *LVLogicalVisitor::createElement(TypeIndex TI, TypeLeafKind Kind) {
  LVElement *Element = Shared->TypeRecords.find(StreamTPI, TI);
  if (!Element) {
    // We are dealing with a base type or pointer to a base type, which are
    // not included explicitly in the CodeView format.
    if (Kind < TypeIndex::FirstNonSimpleIndex) {
      Element = createElement(Kind);
      Element->setIsFinalized();
      Shared->TypeRecords.add(StreamTPI, (TypeIndex)Kind, Kind, Element);
      Element->setOffset(Kind);
      return Element;
    }
    // We are dealing with a pointer to a base type.
    if (TI.getIndex() < TypeIndex::FirstNonSimpleIndex) {
      Element = createElement(Kind);
      Shared->TypeRecords.add(StreamTPI, TI, Kind, Element);
      Element->setOffset(TI.getIndex());
      Element->setOffsetFromTypeIndex();
      return Element;
    }

    W.printString("** Not implemented. **");
    printTypeIndex("TypeIndex", TI, StreamTPI);
    W.printString("TypeLeafKind", formatTypeLeafKind(Kind));
    return nullptr;
  }

  Element->setOffset(TI.getIndex());
  Element->setOffsetFromTypeIndex();
  return Element;
}

void LVLogicalVisitor::createDataMember(CVMemberRecord &Record, LVScope *Parent,
                                        StringRef Name, TypeIndex TI,
                                        MemberAccess Access) {
  LLVM_DEBUG({
    printTypeIndex("TypeIndex", TI, StreamTPI);
    W.printString("TypeName", Name);
  });

  createElement(Record.Kind);
  if (LVSymbol *Symbol = CurrentSymbol) {
    Symbol->setName(Name);
    if (TI.isNoneType() || TI.isSimple())
      Symbol->setType(getElement(StreamTPI, TI));
    else {
      LazyRandomTypeCollection &Types = types();
      CVType CVMemberType = Types.getType(TI);
      if (CVMemberType.kind() == LF_BITFIELD) {
        if (Error Err = finishVisitation(CVMemberType, TI, Symbol)) {
          consumeError(std::move(Err));
          return;
        }
      } else
        Symbol->setType(getElement(StreamTPI, TI));
    }
    Symbol->setAccessibilityCode(Access);
    Parent->addElement(Symbol);
  }
}

LVSymbol *LVLogicalVisitor::createParameter(LVElement *Element, StringRef Name,
                                            LVScope *Parent) {
  LVSymbol *Parameter = Reader->createSymbol();
  Parent->addElement(Parameter);
  Parameter->setIsParameter();
  Parameter->setTag(dwarf::DW_TAG_formal_parameter);
  Parameter->setName(Name);
  Parameter->setType(Element);
  return Parameter;
}

LVSymbol *LVLogicalVisitor::createParameter(TypeIndex TI, StringRef Name,
                                            LVScope *Parent) {
  return createParameter(getElement(StreamTPI, TI), Name, Parent);
}

LVType *LVLogicalVisitor::createBaseType(TypeIndex TI, StringRef TypeName) {
  TypeLeafKind SimpleKind = (TypeLeafKind)TI.getSimpleKind();
  TypeIndex TIR = (TypeIndex)SimpleKind;
  LLVM_DEBUG({
    printTypeIndex("TypeIndex", TIR, StreamTPI);
    W.printString("TypeName", TypeName);
  });

  if (LVElement *Element = Shared->TypeRecords.find(StreamTPI, TIR))
    return static_cast<LVType *>(Element);

  if (createElement(TIR, SimpleKind)) {
    CurrentType->setName(TypeName);
    Reader->getCompileUnit()->addElement(CurrentType);
  }
  return CurrentType;
}

LVType *LVLogicalVisitor::createPointerType(TypeIndex TI, StringRef TypeName) {
  LLVM_DEBUG({
    printTypeIndex("TypeIndex", TI, StreamTPI);
    W.printString("TypeName", TypeName);
  });

  if (LVElement *Element = Shared->TypeRecords.find(StreamTPI, TI))
    return static_cast<LVType *>(Element);

  LVType *Pointee = createBaseType(TI, TypeName.drop_back(1));
  if (createElement(TI, TypeLeafKind::LF_POINTER)) {
    CurrentType->setIsFinalized();
    CurrentType->setType(Pointee);
    Reader->getCompileUnit()->addElement(CurrentType);
  }
  return CurrentType;
}

void LVLogicalVisitor::createParents(StringRef ScopedName, LVElement *Element) {
  // For the given test case:
  //
  // struct S { enum E { ... }; };
  // S::E V;
  //
  //      0 | S_LOCAL `V`
  //          type=0x1004 (S::E), flags = none
  // 0x1004 | LF_ENUM  `S::E`
  //          options: has unique name | is nested
  // 0x1009 | LF_STRUCTURE `S`
  //          options: contains nested class
  //
  // When the local 'V' is processed, its type 'E' is created. But There is
  // no direct reference to its parent 'S'. We use the scoped name for 'E',
  // to create its parents.

  // The input scoped name must have at least parent and nested names.
  // Drop the last element name, as it corresponds to the nested type.
  LVStringRefs Components = getAllLexicalComponents(ScopedName);
  if (Components.size() < 2)
    return;
  Components.pop_back();

  LVStringRefs::size_type FirstNamespace;
  LVStringRefs::size_type FirstAggregate;
  std::tie(FirstNamespace, FirstAggregate) =
      Shared->NamespaceDeduction.find(Components);

  LLVM_DEBUG({
    W.printString("First Namespace", Components[FirstNamespace]);
    W.printString("First NonNamespace", Components[FirstAggregate]);
  });

  // Create any referenced namespaces.
  if (FirstNamespace < FirstAggregate) {
    Shared->NamespaceDeduction.get(
        LVStringRefs(Components.begin() + FirstNamespace,
                     Components.begin() + FirstAggregate));
  }

  // Traverse the enclosing scopes (aggregates) and create them. In the
  // case of nested empty aggregates, MSVC does not emit a full record
  // description. It emits only the reference record.
  LVScope *Aggregate = nullptr;
  TypeIndex TIAggregate;
  std::string AggregateName = getScopedName(
      LVStringRefs(Components.begin(), Components.begin() + FirstAggregate));

  // This traversal is executed at least once.
  for (LVStringRefs::size_type Index = FirstAggregate;
       Index < Components.size(); ++Index) {
    AggregateName = getScopedName(LVStringRefs(Components.begin() + Index,
                                               Components.begin() + Index + 1),
                                  AggregateName);
    TIAggregate = Shared->ForwardReferences.remap(
        Shared->TypeRecords.find(StreamTPI, AggregateName));
    Aggregate =
        TIAggregate.isNoneType()
            ? nullptr
            : static_cast<LVScope *>(getElement(StreamTPI, TIAggregate));
  }

  // Workaround for cases where LF_NESTTYPE is missing for nested templates.
  // If we manage to get parent information from the scoped name, we can add
  // the nested type without relying on the LF_NESTTYPE.
  if (Aggregate && !Element->getIsScopedAlready()) {
    Aggregate->addElement(Element);
    Element->setIsScopedAlready();
  }
}

LVElement *LVLogicalVisitor::getElement(uint32_t StreamIdx, TypeIndex TI,
                                        LVScope *Parent) {
  LLVM_DEBUG({ printTypeIndex("TypeIndex", TI, StreamTPI); });
  TI = Shared->ForwardReferences.remap(TI);
  LLVM_DEBUG({ printTypeIndex("TypeIndex Remap", TI, StreamTPI); });

  LVElement *Element = Shared->TypeRecords.find(StreamIdx, TI);
  if (!Element) {
    if (TI.isNoneType() || TI.isSimple()) {
      StringRef TypeName = TypeIndex::simpleTypeName(TI);
      // If the name ends with "*", create 2 logical types: a pointer and a
      // pointee type. TypeIndex is composed of a SympleTypeMode byte followed
      // by a SimpleTypeKind byte. The logical pointer will be identified by
      // the full TypeIndex value and the pointee by the SimpleTypeKind.
      return (TypeName.back() == '*') ? createPointerType(TI, TypeName)
                                      : createBaseType(TI, TypeName);
    }

    LLVM_DEBUG({ W.printHex("TypeIndex not implemented: ", TI.getIndex()); });
    return nullptr;
  }

  // The element has been finalized.
  if (Element->getIsFinalized())
    return Element;

  // Add the element in case of a given parent.
  if (Parent)
    Parent->addElement(Element);

  // Check for a composite type.
  LazyRandomTypeCollection &Types = types();
  CVType CVRecord = Types.getType(TI);
  if (Error Err = finishVisitation(CVRecord, TI, Element)) {
    consumeError(std::move(Err));
    return nullptr;
  }
  Element->setIsFinalized();
  return Element;
}

void LVLogicalVisitor::processLines() {
  // Traverse the collected LF_UDT_SRC_LINE records and add the source line
  // information to the logical elements.
  for (const TypeIndex &Entry : Shared->LineRecords) {
    CVType CVRecord = ids().getType(Entry);
    UdtSourceLineRecord Line;
    if (Error Err = TypeDeserializer::deserializeAs(
            const_cast<CVType &>(CVRecord), Line))
      consumeError(std::move(Err));
    else {
      LLVM_DEBUG({
        printTypeIndex("UDT", Line.getUDT(), StreamIPI);
        printTypeIndex("SourceFile", Line.getSourceFile(), StreamIPI);
        W.printNumber("LineNumber", Line.getLineNumber());
      });

      // The TypeIndex returned by 'getUDT()' must point to an already
      // created logical element. If no logical element is found, it means
      // the LF_UDT_SRC_LINE is associated with a system TypeIndex.
      if (LVElement *Element = Shared->TypeRecords.find(
              StreamTPI, Line.getUDT(), /*Create=*/false)) {
        Element->setLineNumber(Line.getLineNumber());
        Element->setFilenameIndex(
            Shared->StringRecords.findIndex(Line.getSourceFile()));
      }
    }
  }
}

void LVLogicalVisitor::processNamespaces() {
  // Create namespaces.
  Shared->NamespaceDeduction.init();
}

void LVLogicalVisitor::processFiles() { Shared->StringRecords.addFilenames(); }

void LVLogicalVisitor::printRecords(raw_ostream &OS) const {
  if (!options().getInternalTag())
    return;

  unsigned Count = 0;
  auto PrintItem = [&](StringRef Name) {
    auto NewLine = [&]() {
      if (++Count == 4) {
        Count = 0;
        OS << "\n";
      }
    };
    OS << format("%20s", Name.str().c_str());
    NewLine();
  };

  OS << "\nTypes:\n";
  for (const TypeLeafKind &Kind : Shared->TypeKinds)
    PrintItem(formatTypeLeafKind(Kind));
  Shared->TypeKinds.clear();

  Count = 0;
  OS << "\nSymbols:\n";
  for (const SymbolKind &Kind : Shared->SymbolKinds)
    PrintItem(LVCodeViewReader::getSymbolKindName(Kind));
  Shared->SymbolKinds.clear();

  OS << "\n";
}

Error LVLogicalVisitor::inlineSiteAnnotation(LVScope *AbstractFunction,
                                             LVScope *InlinedFunction,
                                             InlineSiteSym &InlineSite) {
  // Get the parent scope to update the address ranges of the nested
  // scope representing the inlined function.
  LVAddress ParentLowPC = 0;
  LVScope *Parent = InlinedFunction->getParentScope();
  if (const LVLocations *Locations = Parent->getRanges()) {
    if (!Locations->empty())
      ParentLowPC = (*Locations->begin())->getLowerAddress();
  }

  // For the given inlinesite, get the initial line number and its
  // source filename. Update the logical scope representing it.
  uint32_t LineNumber = 0;
  StringRef Filename;
  LVInlineeInfo::iterator Iter = InlineeInfo.find(InlineSite.Inlinee);
  if (Iter != InlineeInfo.end()) {
    LineNumber = Iter->second.first;
    Filename = Iter->second.second;
    AbstractFunction->setLineNumber(LineNumber);
    // TODO: This part needs additional work in order to set properly the
    // correct filename in order to detect changes between filenames.
    // AbstractFunction->setFilename(Filename);
  }

  LLVM_DEBUG({
    dbgs() << "inlineSiteAnnotation\n"
           << "Abstract: " << AbstractFunction->getName() << "\n"
           << "Inlined: " << InlinedFunction->getName() << "\n"
           << "Parent: " << Parent->getName() << "\n"
           << "Low PC: " << hexValue(ParentLowPC) << "\n";
  });

  // Get the source lines if requested by command line option.
  if (!options().getPrintLines())
    return Error::success();

  // Limitation: Currently we don't track changes in the FileOffset. The
  // side effects are the caller that it is unable to differentiate the
  // source filename for the inlined code.
  uint64_t CodeOffset = ParentLowPC;
  int32_t LineOffset = LineNumber;
  uint32_t FileOffset = 0;

  auto UpdateClose = [&]() { LLVM_DEBUG({ dbgs() << ("\n"); }); };
  auto UpdateCodeOffset = [&](uint32_t Delta) {
    CodeOffset += Delta;
    LLVM_DEBUG({
      dbgs() << formatv(" code 0x{0} (+0x{1})", utohexstr(CodeOffset),
                        utohexstr(Delta));
    });
  };
  auto UpdateLineOffset = [&](int32_t Delta) {
    LineOffset += Delta;
    LLVM_DEBUG({
      char Sign = Delta > 0 ? '+' : '-';
      dbgs() << formatv(" line {0} ({1}{2})", LineOffset, Sign,
                        std::abs(Delta));
    });
  };
  auto UpdateFileOffset = [&](int32_t Offset) {
    FileOffset = Offset;
    LLVM_DEBUG({ dbgs() << formatv(" file {0}", FileOffset); });
  };

  LVLines InlineeLines;
  auto CreateLine = [&]() {
    // Create the logical line record.
    LVLineDebug *Line = Reader->createLineDebug();
    Line->setAddress(CodeOffset);
    Line->setLineNumber(LineOffset);
    // TODO: This part needs additional work in order to set properly the
    // correct filename in order to detect changes between filenames.
    // Line->setFilename(Filename);
    InlineeLines.push_back(Line);
  };

  bool SeenLowAddress = false;
  bool SeenHighAddress = false;
  uint64_t LowPC = 0;
  uint64_t HighPC = 0;

  for (auto &Annot : InlineSite.annotations()) {
    LLVM_DEBUG({
      dbgs() << formatv("  {0}",
                        fmt_align(toHex(Annot.Bytes), AlignStyle::Left, 9));
    });

    // Use the opcode to interpret the integer values.
    switch (Annot.OpCode) {
    case BinaryAnnotationsOpCode::ChangeCodeOffset:
    case BinaryAnnotationsOpCode::CodeOffset:
    case BinaryAnnotationsOpCode::ChangeCodeLength:
      UpdateCodeOffset(Annot.U1);
      UpdateClose();
      if (Annot.OpCode == BinaryAnnotationsOpCode::ChangeCodeOffset) {
        CreateLine();
        LowPC = CodeOffset;
        SeenLowAddress = true;
        break;
      }
      if (Annot.OpCode == BinaryAnnotationsOpCode::ChangeCodeLength) {
        HighPC = CodeOffset - 1;
        SeenHighAddress = true;
      }
      break;
    case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
      UpdateCodeOffset(Annot.U2);
      UpdateClose();
      break;
    case BinaryAnnotationsOpCode::ChangeLineOffset:
    case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
      UpdateCodeOffset(Annot.U1);
      UpdateLineOffset(Annot.S1);
      UpdateClose();
      if (Annot.OpCode ==
          BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset)
        CreateLine();
      break;
    case BinaryAnnotationsOpCode::ChangeFile:
      UpdateFileOffset(Annot.U1);
      UpdateClose();
      break;
    default:
      break;
    }
    if (SeenLowAddress && SeenHighAddress) {
      SeenLowAddress = false;
      SeenHighAddress = false;
      InlinedFunction->addObject(LowPC, HighPC);
    }
  }

  Reader->addInlineeLines(InlinedFunction, InlineeLines);
  UpdateClose();

  return Error::success();
}
