Example #1
0
std::pair<uint64_t, uint64_t> InstrProfWriter::writeImpl(raw_ostream &OS) {
  OnDiskChainedHashTableGenerator<InstrProfRecordTrait> Generator;

  // Populate the hash table generator.
  for (const auto &I : FunctionData)
    Generator.insert(I.getKey(), &I.getValue());

  using namespace llvm::support;
  endian::Writer<little> LE(OS);

  // Write the header.
  IndexedInstrProf::Header Header;
  Header.Magic = IndexedInstrProf::Magic;
  Header.Version = IndexedInstrProf::Version;
  Header.MaxFunctionCount = MaxFunctionCount;
  Header.HashType = static_cast<uint64_t>(IndexedInstrProf::HashType);
  Header.HashOffset = 0;
  int N = sizeof(IndexedInstrProf::Header) / sizeof(uint64_t);

  // Only write out all the fields execpt 'HashOffset'. We need
  // to remember the offset of that field to allow back patching
  // later.
  for (int I = 0; I < N - 1; I++)
    LE.write<uint64_t>(reinterpret_cast<uint64_t *>(&Header)[I]);

  // Save a space to write the hash table start location.
  uint64_t HashTableStartLoc = OS.tell();
  // Reserve the space for HashOffset field.
  LE.write<uint64_t>(0);
  // Write the hash table.
  uint64_t HashTableStart = Generator.Emit(OS);

  return std::make_pair(HashTableStartLoc, HashTableStart);
}
Example #2
0
/// EmitIdentifierTable - Emits two tables to the PTH file.  The first is
///  a hashtable mapping from identifier strings to persistent IDs.  The second
///  is a straight table mapping from persistent IDs to string data (the
///  keys of the first table).
///
std::pair<Offset,Offset> PTHWriter::EmitIdentifierTable() {
  // Build two maps:
  //  (1) an inverse map from persistent IDs -> (IdentifierInfo*,Offset)
  //  (2) a map from (IdentifierInfo*, Offset)* -> persistent IDs

  // Note that we use 'calloc', so all the bytes are 0.
  PTHIdKey *IIDMap = (PTHIdKey*)calloc(idcount, sizeof(PTHIdKey));

  // Create the hashtable.
  OnDiskChainedHashTableGenerator<PTHIdentifierTableTrait> IIOffMap;

  // Generate mapping from persistent IDs -> IdentifierInfo*.
  for (IDMap::iterator I = IM.begin(), E = IM.end(); I != E; ++I) {
    // Decrement by 1 because we are using a vector for the lookup and
    // 0 is reserved for NULL.
    assert(I->second > 0);
    assert(I->second-1 < idcount);
    unsigned idx = I->second-1;

    // Store the mapping from persistent ID to IdentifierInfo*
    IIDMap[idx].II = I->first;

    // Store the reverse mapping in a hashtable.
    IIOffMap.insert(&IIDMap[idx], I->second);
  }

  // Write out the inverse map first.  This causes the PCIDKey entries to
  // record PTH file offsets for the string data.  This is used to write
  // the second table.
  Offset StringTableOffset = IIOffMap.Emit(Out);

  // Now emit the table mapping from persistent IDs to PTH file offsets.
  Offset IDOff = Out.tell();
  Emit32(idcount);  // Emit the number of identifiers.
  for (unsigned i = 0 ; i < idcount; ++i)
    Emit32(IIDMap[i].FileOffset);

  // Finally, release the inverse map.
  free(IIDMap);

  return std::make_pair(IDOff, StringTableOffset);
}
Example #3
0
std::pair<uint64_t, uint64_t> InstrProfWriter::writeImpl(raw_ostream &OS) {
  OnDiskChainedHashTableGenerator<InstrProfRecordTrait> Generator;

  // Populate the hash table generator.
  for (const auto &I : FunctionData)
    Generator.insert(I.getKey(), &I.getValue());

  using namespace llvm::support;
  endian::Writer<little> LE(OS);

  // Write the header.
  LE.write<uint64_t>(IndexedInstrProf::Magic);
  LE.write<uint64_t>(IndexedInstrProf::Version);
  LE.write<uint64_t>(MaxFunctionCount);
  LE.write<uint64_t>(static_cast<uint64_t>(IndexedInstrProf::HashType));

  // Save a space to write the hash table start location.
  uint64_t HashTableStartLoc = OS.tell();
  LE.write<uint64_t>(0);
  // Write the hash table.
  uint64_t HashTableStart = Generator.Emit(OS);

  return std::make_pair(HashTableStartLoc, HashTableStart);
}
Example #4
0
void GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {
  using namespace llvm;
  
  // Emit the file header.
  Stream.Emit((unsigned)'B', 8);
  Stream.Emit((unsigned)'C', 8);
  Stream.Emit((unsigned)'G', 8);
  Stream.Emit((unsigned)'I', 8);

  // Write the block-info block, which describes the records in this bitcode
  // file.
  emitBlockInfoBlock(Stream);

  Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3);

  // Write the metadata.
  SmallVector<uint64_t, 2> Record;
  Record.push_back(CurrentVersion);
  Stream.EmitRecord(INDEX_METADATA, Record);

  // Write the set of known module files.
  for (ModuleFilesMap::iterator M = ModuleFiles.begin(),
                                MEnd = ModuleFiles.end();
       M != MEnd; ++M) {
    Record.clear();
    Record.push_back(M->second.ID);
    Record.push_back(M->first->getSize());
    Record.push_back(M->first->getModificationTime());

    // File name
    StringRef Name(M->first->getName());
    Record.push_back(Name.size());
    Record.append(Name.begin(), Name.end());

    // Dependencies
    Record.push_back(M->second.Dependencies.size());
    Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end());
    Stream.EmitRecord(MODULE, Record);
  }

  // Write the identifier -> module file mapping.
  {
    OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator;
    IdentifierIndexWriterTrait Trait;

    // Populate the hash table.
    for (InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(),
                                            IEnd = InterestingIdentifiers.end();
         I != IEnd; ++I) {
      Generator.insert(I->first(), I->second, Trait);
    }
    
    // Create the on-disk hash table in a buffer.
    SmallString<4096> IdentifierTable;
    uint32_t BucketOffset;
    {
      llvm::raw_svector_ostream Out(IdentifierTable);
      // Make sure that no bucket is at offset 0
      clang::io::Emit32(Out, 0);
      BucketOffset = Generator.Emit(Out, Trait);
    }

    // Create a blob abbreviation
    BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
    Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
    unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev);

    // Write the identifier table
    Record.clear();
    Record.push_back(IDENTIFIER_INDEX);
    Record.push_back(BucketOffset);
    Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str());
  }

  // FIXME: Selectors.

  Stream.ExitBlock();
}
Example #5
0
void InstrProfWriter::writeImpl(ProfOStream &OS) {
  using namespace IndexedInstrProf;

  OnDiskChainedHashTableGenerator<InstrProfRecordWriterTrait> Generator;

  InstrProfSummaryBuilder ISB(ProfileSummaryBuilder::DefaultCutoffs);
  InfoObj->SummaryBuilder = &ISB;
  InstrProfSummaryBuilder CSISB(ProfileSummaryBuilder::DefaultCutoffs);
  InfoObj->CSSummaryBuilder = &CSISB;

  // Populate the hash table generator.
  for (const auto &I : FunctionData)
    if (shouldEncodeData(I.getValue()))
      Generator.insert(I.getKey(), &I.getValue());
  // Write the header.
  IndexedInstrProf::Header Header;
  Header.Magic = IndexedInstrProf::Magic;
  Header.Version = IndexedInstrProf::ProfVersion::CurrentVersion;
  if (ProfileKind == PF_IRLevel)
    Header.Version |= VARIANT_MASK_IR_PROF;
  if (ProfileKind == PF_IRLevelWithCS) {
    Header.Version |= VARIANT_MASK_IR_PROF;
    Header.Version |= VARIANT_MASK_CSIR_PROF;
  }
  Header.Unused = 0;
  Header.HashType = static_cast<uint64_t>(IndexedInstrProf::HashType);
  Header.HashOffset = 0;
  int N = sizeof(IndexedInstrProf::Header) / sizeof(uint64_t);

  // Only write out all the fields except 'HashOffset'. We need
  // to remember the offset of that field to allow back patching
  // later.
  for (int I = 0; I < N - 1; I++)
    OS.write(reinterpret_cast<uint64_t *>(&Header)[I]);

  // Save the location of Header.HashOffset field in \c OS.
  uint64_t HashTableStartFieldOffset = OS.tell();
  // Reserve the space for HashOffset field.
  OS.write(0);

  // Reserve space to write profile summary data.
  uint32_t NumEntries = ProfileSummaryBuilder::DefaultCutoffs.size();
  uint32_t SummarySize = Summary::getSize(Summary::NumKinds, NumEntries);
  // Remember the summary offset.
  uint64_t SummaryOffset = OS.tell();
  for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
    OS.write(0);
  uint64_t CSSummaryOffset = 0;
  uint64_t CSSummarySize = 0;
  if (ProfileKind == PF_IRLevelWithCS) {
    CSSummaryOffset = OS.tell();
    CSSummarySize = SummarySize / sizeof(uint64_t);
    for (unsigned I = 0; I < CSSummarySize; I++)
      OS.write(0);
  }

  // Write the hash table.
  uint64_t HashTableStart = Generator.Emit(OS.OS, *InfoObj);

  // Allocate space for data to be serialized out.
  std::unique_ptr<IndexedInstrProf::Summary> TheSummary =
      IndexedInstrProf::allocSummary(SummarySize);
  // Compute the Summary and copy the data to the data
  // structure to be serialized out (to disk or buffer).
  std::unique_ptr<ProfileSummary> PS = ISB.getSummary();
  setSummary(TheSummary.get(), *PS);
  InfoObj->SummaryBuilder = nullptr;

  // For Context Sensitive summary.
  std::unique_ptr<IndexedInstrProf::Summary> TheCSSummary = nullptr;
  if (ProfileKind == PF_IRLevelWithCS) {
    TheCSSummary = IndexedInstrProf::allocSummary(SummarySize);
    std::unique_ptr<ProfileSummary> CSPS = CSISB.getSummary();
    setSummary(TheCSSummary.get(), *CSPS);
  }
  InfoObj->CSSummaryBuilder = nullptr;

  // Now do the final patch:
  PatchItem PatchItems[] = {
      // Patch the Header.HashOffset field.
      {HashTableStartFieldOffset, &HashTableStart, 1},
      // Patch the summary data.
      {SummaryOffset, reinterpret_cast<uint64_t *>(TheSummary.get()),
       (int)(SummarySize / sizeof(uint64_t))},
      {CSSummaryOffset, reinterpret_cast<uint64_t *>(TheCSSummary.get()),
       (int)CSSummarySize}};

  OS.patch(PatchItems, sizeof(PatchItems) / sizeof(*PatchItems));
}
Example #6
0
void InstrProfWriter::writeImpl(ProfOStream &OS) {
  OnDiskChainedHashTableGenerator<InstrProfRecordWriterTrait> Generator;

  using namespace IndexedInstrProf;
  std::vector<uint32_t> Cutoffs(&SummaryCutoffs[0],
                                &SummaryCutoffs[NumSummaryCutoffs]);
  ProfileSummary PS(Cutoffs);
  InfoObj->TheProfileSummary = &PS;

  // Populate the hash table generator.
  for (const auto &I : FunctionData)
    if (shouldEncodeData(I.getValue()))
      Generator.insert(I.getKey(), &I.getValue());
  // Write the header.
  IndexedInstrProf::Header Header;
  Header.Magic = IndexedInstrProf::Magic;
  Header.Version = IndexedInstrProf::ProfVersion::CurrentVersion;
  Header.Unused = 0;
  Header.HashType = static_cast<uint64_t>(IndexedInstrProf::HashType);
  Header.HashOffset = 0;
  int N = sizeof(IndexedInstrProf::Header) / sizeof(uint64_t);

  // Only write out all the fields except 'HashOffset'. We need
  // to remember the offset of that field to allow back patching
  // later.
  for (int I = 0; I < N - 1; I++)
    OS.write(reinterpret_cast<uint64_t *>(&Header)[I]);

  // Save the location of Header.HashOffset field in \c OS.
  uint64_t HashTableStartFieldOffset = OS.tell();
  // Reserve the space for HashOffset field.
  OS.write(0);

  // Reserve space to write profile summary data.
  uint32_t NumEntries = Cutoffs.size();
  uint32_t SummarySize = Summary::getSize(Summary::NumKinds, NumEntries);
  // Remember the summary offset.
  uint64_t SummaryOffset = OS.tell();
  for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
    OS.write(0);

  // Write the hash table.
  uint64_t HashTableStart = Generator.Emit(OS.OS, *InfoObj);

  // Allocate space for data to be serialized out.
  std::unique_ptr<IndexedInstrProf::Summary> TheSummary =
      IndexedInstrProf::allocSummary(SummarySize);
  // Compute the Summary and copy the data to the data
  // structure to be serialized out (to disk or buffer).
  setSummary(TheSummary.get(), PS);
  InfoObj->TheProfileSummary = 0;

  // Now do the final patch:
  PatchItem PatchItems[] = {
      // Patch the Header.HashOffset field.
      {HashTableStartFieldOffset, &HashTableStart, 1},
      // Patch the summary data.
      {SummaryOffset, reinterpret_cast<uint64_t *>(TheSummary.get()),
       (int)(SummarySize / sizeof(uint64_t))}};
  OS.patch(PatchItems, sizeof(PatchItems) / sizeof(*PatchItems));
}