#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"

#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h"
#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
#include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h"
#include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
#include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.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/PDBSymbol.h"
#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"

using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::pdb;

// Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
// to instantiate a NativeBuiltinSymbol for that type.
static const struct BuiltinTypeEntry {
  codeview::SimpleTypeKind Kind;
  PDB_BuiltinType Type;
  uint32_t Size;
} BuiltinTypes[] = {
    {codeview::SimpleTypeKind::None, PDB_BuiltinType::None, 0},
    {codeview::SimpleTypeKind::Void, PDB_BuiltinType::Void, 0},
    {codeview::SimpleTypeKind::HResult, PDB_BuiltinType::HResult, 4},
    {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
    {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
    {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
    {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
    {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
    {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
    {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
    {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
    {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
    {codeview::SimpleTypeKind::WideCharacter, PDB_BuiltinType::WCharT, 2},
    {codeview::SimpleTypeKind::Character16, PDB_BuiltinType::Char16, 2},
    {codeview::SimpleTypeKind::Character32, PDB_BuiltinType::Char32, 4},
    {codeview::SimpleTypeKind::Character8, PDB_BuiltinType::Char8, 1},
    {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
    {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
    {codeview::SimpleTypeKind::Float32, PDB_BuiltinType::Float, 4},
    {codeview::SimpleTypeKind::Float64, PDB_BuiltinType::Float, 8},
    {codeview::SimpleTypeKind::Float80, PDB_BuiltinType::Float, 10},
    {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1},
    // This table can be grown as necessary, but these are the only types we've
    // needed so far.
};

SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
    : Session(Session), Dbi(Dbi) {
  // Id 0 is reserved for the invalid symbol.
  Cache.push_back(nullptr);
  SourceFiles.push_back(nullptr);

  if (Dbi)
    Compilands.resize(Dbi->modules().getModuleCount());
}

std::unique_ptr<IPDBEnumSymbols>
SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
  return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
}

std::unique_ptr<IPDBEnumSymbols>
SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
  auto Tpi = Session.getPDBFile().getPDBTpiStream();
  if (!Tpi) {
    consumeError(Tpi.takeError());
    return nullptr;
  }
  auto &Types = Tpi->typeCollection();
  return std::unique_ptr<IPDBEnumSymbols>(
      new NativeEnumTypes(Session, Types, std::move(Kinds)));
}

std::unique_ptr<IPDBEnumSymbols>
SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {
  return std::unique_ptr<IPDBEnumSymbols>(
      new NativeEnumGlobals(Session, {Kind}));
}

SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
                                         ModifierOptions Mods) const {
  if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
    return createSymbol<NativeTypePointer>(Index);

  const auto Kind = Index.getSimpleKind();
  const auto It =
      llvm::find_if(BuiltinTypes, [Kind](const BuiltinTypeEntry &Builtin) {
        return Builtin.Kind == Kind;
      });
  if (It == std::end(BuiltinTypes))
    return 0;
  return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
}

SymIndexId
SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
                                         codeview::CVType CVT) const {
  ModifierRecord Record;
  if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
    consumeError(std::move(EC));
    return 0;
  }

  if (Record.ModifiedType.isSimple())
    return createSimpleType(Record.ModifiedType, Record.Modifiers);

  // Make sure we create and cache a record for the unmodified type.
  SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
  NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];

  switch (UnmodifiedNRS.getSymTag()) {
  case PDB_SymType::Enum:
    return createSymbol<NativeTypeEnum>(
        static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));
  case PDB_SymType::UDT:
    return createSymbol<NativeTypeUDT>(
        static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record));
  default:
    // No other types can be modified.  (LF_POINTER, for example, records
    // its modifiers a different way.
    assert(false && "Invalid LF_MODIFIER record");
    break;
  }
  return 0;
}

SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) const {
  // First see if it's already in our cache.
  const auto Entry = TypeIndexToSymbolId.find(Index);
  if (Entry != TypeIndexToSymbolId.end())
    return Entry->second;

  // Symbols for built-in types are created on the fly.
  if (Index.isSimple()) {
    SymIndexId Result = createSimpleType(Index, ModifierOptions::None);
    assert(TypeIndexToSymbolId.count(Index) == 0);
    TypeIndexToSymbolId[Index] = Result;
    return Result;
  }

  // We need to instantiate and cache the desired type symbol.
  auto Tpi = Session.getPDBFile().getPDBTpiStream();
  if (!Tpi) {
    consumeError(Tpi.takeError());
    return 0;
  }
  codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
  codeview::CVType CVT = Types.getType(Index);

  if (isUdtForwardRef(CVT)) {
    Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index);

    if (!EFD)
      consumeError(EFD.takeError());
    else if (*EFD != Index) {
      assert(!isUdtForwardRef(Types.getType(*EFD)));
      SymIndexId Result = findSymbolByTypeIndex(*EFD);
      // Record a mapping from ForwardRef -> SymIndex of complete type so that
      // we'll take the fast path next time.
      assert(TypeIndexToSymbolId.count(Index) == 0);
      TypeIndexToSymbolId[Index] = Result;
      return Result;
    }
  }

  // At this point if we still have a forward ref udt it means the full decl was
  // not in the PDB.  We just have to deal with it and use the forward ref.
  SymIndexId Id = 0;
  switch (CVT.kind()) {
  case codeview::LF_ENUM:
    Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
    break;
  case codeview::LF_ARRAY:
    Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,
                                                           std::move(CVT));
    break;
  case codeview::LF_CLASS:
  case codeview::LF_STRUCTURE:
  case codeview::LF_INTERFACE:
    Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
    break;
  case codeview::LF_UNION:
    Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
    break;
  case codeview::LF_POINTER:
    Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
                                                               std::move(CVT));
    break;
  case codeview::LF_MODIFIER:
    Id = createSymbolForModifiedType(Index, std::move(CVT));
    break;
  case codeview::LF_PROCEDURE:
    Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
        Index, std::move(CVT));
    break;
  case codeview::LF_MFUNCTION:
    Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
        Index, std::move(CVT));
    break;
  case codeview::LF_VTSHAPE:
    Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
        Index, std::move(CVT));
    break;
  default:
    Id = createSymbolPlaceholder();
    break;
  }
  if (Id != 0) {
    assert(TypeIndexToSymbolId.count(Index) == 0);
    TypeIndexToSymbolId[Index] = Id;
  }
  return Id;
}

std::unique_ptr<PDBSymbol>
SymbolCache::getSymbolById(SymIndexId SymbolId) const {
  assert(SymbolId < Cache.size());

  // Id 0 is reserved.
  if (SymbolId == 0 || SymbolId >= Cache.size())
    return nullptr;

  // Make sure to handle the case where we've inserted a placeholder symbol
  // for types we don't yet support.
  NativeRawSymbol *NRS = Cache[SymbolId].get();
  if (!NRS)
    return nullptr;

  return PDBSymbol::create(Session, *NRS);
}

NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
  return *Cache[SymbolId];
}

uint32_t SymbolCache::getNumCompilands() const {
  if (!Dbi)
    return 0;

  return Dbi->modules().getModuleCount();
}

SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
  auto Iter = GlobalOffsetToSymbolId.find(Offset);
  if (Iter != GlobalOffsetToSymbolId.end())
    return Iter->second;

  SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());
  CVSymbol CVS = SS.readRecord(Offset);
  SymIndexId Id = 0;
  switch (CVS.kind()) {
  case SymbolKind::S_UDT: {
    UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));
    Id = createSymbol<NativeTypeTypedef>(std::move(US));
    break;
  }
  default:
    Id = createSymbolPlaceholder();
    break;
  }
  if (Id != 0) {
    assert(GlobalOffsetToSymbolId.count(Offset) == 0);
    GlobalOffsetToSymbolId[Offset] = Id;
  }

  return Id;
}

SymIndexId SymbolCache::getOrCreateInlineSymbol(InlineSiteSym Sym,
                                                uint64_t ParentAddr,
                                                uint16_t Modi,
                                                uint32_t RecordOffset) const {
  auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset});
  if (Iter != SymTabOffsetToSymbolId.end())
    return Iter->second;

  SymIndexId Id = createSymbol<NativeInlineSiteSymbol>(Sym, ParentAddr);
  SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id});
  return Id;
}

std::unique_ptr<PDBSymbol>
SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
                                    PDB_SymType Type) {
  switch (Type) {
  case PDB_SymType::Function:
    return findFunctionSymbolBySectOffset(Sect, Offset);
  case PDB_SymType::PublicSymbol:
    return findPublicSymbolBySectOffset(Sect, Offset);
  case PDB_SymType::Compiland: {
    uint16_t Modi;
    if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
      return nullptr;
    return getOrCreateCompiland(Modi);
  }
  case PDB_SymType::None: {
    // FIXME: Implement for PDB_SymType::Data. The symbolizer calls this but
    // only uses it to find the symbol length.
    if (auto Sym = findFunctionSymbolBySectOffset(Sect, Offset))
      return Sym;
    return nullptr;
  }
  default:
    return nullptr;
  }
}

std::unique_ptr<PDBSymbol>
SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
  auto Iter = AddressToSymbolId.find({Sect, Offset});
  if (Iter != AddressToSymbolId.end())
    return getSymbolById(Iter->second);

  if (!Dbi)
    return nullptr;

  uint16_t Modi;
  if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
    return nullptr;

  Expected<ModuleDebugStreamRef> ExpectedModS =
      Session.getModuleDebugStream(Modi);
  if (!ExpectedModS) {
    consumeError(ExpectedModS.takeError());
    return nullptr;
  }
  CVSymbolArray Syms = ExpectedModS->getSymbolArray();

  // Search for the symbol in this module.
  for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) {
    if (I->kind() != S_LPROC32 && I->kind() != S_GPROC32)
      continue;
    auto PS = cantFail(SymbolDeserializer::deserializeAs<ProcSym>(*I));
    if (Sect == PS.Segment && Offset >= PS.CodeOffset &&
        Offset < PS.CodeOffset + PS.CodeSize) {
      // Check if the symbol is already cached.
      auto Found = AddressToSymbolId.find({PS.Segment, PS.CodeOffset});
      if (Found != AddressToSymbolId.end())
        return getSymbolById(Found->second);

      // Otherwise, create a new symbol.
      SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS, I.offset());
      AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset}, Id});
      return getSymbolById(Id);
    }

    // Jump to the end of this ProcSym.
    I = Syms.at(PS.End);
  }
  return nullptr;
}

std::unique_ptr<PDBSymbol>
SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
  auto Iter = AddressToPublicSymId.find({Sect, Offset});
  if (Iter != AddressToPublicSymId.end())
    return getSymbolById(Iter->second);

  auto Publics = Session.getPDBFile().getPDBPublicsStream();
  if (!Publics)
    return nullptr;

  auto ExpectedSyms = Session.getPDBFile().getPDBSymbolStream();
  if (!ExpectedSyms)
    return nullptr;
  BinaryStreamRef SymStream =
      ExpectedSyms->getSymbolArray().getUnderlyingStream();

  // Use binary search to find the first public symbol with an address greater
  // than or equal to Sect, Offset.
  auto AddrMap = Publics->getAddressMap();
  auto First = AddrMap.begin();
  auto It = AddrMap.begin();
  size_t Count = AddrMap.size();
  size_t Half;
  while (Count > 0) {
    It = First;
    Half = Count / 2;
    It += Half;
    Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
    if (!Sym) {
      consumeError(Sym.takeError());
      return nullptr;
    }

    auto PS =
        cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
    if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <= Offset)) {
      First = ++It;
      Count -= Half + 1;
    } else
      Count = Half;
  }
  if (It == AddrMap.begin())
    return nullptr;
  --It;

  Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
  if (!Sym) {
    consumeError(Sym.takeError());
    return nullptr;
  }

  // Check if the symbol is already cached.
  auto PS = cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
  auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset});
  if (Found != AddressToPublicSymId.end())
    return getSymbolById(Found->second);

  // Otherwise, create a new symbol.
  SymIndexId Id = createSymbol<NativePublicSymbol>(PS);
  AddressToPublicSymId.insert({{PS.Segment, PS.Offset}, Id});
  return getSymbolById(Id);
}

std::vector<SymbolCache::LineTableEntry>
SymbolCache::findLineTable(uint16_t Modi) const {
  // Check if this module has already been added.
  auto [LineTableIter, Inserted] = LineTable.try_emplace(Modi);
  if (!Inserted)
    return LineTableIter->second;

  std::vector<LineTableEntry> &ModuleLineTable = LineTableIter->second;

  // If there is an error or there are no lines, just return the
  // empty vector.
  Expected<ModuleDebugStreamRef> ExpectedModS =
      Session.getModuleDebugStream(Modi);
  if (!ExpectedModS) {
    consumeError(ExpectedModS.takeError());
    return ModuleLineTable;
  }

  std::vector<std::vector<LineTableEntry>> EntryList;
  for (const auto &SS : ExpectedModS->getSubsectionsArray()) {
    if (SS.kind() != DebugSubsectionKind::Lines)
      continue;

    DebugLinesSubsectionRef Lines;
    BinaryStreamReader Reader(SS.getRecordData());
    if (auto EC = Lines.initialize(Reader)) {
      consumeError(std::move(EC));
      continue;
    }

    uint32_t RelocSegment = Lines.header()->RelocSegment;
    uint32_t RelocOffset = Lines.header()->RelocOffset;
    for (const LineColumnEntry &Group : Lines) {
      if (Group.LineNumbers.empty())
        continue;

      std::vector<LineTableEntry> Entries;

      // If there are column numbers, then they should be in a parallel stream
      // to the line numbers.
      auto ColIt = Group.Columns.begin();
      auto ColsEnd = Group.Columns.end();

      // Add a line to mark the beginning of this section.
      uint64_t StartAddr =
          Session.getVAFromSectOffset(RelocSegment, RelocOffset);
      LineInfo FirstLine(Group.LineNumbers.front().Flags);
      uint32_t ColNum =
          (Lines.hasColumnInfo()) ? Group.Columns.front().StartColumn : 0;
      Entries.push_back({StartAddr, FirstLine, ColNum, Group.NameIndex, false});

      for (const LineNumberEntry &LN : Group.LineNumbers) {
        uint64_t VA =
            Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.Offset);
        LineInfo Line(LN.Flags);
        ColNum = 0;

        if (Lines.hasColumnInfo() && ColIt != ColsEnd) {
          ColNum = ColIt->StartColumn;
          ++ColIt;
        }
        Entries.push_back({VA, Line, ColNum, Group.NameIndex, false});
      }

      // Add a terminal entry line to mark the end of this subsection.
      uint64_t EndAddr = StartAddr + Lines.header()->CodeSize;
      LineInfo LastLine(Group.LineNumbers.back().Flags);
      ColNum = (Lines.hasColumnInfo()) ? Group.Columns.back().StartColumn : 0;
      Entries.push_back({EndAddr, LastLine, ColNum, Group.NameIndex, true});

      EntryList.push_back(Entries);
    }
  }

  // Sort EntryList, and add flattened contents to the line table.
  llvm::sort(EntryList, [](const std::vector<LineTableEntry> &LHS,
                           const std::vector<LineTableEntry> &RHS) {
    return LHS[0].Addr < RHS[0].Addr;
  });
  for (std::vector<LineTableEntry> &I : EntryList)
    llvm::append_range(ModuleLineTable, I);

  return ModuleLineTable;
}

std::unique_ptr<IPDBEnumLineNumbers>
SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
  uint16_t Modi;
  if (!Session.moduleIndexForVA(VA, Modi))
    return nullptr;

  std::vector<LineTableEntry> Lines = findLineTable(Modi);
  if (Lines.empty())
    return nullptr;

  // Find the first line in the line table whose address is not greater than
  // the one we are searching for.
  auto LineIter = llvm::partition_point(Lines, [&](const LineTableEntry &E) {
    return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry));
  });

  // Try to back up if we've gone too far.
  if (LineIter == Lines.end() || LineIter->Addr > VA) {
    if (LineIter == Lines.begin() || std::prev(LineIter)->IsTerminalEntry)
      return nullptr;
    --LineIter;
  }

  Expected<ModuleDebugStreamRef> ExpectedModS =
      Session.getModuleDebugStream(Modi);
  if (!ExpectedModS) {
    consumeError(ExpectedModS.takeError());
    return nullptr;
  }
  Expected<DebugChecksumsSubsectionRef> ExpectedChecksums =
      ExpectedModS->findChecksumsSubsection();
  if (!ExpectedChecksums) {
    consumeError(ExpectedChecksums.takeError());
    return nullptr;
  }

  // Populate a vector of NativeLineNumbers that have addresses in the given
  // address range.
  std::vector<NativeLineNumber> LineNumbers;
  while (LineIter != Lines.end()) {
    if (LineIter->IsTerminalEntry) {
      ++LineIter;
      continue;
    }

    // If the line is still within the address range, create a NativeLineNumber
    // and add to the list.
    if (LineIter->Addr > VA + Length)
      break;

    uint32_t LineSect, LineOff;
    Session.addressForVA(LineIter->Addr, LineSect, LineOff);
    uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr;
    auto ChecksumIter =
        ExpectedChecksums->getArray().at(LineIter->FileNameIndex);
    uint32_t SrcFileId = getOrCreateSourceFile(*ChecksumIter);
    NativeLineNumber LineNum(Session, LineIter->Line, LineIter->ColumnNumber,
                             LineSect, LineOff, LineLength, SrcFileId, Modi);
    LineNumbers.push_back(LineNum);
    ++LineIter;
  }
  return std::make_unique<NativeEnumLineNumbers>(std::move(LineNumbers));
}

std::unique_ptr<PDBSymbolCompiland>
SymbolCache::getOrCreateCompiland(uint32_t Index) {
  if (!Dbi)
    return nullptr;

  if (Index >= Compilands.size())
    return nullptr;

  if (Compilands[Index] == 0) {
    const DbiModuleList &Modules = Dbi->modules();
    Compilands[Index] =
        createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
  }

  return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
}

std::unique_ptr<IPDBSourceFile>
SymbolCache::getSourceFileById(SymIndexId FileId) const {
  assert(FileId < SourceFiles.size());

  // Id 0 is reserved.
  if (FileId == 0)
    return nullptr;

  return std::make_unique<NativeSourceFile>(*SourceFiles[FileId].get());
}

SymIndexId
SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const {
  auto Iter = FileNameOffsetToId.find(Checksums.FileNameOffset);
  if (Iter != FileNameOffsetToId.end())
    return Iter->second;

  SymIndexId Id = SourceFiles.size();
  auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums);
  SourceFiles.push_back(std::move(SrcFile));
  FileNameOffsetToId[Checksums.FileNameOffset] = Id;
  return Id;
}


