//===-- 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/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.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);
  }
}

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;
    }
    if (block.Parent == 0) {
      LLDB_LOG(GetLog(LLDBLog::Symbols), "BlockSym record ({0}) with parent=0",
               block_id);
      return nullptr;
    }
    PdbCompilandSymId parent_id(block_id.modi, block.Parent);
    Block *parent_block = GetOrCreateBlock(parent_id);
    if (!parent_block)
      return nullptr;
    Function *func = parent_block->CalculateSymbolContextFunction();
    if (!func) {
      LLDB_LOG(GetLog(LLDBLog::Symbols), "parent of {0} is not a function",
               parent_id);
      return nullptr;
    }
    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:
    LLDB_LOG(GetLog(LLDBLog::Symbols), "{0} is not a block", block_id);
    return nullptr;
  }

  return nullptr;
}

lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,
                                                     CompileUnit &comp_unit) {
  const CompilandIndexItem *cci =
      m_index->compilands().GetCompiland(func_id.modi);
  if (!cci) {
    LLDB_LOG(GetLog(LLDBLog::Symbols), "missing compiland {0}", func_id.modi);
    return nullptr;
  }

  CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset);
  if (sym_record.kind() != S_LPROC32 && sym_record.kind() != S_GPROC32) {
    LLDB_LOG(GetLog(LLDBLog::Symbols), "{0} is not a function", func_id);
    return nullptr;
  }

  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 (cvs.kind() != S_CONSTANT)
    return nullptr;

  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);
    LLDB_LOG(GetLog(LLDBLog::Symbols), "failed to create compile unit for {0}",
             cci.m_id.modi);
  }

  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();
  assert(index < UINT16_MAX && "Invalid compile unit index");
  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());
  if (uid.kind() != PdbSymUidKind::Compiland) {
    assert(false && "uid of compile unit not a compiland");
    return lldb::eLanguageTypeUnknown;
  }

  CompilandIndexItem *item =
      m_index->compilands().GetCompiland(uid.asCompiland().modi);
  assert(item);
  if (!item || !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;

  llvm::DenseMap<lldb::addr_t, llvm::SmallVector<uint32_t, 1>> symbols_by_addr;
  for (uint32_t i = 0, n = symtab.GetNumSymbols(); i < n; ++i) {
    Symbol *sym = symtab.SymbolAtIndex(i);
    if (sym && sym->ValueIsAddress())
      symbols_by_addr[sym->GetAddressRef().GetFileAddress()].push_back(i);
  }

  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) {
      if (next->Offset < last_sym.Offset) {
        LLDB_LOG(GetLog(LLDBLog::Symbols),
                 "Ignoring size estimate for '{0}': segment {1} offset {2} is "
                 "greater than the following offset {3}",
                 last_sym.Name, last_sym.Segment, last_sym.Offset,
                 next->Offset);
        return;
      }
      last->SetByteSize(next->Offset - last_sym.Offset);
    } else {
      // the last symbol was the last in its section
      if (section_sp->GetByteSize() < last_sym.Offset) {
        LLDB_LOG(GetLog(LLDBLog::Symbols),
                 "Ignoring size estimate for '{0}': segment {1} offset {2} is "
                 "past the end of section '{3}' (size {4})",
                 last_sym.Name, last_sym.Segment, last_sym.Offset,
                 section_sp->GetName(), section_sp->GetByteSize());
        return;
      }
      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;

    Symbol pub_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);

    auto it = symbols_by_addr.find(pub_symbol.GetAddressRef().GetFileAddress());
    if (it != symbols_by_addr.end() &&
        llvm::any_of(it->second, [&](uint32_t idx) {
          Symbol *sym = symtab.SymbolAtIndex(idx);
          return sym && sym->GetMangled() == pub_symbol.GetMangled();
        }))
      pub_symbol.SetType(lldb::eSymbolTypeAdditional);

    last_sym_idx = symtab.AddSymbol(pub_symbol);
    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()};
  if (uid.kind() != PdbSymUidKind::Compiland) {
    assert(false && "uid of compile unit not a compiland");
    return 0;
  }
  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();
  if (new_count < count) {
    assert(false && "less functions after parsing than before");
    return 0;
  }
  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) {
    if (!sc.comp_unit) {
      LLDB_LOG(GetLog(LLDBLog::Symbols),
               "missing compile unit for symbol at address {0:x}", file_addr);
      return 0;
    }
    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) {
    if (!sc.comp_unit) {
      LLDB_LOG(GetLog(LLDBLog::Symbols),
               "missing compile unit for symbol at address {0:x}", file_addr);
      return 0;
    }
    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());
  if (cu_id.kind() != PdbSymUidKind::Compiland) {
    assert(false && "uid of compile unit not a compiland");
    return false;
  }
  uint16_t modi = cu_id.asCompiland().modi;
  CompilandIndexItem *cii = m_index->compilands().GetCompiland(modi);
  if (!cii) {
    LLDB_LOG(GetLog(LLDBLog::Symbols), "missing compiland for modi={0}", modi);
    return false;
  }

  // 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();
      if (group.LineNumbers.empty()) {
        LLDB_LOG(GetLog(LLDBLog::Symbols),
                 "no line numbers for {0} in modi={1}", group.NameIndex, modi);
        continue;
      }
      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());
  if (cu_id.kind() != PdbSymUidKind::Compiland) {
    assert(false && "uid of compile unit not a compiland");
    return false;
  }
  CompilandIndexItem *cci =
      m_index->compilands().GetCompiland(cu_id.asCompiland().modi);
  if (!cci) {
    LLDB_LOG(GetLog(LLDBLog::Symbols), "missing compiland for modi={0}",
             cu_id.asCompiland().modi);
    return false;
  }

  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);
  if (sym.kind() != S_INLINESITE)
    return;

  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();
      if (kind != S_PROCREF && kind != S_LPROCREF) {
        LLDB_LOG(GetLog(LLDBLog::Symbols), "{0} is not a proc reference",
                 global);
        continue;
      }

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

  BuildParentMap();

  // 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) {
  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);
    if (sym.kind() != S_CONSTANT)
      return nullptr;
    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);
  if (sym.kind() != S_UDT) {
    LLDB_LOG(GetLog(LLDBLog::Symbols), "{0} is not an S_UDT", id);
    return nullptr;
  }

  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:
    LLDB_LOG(GetLog(LLDBLog::Symbols), "{0} is not a block", block_id);
    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());

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

  LLDB_LOG(GetLog(LLDBLog::Symbols),
           "missing missing block, function, or module for symbol context");
  return 0;
}

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);
  if (uid.kind() != PdbSymUidKind::Type) {
    assert(false && "uid is not a type index");
    return nullptr;
  }
  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() {
  if (m_parent_map_built)
    return;
  m_parent_map_built = true;

  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);
    if (field_list_cvt.kind() != LF_FIELDLIST)
      continue; // Invalid reference to a field list.

    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.
      LLDB_LOG(GetLog(LLDBLog::Symbols), "invalid compiland symbol id: {0}",
               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) {
  BuildParentMap();
  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);
}
