//===- TypeReferenceTracker.cpp ------------------------------- *- C++ --*-===//
//
// 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 "TypeReferenceTracker.h"

#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"

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

// LazyRandomTypeCollection doesn't appear to expose the number of records, so
// just iterate up front to find out.
static uint32_t getNumRecordsInCollection(LazyRandomTypeCollection &Types) {
  uint32_t NumTypes = 0;
  for (Optional<TypeIndex> TI = Types.getFirst(); TI; TI = Types.getNext(*TI))
    ++NumTypes;
  return NumTypes;
}

TypeReferenceTracker::TypeReferenceTracker(InputFile &File)
    : File(File), Types(File.types()),
      Ids(File.isPdb() ? &File.ids() : nullptr) {
  NumTypeRecords = getNumRecordsInCollection(Types);
  TypeReferenced.resize(NumTypeRecords, false);

  // If this is a PDB, ids are stored separately, so make a separate bit vector.
  if (Ids) {
    NumIdRecords = getNumRecordsInCollection(*Ids);
    IdReferenced.resize(NumIdRecords, false);
  }

  // Get the TpiStream pointer for forward decl resolution if this is a pdb.
  // Build the hash map to enable resolving forward decls.
  if (File.isPdb()) {
    Tpi = &cantFail(File.pdb().getPDBTpiStream());
    Tpi->buildHashMap();
  }
}

void TypeReferenceTracker::mark() {
  // Walk type roots:
  // - globals
  // - modi symbols
  // - LF_UDT_MOD_SRC_LINE? VC always links these in.
  for (SymbolGroup SG : File.symbol_groups()) {
    if (File.isObj()) {
      for (const auto &SS : SG.getDebugSubsections()) {
        // FIXME: Are there other type-referencing subsections? Inlinees?
        // Probably for IDs.
        if (SS.kind() != DebugSubsectionKind::Symbols)
          continue;

        CVSymbolArray Symbols;
        BinaryStreamReader Reader(SS.getRecordData());
        cantFail(Reader.readArray(Symbols, Reader.getLength()));
        for (const CVSymbol &S : Symbols)
          addTypeRefsFromSymbol(S);
      }
    } else if (SG.hasDebugStream()) {
      for (const CVSymbol &S : SG.getPdbModuleStream().getSymbolArray())
        addTypeRefsFromSymbol(S);
    }
  }

  // Walk globals and mark types referenced from globals.
  if (File.isPdb() && File.pdb().hasPDBGlobalsStream()) {
    SymbolStream &SymStream = cantFail(File.pdb().getPDBSymbolStream());
    GlobalsStream &GS = cantFail(File.pdb().getPDBGlobalsStream());
    for (uint32_t PubSymOff : GS.getGlobalsTable()) {
      CVSymbol Sym = SymStream.readRecord(PubSymOff);
      addTypeRefsFromSymbol(Sym);
    }
  }

  // FIXME: Should we walk Ids?
}

void TypeReferenceTracker::addOneTypeRef(TiRefKind RefKind, TypeIndex RefTI) {
  // If it's simple or already seen, no need to add to work list.
  BitVector &TypeOrIdReferenced =
      (Ids && RefKind == TiRefKind::IndexRef) ? IdReferenced : TypeReferenced;
  if (RefTI.isSimple() || TypeOrIdReferenced.test(RefTI.toArrayIndex()))
    return;

  // Otherwise, mark it seen and add it to the work list.
  TypeOrIdReferenced.set(RefTI.toArrayIndex());
  RefWorklist.push_back({RefKind, RefTI});
}

void TypeReferenceTracker::addTypeRefsFromSymbol(const CVSymbol &Sym) {
  SmallVector<TiReference, 4> DepList;
  // FIXME: Check for failure.
  discoverTypeIndicesInSymbol(Sym, DepList);
  addReferencedTypes(Sym.content(), DepList);
  markReferencedTypes();
}

void TypeReferenceTracker::addReferencedTypes(ArrayRef<uint8_t> RecData,
                                              ArrayRef<TiReference> DepList) {
  for (const auto &Ref : DepList) {
    // FIXME: Report OOB slice instead of truncating.
    ArrayRef<uint8_t> ByteSlice =
        RecData.drop_front(Ref.Offset).take_front(4 * Ref.Count);
    ArrayRef<TypeIndex> TIs(
        reinterpret_cast<const TypeIndex *>(ByteSlice.data()),
        ByteSlice.size() / 4);

    // If this is a PDB and this is an item reference, track it in the IPI
    // bitvector. Otherwise, it's a type ref, or there is only one stream.
    for (TypeIndex RefTI : TIs)
      addOneTypeRef(Ref.Kind, RefTI);
  }
}

void TypeReferenceTracker::markReferencedTypes() {
  while (!RefWorklist.empty()) {
    TiRefKind RefKind;
    TypeIndex RefTI;
    std::tie(RefKind, RefTI) = RefWorklist.pop_back_val();
    Optional<CVType> Rec = (Ids && RefKind == TiRefKind::IndexRef)
                               ? Ids->tryGetType(RefTI)
                               : Types.tryGetType(RefTI);
    if (!Rec)
      continue; // FIXME: Report a reference to a non-existant type.

    SmallVector<TiReference, 4> DepList;
    // FIXME: Check for failure.
    discoverTypeIndices(*Rec, DepList);
    addReferencedTypes(Rec->content(), DepList);

    // If this is a tag kind and this is a PDB input, mark the complete type as
    // referenced.
    // FIXME: This limitation makes this feature somewhat useless on object file
    // inputs.
    if (Tpi) {
      switch (Rec->kind()) {
      default:
        break;
      case LF_CLASS:
      case LF_INTERFACE:
      case LF_STRUCTURE:
      case LF_UNION:
      case LF_ENUM:
        addOneTypeRef(TiRefKind::TypeRef,
                      cantFail(Tpi->findFullDeclForForwardRef(RefTI)));
        break;
      }
    }
  }
}
