//===-- 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/InputFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/Demangle/Demangle.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/Error.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) {
    auto [It, Inserted] =
        ForwardTypesNames.try_emplace(Name, TIForward, TypeIndex::None());
    if (!Inserted) {
      // Update a recorded definition with its reference.
      It->second.first = TIForward;
      add(TIForward, It->second.second);
    }
  }

  // Update a previously recorded forward reference with its definition.
  void update(StringRef Name, TypeIndex TIReference) {
    auto [It, Inserted] =
        ForwardTypesNames.try_emplace(Name, TypeIndex::None(), TIReference);
    if (!Inserted) {
      // Update the recorded forward reference with its definition.
      It->second.second = TIReference;
      add(It->second.first, 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) {
    auto It = ForwardTypes.find(TIForward);
    return It != ForwardTypes.end() ? It->second : TypeIndex::None();
  }

  TypeIndex find(StringRef Name) {
    auto It = ForwardTypesNames.find(Name);
    return It != ForwardTypesNames.end() ? It->second.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) {
    auto It = NamespaceNames.find(Name);
    LVScope *Namespace = It != NamespaceNames.end() ? It->second : 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;
    auto [It, Inserted] = Strings.try_emplace(TI);
    if (Inserted)
      It->second = std::make_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);
    };

    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);
  });

  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); });

  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 == "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);

    setLocalVariableType(Symbol, Local.Type);
  }

  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 == "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);

    setLocalVariableType(Symbol, Local.Type);
  }

  return Error::success();
}

// S_REGREL32_INDIR
Error LVSymbolVisitor::visitKnownRecord(CVSymbol &Record,
                                        RegRelativeIndirSym &Local) {
  LLVM_DEBUG({
    printTypeIndex("Type", Local.Type);
    W.printNumber("Offset", Local.Offset);
    W.printNumber("OffsetInUdt", Local.OffsetInUdt);
    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 == "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);

    setLocalVariableType(Symbol, Local.Type);
  }

  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);
    if (options().getAttributeLanguage())
      Scope->setSourceLanguage(LVSourceLanguage{
          static_cast<llvm::codeview::SourceLanguage>(Compile2.getLanguage())});
    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);
    if (options().getAttributeLanguage())
      Scope->setSourceLanguage(LVSourceLanguage{
          static_cast<llvm::codeview::SourceLanguage>(Compile3.getLanguage())});
    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_REL_INDIR
Error LVSymbolVisitor::visitKnownRecord(
    CVSymbol &Record, DefRangeRegisterRelIndirSym &DefRangeRegisterRelIndir) {
  // DefRanges don't have types, just registers and code offsets.
  LLVM_DEBUG({
    if (LocalSymbol)
      W.getOStream() << formatv("Symbol: {0}, ", LocalSymbol->getName());

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

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

    // Add location debug location. Operands: [Register, Offset, OffsetInUdt].
    dwarf::Attribute Attr =
        dwarf::Attribute(SymbolKind::S_DEFRANGE_REGISTER_REL_INDIR);
    const uint64_t Operand1 = DefRangeRegisterRelIndir.Hdr.Register;
    const uint64_t Operand2 = DefRangeRegisterRelIndir.Hdr.BasePointerOffset;
    const uint64_t Operand3 = DefRangeRegisterRelIndir.Hdr.OffsetInUdt;

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

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

  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 == "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);

    setLocalVariableType(Symbol, Local.Type);

    // 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 == 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();
}

void LVSymbolVisitor::setLocalVariableType(LVSymbol *Symbol, TypeIndex TI) {
  LVElement *Element = LogicalVisitor->getElement(StreamTPI, TI);
  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);
}

#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());
  Scope->setBitSize(Class.getSize() * DWARF_CHAR_BIT);

  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());
  Scope->setBitSize(Union.getSize() * DWARF_CHAR_BIT);

  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 == 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_REGREL32_INDIR:
  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);
    CurrentType->setBitSize(getSizeInBytesForTypeIndex(TIR) * DWARF_CHAR_BIT);
    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 << formatv("{0,20}", Name);
    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();
}
