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

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