//===-- SymbolFileNativePDB.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
//
//===----------------------------------------------------------------------===//

#include "SymbolFileNativePDB.h"

#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
#include "Plugins/ObjectFile/PDB/ObjectFilePDB.h"
#include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"

#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/Formatters.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/RecordName.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/PDB.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/Demangle/MicrosoftDemangle.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"

#include "DWARFLocationExpression.h"
#include "PdbSymUid.h"
#include "PdbUtil.h"
#include "UdtRecordCompleter.h"
#include <optional>
#include <string_view>

using namespace lldb;
using namespace lldb_private;
using namespace npdb;
using namespace llvm::codeview;
using namespace llvm::pdb;

char SymbolFileNativePDB::ID;

static lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
  switch (lang) {
  case PDB_Lang::Cpp:
    return lldb::LanguageType::eLanguageTypeC_plus_plus;
  case PDB_Lang::C:
    return lldb::LanguageType::eLanguageTypeC;
  case PDB_Lang::Swift:
    return lldb::LanguageType::eLanguageTypeSwift;
  case PDB_Lang::Rust:
    return lldb::LanguageType::eLanguageTypeRust;
  case PDB_Lang::ObjC:
    return lldb::LanguageType::eLanguageTypeObjC;
  case PDB_Lang::ObjCpp:
    return lldb::LanguageType::eLanguageTypeObjC_plus_plus;
  default:
    return lldb::LanguageType::eLanguageTypeUnknown;
  }
}

static std::optional<std::string>
findMatchingPDBFilePath(llvm::StringRef original_pdb_path,
                        llvm::StringRef exe_path) {
  const FileSystem &fs = FileSystem::Instance();

  if (fs.Exists(original_pdb_path))
    return std::string(original_pdb_path);

  const auto exe_dir = FileSpec(exe_path).CopyByRemovingLastPathComponent();
  // While the exe_path uses the native style, the exe might be compiled on a
  // different OS, so try to guess the style used.
  const FileSpec original_pdb_spec(original_pdb_path,
                                   FileSpec::GuessPathStyle(original_pdb_path)
                                       .value_or(FileSpec::Style::native));
  const llvm::StringRef pdb_filename = original_pdb_spec.GetFilename();

  // If the file doesn't exist, perhaps the path specified at build time
  // doesn't match the PDB's current location, so check the location of the
  // executable.
  const FileSpec local_pdb = exe_dir.CopyByAppendingPathComponent(pdb_filename);
  if (fs.Exists(local_pdb))
    return local_pdb.GetPath();

  // Otherwise, search for one in target.debug-file-search-paths
  FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
  for (const FileSpec &search_dir : search_paths) {
    FileSpec pdb_path = search_dir.CopyByAppendingPathComponent(pdb_filename);
    if (fs.Exists(pdb_path))
      return pdb_path.GetPath();
  }

  return std::nullopt;
}

static std::unique_ptr<PDBFile>
loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {
  // Try to find a matching PDB for an EXE.
  using namespace llvm::object;
  auto expected_binary = createBinary(exe_path);

  // If the file isn't a PE/COFF executable, fail.
  if (!expected_binary) {
    llvm::consumeError(expected_binary.takeError());
    return nullptr;
  }
  OwningBinary<Binary> binary = std::move(*expected_binary);

  // TODO: Avoid opening the PE/COFF binary twice by reading this information
  // directly from the lldb_private::ObjectFile.
  auto *obj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary.getBinary());
  if (!obj)
    return nullptr;
  const llvm::codeview::DebugInfo *pdb_info = nullptr;

  // If it doesn't have a debug directory, fail.
  llvm::StringRef pdb_file;
  if (llvm::Error e = obj->getDebugPDBInfo(pdb_info, pdb_file)) {
    consumeError(std::move(e));
    return nullptr;
  }

  std::optional<std::string> resolved_pdb_path =
      findMatchingPDBFilePath(pdb_file, exe_path);
  if (!resolved_pdb_path)
    return nullptr;

  // If the file is not a PDB or if it doesn't have a matching GUID, fail.
  auto pdb =
      ObjectFilePDB::loadPDBFile(*std::move(resolved_pdb_path), allocator);
  if (!pdb)
    return nullptr;

  auto expected_info = pdb->getPDBInfoStream();
  if (!expected_info) {
    llvm::consumeError(expected_info.takeError());
    return nullptr;
  }
  llvm::codeview::GUID guid;
  memcpy(&guid, pdb_info->PDB70.Signature, 16);

  if (expected_info->getGuid() != guid)
    return nullptr;

  return pdb;
}

static bool IsFunctionPrologue(const CompilandIndexItem &cci,
                               lldb::addr_t addr) {
  // FIXME: Implement this.
  return false;
}

static bool IsFunctionEpilogue(const CompilandIndexItem &cci,
                               lldb::addr_t addr) {
  // FIXME: Implement this.
  return false;
}

// See llvm::codeview::TypeIndex::simpleTypeName as well as strForPrimitiveTi
// from the original pdbdump:
// https://github.com/microsoft/microsoft-pdb/blob/805655a28bd8198004be2ac27e6e0290121a5e89/pdbdump/pdbdump.cpp#L1896-L1974
//
// For 64bit integers we use "long long" like DIA instead of "__int64".
static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) {
  switch (kind) {
  case SimpleTypeKind::Boolean128:
    return "__bool128";
  case SimpleTypeKind::Boolean64:
    return "__bool64";
  case SimpleTypeKind::Boolean32:
    return "__bool32";
  case SimpleTypeKind::Boolean16:
    return "__bool16";
  case SimpleTypeKind::Boolean8:
    return "bool";

  case SimpleTypeKind::Byte:
  case SimpleTypeKind::UnsignedCharacter:
    return "unsigned char";
  case SimpleTypeKind::NarrowCharacter:
    return "char";
  case SimpleTypeKind::SignedCharacter:
  case SimpleTypeKind::SByte:
    return "signed char";
  case SimpleTypeKind::Character32:
    return "char32_t";
  case SimpleTypeKind::Character16:
    return "char16_t";
  case SimpleTypeKind::Character8:
    return "char8_t";

  case SimpleTypeKind::Complex128:
    return "_Complex __float128";
  case SimpleTypeKind::Complex80:
    return "_Complex long double";
  case SimpleTypeKind::Complex64:
    return "_Complex double";
  case SimpleTypeKind::Complex48:
    return "_Complex __float48";
  case SimpleTypeKind::Complex32:
  case SimpleTypeKind::Complex32PartialPrecision:
    return "_Complex float";
  case SimpleTypeKind::Complex16:
    return "_Complex _Float16";

  case SimpleTypeKind::Float128:
    return "__float128";
  case SimpleTypeKind::Float80:
    return "long double";
  case SimpleTypeKind::Float64:
    return "double";
  case SimpleTypeKind::Float48:
    return "__float48";
  case SimpleTypeKind::Float32:
  case SimpleTypeKind::Float32PartialPrecision:
    return "float";
  case SimpleTypeKind::Float16:
    return "_Float16";

  case SimpleTypeKind::Int128Oct:
  case SimpleTypeKind::Int128:
    return "__int128";
  case SimpleTypeKind::Int64:
  case SimpleTypeKind::Int64Quad:
    return "long long";
  case SimpleTypeKind::Int32Long:
    return "long";
  case SimpleTypeKind::Int32:
    return "int";
  case SimpleTypeKind::Int16:
  case SimpleTypeKind::Int16Short:
    return "short";

  case SimpleTypeKind::UInt128Oct:
  case SimpleTypeKind::UInt128:
    return "unsigned __int128";
  case SimpleTypeKind::UInt64:
  case SimpleTypeKind::UInt64Quad:
    return "unsigned long long";
  case SimpleTypeKind::UInt32:
    return "unsigned";
  case SimpleTypeKind::UInt16:
  case SimpleTypeKind::UInt16Short:
    return "unsigned short";
  case SimpleTypeKind::UInt32Long:
    return "unsigned long";

  case SimpleTypeKind::HResult:
    return "HRESULT";
  case SimpleTypeKind::Void:
    return "void";
  case SimpleTypeKind::WideCharacter:
    return "wchar_t";

  case SimpleTypeKind::None:
  case SimpleTypeKind::NotTranslated:
    return "";
  }
  return "";
}

static bool IsClassRecord(TypeLeafKind kind) {
  switch (kind) {
  case LF_STRUCTURE:
  case LF_CLASS:
  case LF_INTERFACE:
    return true;
  default:
    return false;
  }
}

static std::optional<CVTagRecord>
GetNestedTagDefinition(const NestedTypeRecord &Record,
                       const CVTagRecord &parent, TpiStream &tpi) {
  // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it
  // is also used to indicate the primary definition of a nested class.  That is
  // to say, if you have:
  // struct A {
  //   struct B {};
  //   using C = B;
  // };
  // Then in the debug info, this will appear as:
  // LF_STRUCTURE `A::B` [type index = N]
  // LF_STRUCTURE `A`
  //   LF_NESTTYPE [name = `B`, index = N]
  //   LF_NESTTYPE [name = `C`, index = N]
  // In order to accurately reconstruct the decl context hierarchy, we need to
  // know which ones are actual definitions and which ones are just aliases.

  // If it's a simple type, then this is something like `using foo = int`.
  if (Record.Type.isSimple())
    return std::nullopt;

  CVType cvt = tpi.getType(Record.Type);

  if (!IsTagRecord(cvt))
    return std::nullopt;

  // If it's an inner definition, then treat whatever name we have here as a
  // single component of a mangled name.  So we can inject it into the parent's
  // mangled name to see if it matches.
  CVTagRecord child = CVTagRecord::create(cvt);
  std::string qname = std::string(parent.asTag().getUniqueName());
  if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4)
    return std::nullopt;

  // qname[3] is the tag type identifier (struct, class, union, etc).  Since the
  // inner tag type is not necessarily the same as the outer tag type, re-write
  // it to match the inner tag type.
  qname[3] = child.asTag().getUniqueName()[3];
  std::string piece;
  if (qname[3] == 'W')
    piece = "4";
  piece += Record.Name;
  piece.push_back('@');
  qname.insert(4, std::move(piece));
  if (qname != child.asTag().UniqueName)
    return std::nullopt;

  return std::move(child);
}

void SymbolFileNativePDB::Initialize() {
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                GetPluginDescriptionStatic(), CreateInstance,
                                DebuggerInitialize);
}

void SymbolFileNativePDB::Terminate() {
  PluginManager::UnregisterPlugin(CreateInstance);
}

void SymbolFileNativePDB::DebuggerInitialize(Debugger &debugger) {}

llvm::StringRef SymbolFileNativePDB::GetPluginDescriptionStatic() {
  return "Microsoft PDB debug symbol cross-platform file reader.";
}

SymbolFile *SymbolFileNativePDB::CreateInstance(ObjectFileSP objfile_sp) {
  if (!SymbolFilePDB::UseNativePDB())
    return nullptr;

  return new SymbolFileNativePDB(std::move(objfile_sp));
}

SymbolFileNativePDB::SymbolFileNativePDB(ObjectFileSP objfile_sp)
    : SymbolFileCommon(std::move(objfile_sp)) {}

SymbolFileNativePDB::~SymbolFileNativePDB() = default;

uint32_t SymbolFileNativePDB::CalculateAbilities() {
  uint32_t abilities = 0;
  if (!m_objfile_sp)
    return 0;

  if (!m_index) {
    // Lazily load and match the PDB file, but only do this once.
    PDBFile *pdb_file;
    if (auto *pdb = llvm::dyn_cast<ObjectFilePDB>(m_objfile_sp.get())) {
      pdb_file = &pdb->GetPDBFile();
    } else {
      m_file_up = loadMatchingPDBFile(m_objfile_sp->GetFileSpec().GetPath(),
                                      m_allocator);
      pdb_file = m_file_up.get();
    }

    if (!pdb_file)
      return 0;

    LLDB_LOG(
        GetLog(LLDBLog::Symbols), "Loading {0} for {1}",
        pdb_file->getFilePath(),
        m_objfile_sp->GetModule()->GetObjectFile()->GetFileSpec().GetPath());

    auto expected_index = PdbIndex::create(pdb_file);
    if (!expected_index) {
      llvm::consumeError(expected_index.takeError());
      return 0;
    }
    m_index = std::move(*expected_index);
  }
  if (!m_index)
    return 0;

  // We don't especially have to be precise here.  We only distinguish between
  // stripped and not stripped.
  abilities = kAllAbilities;

  if (m_index->dbi().isStripped())
    abilities &= ~(Blocks | LocalVariables);
  return abilities;
}

void SymbolFileNativePDB::InitializeObject() {
  m_obj_load_address = m_objfile_sp->GetModule()
                           ->GetObjectFile()
                           ->GetBaseAddress()
                           .GetFileAddress();
  m_index->SetLoadAddress(m_obj_load_address);
  m_index->ParseSectionContribs();

  auto ts_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage(
      lldb::eLanguageTypeC_plus_plus);
  if (auto err = ts_or_err.takeError()) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                   "Failed to initialize: {0}");
  } else {
    if (auto ts = *ts_or_err)
      ts->SetSymbolFile(this);
    BuildParentMap();
  }
}

uint32_t SymbolFileNativePDB::CalculateNumCompileUnits() {
  const DbiModuleList &modules = m_index->dbi().modules();
  uint32_t count = modules.getModuleCount();
  if (count == 0)
    return count;

  // The linker can inject an additional "dummy" compilation unit into the
  // PDB. Ignore this special compile unit for our purposes, if it is there.
  // It is always the last one.
  DbiModuleDescriptor last = modules.getModuleDescriptor(count - 1);
  if (last.getModuleName() == "* Linker *")
    --count;
  return count;
}

Block *SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
  CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
  CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
  CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);
  lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id);
  auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
  if (auto err = ts_or_err.takeError())
    return nullptr;
  auto ts = *ts_or_err;
  if (!ts)
    return nullptr;
  PdbAstBuilder* ast_builder = ts->GetNativePDBParser();

  switch (sym.kind()) {
  case S_GPROC32:
  case S_LPROC32:
    // This is a function.  It must be global.  Creating the Function entry
    // for it automatically creates a block for it.
    if (FunctionSP func = GetOrCreateFunction(block_id, *comp_unit))
      return &func->GetBlock(false);
    break;
  case S_BLOCK32: {
    // This is a block.  Its parent is either a function or another block.  In
    // either case, its parent can be viewed as a block (e.g. a function
    // contains 1 big block.  So just get the parent block and add this block
    // to it.
    BlockSym block(static_cast<SymbolRecordKind>(sym.kind()));
    if (auto err = SymbolDeserializer::deserializeAs<BlockSym>(sym, block)) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                     "Failed to deserialize BlockSym record: {0}");
      return nullptr;
    }
    lldbassert(block.Parent != 0);
    PdbCompilandSymId parent_id(block_id.modi, block.Parent);
    Block *parent_block = GetOrCreateBlock(parent_id);
    if (!parent_block)
      return nullptr;
    Function *func = parent_block->CalculateSymbolContextFunction();
    lldbassert(func);
    lldb::addr_t block_base =
        m_index->MakeVirtualAddress(block.Segment, block.CodeOffset);
    lldb::addr_t func_base = func->GetAddress().GetFileAddress();
    BlockSP child_block = parent_block->CreateChild(opaque_block_uid);
    if (block_base >= func_base)
      child_block->AddRange(Block::Range(block_base - func_base, block.CodeSize));
    else {
      GetObjectFile()->GetModule()->ReportError(
          "S_BLOCK32 at modi: {0:d} offset: {1:d}: adding range "
          "[{2:x16}-{3:x16}) which has a base that is less than the "
          "function's "
          "low PC 0x%" PRIx64 ". Please file a bug and attach the file at the "
          "start of this error message",
          block_id.modi, block_id.offset, block_base,
          block_base + block.CodeSize, func_base);
    }
    if (ast_builder)
      ast_builder->EnsureBlock(block_id);
    m_blocks.insert({opaque_block_uid, child_block});
    break;
  }
  case S_INLINESITE: {
    // This ensures line table is parsed first so we have inline sites info.
    comp_unit->GetLineTable();

    std::shared_ptr<InlineSite> inline_site = m_inline_sites[opaque_block_uid];
    Block *parent_block = GetOrCreateBlock(inline_site->parent_id);
    if (!parent_block)
      return nullptr;
    BlockSP child_block = parent_block->CreateChild(opaque_block_uid);
    if (ast_builder)
      ast_builder->EnsureInlinedFunction(block_id);
    // Copy ranges from InlineSite to Block.
    for (size_t i = 0; i < inline_site->ranges.GetSize(); ++i) {
      auto *entry = inline_site->ranges.GetEntryAtIndex(i);
      child_block->AddRange(
          Block::Range(entry->GetRangeBase(), entry->GetByteSize()));
    }
    child_block->FinalizeRanges();

    // Get the inlined function callsite info.
    Declaration &decl = inline_site->inline_function_info->GetDeclaration();
    Declaration &callsite = inline_site->inline_function_info->GetCallSite();
    child_block->SetInlinedFunctionInfo(
        inline_site->inline_function_info->GetName().GetCString(), nullptr,
        &decl, &callsite);
    m_blocks.insert({opaque_block_uid, child_block});
    break;
  }
  default:
    lldbassert(false && "Symbol is not a block!");
  }

  return nullptr;
}

lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,
                                                     CompileUnit &comp_unit) {
  const CompilandIndexItem *cci =
      m_index->compilands().GetCompiland(func_id.modi);
  lldbassert(cci);
  CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset);

  lldbassert(sym_record.kind() == S_LPROC32 || sym_record.kind() == S_GPROC32);
  SegmentOffsetLength sol = GetSegmentOffsetAndLength(sym_record);

  auto file_vm_addr =
      m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset);
  if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
    return nullptr;

  Address func_addr(file_vm_addr, comp_unit.GetModule()->GetSectionList());
  if (!func_addr.IsValid())
    return nullptr;

  ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
  if (auto err = SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc)) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                   "Failed to deserialize ProcSym record: {0}");
    return nullptr;
  }
  if (proc.FunctionType == TypeIndex::None())
    return nullptr;
  TypeSP func_type = GetOrCreateType(proc.FunctionType);
  if (!func_type)
    return nullptr;

  PdbTypeSymId sig_id(proc.FunctionType, false);

  std::optional<llvm::StringRef> mangled_opt = FindMangledSymbol(
      SegmentOffset(proc.Segment, proc.CodeOffset), proc.FunctionType);
  Mangled mangled(mangled_opt.value_or(proc.Name));

  FunctionSP func_sp = std::make_shared<Function>(
      &comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled,
      func_type.get(), func_addr,
      AddressRanges{AddressRange(func_addr, sol.length)});

  comp_unit.AddFunction(func_sp);

  auto ts_or_err = GetTypeSystemForLanguage(comp_unit.GetLanguage());
  if (auto err = ts_or_err.takeError())
    return func_sp;
  auto ts = *ts_or_err;
  if (ts) {
    if (PdbAstBuilder *ast_builder = ts->GetNativePDBParser())
      ast_builder->EnsureFunction(func_id);
  }

  return func_sp;
}

CompUnitSP
SymbolFileNativePDB::CreateCompileUnit(const CompilandIndexItem &cci) {
  lldb::LanguageType lang =
      cci.m_compile_opts ? TranslateLanguage(cci.m_compile_opts->getLanguage())
                         : lldb::eLanguageTypeUnknown;

  LazyBool optimized = eLazyBoolNo;
  if (cci.m_compile_opts && cci.m_compile_opts->hasOptimizations())
    optimized = eLazyBoolYes;

  llvm::SmallString<64> source_file_name;
  if (auto main_file_or_err = m_index->compilands().GetMainSourceFile(cci)) {
    source_file_name = std::move(*main_file_or_err);
  } else {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), main_file_or_err.takeError(),
                   "Failed to determine main source file: {0}");
  }
  FileSpec fs(llvm::sys::path::convert_to_slash(
      source_file_name, llvm::sys::path::Style::windows_backslash));

  CompUnitSP cu_sp = std::make_shared<CompileUnit>(
      m_objfile_sp->GetModule(), nullptr, std::make_shared<SupportFile>(fs),
      toOpaqueUid(cci.m_id), lang, optimized);

  SetCompileUnitAtIndex(cci.m_id.modi, cu_sp);
  return cu_sp;
}

lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id,
                                                     const ModifierRecord &mr,
                                                     CompilerType ct) {
  TpiStream &stream = m_index->tpi();

  std::string name;

  if ((mr.Modifiers & ModifierOptions::Const) != ModifierOptions::None)
    name += "const ";
  if ((mr.Modifiers & ModifierOptions::Volatile) != ModifierOptions::None)
    name += "volatile ";
  if ((mr.Modifiers & ModifierOptions::Unaligned) != ModifierOptions::None)
    name += "__unaligned ";

  if (mr.ModifiedType.isSimple())
    name += GetSimpleTypeName(mr.ModifiedType.getSimpleKind());
  else
    name += computeTypeName(stream.typeCollection(), mr.ModifiedType);
  Declaration decl;
  lldb::TypeSP modified_type = GetOrCreateType(mr.ModifiedType);

  return MakeType(toOpaqueUid(type_id), ConstString(name),
                  llvm::expectedToOptional(modified_type->GetByteSize(nullptr)),
                  nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
                  Type::ResolveState::Full);
}

lldb::TypeSP
SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id,
                                       const llvm::codeview::PointerRecord &pr,
                                       CompilerType ct) {
  TypeSP pointee = GetOrCreateType(pr.ReferentType);
  if (!pointee)
    return nullptr;

  if (pr.isPointerToMember()) {
    MemberPointerInfo mpi = pr.getMemberInfo();
    GetOrCreateType(mpi.ContainingType);
  }

  Declaration decl;
  return MakeType(toOpaqueUid(type_id), ConstString(), pr.getSize(), nullptr,
                  LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
                  Type::ResolveState::Full);
}

lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
                                                   CompilerType ct) {
  uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false));
  if (ti == TypeIndex::NullptrT()) {
    Declaration decl;
    return MakeType(uid, ConstString("decltype(nullptr)"), std::nullopt,
                    nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
                    Type::ResolveState::Full);
  }

  if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
    TypeSP direct_sp = GetOrCreateType(ti.makeDirect());
    uint32_t pointer_size = 0;
    switch (ti.getSimpleMode()) {
    case SimpleTypeMode::FarPointer32:
    case SimpleTypeMode::NearPointer32:
      pointer_size = 4;
      break;
    case SimpleTypeMode::NearPointer64:
      pointer_size = 8;
      break;
    default:
      // 128-bit and 16-bit pointers unsupported.
      return nullptr;
    }
    Declaration decl;
    return MakeType(uid, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID,
                    Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
  }

  if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
    return nullptr;

  size_t size = GetTypeSizeForSimpleKind(ti.getSimpleKind());
  llvm::StringRef type_name = GetSimpleTypeName(ti.getSimpleKind());

  Declaration decl;
  return MakeType(uid, ConstString(type_name), size, nullptr, LLDB_INVALID_UID,
                  Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
}

static std::string GetUnqualifiedTypeName(const TagRecord &record) {
  if (!record.hasUniqueName())
    return std::string(MSVCUndecoratedNameParser::DropScope(record.Name));

  llvm::ms_demangle::Demangler demangler;
  std::string_view sv(record.UniqueName.begin(), record.UniqueName.size());
  llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
  if (demangler.Error)
    return std::string(MSVCUndecoratedNameParser::DropScope(record.Name));

  llvm::ms_demangle::IdentifierNode *idn =
      ttn->QualifiedName->getUnqualifiedIdentifier();
  return idn->toString();
}

lldb::TypeSP
SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id,
                                            const TagRecord &record,
                                            size_t size, CompilerType ct) {

  std::string uname = GetUnqualifiedTypeName(record);

  llvm::Expected<Declaration> maybeDecl = ResolveUdtDeclaration(type_id);
  Declaration decl;
  if (maybeDecl)
    decl = std::move(*maybeDecl);
  else
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), maybeDecl.takeError(),
                   "Failed to resolve declaration for '{1}': {0}", uname);

  return MakeType(toOpaqueUid(type_id), ConstString(uname), size, nullptr,
                  LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
                  Type::ResolveState::Forward);
}

lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
                                                const ClassRecord &cr,
                                                CompilerType ct) {
  return CreateClassStructUnion(type_id, cr, cr.getSize(), ct);
}

lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
                                                const UnionRecord &ur,
                                                CompilerType ct) {
  return CreateClassStructUnion(type_id, ur, ur.getSize(), ct);
}

lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
                                                const EnumRecord &er,
                                                CompilerType ct) {
  std::string uname = GetUnqualifiedTypeName(er);

  llvm::Expected<Declaration> maybeDecl = ResolveUdtDeclaration(type_id);
  Declaration decl;
  if (maybeDecl)
    decl = std::move(*maybeDecl);
  else
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), maybeDecl.takeError(),
                   "Failed to resolve declaration for '{1}': {0}", uname);

  TypeSP underlying_type = GetOrCreateType(er.UnderlyingType);

  return MakeType(
      toOpaqueUid(type_id), ConstString(uname),
      llvm::expectedToOptional(underlying_type->GetByteSize(nullptr)), nullptr,
      LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct,
      lldb_private::Type::ResolveState::Forward);
}

TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id,
                                            const ArrayRecord &ar,
                                            CompilerType ct) {
  TypeSP element_type = GetOrCreateType(ar.ElementType);

  Declaration decl;
  TypeSP array_sp =
      MakeType(toOpaqueUid(type_id), ConstString(), ar.Size, nullptr,
               LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct,
               lldb_private::Type::ResolveState::Full);
  array_sp->SetEncodingType(element_type.get());
  return array_sp;
}

TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id,
                                               const MemberFunctionRecord &mfr,
                                               CompilerType ct) {
  if (mfr.ReturnType.isSimple())
    GetOrCreateType(mfr.ReturnType);
  CreateSimpleArgumentListTypes(mfr.ArgumentList);

  Declaration decl;
  return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,
                  LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
                  ct, lldb_private::Type::ResolveState::Full);
}

TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id,
                                                const ProcedureRecord &pr,
                                                CompilerType ct) {
  if (pr.ReturnType.isSimple())
    GetOrCreateType(pr.ReturnType);
  CreateSimpleArgumentListTypes(pr.ArgumentList);

  Declaration decl;
  return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,
                  LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
                  ct, lldb_private::Type::ResolveState::Full);
}

void SymbolFileNativePDB::CreateSimpleArgumentListTypes(
    llvm::codeview::TypeIndex arglist_ti) {
  if (arglist_ti.isNoneType())
    return;

  CVType arglist_cvt = m_index->tpi().getType(arglist_ti);
  if (arglist_cvt.kind() != LF_ARGLIST)
    return; // invalid debug info

  ArgListRecord alr;
  if (auto err =
          TypeDeserializer::deserializeAs<ArgListRecord>(arglist_cvt, alr)) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                   "Failed to deserialize ArgListRecord record ({1}): {0}",
                   arglist_ti);
    return;
  }
  for (TypeIndex id : alr.getIndices())
    if (!id.isNoneType() && id.isSimple())
      GetOrCreateType(id);
}

TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) {
  if (type_id.index.isSimple())
    return CreateSimpleType(type_id.index, ct);

  TpiStream &stream = type_id.is_ipi ? m_index->ipi() : m_index->tpi();
  CVType cvt = stream.getType(type_id.index);

  if (cvt.kind() == LF_MODIFIER) {
    ModifierRecord modifier;
    if (auto err =
            TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier)) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                     "Failed to deserialize ModifierRecord record ({1}): {0}",
                     type_id.index);
      return nullptr;
    }
    return CreateModifierType(type_id, modifier, ct);
  }

  if (cvt.kind() == LF_POINTER) {
    PointerRecord pointer;
    if (auto err =
            TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer)) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                     "Failed to deserialize PointerRecord record ({1}): {0}",
                     type_id.index);
      return nullptr;
    }
    return CreatePointerType(type_id, pointer, ct);
  }

  if (IsClassRecord(cvt.kind())) {
    ClassRecord cr;
    if (auto err = TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr)) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                     "Failed to deserialize ClassRecord record ({1}): {0}",
                     type_id.index);
      return nullptr;
    }
    return CreateTagType(type_id, cr, ct);
  }

  if (cvt.kind() == LF_ENUM) {
    EnumRecord er;
    if (auto err = TypeDeserializer::deserializeAs<EnumRecord>(cvt, er)) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                     "Failed to deserialize EnumRecord record ({1}): {0}",
                     type_id.index);
      return nullptr;
    }
    return CreateTagType(type_id, er, ct);
  }

  if (cvt.kind() == LF_UNION) {
    UnionRecord ur;
    if (auto err = TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur)) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                     "Failed to deserialize UnionRecord record ({1}): {0}",
                     type_id.index);
      return nullptr;
    }
    return CreateTagType(type_id, ur, ct);
  }

  if (cvt.kind() == LF_ARRAY) {
    ArrayRecord ar;
    if (auto err = TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar)) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                     "Failed to deserialize ArrayRecord record ({1}): {0}",
                     type_id.index);
      return nullptr;
    }
    return CreateArrayType(type_id, ar, ct);
  }

  if (cvt.kind() == LF_PROCEDURE) {
    ProcedureRecord pr;
    if (auto err = TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr)) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                     "Failed to deserialize ProcedureRecord record ({1}): {0}",
                     type_id.index);
      return nullptr;
    }
    return CreateProcedureType(type_id, pr, ct);
  }
  if (cvt.kind() == LF_MFUNCTION) {
    MemberFunctionRecord mfr;
    if (auto err =
            TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr)) {
      LLDB_LOG_ERROR(
          GetLog(LLDBLog::Symbols), std::move(err),
          "Failed to deserialize MemberFunctionRecord record ({1}): {0}",
          type_id.index);
      return nullptr;
    }
    return CreateFunctionType(type_id, mfr, ct);
  }

  return nullptr;
}

TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) {
  // If they search for a UDT which is a forward ref, try and resolve the full
  // decl and just map the forward ref uid to the full decl record.
  std::optional<PdbTypeSymId> full_decl_uid;
  if (IsForwardRefUdt(type_id, m_index->tpi())) {
    auto expected_full_ti =
        m_index->tpi().findFullDeclForForwardRef(type_id.index);
    if (!expected_full_ti)
      llvm::consumeError(expected_full_ti.takeError());
    else if (*expected_full_ti != type_id.index) {
      full_decl_uid = PdbTypeSymId(*expected_full_ti, false);

      // It's possible that a lookup would occur for the full decl causing it
      // to be cached, then a second lookup would occur for the forward decl.
      // We don't want to create a second full decl, so make sure the full
      // decl hasn't already been cached.
      auto full_iter = m_types.find(toOpaqueUid(*full_decl_uid));
      if (full_iter != m_types.end()) {
        TypeSP result = full_iter->second;
        // Map the forward decl to the TypeSP for the full decl so we can take
        // the fast path next time.
        m_types[toOpaqueUid(type_id)] = result;
        return result;
      }
    }
  }

  PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id;
  auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
  if (auto err = ts_or_err.takeError())
    return nullptr;
  auto ts = *ts_or_err;
  if (!ts)
    return nullptr;
  PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
  if (!ast_builder)
    return nullptr;
  CompilerType ct = ast_builder->GetOrCreateType(best_decl_id);
  if (!ct)
    return nullptr;

  TypeSP result = CreateType(best_decl_id, ct);
  if (!result)
    return nullptr;

  uint64_t best_uid = toOpaqueUid(best_decl_id);
  m_types[best_uid] = result;
  // If we had both a forward decl and a full decl, make both point to the new
  // type.
  if (full_decl_uid)
    m_types[toOpaqueUid(type_id)] = result;

  return result;
}

TypeSP SymbolFileNativePDB::GetOrCreateType(PdbTypeSymId type_id) {
  // We can't use try_emplace / overwrite here because the process of creating
  // a type could create nested types, which could invalidate iterators.  So
  // we have to do a 2-phase lookup / insert.
  auto iter = m_types.find(toOpaqueUid(type_id));
  if (iter != m_types.end())
    return iter->second;

  TypeSP type = CreateAndCacheType(type_id);
  if (type)
    GetTypeList().Insert(type);
  return type;
}

VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
  CVSymbol sym = m_index->symrecords().readRecord(var_id.offset);
  if (sym.kind() == S_CONSTANT)
    return CreateConstantSymbol(var_id, sym);

  lldb::ValueType scope = eValueTypeInvalid;
  TypeIndex ti;
  llvm::StringRef name;
  lldb::addr_t addr = 0;
  uint16_t section = 0;
  uint32_t offset = 0;
  bool is_external = false;
  switch (sym.kind()) {
  case S_GDATA32:
    is_external = true;
    [[fallthrough]];
  case S_LDATA32: {
    DataSym ds(sym.kind());
    if (auto err = SymbolDeserializer::deserializeAs<DataSym>(sym, ds)) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                     "Failed to deserialize DataSym record: {0}");
      return nullptr;
    }
    ti = ds.Type;
    scope = (sym.kind() == S_GDATA32) ? eValueTypeVariableGlobal
                                      : eValueTypeVariableStatic;
    name = ds.Name;
    section = ds.Segment;
    offset = ds.DataOffset;
    addr = m_index->MakeVirtualAddress(ds.Segment, ds.DataOffset);
    break;
  }
  case S_GTHREAD32:
    is_external = true;
    [[fallthrough]];
  case S_LTHREAD32: {
    ThreadLocalDataSym tlds(sym.kind());
    if (auto err =
            SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, tlds)) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                     "Failed to deserialize ThreadLocalDataSym record: {0}");
      return nullptr;
    }
    ti = tlds.Type;
    name = tlds.Name;
    section = tlds.Segment;
    offset = tlds.DataOffset;
    addr = m_index->MakeVirtualAddress(tlds.Segment, tlds.DataOffset);
    scope = eValueTypeVariableThreadLocal;
    break;
  }
  default:
    llvm_unreachable("unreachable!");
  }

  CompUnitSP comp_unit;
  std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr);
  // Some globals has modi points to the linker module, ignore them.
  if (!modi || modi >= GetNumCompileUnits())
    return nullptr;

  CompilandIndexItem &cci = m_index->compilands().GetOrCreateCompiland(*modi);
  comp_unit = GetOrCreateCompileUnit(cci);

  Declaration decl;
  PdbTypeSymId tid(ti, false);
  SymbolFileTypeSP type_sp =
      std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
  Variable::RangeList ranges;
  auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
  if (auto err = ts_or_err.takeError())
    return nullptr;
  auto ts = *ts_or_err;
  if (ts) {
    if (PdbAstBuilder *ast_builder = ts->GetNativePDBParser())
      ast_builder->EnsureVariable(var_id);
  }

  ModuleSP module_sp = GetObjectFile()->GetModule();
  DWARFExpressionList location(
      module_sp, MakeGlobalLocationExpression(section, offset, module_sp),
      nullptr);

  std::string global_name("::");
  global_name += name;
  bool artificial = false;
  bool location_is_constant_data = false;
  bool static_member = false;
  VariableSP var_sp = std::make_shared<Variable>(
      toOpaqueUid(var_id), name.str().c_str(), global_name.c_str(), type_sp,
      scope, comp_unit.get(), ranges, &decl, location, is_external, artificial,
      location_is_constant_data, static_member);

  return var_sp;
}

lldb::VariableSP
SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id,
                                          const CVSymbol &cvs) {
  TpiStream &tpi = m_index->tpi();
  ConstantSym constant(cvs.kind());

  if (auto err =
          SymbolDeserializer::deserializeAs<ConstantSym>(cvs, constant)) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                   "Failed to deserialize ConstantSym record: {0}");
    return nullptr;
  }
  std::string global_name("::");
  global_name += constant.Name;
  PdbTypeSymId tid(constant.Type, false);
  SymbolFileTypeSP type_sp =
      std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));

  Declaration decl;
  Variable::RangeList ranges;
  ModuleSP module = GetObjectFile()->GetModule();
  auto location_or_err = MakeConstantLocationExpression(constant.Type, tpi,
                                                        constant.Value, module);
  if (!location_or_err) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), location_or_err.takeError(),
                   "Failed to make constant location expression for {1}: {0}",
                   constant.Name);
    return nullptr;
  }
  DWARFExpressionList location(module, std::move(*location_or_err), nullptr);

  bool external = false;
  bool artificial = false;
  bool location_is_constant_data = true;
  bool static_member = false;
  VariableSP var_sp = std::make_shared<Variable>(
      toOpaqueUid(var_id), constant.Name.str().c_str(), global_name.c_str(),
      type_sp, eValueTypeVariableGlobal, module.get(), ranges, &decl, location,
      external, artificial, location_is_constant_data, static_member);
  return var_sp;
}

VariableSP
SymbolFileNativePDB::GetOrCreateGlobalVariable(PdbGlobalSymId var_id) {
  auto emplace_result = m_global_vars.try_emplace(toOpaqueUid(var_id), nullptr);
  if (emplace_result.second) {
    if (VariableSP var_sp = CreateGlobalVariable(var_id))
      emplace_result.first->second = var_sp;
    else
      return nullptr;
  }

  return emplace_result.first->second;
}

lldb::TypeSP SymbolFileNativePDB::GetOrCreateType(TypeIndex ti) {
  return GetOrCreateType(PdbTypeSymId(ti, false));
}

FunctionSP SymbolFileNativePDB::GetOrCreateFunction(PdbCompilandSymId func_id,
                                                    CompileUnit &comp_unit) {
  auto emplace_result = m_functions.try_emplace(toOpaqueUid(func_id), nullptr);
  if (emplace_result.second)
    emplace_result.first->second = CreateFunction(func_id, comp_unit);

  return emplace_result.first->second;
}

CompUnitSP
SymbolFileNativePDB::GetOrCreateCompileUnit(const CompilandIndexItem &cci) {

  auto emplace_result =
      m_compilands.try_emplace(toOpaqueUid(cci.m_id), nullptr);
  if (emplace_result.second)
    emplace_result.first->second = CreateCompileUnit(cci);

  lldbassert(emplace_result.first->second);
  return emplace_result.first->second;
}

Block *SymbolFileNativePDB::GetOrCreateBlock(PdbCompilandSymId block_id) {
  auto iter = m_blocks.find(toOpaqueUid(block_id));
  if (iter != m_blocks.end())
    return iter->second.get();

  return CreateBlock(block_id);
}

void SymbolFileNativePDB::ParseDeclsForContext(
    lldb_private::CompilerDeclContext decl_ctx) {
  TypeSystem *ts = decl_ctx.GetTypeSystem();
  if (!ts)
    return;
  PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
  if (!ast_builder)
    return;
  ast_builder->ParseDeclsForContext(decl_ctx);
}

lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) {
  if (index >= GetNumCompileUnits())
    return CompUnitSP();
  lldbassert(index < UINT16_MAX);
  if (index >= UINT16_MAX)
    return nullptr;

  CompilandIndexItem &item = m_index->compilands().GetOrCreateCompiland(index);

  return GetOrCreateCompileUnit(item);
}

lldb::LanguageType SymbolFileNativePDB::ParseLanguage(CompileUnit &comp_unit) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  PdbSymUid uid(comp_unit.GetID());
  lldbassert(uid.kind() == PdbSymUidKind::Compiland);

  CompilandIndexItem *item =
      m_index->compilands().GetCompiland(uid.asCompiland().modi);
  lldbassert(item);
  if (!item->m_compile_opts)
    return lldb::eLanguageTypeUnknown;

  return TranslateLanguage(item->m_compile_opts->getLanguage());
}

void SymbolFileNativePDB::AddSymbols(Symtab &symtab) {
  auto *section_list =
      m_objfile_sp->GetModule()->GetObjectFile()->GetSectionList();
  if (!section_list)
    return;

  PublicSym32 last_sym;
  size_t last_sym_idx = 0;
  lldb::SectionSP section_sp;

  // To estimate the size of a symbol, we use the difference to the next symbol.
  // If there's no next symbol or the section/segment changed, the symbol will
  // take the remaining space. The estimate can be too high in case there's
  // padding between symbols. This similar to the algorithm used by the DIA
  // SDK.
  auto finish_last_symbol = [&](const PublicSym32 *next) {
    if (!section_sp)
      return;
    Symbol *last = symtab.SymbolAtIndex(last_sym_idx);
    if (!last)
      return;

    if (next && last_sym.Segment == next->Segment) {
      assert(last_sym.Offset <= next->Offset);
      last->SetByteSize(next->Offset - last_sym.Offset);
    } else {
      // the last symbol was the last in its section
      assert(section_sp->GetByteSize() >= last_sym.Offset);
      assert(!next || next->Segment > last_sym.Segment);
      last->SetByteSize(section_sp->GetByteSize() - last_sym.Offset);
    }
  };

  // The address map is sorted by the address of a symbol.
  for (auto pid : m_index->publics().getAddressMap()) {
    PdbGlobalSymId global{pid, true};
    CVSymbol sym = m_index->ReadSymbolRecord(global);
    auto kind = sym.kind();
    if (kind != S_PUB32)
      continue;
    auto pub_or_err = SymbolDeserializer::deserializeAs<PublicSym32>(sym);
    if (!pub_or_err) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), pub_or_err.takeError(),
                     "Failed to deserialize PublicSym32 record: {0}");
      continue;
    }
    PublicSym32 pub = std::move(*pub_or_err);
    finish_last_symbol(&pub);

    if (!section_sp || last_sym.Segment != pub.Segment)
      section_sp = section_list->FindSectionByID(pub.Segment);

    if (!section_sp)
      continue;

    lldb::SymbolType type = eSymbolTypeData;
    if ((pub.Flags & PublicSymFlags::Function) != PublicSymFlags::None ||
        (pub.Flags & PublicSymFlags::Code) != PublicSymFlags::None)
      type = eSymbolTypeCode;

    last_sym_idx =
        symtab.AddSymbol(Symbol(/*symID=*/pid,
                                /*name=*/pub.Name,
                                /*type=*/type,
                                /*external=*/true,
                                /*is_debug=*/true,
                                /*is_trampoline=*/false,
                                /*is_artificial=*/false,
                                /*section_sp=*/section_sp,
                                /*value=*/pub.Offset,
                                /*size=*/0,
                                /*size_is_valid=*/false,
                                /*contains_linker_annotations=*/false,
                                /*flags=*/0));
    last_sym = pub;
  }

  finish_last_symbol(nullptr);
}

size_t SymbolFileNativePDB::ParseFunctions(CompileUnit &comp_unit) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  PdbSymUid uid{comp_unit.GetID()};
  lldbassert(uid.kind() == PdbSymUidKind::Compiland);
  uint16_t modi = uid.asCompiland().modi;
  CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(modi);

  size_t count = comp_unit.GetNumFunctions();
  const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
  for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
    if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32)
      continue;

    PdbCompilandSymId sym_id{modi, iter.offset()};

    FunctionSP func = GetOrCreateFunction(sym_id, comp_unit);
  }

  size_t new_count = comp_unit.GetNumFunctions();
  lldbassert(new_count >= count);
  return new_count - count;
}

static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) {
  // If any of these flags are set, we need to resolve the compile unit.
  uint32_t flags = eSymbolContextCompUnit;
  flags |= eSymbolContextVariable;
  flags |= eSymbolContextFunction;
  flags |= eSymbolContextBlock;
  flags |= eSymbolContextLineEntry;
  return (resolve_scope & flags) != 0;
}

uint32_t SymbolFileNativePDB::ResolveSymbolContext(
    const Address &addr, SymbolContextItem resolve_scope, SymbolContext &sc) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  uint32_t resolved_flags = 0;
  lldb::addr_t file_addr = addr.GetFileAddress();

  if (NeedsResolvedCompileUnit(resolve_scope)) {
    std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr);
    if (!modi)
      return 0;
    CompUnitSP cu_sp = GetCompileUnitAtIndex(*modi);
    if (!cu_sp)
      return 0;

    sc.comp_unit = cu_sp.get();
    resolved_flags |= eSymbolContextCompUnit;
  }

  if (resolve_scope & eSymbolContextFunction ||
      resolve_scope & eSymbolContextBlock) {
    lldbassert(sc.comp_unit);
    std::vector<SymbolAndUid> matches = m_index->FindSymbolsByVa(file_addr);
    // Search the matches in reverse.  This way if there are multiple matches
    // (for example we are 3 levels deep in a nested scope) it will find the
    // innermost one first.
    for (const auto &match : llvm::reverse(matches)) {
      if (match.uid.kind() != PdbSymUidKind::CompilandSym)
        continue;

      PdbCompilandSymId csid = match.uid.asCompilandSym();
      CVSymbol cvs = m_index->ReadSymbolRecord(csid);
      PDB_SymType type = CVSymToPDBSym(cvs.kind());
      if (type != PDB_SymType::Function && type != PDB_SymType::Block)
        continue;
      if (type == PDB_SymType::Function) {
        sc.function = GetOrCreateFunction(csid, *sc.comp_unit).get();
        if (sc.function) {
          Block &block = sc.function->GetBlock(true);
          addr_t func_base = sc.function->GetAddress().GetFileAddress();
          addr_t offset = file_addr - func_base;
          sc.block = block.FindInnermostBlockByOffset(offset);
        }
      }

      if (type == PDB_SymType::Block) {
        Block *block = GetOrCreateBlock(csid);
        if (!block)
          continue;
        sc.function = block->CalculateSymbolContextFunction();
        if (sc.function) {
          sc.function->GetBlock(true);
          addr_t func_base = sc.function->GetAddress().GetFileAddress();
          addr_t offset = file_addr - func_base;
          sc.block = block->FindInnermostBlockByOffset(offset);
        }
      }
      if (sc.function)
        resolved_flags |= eSymbolContextFunction;
      if (sc.block)
        resolved_flags |= eSymbolContextBlock;
      break;
    }
  }

  if (resolve_scope & eSymbolContextLineEntry) {
    lldbassert(sc.comp_unit);
    if (auto *line_table = sc.comp_unit->GetLineTable()) {
      if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
        resolved_flags |= eSymbolContextLineEntry;
    }
  }

  return resolved_flags;
}

uint32_t SymbolFileNativePDB::ResolveSymbolContext(
    const SourceLocationSpec &src_location_spec,
    lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  const uint32_t prev_size = sc_list.GetSize();
  if (resolve_scope & eSymbolContextCompUnit) {
    for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus;
         ++cu_idx) {
      CompileUnit *cu = ParseCompileUnitAtIndex(cu_idx).get();
      if (!cu)
        continue;

      bool file_spec_matches_cu_file_spec = FileSpec::Match(
          src_location_spec.GetFileSpec(), cu->GetPrimaryFile());
      if (file_spec_matches_cu_file_spec) {
        cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list);
        break;
      }
    }
  }
  return sc_list.GetSize() - prev_size;
}

bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) {
  // Unfortunately LLDB is set up to parse the entire compile unit line table
  // all at once, even if all it really needs is line info for a specific
  // function.  In the future it would be nice if it could set the sc.m_function
  // member, and we could only get the line info for the function in question.
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  PdbSymUid cu_id(comp_unit.GetID());
  lldbassert(cu_id.kind() == PdbSymUidKind::Compiland);
  uint16_t modi = cu_id.asCompiland().modi;
  CompilandIndexItem *cii = m_index->compilands().GetCompiland(modi);
  lldbassert(cii);

  // Parse DEBUG_S_LINES subsections first, then parse all S_INLINESITE records
  // in this CU. Add line entries into the set first so that if there are line
  // entries with same addres, the later is always more accurate than the
  // former.
  std::set<LineTable::Entry, LineTableEntryComparator> line_set;

  // This is basically a copy of the .debug$S subsections from all original COFF
  // object files merged together with address relocations applied.  We are
  // looking for all DEBUG_S_LINES subsections.
  for (const DebugSubsectionRecord &dssr :
       cii->m_debug_stream.getSubsectionsArray()) {
    if (dssr.kind() != DebugSubsectionKind::Lines)
      continue;

    DebugLinesSubsectionRef lines;
    llvm::BinaryStreamReader reader(dssr.getRecordData());
    if (auto EC = lines.initialize(reader)) {
      llvm::consumeError(std::move(EC));
      return false;
    }

    const LineFragmentHeader *lfh = lines.header();
    uint64_t virtual_addr =
        m_index->MakeVirtualAddress(lfh->RelocSegment, lfh->RelocOffset);
    if (virtual_addr == LLDB_INVALID_ADDRESS)
      continue;

    for (const LineColumnEntry &group : lines) {
      llvm::Expected<uint32_t> file_index_or_err =
          GetFileIndex(*cii, group.NameIndex);
      if (!file_index_or_err) {
        LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), file_index_or_err.takeError(),
                       "failed to get file index for line entry: {0}");
        continue;
      }
      uint32_t file_index = file_index_or_err.get();
      lldbassert(!group.LineNumbers.empty());
      CompilandIndexItem::GlobalLineTable::Entry line_entry(
          LLDB_INVALID_ADDRESS, 0);
      for (const LineNumberEntry &entry : group.LineNumbers) {
        LineInfo cur_info(entry.Flags);

        if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto())
          continue;

        uint64_t addr = virtual_addr + entry.Offset;

        bool is_statement = cur_info.isStatement();
        bool is_prologue = IsFunctionPrologue(*cii, addr);
        bool is_epilogue = IsFunctionEpilogue(*cii, addr);

        uint32_t lno = cur_info.getStartLine();

        LineTable::Entry new_entry(addr, lno, 0, file_index, is_statement, false,
                                 is_prologue, is_epilogue, false);
        // Terminal entry has lower precedence than new entry.
        auto iter = line_set.find(new_entry);
        if (iter != line_set.end() && iter->is_terminal_entry)
          line_set.erase(iter);
        line_set.insert(new_entry);

        if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) {
          line_entry.SetRangeEnd(addr);
          cii->m_global_line_table.Append(line_entry);
        }
        line_entry.SetRangeBase(addr);
        line_entry.data = {file_index, lno};
      }
      LineInfo last_line(group.LineNumbers.back().Flags);
      line_set.emplace(virtual_addr + lfh->CodeSize, last_line.getEndLine(), 0,
                       file_index, false, false, false, false, true);

      if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) {
        line_entry.SetRangeEnd(virtual_addr + lfh->CodeSize);
        cii->m_global_line_table.Append(line_entry);
      }
    }
  }

  cii->m_global_line_table.Sort();

  // Parse all S_INLINESITE in this CU.
  const CVSymbolArray &syms = cii->m_debug_stream.getSymbolArray();
  for (auto iter = syms.begin(); iter != syms.end();) {
    if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32) {
      ++iter;
      continue;
    }

    uint32_t record_offset = iter.offset();
    CVSymbol func_record =
        cii->m_debug_stream.readSymbolAtOffset(record_offset);
    SegmentOffsetLength sol = GetSegmentOffsetAndLength(func_record);
    addr_t file_vm_addr =
        m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset);
    if (file_vm_addr == LLDB_INVALID_ADDRESS)
      continue;

    Address func_base(file_vm_addr, comp_unit.GetModule()->GetSectionList());
    PdbCompilandSymId func_id{modi, record_offset};

    // Iterate all S_INLINESITEs in the function.
    auto parse_inline_sites = [&](SymbolKind kind, PdbCompilandSymId id) {
      if (kind != S_INLINESITE)
        return false;

      ParseInlineSite(id, func_base);

      for (const auto &line_entry :
           m_inline_sites[toOpaqueUid(id)]->line_entries) {
        // If line_entry is not terminal entry, remove previous line entry at
        // the same address and insert new one. Terminal entry inside an inline
        // site might not be terminal entry for its parent.
        if (!line_entry.is_terminal_entry)
          line_set.erase(line_entry);
        line_set.insert(line_entry);
      }
      // No longer useful after adding to line_set.
      m_inline_sites[toOpaqueUid(id)]->line_entries.clear();
      return true;
    };
    ParseSymbolArrayInScope(func_id, parse_inline_sites);
    // Jump to the end of the function record.
    iter = syms.at(getScopeEndOffset(func_record));
  }

  cii->m_global_line_table.Clear();

  // Add line entries in line_set to line_table.
  std::vector<LineTable::Sequence> sequence(1);
  for (const auto &line_entry : line_set) {
    LineTable::AppendLineEntryToSequence(
        sequence.back(), line_entry.file_addr, line_entry.line,
        line_entry.column, line_entry.file_idx,
        line_entry.is_start_of_statement, line_entry.is_start_of_basic_block,
        line_entry.is_prologue_end, line_entry.is_epilogue_begin,
        line_entry.is_terminal_entry);
  }
  auto line_table =
      std::make_unique<LineTable>(&comp_unit, std::move(sequence));

  if (line_table->GetSize() == 0)
    return false;

  comp_unit.SetLineTable(line_table.release());
  return true;
}

bool SymbolFileNativePDB::ParseDebugMacros(CompileUnit &comp_unit) {
  // PDB doesn't contain information about macros
  return false;
}

llvm::Expected<uint32_t>
SymbolFileNativePDB::GetFileIndex(const CompilandIndexItem &cii,
                                  uint32_t file_id) {
  if (!cii.m_strings.hasChecksums() || !cii.m_strings.hasStrings())
    return llvm::make_error<RawError>(raw_error_code::no_entry);

  const auto &checksums = cii.m_strings.checksums().getArray();
  const auto &strings = cii.m_strings.strings();
  // Indices in this structure are actually offsets of records in the
  // DEBUG_S_FILECHECKSUMS subsection.  Those entries then have an index
  // into the global PDB string table.
  auto iter = checksums.at(file_id);
  if (iter == checksums.end())
    return llvm::make_error<RawError>(raw_error_code::no_entry);

  llvm::Expected<llvm::StringRef> efn = strings.getString(iter->FileNameOffset);
  if (!efn) {
    return efn.takeError();
  }

  // LLDB wants the index of the file in the list of support files.
  auto fn_iter = llvm::find(cii.m_file_list, *efn);
  if (fn_iter != cii.m_file_list.end())
    return std::distance(cii.m_file_list.begin(), fn_iter);
  return llvm::make_error<RawError>(raw_error_code::no_entry);
}

bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit,
                                            SupportFileList &support_files) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  PdbSymUid cu_id(comp_unit.GetID());
  lldbassert(cu_id.kind() == PdbSymUidKind::Compiland);
  CompilandIndexItem *cci =
      m_index->compilands().GetCompiland(cu_id.asCompiland().modi);
  lldbassert(cci);

  for (llvm::StringRef f : cci->m_file_list) {
    FileSpec::Style style =
        f.starts_with("/") ? FileSpec::Style::posix : FileSpec::Style::windows;
    FileSpec spec(f, style);
    support_files.Append(spec);
  }
  return true;
}

bool SymbolFileNativePDB::ParseImportedModules(
    const SymbolContext &sc, std::vector<SourceModule> &imported_modules) {
  // PDB does not yet support module debug info
  return false;
}

void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id,
                                          Address func_addr) {
  lldb::user_id_t opaque_uid = toOpaqueUid(id);
  if (m_inline_sites.contains(opaque_uid))
    return;

  addr_t func_base = func_addr.GetFileAddress();
  CompilandIndexItem *cii = m_index->compilands().GetCompiland(id.modi);
  CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(id.offset);
  CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);

  InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind()));
  if (auto err =
          SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site)) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                   "Failed to deserialize InlineSiteSym record: {0}");
    return;
  }
  PdbCompilandSymId parent_id(id.modi, inline_site.Parent);

  std::shared_ptr<InlineSite> inline_site_sp =
      std::make_shared<InlineSite>(parent_id);

  // Get the inlined function declaration info.
  auto iter = cii->m_inline_map.find(inline_site.Inlinee);
  if (iter == cii->m_inline_map.end())
    return;
  InlineeSourceLine inlinee_line = iter->second;

  const SupportFileList &files = comp_unit->GetSupportFiles();
  FileSpec decl_file;
  llvm::Expected<uint32_t> file_index_or_err =
      GetFileIndex(*cii, inlinee_line.Header->FileID);
  if (!file_index_or_err) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), file_index_or_err.takeError(),
                   "failed to get file index for inline site: {0}");
    return;
  }
  uint32_t file_offset = file_index_or_err.get();
  decl_file = files.GetFileSpecAtIndex(file_offset);
  uint32_t decl_line = inlinee_line.Header->SourceLineNum;
  std::unique_ptr<Declaration> decl_up =
      std::make_unique<Declaration>(decl_file, decl_line);

  // Parse range and line info.
  uint32_t code_offset = 0;
  int32_t line_offset = 0;
  std::optional<uint32_t> code_offset_base;
  std::optional<uint32_t> code_offset_end;
  std::optional<int32_t> cur_line_offset;
  std::optional<int32_t> next_line_offset;
  std::optional<uint32_t> next_file_offset;

  bool is_terminal_entry = false;
  bool is_start_of_statement = true;
  // The first instruction is the prologue end.
  bool is_prologue_end = true;

  auto update_code_offset = [&](uint32_t code_delta) {
    if (!code_offset_base)
      code_offset_base = code_offset;
    else if (!code_offset_end)
      code_offset_end = *code_offset_base + code_delta;
  };
  auto update_line_offset = [&](int32_t line_delta) {
    line_offset += line_delta;
    if (!code_offset_base || !cur_line_offset)
      cur_line_offset = line_offset;
    else
      next_line_offset = line_offset;
    ;
  };
  auto update_file_offset = [&](uint32_t offset) {
    if (!code_offset_base)
      file_offset = offset;
    else
      next_file_offset = offset;
  };

  for (auto &annot : inline_site.annotations()) {
    switch (annot.OpCode) {
    case BinaryAnnotationsOpCode::CodeOffset:
    case BinaryAnnotationsOpCode::ChangeCodeOffset:
    case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
      code_offset += annot.U1;
      update_code_offset(annot.U1);
      break;
    case BinaryAnnotationsOpCode::ChangeLineOffset:
      update_line_offset(annot.S1);
      break;
    case BinaryAnnotationsOpCode::ChangeCodeLength:
      update_code_offset(annot.U1);
      code_offset += annot.U1;
      is_terminal_entry = true;
      break;
    case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
      code_offset += annot.U1;
      update_code_offset(annot.U1);
      update_line_offset(annot.S1);
      break;
    case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
      code_offset += annot.U2;
      update_code_offset(annot.U2);
      update_code_offset(annot.U1);
      code_offset += annot.U1;
      is_terminal_entry = true;
      break;
    case BinaryAnnotationsOpCode::ChangeFile:
      update_file_offset(annot.U1);
      break;
    default:
      break;
    }

    // Add range if current range is finished.
    if (code_offset_base && code_offset_end && cur_line_offset) {
      inline_site_sp->ranges.Append(RangeSourceLineVector::Entry(
          *code_offset_base, *code_offset_end - *code_offset_base,
          decl_line + *cur_line_offset));
      // Set base, end, file offset and line offset for next range.
      if (next_file_offset)
        file_offset = *next_file_offset;
      if (next_line_offset) {
        cur_line_offset = next_line_offset;
        next_line_offset = std::nullopt;
      }
      code_offset_base = is_terminal_entry ? std::nullopt : code_offset_end;
      code_offset_end = next_file_offset = std::nullopt;
    }
    if (code_offset_base && cur_line_offset) {
      if (is_terminal_entry) {
        LineTable::Entry line_entry(
            func_base + *code_offset_base, decl_line + *cur_line_offset, 0,
            file_offset, false, false, false, false, true);
        inline_site_sp->line_entries.push_back(line_entry);
      } else {
        LineTable::Entry line_entry(func_base + *code_offset_base,
                                    decl_line + *cur_line_offset, 0,
                                    file_offset, is_start_of_statement, false,
                                    is_prologue_end, false, false);
        inline_site_sp->line_entries.push_back(line_entry);
        is_prologue_end = false;
        is_start_of_statement = false;
      }
    }
    if (is_terminal_entry)
      is_start_of_statement = true;
    is_terminal_entry = false;
  }

  inline_site_sp->ranges.Sort();

  // Get the inlined function callsite info.
  std::unique_ptr<Declaration> callsite_up;
  if (!inline_site_sp->ranges.IsEmpty()) {
    auto *entry = inline_site_sp->ranges.GetEntryAtIndex(0);
    addr_t base_offset = entry->GetRangeBase();
    if (cii->m_debug_stream.readSymbolAtOffset(parent_id.offset).kind() ==
        S_INLINESITE) {
      // Its parent is another inline site, lookup parent site's range vector
      // for callsite line.
      ParseInlineSite(parent_id, Address(func_base));
      std::shared_ptr<InlineSite> parent_site =
          m_inline_sites[toOpaqueUid(parent_id)];
      FileSpec &parent_decl_file =
          parent_site->inline_function_info->GetDeclaration().GetFile();
      if (auto *parent_entry =
              parent_site->ranges.FindEntryThatContains(base_offset)) {
        callsite_up =
            std::make_unique<Declaration>(parent_decl_file, parent_entry->data);
      }
    } else {
      // Its parent is a function, lookup global line table for callsite.
      if (auto *entry = cii->m_global_line_table.FindEntryThatContains(
              func_base + base_offset)) {
        const FileSpec &callsite_file =
            files.GetFileSpecAtIndex(entry->data.first);
        callsite_up =
            std::make_unique<Declaration>(callsite_file, entry->data.second);
      }
    }
  }

  // Get the inlined function name.
  std::string inlinee_name;
  llvm::Expected<CVType> inlinee_cvt =
      m_index->ipi().typeCollection().getTypeOrError(inline_site.Inlinee);
  if (!inlinee_cvt) {
    inlinee_name = "[error reading function name: " +
                   llvm::toString(inlinee_cvt.takeError()) + "]";
  } else if (inlinee_cvt->kind() == LF_MFUNC_ID) {
    MemberFuncIdRecord mfr;
    if (auto err = TypeDeserializer::deserializeAs<MemberFuncIdRecord>(
            *inlinee_cvt, mfr)) {
      inlinee_name =
          "[error reading function name: " + llvm::toString(std::move(err)) +
          "]";
    } else {
      LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
      inlinee_name.append(std::string(types.getTypeName(mfr.ClassType)));
      inlinee_name.append("::");
      inlinee_name.append(mfr.getName().str());
    }
  } else if (inlinee_cvt->kind() == LF_FUNC_ID) {
    FuncIdRecord fir;
    if (auto err =
            TypeDeserializer::deserializeAs<FuncIdRecord>(*inlinee_cvt, fir)) {
      inlinee_name =
          "[error reading function name: " + llvm::toString(std::move(err)) +
          "]";
    } else {
      TypeIndex parent_idx = fir.getParentScope();
      if (!parent_idx.isNoneType()) {
        LazyRandomTypeCollection &ids = m_index->ipi().typeCollection();
        inlinee_name.append(std::string(ids.getTypeName(parent_idx)));
        inlinee_name.append("::");
      }
      inlinee_name.append(fir.getName().str());
    }
  }
  inline_site_sp->inline_function_info = std::make_shared<InlineFunctionInfo>(
      inlinee_name.c_str(), llvm::StringRef(), decl_up.get(),
      callsite_up.get());

  m_inline_sites[opaque_uid] = inline_site_sp;
}

size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  PdbCompilandSymId func_id = PdbSymUid(func.GetID()).asCompilandSym();
  // After we iterate through inline sites inside the function, we already get
  // all the info needed, removing from the map to save memory.
  std::set<uint64_t> remove_uids;
  auto parse_blocks = [&](SymbolKind kind, PdbCompilandSymId id) {
    if (kind == S_GPROC32 || kind == S_LPROC32 || kind == S_BLOCK32 ||
        kind == S_INLINESITE) {
      GetOrCreateBlock(id);
      if (kind == S_INLINESITE)
        remove_uids.insert(toOpaqueUid(id));
      return true;
    }
    return false;
  };
  size_t count = ParseSymbolArrayInScope(func_id, parse_blocks);
  for (uint64_t uid : remove_uids) {
    m_inline_sites.erase(uid);
  }

  func.GetBlock(false).SetBlockInfoHasBeenParsed(true, true);
  return count;
}

size_t SymbolFileNativePDB::ParseSymbolArrayInScope(
    PdbCompilandSymId parent_id,
    llvm::function_ref<bool(SymbolKind, PdbCompilandSymId)> fn) {
  CompilandIndexItem *cii = m_index->compilands().GetCompiland(parent_id.modi);
  CVSymbolArray syms =
      cii->m_debug_stream.getSymbolArrayForScope(parent_id.offset);

  size_t count = 1;
  for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
    PdbCompilandSymId child_id(parent_id.modi, iter.offset());
    if (fn(iter->kind(), child_id))
      ++count;
  }

  return count;
}

void SymbolFileNativePDB::DumpClangAST(Stream &s, llvm::StringRef filter,
                                       bool show_color) {
  auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
  if (!ts_or_err) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), ts_or_err.takeError(),
                   "failed to get C++ type system: {0}");
    return;
  }
  auto ts = *ts_or_err;
  TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
  if (!clang)
    return;
  PdbAstBuilder *ast_builder = clang->GetNativePDBParser();
  if (!ast_builder)
    return;
  ast_builder->Dump(s, filter, show_color);
}

void SymbolFileNativePDB::CacheGlobalBaseNames() {
  if (!m_func_full_names.IsEmpty() || !m_global_variable_base_names.IsEmpty())
    return;

  // (segment, code offset) -> gid
  std::map<std::pair<uint16_t, uint32_t>, uint32_t> func_addr_ids;

  // First, look through all items in the globals table.
  for (const uint32_t gid : m_index->globals().getGlobalsTable()) {
    CVSymbol sym = m_index->symrecords().readRecord(gid);
    auto kind = sym.kind();

    // If this is a global variable, we only need to look at the name
    llvm::StringRef name;
    switch (kind) {
    case SymbolKind::S_GDATA32:
    case SymbolKind::S_LDATA32: {
      auto data_or_err = SymbolDeserializer::deserializeAs<DataSym>(sym);
      if (!data_or_err) {
        LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), data_or_err.takeError(),
                       "Failed to deserialize DataSym record: {0}");
        continue;
      }
      name = data_or_err->Name;
      break;
    }
    case SymbolKind::S_GTHREAD32:
    case SymbolKind::S_LTHREAD32: {
      auto data_or_err =
          SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym);
      if (!data_or_err) {
        LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), data_or_err.takeError(),
                       "Failed to deserialize ThreadLocalDataSym record: {0}");
        continue;
      }
      name = data_or_err->Name;
      break;
    }
    case SymbolKind::S_CONSTANT: {
      auto data_or_err = SymbolDeserializer::deserializeAs<ConstantSym>(sym);
      if (!data_or_err) {
        LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), data_or_err.takeError(),
                       "Failed to deserialize ConstantSym record: {0}");
        continue;
      }
      name = data_or_err->Name;
      break;
    }
    default:
      break;
    }

    if (!name.empty()) {
      llvm::StringRef base = MSVCUndecoratedNameParser::DropScope(name);
      if (base.empty())
        base = name;

      m_global_variable_base_names.Append(ConstString(base), gid);
      continue;
    }

    if (kind != S_PROCREF && kind != S_LPROCREF)
      continue;

    // For functions, we need to follow the reference to the procedure and look
    // at the type

    auto ref_or_err = SymbolDeserializer::deserializeAs<ProcRefSym>(sym);
    if (!ref_or_err) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), ref_or_err.takeError(),
                     "Failed to deserialize ProcRefSym record: {0}");
      continue;
    }
    ProcRefSym ref = std::move(*ref_or_err);
    if (ref.Name.empty())
      continue;

    // Find the function this is referencing.
    CompilandIndexItem &cci =
        m_index->compilands().GetOrCreateCompiland(ref.modi());
    auto iter = cci.m_debug_stream.getSymbolArray().at(ref.SymOffset);
    if (iter == cci.m_debug_stream.getSymbolArray().end())
      continue;
    kind = iter->kind();
    if (kind != S_GPROC32 && kind != S_LPROC32)
      continue;

    auto proc_or_err = SymbolDeserializer::deserializeAs<ProcSym>(*iter);
    if (!proc_or_err) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), proc_or_err.takeError(),
                     "Failed to deserialize ProcSym record: {0}");
      continue;
    }
    ProcSym proc = std::move(*proc_or_err);
    if ((proc.Flags & ProcSymFlags::IsUnreachable) != ProcSymFlags::None)
      continue;
    if (proc.Name.empty() || proc.FunctionType.isSimple())
      continue;

    // The function/procedure symbol only contains the demangled name.
    // The mangled names are in the publics table. Save the address of this
    // function to lookup the mangled name later.
    func_addr_ids.emplace(std::make_pair(proc.Segment, proc.CodeOffset), gid);

    llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(proc.Name);
    if (basename.empty())
      basename = proc.Name;

    m_func_base_names.Append(ConstString(basename), gid);
    m_func_full_names.Append(ConstString(proc.Name), gid);

    // To see if this is a member function, check the type.
    auto type = m_index->tpi().getType(proc.FunctionType);
    if (type.kind() == LF_MFUNCTION) {
      MemberFunctionRecord mfr;
      if (auto err = TypeDeserializer::deserializeAs<MemberFunctionRecord>(
              type, mfr)) {
        LLDB_LOG_ERROR(
            GetLog(LLDBLog::Symbols), std::move(err),
            "Failed to deserialize MemberFunctionRecord record ({1}): {0}",
            proc.FunctionType);
      } else if (!mfr.getThisType().isNoneType())
        m_func_method_names.Append(ConstString(basename), gid);
    }
  }

  // The publics stream contains all mangled function names and their address.
  for (auto pid : m_index->publics().getPublicsTable()) {
    PdbGlobalSymId global{pid, true};
    CVSymbol sym = m_index->ReadSymbolRecord(global);
    auto kind = sym.kind();
    if (kind != S_PUB32)
      continue;
    auto pub_or_err = SymbolDeserializer::deserializeAs<PublicSym32>(sym);
    if (!pub_or_err) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), pub_or_err.takeError(),
                     "Failed to deserialize PublicSym32 record: {0}");
      continue;
    }
    PublicSym32 pub = std::move(*pub_or_err);
    // We only care about mangled names - if the name isn't mangled, it's
    // already in the full name map.
    if (!Mangled::IsMangledName(pub.Name))
      continue;

    // Check if this symbol is for one of our functions.
    auto it = func_addr_ids.find({pub.Segment, pub.Offset});
    if (it != func_addr_ids.end())
      m_func_full_names.Append(ConstString(pub.Name), it->second);
  }

  // Sort them before value searching is working properly.
  m_func_full_names.Sort(std::less<uint32_t>());
  m_func_full_names.SizeToFit();
  m_func_method_names.Sort(std::less<uint32_t>());
  m_func_method_names.SizeToFit();
  m_func_base_names.Sort(std::less<uint32_t>());
  m_func_base_names.SizeToFit();
  m_global_variable_base_names.Sort(std::less<uint32_t>());
  m_global_variable_base_names.SizeToFit();
}

void SymbolFileNativePDB::FindGlobalVariables(
    ConstString name, const CompilerDeclContext &parent_decl_ctx,
    uint32_t max_matches, VariableList &variables) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());

  CacheGlobalBaseNames();

  std::vector<uint32_t> results;
  m_global_variable_base_names.GetValues(name, results);

  size_t n_matches = 0;
  for (uint32_t gid : results) {
    PdbGlobalSymId global(gid, false);

    if (parent_decl_ctx.IsValid() &&
        GetDeclContextContainingUID(toOpaqueUid(global)) != parent_decl_ctx)
      continue;

    VariableSP var = GetOrCreateGlobalVariable(global);
    if (!var)
      continue;
    variables.AddVariable(var);

    if (++n_matches >= max_matches)
      break;
  }
}

void SymbolFileNativePDB::FindFunctions(
    const Module::LookupInfo &lookup_info,
    const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
    SymbolContextList &sc_list) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  ConstString name = lookup_info.GetLookupName();
  FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
  if (name_type_mask & eFunctionNameTypeFull)
    name = lookup_info.GetName();

  if (!(name_type_mask & eFunctionNameTypeFull ||
        name_type_mask & eFunctionNameTypeBase ||
        name_type_mask & eFunctionNameTypeMethod))
    return;
  CacheGlobalBaseNames();

  std::set<uint32_t> resolved_ids; // avoid duplicate lookups
  auto resolve_from = [&](UniqueCStringMap<uint32_t> &Names) {
    std::vector<uint32_t> ids;
    if (!Names.GetValues(name, ids))
      return;

    for (uint32_t id : ids) {
      if (!resolved_ids.insert(id).second)
        continue;

      PdbGlobalSymId global{id, false};
      if (parent_decl_ctx.IsValid() &&
          GetDeclContextContainingUID(toOpaqueUid(global)) != parent_decl_ctx)
        continue;

      CVSymbol sym = m_index->ReadSymbolRecord(global);
      auto kind = sym.kind();
      lldbassert(kind == S_PROCREF || kind == S_LPROCREF);

      auto proc_or_err = SymbolDeserializer::deserializeAs<ProcRefSym>(sym);
      if (!proc_or_err) {
        LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), proc_or_err.takeError(),
                       "Failed to deserialize ProcRefSym record: {0}");
        continue;
      }
      ProcRefSym proc = std::move(*proc_or_err);

      if (!IsValidRecord(proc))
        continue;

      CompilandIndexItem &cci =
          m_index->compilands().GetOrCreateCompiland(proc.modi());
      SymbolContext sc;

      sc.comp_unit = GetOrCreateCompileUnit(cci).get();
      if (!sc.comp_unit)
        continue;

      PdbCompilandSymId func_id(proc.modi(), proc.SymOffset);
      sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get();
      if (!sc.function)
        continue;

      sc_list.Append(sc);
    }
  };

  if (name_type_mask & eFunctionNameTypeFull)
    resolve_from(m_func_full_names);
  if (name_type_mask & eFunctionNameTypeBase)
    resolve_from(m_func_base_names);
  if (name_type_mask & eFunctionNameTypeMethod)
    resolve_from(m_func_method_names);
}

void SymbolFileNativePDB::FindFunctions(const RegularExpression &regex,
                                        bool include_inlines,
                                        SymbolContextList &sc_list) {}

void SymbolFileNativePDB::FindTypes(const lldb_private::TypeQuery &query,
                                    lldb_private::TypeResults &results) {

  // Make sure we haven't already searched this SymbolFile before.
  if (results.AlreadySearched(this))
    return;

  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());

  // We can't query for the full name because the type might reside
  // in an anonymous namespace. Search for the basename in our map and check the
  // matching types afterwards.
  std::vector<uint32_t> matches;
  m_type_base_names.GetValues(query.GetTypeBasename(), matches);

  for (uint32_t match_idx : matches) {
    std::vector context = GetContextForType(TypeIndex(match_idx));
    if (context.empty())
      continue;

    if (query.ContextMatches(context)) {
      TypeSP type_sp = GetOrCreateType(TypeIndex(match_idx));
      if (!type_sp)
        continue;

      results.InsertUnique(type_sp);
      if (results.Done(query))
        return;
    }
  }
}

void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name,
                                          uint32_t max_matches,
                                          TypeMap &types) {

  std::vector<TypeIndex> matches = m_index->tpi().findRecordsByName(name);
  if (max_matches > 0 && max_matches < matches.size())
    matches.resize(max_matches);

  for (TypeIndex ti : matches) {
    TypeSP type = GetOrCreateType(ti);
    if (!type)
      continue;

    types.Insert(type);
  }
}

size_t SymbolFileNativePDB::ParseTypes(CompileUnit &comp_unit) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  // Only do the full type scan the first time.
  if (m_done_full_type_scan)
    return 0;

  const size_t old_count = GetTypeList().GetSize();
  LazyRandomTypeCollection &types = m_index->tpi().typeCollection();

  // First process the entire TPI stream.
  for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
    TypeSP type = GetOrCreateType(*ti);
    if (type)
      (void)type->GetFullCompilerType();
  }

  // Next look for S_UDT records in the globals stream.
  for (const uint32_t gid : m_index->globals().getGlobalsTable()) {
    PdbGlobalSymId global{gid, false};
    CVSymbol sym = m_index->ReadSymbolRecord(global);
    if (sym.kind() != S_UDT)
      continue;

    auto udt_or_err = SymbolDeserializer::deserializeAs<UDTSym>(sym);
    if (!udt_or_err) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), udt_or_err.takeError(),
                     "Failed to deserialize UDTSym record: {0}");
      continue;
    }
    UDTSym udt = std::move(*udt_or_err);
    bool is_typedef = true;
    if (IsTagRecord(PdbTypeSymId{udt.Type, false}, m_index->tpi())) {
      CVType cvt = m_index->tpi().getType(udt.Type);
      llvm::StringRef name = CVTagRecord::create(cvt).name();
      if (name == udt.Name)
        is_typedef = false;
    }

    if (is_typedef)
      GetOrCreateTypedef(global);
  }

  const size_t new_count = GetTypeList().GetSize();

  m_done_full_type_scan = true;

  return new_count - old_count;
}

size_t
SymbolFileNativePDB::ParseVariablesForCompileUnit(CompileUnit &comp_unit,
                                                  VariableList &variables) {
  PdbSymUid sym_uid(comp_unit.GetID());
  lldbassert(sym_uid.kind() == PdbSymUidKind::Compiland);
  for (const uint32_t gid : m_index->globals().getGlobalsTable()) {
    PdbGlobalSymId global{gid, false};
    CVSymbol sym = m_index->ReadSymbolRecord(global);
    // TODO: S_CONSTANT is not handled here to prevent a possible crash in
    // lldb_private::npdb::MakeConstantLocationExpression when it's a record
    // type (e.g. std::strong_ordering::equal). That function needs to be
    // updated to handle this case when we add S_CONSTANT case here.
    switch (sym.kind()) {
    case SymbolKind::S_GDATA32:
    case SymbolKind::S_LDATA32:
    case SymbolKind::S_GTHREAD32:
    case SymbolKind::S_LTHREAD32: {
      if (VariableSP var = GetOrCreateGlobalVariable(global))
        variables.AddVariable(var);
      break;
    }
    default:
      break;
    }
  }
  return variables.GetSize();
}

VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
                                                    PdbCompilandSymId var_id,
                                                    bool is_param,
                                                    bool is_constant) {
  ModuleSP module = GetObjectFile()->GetModule();
  Block *block = GetOrCreateBlock(scope_id);
  if (!block)
    return nullptr;

  CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
  if (!cii)
    return nullptr;
  CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);

  VariableInfo var_info;
  bool location_is_constant_data = is_constant;

  if (is_constant) {
    CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(var_id.offset);
    assert(sym.kind() == S_CONSTANT);
    ConstantSym constant(sym.kind());
    if (auto err =
            SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant)) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                     "Failed to deserialize ConstantSym record: {0}");
      return nullptr;
    }

    var_info.name = constant.Name;
    var_info.type = constant.Type;
    auto location_or_err = MakeConstantLocationExpression(
        constant.Type, m_index->tpi(), constant.Value, module);
    if (!location_or_err) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), location_or_err.takeError(),
                     "Failed to make constant location expression for {1}: {0}",
                     constant.Name);
      return nullptr;
    }
    var_info.location =
        DWARFExpressionList(module, std::move(*location_or_err), nullptr);
  } else {
    // Get function block.
    Block *func_block = block;
    while (func_block->GetParent())
      func_block = func_block->GetParent();

    Address addr;
    func_block->GetStartAddress(addr);
    var_info = GetVariableLocationInfo(*m_index, var_id, *func_block, module);
    Function *func = func_block->CalculateSymbolContextFunction();
    if (!func)
      return nullptr;
    // Use empty dwarf expr if optimized away so that it won't be filtered out
    // when lookuping local variables in this scope.
    if (!var_info.location.IsValid())
      var_info.location =
          DWARFExpressionList(module, DWARFExpression(), nullptr);
    var_info.location.SetFuncFileAddress(func->GetAddress().GetFileAddress());
  }

  TypeSP type_sp = GetOrCreateType(var_info.type);
  if (!type_sp)
    return nullptr;
  std::string name = var_info.name.str();
  Declaration decl;
  SymbolFileTypeSP sftype =
      std::make_shared<SymbolFileType>(*this, type_sp->GetID());

  is_param |= var_info.is_param;
  ValueType var_scope =
      is_param ? eValueTypeVariableArgument : eValueTypeVariableLocal;
  bool external = false;
  bool artificial = false;
  bool static_member = false;
  Variable::RangeList scope_ranges;
  VariableSP var_sp = std::make_shared<Variable>(
      toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope, block,
      scope_ranges, &decl, var_info.location, external, artificial,
      location_is_constant_data, static_member);
  if (!is_param) {
    auto ts_or_err = GetTypeSystemForLanguage(comp_unit_sp->GetLanguage());
    if (auto err = ts_or_err.takeError())
      return nullptr;
    auto ts = *ts_or_err;
    if (ts) {
      if (PdbAstBuilder *ast_builder = ts->GetNativePDBParser())
        ast_builder->EnsureVariable(scope_id, var_id);
    }
  }
  m_local_variables[toOpaqueUid(var_id)] = var_sp;
  return var_sp;
}

VariableSP
SymbolFileNativePDB::GetOrCreateLocalVariable(PdbCompilandSymId scope_id,
                                              PdbCompilandSymId var_id,
                                              bool is_param, bool is_constant) {
  auto iter = m_local_variables.find(toOpaqueUid(var_id));
  if (iter != m_local_variables.end())
    return iter->second;

  return CreateLocalVariable(scope_id, var_id, is_param, is_constant);
}

TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) {
  CVSymbol sym = m_index->ReadSymbolRecord(id);
  lldbassert(sym.kind() == SymbolKind::S_UDT);

  auto udt_or_err = SymbolDeserializer::deserializeAs<UDTSym>(sym);
  if (!udt_or_err) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), udt_or_err.takeError(),
                   "Failed to deserialize UDTSym record: {0}");
    return nullptr;
  }
  UDTSym udt = std::move(*udt_or_err);

  TypeSP target_type = GetOrCreateType(udt.Type);

  auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
  if (auto err = ts_or_err.takeError())
    return nullptr;
  auto ts = *ts_or_err;
  if (!ts)
    return nullptr;
  PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
  if (!ast_builder)
    return nullptr;
  CompilerType ct = ast_builder->GetOrCreateTypedefType(id);
  if (!ct)
    ct = target_type->GetForwardCompilerType();

  Declaration decl;
  return MakeType(toOpaqueUid(id), ConstString(udt.Name),
                  llvm::expectedToOptional(target_type->GetByteSize(nullptr)),
                  nullptr, target_type->GetID(),
                  lldb_private::Type::eEncodingIsTypedefUID, decl, ct,
                  lldb_private::Type::ResolveState::Forward);
}

TypeSP SymbolFileNativePDB::GetOrCreateTypedef(PdbGlobalSymId id) {
  auto iter = m_types.find(toOpaqueUid(id));
  if (iter != m_types.end())
    return iter->second;

  return CreateTypedef(id);
}

size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) {
  Block *block = GetOrCreateBlock(block_id);
  if (!block)
    return 0;

  size_t count = 0;

  CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
  CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
  uint32_t params_remaining = 0;
  switch (sym.kind()) {
  case S_GPROC32:
  case S_LPROC32: {
    ProcSym proc(static_cast<SymbolRecordKind>(sym.kind()));
    if (auto err = SymbolDeserializer::deserializeAs<ProcSym>(sym, proc)) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                     "Failed to deserialize ProcSym record: {0}");
      return 0;
    }
    CVType signature = m_index->tpi().getType(proc.FunctionType);
    if (signature.kind() == LF_PROCEDURE) {
      ProcedureRecord sig;
      if (llvm::Error e = TypeDeserializer::deserializeAs<ProcedureRecord>(
              signature, sig)) {
        llvm::consumeError(std::move(e));
        return 0;
      }
      params_remaining = sig.getParameterCount();
    } else if (signature.kind() == LF_MFUNCTION) {
      MemberFunctionRecord sig;
      if (llvm::Error e = TypeDeserializer::deserializeAs<MemberFunctionRecord>(
              signature, sig)) {
        llvm::consumeError(std::move(e));
        return 0;
      }
      params_remaining = sig.getParameterCount();
    } else
      return 0;
    break;
  }
  case S_BLOCK32:
    break;
  case S_INLINESITE:
    break;
  default:
    lldbassert(false && "Symbol is not a block!");
    return 0;
  }

  VariableListSP variables = block->GetBlockVariableList(false);
  if (!variables) {
    variables = std::make_shared<VariableList>();
    block->SetVariableList(variables);
  }

  CVSymbolArray syms = limitSymbolArrayToScope(
      cii->m_debug_stream.getSymbolArray(), block_id.offset);

  // Skip the first record since it's a PROC32 or BLOCK32, and there's
  // no point examining it since we know it's not a local variable.
  syms.drop_front();
  auto iter = syms.begin();
  auto end = syms.end();

  while (iter != end) {
    uint32_t record_offset = iter.offset();
    CVSymbol variable_cvs = *iter;
    PdbCompilandSymId child_sym_id(block_id.modi, record_offset);
    ++iter;

    // If this is a block or inline site, recurse into its children and then
    // skip it.
    if (variable_cvs.kind() == S_BLOCK32 ||
        variable_cvs.kind() == S_INLINESITE) {
      uint32_t block_end = getScopeEndOffset(variable_cvs);
      count += ParseVariablesForBlock(child_sym_id);
      iter = syms.at(block_end);
      continue;
    }

    bool is_param = params_remaining > 0;
    VariableSP variable;
    switch (variable_cvs.kind()) {
    case S_REGREL32:
    case S_REGREL32_INDIR:
    case S_REGISTER:
    case S_LOCAL:
      variable = GetOrCreateLocalVariable(block_id, child_sym_id, is_param);
      if (is_param)
        --params_remaining;
      if (variable)
        variables->AddVariableIfUnique(variable);
      break;
    case S_CONSTANT:
      variable = GetOrCreateLocalVariable(block_id, child_sym_id,
                                          /*is_param=*/false,
                                          /*is_constant=*/true);
      if (variable)
        variables->AddVariableIfUnique(variable);
      break;
    default:
      break;
    }
  }

  // Pass false for set_children, since we call this recursively so that the
  // children will call this for themselves.
  block->SetDidParseVariables(true, false);

  return count;
}

size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  lldbassert(sc.function || sc.comp_unit);

  VariableListSP variables;
  if (sc.block) {
    PdbSymUid block_id(sc.block->GetID());

    size_t count = ParseVariablesForBlock(block_id.asCompilandSym());
    return count;
  }

  if (sc.function) {
    PdbSymUid block_id(sc.function->GetID());

    size_t count = ParseVariablesForBlock(block_id.asCompilandSym());
    return count;
  }

  if (sc.comp_unit) {
    variables = sc.comp_unit->GetVariableList(false);
    if (!variables) {
      variables = std::make_shared<VariableList>();
      sc.comp_unit->SetVariableList(variables);
    }
    return ParseVariablesForCompileUnit(*sc.comp_unit, *variables);
  }

  llvm_unreachable("Unreachable!");
}

CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) {
  auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
  if (auto err = ts_or_err.takeError())
    return CompilerDecl();
  auto ts = *ts_or_err;
  if (!ts)
    return {};
  PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
  if (!ast_builder)
    return {};
  return ast_builder->GetOrCreateDeclForUid(uid);
}

CompilerDeclContext
SymbolFileNativePDB::GetDeclContextForUID(lldb::user_id_t uid) {
  auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
  if (auto err = ts_or_err.takeError())
    return {};
  auto ts = *ts_or_err;
  if (!ts)
    return {};
  PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
  if (!ast_builder)
    return {};
  return ast_builder->GetOrCreateDeclContextForUid(PdbSymUid(uid));
}

CompilerDeclContext
SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
  auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
  if (auto err = ts_or_err.takeError())
    return CompilerDeclContext();
  auto ts = *ts_or_err;
  if (!ts)
    return {};
  PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
  if (!ast_builder)
    return {};
  return ast_builder->GetParentDeclContext(PdbSymUid(uid));
}

Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  auto iter = m_types.find(type_uid);
  // lldb should not be passing us non-sensical type uids.  the only way it
  // could have a type uid in the first place is if we handed it out, in which
  // case we should know about the type.  However, that doesn't mean we've
  // instantiated it yet.  We can vend out a UID for a future type.  So if the
  // type doesn't exist, let's instantiate it now.
  if (iter != m_types.end())
    return &*iter->second;

  PdbSymUid uid(type_uid);
  lldbassert(uid.kind() == PdbSymUidKind::Type);
  PdbTypeSymId type_id = uid.asTypeSym();
  if (type_id.index.isNoneType())
    return nullptr;

  TypeSP type_sp = CreateAndCacheType(type_id);
  if (!type_sp)
    return nullptr;
  return &*type_sp;
}

std::optional<SymbolFile::ArrayInfo>
SymbolFileNativePDB::GetDynamicArrayInfoForUID(
    lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
  return std::nullopt;
}

bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  auto ts = compiler_type.GetTypeSystem();
  if (!ts)
    return false;

  PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
  if (!ast_builder)
    return false;
  return ast_builder->CompleteType(compiler_type);
}

void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
                                   TypeClass type_mask,
                                   lldb_private::TypeList &type_list) {}

CompilerDeclContext
SymbolFileNativePDB::FindNamespace(ConstString name,
                                   const CompilerDeclContext &parent_decl_ctx,
                                   bool /* only_root_namespaces */) {
  std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
  auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
  if (auto err = ts_or_err.takeError())
    return {};
  auto ts = *ts_or_err;
  if (!ts)
    return {};
  auto *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
  if (!clang)
    return {};

  PdbAstBuilder *ast_builder = clang->GetNativePDBParser();
  if (!ast_builder)
    return {};

  return ast_builder->FindNamespaceDecl(parent_decl_ctx, name.GetStringRef());
}

llvm::Expected<lldb::TypeSystemSP>
SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
  auto type_system_or_err =
      m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language);
  if (type_system_or_err)
    if (auto ts = *type_system_or_err)
      ts->SetSymbolFile(this);
  return type_system_or_err;
}

uint64_t SymbolFileNativePDB::GetDebugInfoSize(bool load_all_debug_info) {
  // PDB files are a separate file that contains all debug info.
  return m_index->pdb().getFileSize();
}

void SymbolFileNativePDB::BuildParentMap() {
  LazyRandomTypeCollection &types = m_index->tpi().typeCollection();

  llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full;
  llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward;

  struct RecordIndices {
    TypeIndex forward;
    TypeIndex full;
  };

  llvm::StringMap<RecordIndices> record_indices;

  for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
    CVType type = types.getType(*ti);
    if (!IsTagRecord(type))
      continue;

    CVTagRecord tag = CVTagRecord::create(type);

    RecordIndices &indices = record_indices[tag.asTag().getUniqueName()];
    if (tag.asTag().isForwardRef()) {
      indices.forward = *ti;
    } else {
      indices.full = *ti;

      auto base_name = MSVCUndecoratedNameParser::DropScope(tag.name());
      m_type_base_names.Append(ConstString(base_name), ti->getIndex());
    }

    if (indices.full != TypeIndex::None() &&
        indices.forward != TypeIndex::None()) {
      forward_to_full[indices.forward] = indices.full;
      full_to_forward[indices.full] = indices.forward;
    }

    // We're looking for LF_NESTTYPE records in the field list, so ignore
    // forward references (no field list), and anything without a nested class
    // (since there won't be any LF_NESTTYPE records).
    if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass())
      continue;

    struct ProcessTpiStream : public TypeVisitorCallbacks {
      ProcessTpiStream(PdbIndex &index, TypeIndex parent,
                       const CVTagRecord &parent_cvt,
                       llvm::DenseMap<TypeIndex, TypeIndex> &parents)
          : index(index), parents(parents), parent(parent),
            parent_cvt(parent_cvt) {}

      PdbIndex &index;
      llvm::DenseMap<TypeIndex, TypeIndex> &parents;

      unsigned unnamed_type_index = 1;
      TypeIndex parent;
      const CVTagRecord &parent_cvt;

      llvm::Error visitKnownMember(CVMemberRecord &CVR,
                                   NestedTypeRecord &Record) override {
        std::string unnamed_type_name;
        if (Record.Name.empty()) {
          unnamed_type_name =
              llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str();
          Record.Name = unnamed_type_name;
          ++unnamed_type_index;
        }
        std::optional<CVTagRecord> tag =
            GetNestedTagDefinition(Record, parent_cvt, index.tpi());
        if (!tag)
          return llvm::ErrorSuccess();

        parents[Record.Type] = parent;
        return llvm::ErrorSuccess();
      }
    };

    CVType field_list_cvt = m_index->tpi().getType(tag.asTag().FieldList);
    ProcessTpiStream process(*m_index, *ti, tag, m_parent_types);
    FieldListRecord field_list;
    if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
            field_list_cvt, field_list))
      llvm::consumeError(std::move(error));
    if (llvm::Error error = visitMemberRecordStream(field_list.Data, process))
      llvm::consumeError(std::move(error));
  }

  // After calling Append(), the type-name map needs to be sorted again to be
  // able to look up a type by its name.
  m_type_base_names.Sort(std::less<uint32_t>());

  // Now that we know the forward -> full mapping of all type indices, we can
  // re-write all the indices.  At the end of this process, we want a mapping
  // consisting of fwd -> full and full -> full for all child -> parent indices.
  // We can re-write the values in place, but for the keys, we must save them
  // off so that we don't modify the map in place while also iterating it.
  std::vector<TypeIndex> full_keys;
  std::vector<TypeIndex> fwd_keys;
  for (auto &entry : m_parent_types) {
    TypeIndex key = entry.first;
    TypeIndex value = entry.second;

    auto iter = forward_to_full.find(value);
    if (iter != forward_to_full.end())
      entry.second = iter->second;

    iter = forward_to_full.find(key);
    if (iter != forward_to_full.end())
      fwd_keys.push_back(key);
    else
      full_keys.push_back(key);
  }
  for (TypeIndex fwd : fwd_keys) {
    TypeIndex full = forward_to_full[fwd];
    TypeIndex parent_idx = m_parent_types[fwd];
    m_parent_types[full] = parent_idx;
  }
  for (TypeIndex full : full_keys) {
    TypeIndex fwd = full_to_forward[full];
    m_parent_types[fwd] = m_parent_types[full];
  }
}

std::optional<PdbCompilandSymId>
SymbolFileNativePDB::FindSymbolScope(PdbCompilandSymId id) {
  CVSymbol sym = m_index->ReadSymbolRecord(id);
  if (symbolOpensScope(sym.kind())) {
    // If this exact symbol opens a scope, we can just directly access its
    // parent.
    id.offset = getScopeParentOffset(sym);
    // Global symbols have parent offset of 0.  Return std::nullopt to indicate
    // this.
    if (id.offset == 0)
      return std::nullopt;
    return id;
  }

  // Otherwise we need to start at the beginning and iterate forward until we
  // reach (or pass) this particular symbol
  CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(id.modi);
  const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();

  auto begin = syms.begin();
  auto end = syms.at(id.offset);
  std::vector<PdbCompilandSymId> scope_stack;

  while (begin != end) {
    if (begin.offset() > id.offset) {
      // We passed it.  We couldn't even find this symbol record.
      lldbassert(false && "Invalid compiland symbol id!");
      return std::nullopt;
    }

    // We haven't found the symbol yet.  Check if we need to open or close the
    // scope stack.
    if (symbolOpensScope(begin->kind())) {
      // We can use the end offset of the scope to determine whether or not
      // we can just outright skip this entire scope.
      uint32_t scope_end = getScopeEndOffset(*begin);
      if (scope_end < id.offset) {
        begin = syms.at(scope_end);
      } else {
        // The symbol we're looking for is somewhere in this scope.
        scope_stack.emplace_back(id.modi, begin.offset());
      }
    } else if (symbolEndsScope(begin->kind())) {
      scope_stack.pop_back();
    }
    ++begin;
  }
  if (scope_stack.empty())
    return std::nullopt;
  // We have a match!  Return the top of the stack
  return scope_stack.back();
}

std::optional<llvm::codeview::TypeIndex>
SymbolFileNativePDB::GetParentType(llvm::codeview::TypeIndex ti) {
  auto parent_iter = m_parent_types.find(ti);
  if (parent_iter == m_parent_types.end())
    return std::nullopt;
  return parent_iter->second;
}

std::vector<CompilerContext>
SymbolFileNativePDB::GetContextForType(TypeIndex ti) {
  CVType type = m_index->tpi().getType(ti);
  if (!IsTagRecord(type))
    return {};

  CVTagRecord tag = CVTagRecord::create(type);

  std::optional<Type::ParsedName> parsed_name =
      Type::GetTypeScopeAndBasename(tag.name());
  if (!parsed_name)
    return {{tag.contextKind(), ConstString(tag.name())}};

  std::vector<CompilerContext> ctx;
  // assume everything is a namespace at first
  for (llvm::StringRef scope : parsed_name->scope) {
    ctx.emplace_back(CompilerContextKind::Namespace, ConstString(scope));
  }
  // we know the kind of our own type
  ctx.emplace_back(tag.contextKind(), ConstString(parsed_name->basename));

  // try to find the kind of parents
  for (auto &el : llvm::reverse(llvm::drop_end(ctx))) {
    std::optional<TypeIndex> parent = GetParentType(ti);
    if (!parent)
      break;

    ti = *parent;
    type = m_index->tpi().getType(ti);
    switch (type.kind()) {
    case LF_CLASS:
    case LF_STRUCTURE:
    case LF_INTERFACE:
      el.kind = CompilerContextKind::ClassOrStruct;
      continue;
    case LF_UNION:
      el.kind = CompilerContextKind::Union;
      continue;
    case LF_ENUM:
      el.kind = CompilerContextKind::Enum;
      continue;
    default:
      break;
    }
    break;
  }
  return ctx;
}

std::optional<llvm::StringRef>
SymbolFileNativePDB::FindMangledFunctionName(PdbCompilandSymId func_id) {
  const CompilandIndexItem *cci =
      m_index->compilands().GetCompiland(func_id.modi);
  if (!cci)
    return std::nullopt;

  CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset);
  if (sym_record.kind() != S_LPROC32 && sym_record.kind() != S_GPROC32)
    return std::nullopt;

  ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
  if (auto err = SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc)) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                   "Failed to deserialize ProcSym record: {0}");
    return std::nullopt;
  }

  return FindMangledSymbol(SegmentOffset(proc.Segment, proc.CodeOffset),
                           proc.FunctionType);
}

std::optional<llvm::StringRef>
SymbolFileNativePDB::FindMangledSymbol(SegmentOffset so,
                                       TypeIndex function_type) {
  auto symbol = m_index->publics().findByAddress(m_index->symrecords(),
                                                 so.segment, so.offset);
  if (!symbol)
    return std::nullopt;

  llvm::StringRef name = symbol->first.Name;
  // For functions, we might need to strip the mangled name. See
  // StripMangledFunctionName for more info.
  if (!function_type.isNoneType() &&
      (symbol->first.Flags & PublicSymFlags::Function) != PublicSymFlags::None)
    name = StripMangledFunctionName(name, function_type);

  return name;
}

llvm::StringRef
SymbolFileNativePDB::StripMangledFunctionName(const llvm::StringRef mangled,
                                              PdbTypeSymId func_ty) {
  // "In non-64 bit environments" (on x86 in pactice), __cdecl functions get
  // prefixed with an underscore. For compilers using LLVM, this happens in LLVM
  // (as opposed to the compiler frontend). Because of this, DWARF doesn't
  // contain the "full" mangled name in DW_AT_linkage_name for these functions.
  // We strip the mangling here for compatibility with DWARF. See
  // llvm.org/pr161676 and
  // https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names#FormatC

  if (!mangled.starts_with('_') ||
      m_index->dbi().getMachineType() != PDB_Machine::x86)
    return mangled;

  CVType cvt = m_index->tpi().getType(func_ty.index);
  PDB_CallingConv cc = PDB_CallingConv::NearC;
  if (cvt.kind() == LF_PROCEDURE) {
    ProcedureRecord proc;
    if (llvm::Error error =
            TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, proc))
      llvm::consumeError(std::move(error));
    cc = proc.CallConv;
  } else if (cvt.kind() == LF_MFUNCTION) {
    MemberFunctionRecord mfunc;
    if (llvm::Error error =
            TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfunc))
      llvm::consumeError(std::move(error));
    cc = mfunc.CallConv;
  } else {
    LLDB_LOG(GetLog(LLDBLog::Symbols), "Unexpected function type, got {0}",
             cvt.kind());
    return mangled;
  }

  if (cc == PDB_CallingConv::NearC || cc == PDB_CallingConv::FarC)
    return mangled.drop_front();

  return mangled;
}

void SymbolFileNativePDB::CacheUdtDeclarations() {
  for (CVType cvt : m_index->ipi().typeArray()) {
    switch (cvt.kind()) {
    case LF_UDT_SRC_LINE: {
      UdtSourceLineRecord udt_src;
      if (auto err = TypeDeserializer::deserializeAs(cvt, udt_src)) {
        LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
                       "Failed to deserialize UdtSourceLineRecord record: {0}");
        continue;
      }
      m_udt_declarations.try_emplace(
          udt_src.UDT, UdtDeclaration{/*FileNameIndex=*/udt_src.SourceFile,
                                      /*IsIpiIndex=*/true,
                                      /*Line=*/udt_src.LineNumber});
    } break;
    case LF_UDT_MOD_SRC_LINE: {
      UdtModSourceLineRecord udt_mod_src;
      if (auto err = TypeDeserializer::deserializeAs(cvt, udt_mod_src)) {
        LLDB_LOG_ERROR(
            GetLog(LLDBLog::Symbols), std::move(err),
            "Failed to deserialize UdtModSourceLineRecord record: {0}");
        continue;
      }
      // Some types might be contributed by multiple modules. We assume that
      // they all point to the same file and line because we can only provide
      // one location.
      m_udt_declarations.try_emplace(
          udt_mod_src.UDT,
          UdtDeclaration{/*FileNameIndex=*/udt_mod_src.SourceFile,
                         /*IsIpiIndex=*/false,
                         /*Line=*/udt_mod_src.LineNumber});
    } break;
    default:
      break;
    }
  }
}

llvm::Expected<Declaration>
SymbolFileNativePDB::ResolveUdtDeclaration(PdbTypeSymId type_id) {
  std::call_once(m_cached_udt_declarations, [this] { CacheUdtDeclarations(); });

  auto it = m_udt_declarations.find(type_id.index);
  if (it == m_udt_declarations.end())
    return llvm::createStringError("no UDT declaration found");

  llvm::StringRef file_name;
  if (it->second.IsIpiIndex) {
    CVType cvt = m_index->ipi().getType(it->second.FileNameIndex);
    if (cvt.kind() != LF_STRING_ID)
      return llvm::createStringError("file name was not a LF_STRING_ID");

    StringIdRecord sid;
    if (auto err = TypeDeserializer::deserializeAs(cvt, sid))
      return std::move(err);
    file_name = sid.String;
  } else {
    // The file name index is an index into the string table
    auto string_table = m_index->pdb().getStringTable();
    if (!string_table)
      return string_table.takeError();

    llvm::Expected<llvm::StringRef> string =
        string_table->getStringTable().getString(
            it->second.FileNameIndex.getIndex());
    if (!string)
      return string.takeError();
    file_name = *string;
  }

  // rustc sets the filename to "<unknown>" for some files
  if (file_name == "\\<unknown>")
    return Declaration();

  return Declaration(FileSpec(file_name), it->second.Line);
}
