Changeset View
Changeset View
Standalone View
Standalone View
lib/Bitcode/Writer/BitcodeWriter.cpp
//===--- Bitcode/Writer/BitcodeWriter.cpp - Bitcode Writer ----------------===// | //===--- Bitcode/Writer/BitcodeWriter.cpp - Bitcode Writer ----------------===// | ||||
// | // | ||||
// The LLVM Compiler Infrastructure | // The LLVM Compiler Infrastructure | ||||
// | // | ||||
// This file is distributed under the University of Illinois Open Source | // This file is distributed under the University of Illinois Open Source | ||||
// License. See LICENSE.TXT for details. | // License. See LICENSE.TXT for details. | ||||
// | // | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
// | // | ||||
// Bitcode writer implementation. | // Bitcode writer implementation. | ||||
// | // | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
#include "ValueEnumerator.h" | #include "ValueEnumerator.h" | ||||
#include "llvm/ADT/StringExtras.h" | |||||
#include "llvm/ADT/STLExtras.h" | #include "llvm/ADT/STLExtras.h" | ||||
#include "llvm/ADT/Triple.h" | #include "llvm/ADT/Triple.h" | ||||
#include "llvm/Analysis/BlockFrequencyInfo.h" | #include "llvm/Analysis/BlockFrequencyInfo.h" | ||||
#include "llvm/Analysis/BlockFrequencyInfoImpl.h" | #include "llvm/Analysis/BlockFrequencyInfoImpl.h" | ||||
#include "llvm/Analysis/BranchProbabilityInfo.h" | #include "llvm/Analysis/BranchProbabilityInfo.h" | ||||
#include "llvm/Analysis/LoopInfo.h" | #include "llvm/Analysis/LoopInfo.h" | ||||
#include "llvm/Bitcode/BitstreamWriter.h" | #include "llvm/Bitcode/BitstreamWriter.h" | ||||
#include "llvm/Bitcode/LLVMBitCodes.h" | #include "llvm/Bitcode/LLVMBitCodes.h" | ||||
Show All 11 Lines | |||||
#include "llvm/IR/Operator.h" | #include "llvm/IR/Operator.h" | ||||
#include "llvm/IR/UseListOrder.h" | #include "llvm/IR/UseListOrder.h" | ||||
#include "llvm/IR/ValueSymbolTable.h" | #include "llvm/IR/ValueSymbolTable.h" | ||||
#include "llvm/Support/CommandLine.h" | #include "llvm/Support/CommandLine.h" | ||||
#include "llvm/Support/ErrorHandling.h" | #include "llvm/Support/ErrorHandling.h" | ||||
#include "llvm/Support/MathExtras.h" | #include "llvm/Support/MathExtras.h" | ||||
#include "llvm/Support/Program.h" | #include "llvm/Support/Program.h" | ||||
#include "llvm/Support/raw_ostream.h" | #include "llvm/Support/raw_ostream.h" | ||||
#include "llvm/Support/SHA1.h" | |||||
#include <cctype> | #include <cctype> | ||||
#include <map> | #include <map> | ||||
using namespace llvm; | using namespace llvm; | ||||
/// These are manifest constants used by the bitcode writer. They do not need to | /// These are manifest constants used by the bitcode writer. They do not need to | ||||
/// be kept in sync with the reader, but need to be consistent within this file. | /// be kept in sync with the reader, but need to be consistent within this file. | ||||
enum { | enum { | ||||
// VALUE_SYMTAB_BLOCK abbrev id's. | // VALUE_SYMTAB_BLOCK abbrev id's. | ||||
▲ Show 20 Lines • Show All 2,785 Lines • ▼ Show 20 Lines | static void WriteModStrings(const ModuleSummaryIndex &I, | ||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); | Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); | ||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); | Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); | ||||
unsigned Abbrev8Bit = Stream.EmitAbbrev(Abbv); | unsigned Abbrev8Bit = Stream.EmitAbbrev(Abbv); | ||||
// 7-bit fixed width MST_ENTRY strings. | // 7-bit fixed width MST_ENTRY strings. | ||||
Abbv = new BitCodeAbbrev(); | Abbv = new BitCodeAbbrev(); | ||||
Abbv->Add(BitCodeAbbrevOp(bitc::MST_CODE_ENTRY)); | Abbv->Add(BitCodeAbbrevOp(bitc::MST_CODE_ENTRY)); | ||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); | Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); | ||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); | Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); | ||||
tejohnson: What is the added VBR8 here and in the 6-bit case below? I don't see anything else being… | |||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); | Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); | ||||
unsigned Abbrev7Bit = Stream.EmitAbbrev(Abbv); | unsigned Abbrev7Bit = Stream.EmitAbbrev(Abbv); | ||||
// 6-bit char6 MST_ENTRY strings. | // 6-bit char6 MST_ENTRY strings. | ||||
Abbv = new BitCodeAbbrev(); | Abbv = new BitCodeAbbrev(); | ||||
Abbv->Add(BitCodeAbbrevOp(bitc::MST_CODE_ENTRY)); | Abbv->Add(BitCodeAbbrevOp(bitc::MST_CODE_ENTRY)); | ||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); | Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); | ||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); | Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); | ||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); | Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); | ||||
unsigned Abbrev6Bit = Stream.EmitAbbrev(Abbv); | unsigned Abbrev6Bit = Stream.EmitAbbrev(Abbv); | ||||
SmallVector<unsigned, 64> NameVals; | // Module Hash, 160 bits SHA1. Optionally, emitted after each MST_CODE_ENTRY. | ||||
for (const StringMapEntry<uint64_t> &MPSE : I.modulePaths()) { | Abbv = new BitCodeAbbrev(); | ||||
Abbv->Add(BitCodeAbbrevOp(bitc::MST_CODE_HASH)); | |||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); | |||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); | |||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); | |||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); | |||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); | |||||
unsigned AbbrevHash = Stream.EmitAbbrev(Abbv); | |||||
SmallVector<unsigned, 64> Vals; | |||||
for (const auto &MPSE : I.modulePaths()) { | |||||
"Optionally emitted after..." tejohnson: "Optionally emitted after..." | |||||
StringEncoding Bits = | StringEncoding Bits = | ||||
getStringEncoding(MPSE.getKey().data(), MPSE.getKey().size()); | getStringEncoding(MPSE.getKey().data(), MPSE.getKey().size()); | ||||
unsigned AbbrevToUse = Abbrev8Bit; | unsigned AbbrevToUse = Abbrev8Bit; | ||||
if (Bits == SE_Char6) | if (Bits == SE_Char6) | ||||
AbbrevToUse = Abbrev6Bit; | AbbrevToUse = Abbrev6Bit; | ||||
else if (Bits == SE_Fixed7) | else if (Bits == SE_Fixed7) | ||||
AbbrevToUse = Abbrev7Bit; | AbbrevToUse = Abbrev7Bit; | ||||
NameVals.push_back(MPSE.getValue()); | Vals.push_back(MPSE.getValue().first); | ||||
for (const auto P : MPSE.getKey()) | for (const auto P : MPSE.getKey()) | ||||
NameVals.push_back((unsigned char)P); | Vals.push_back((unsigned char)P); | ||||
// Emit the finished record. | // Emit the finished record. | ||||
Stream.EmitRecord(bitc::MST_CODE_ENTRY, NameVals, AbbrevToUse); | Stream.EmitRecord(bitc::MST_CODE_ENTRY, Vals, AbbrevToUse); | ||||
NameVals.clear(); | |||||
Vals.clear(); | |||||
// Emit an optional hash for the module now | |||||
auto &Hash = MPSE.getValue().second; | |||||
bool AllZero = true; // Detect if the hash is empty, and do not generate it | |||||
for (auto Val : Hash) { | |||||
if (Val) | |||||
AllZero = false; | |||||
Vals.push_back(Val); | |||||
} | |||||
if (!AllZero) { | |||||
// Emit the hash record. | |||||
Stream.EmitRecord(bitc::MST_CODE_HASH, Vals, AbbrevHash); | |||||
} | |||||
Vals.clear(); | |||||
} | } | ||||
Stream.ExitBlock(); | Stream.ExitBlock(); | ||||
} | } | ||||
// Helper to emit a single function summary record. | // Helper to emit a single function summary record. | ||||
static void WritePerModuleFunctionSummaryRecord( | static void WritePerModuleFunctionSummaryRecord( | ||||
SmallVector<uint64_t, 64> &NameVals, FunctionSummary *FS, unsigned ValueID, | SmallVector<uint64_t, 64> &NameVals, FunctionSummary *FS, unsigned ValueID, | ||||
unsigned FSCallsAbbrev, unsigned FSCallsProfileAbbrev, | unsigned FSCallsAbbrev, unsigned FSCallsProfileAbbrev, | ||||
▲ Show 20 Lines • Show All 291 Lines • ▼ Show 20 Lines | static void WriteIdentificationBlock(const Module *M, BitstreamWriter &Stream) { | ||||
Abbv->Add(BitCodeAbbrevOp(bitc::IDENTIFICATION_CODE_EPOCH)); | Abbv->Add(BitCodeAbbrevOp(bitc::IDENTIFICATION_CODE_EPOCH)); | ||||
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); | Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); | ||||
auto EpochAbbrev = Stream.EmitAbbrev(Abbv); | auto EpochAbbrev = Stream.EmitAbbrev(Abbv); | ||||
SmallVector<unsigned, 1> Vals = {bitc::BITCODE_CURRENT_EPOCH}; | SmallVector<unsigned, 1> Vals = {bitc::BITCODE_CURRENT_EPOCH}; | ||||
Stream.EmitRecord(bitc::IDENTIFICATION_CODE_EPOCH, Vals, EpochAbbrev); | Stream.EmitRecord(bitc::IDENTIFICATION_CODE_EPOCH, Vals, EpochAbbrev); | ||||
Stream.ExitBlock(); | Stream.ExitBlock(); | ||||
} | } | ||||
static void writeModuleHash(BitstreamWriter &Stream, | |||||
SmallVectorImpl<char> &Buffer, | |||||
size_t BlockStartPos) { | |||||
5*i32? tejohnson: 5*i32? | |||||
// Emit the module's hash. | |||||
// MODULE_CODE_HASH: [5*i32] | |||||
This produces different results in 32 and 64 bit machines, no? rafael: This produces different results in 32 and 64 bit machines, no? | |||||
Uh, dunno, is it a property of hash_combine_range? mehdi_amini: Uh, dunno, is it a property of hash_combine_range? | |||||
SHA1 Hasher; | |||||
Hasher.write(&Buffer[BlockStartPos], Buffer.size() - BlockStartPos); | |||||
auto Hash = Hasher.result(); | |||||
SmallVector<uint64_t, 20> Vals; | |||||
auto LShift = [&](unsigned char Val, unsigned Amount) | |||||
-> uint64_t { return ((uint64_t)Val) << Amount; }; | |||||
for (int Pos = 0; Pos < 20; Pos += 4) { | |||||
uint32_t SubHash = LShift(Hash[Pos + 0], 24); | |||||
SubHash |= LShift(Hash[Pos + 1], 16) | LShift(Hash[Pos + 2], 8) | | |||||
(unsigned)(unsigned char)Hash[Pos + 3]; | |||||
Vals.push_back(SubHash); | |||||
} | |||||
// Emit the finished record. | |||||
Stream.EmitRecord(bitc::MODULE_CODE_HASH, Vals); | |||||
} | |||||
/// WriteModule - Emit the specified module to the bitstream. | /// WriteModule - Emit the specified module to the bitstream. | ||||
static void WriteModule(const Module *M, BitstreamWriter &Stream, | static void WriteModule(const Module *M, BitstreamWriter &Stream, | ||||
bool ShouldPreserveUseListOrder, | bool ShouldPreserveUseListOrder, | ||||
uint64_t BitcodeStartBit, bool EmitSummaryIndex) { | uint64_t BitcodeStartBit, bool EmitSummaryIndex, | ||||
bool GenerateHash, SmallVectorImpl<char> &Buffer) { | |||||
Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3); | Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3); | ||||
size_t BlockStartPos = Buffer.size(); | |||||
SmallVector<unsigned, 1> Vals; | SmallVector<unsigned, 1> Vals; | ||||
Please make this conditional so it isn't generating a hash if we aren't using a module cache. tejohnson: Please make this conditional so it isn't generating a hash if we aren't using a module cache. | |||||
unsigned CurVersion = 1; | unsigned CurVersion = 1; | ||||
Vals.push_back(CurVersion); | Vals.push_back(CurVersion); | ||||
Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals); | Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals); | ||||
// Analyze the module, enumerating globals, functions, etc. | // Analyze the module, enumerating globals, functions, etc. | ||||
ValueEnumerator VE(*M, ShouldPreserveUseListOrder); | ValueEnumerator VE(*M, ShouldPreserveUseListOrder); | ||||
// Emit blockinfo, which defines the standard abbreviations etc. | // Emit blockinfo, which defines the standard abbreviations etc. | ||||
Show All 38 Lines | static void WriteModule(const Module *M, BitstreamWriter &Stream, | ||||
// Need to write after the above call to WriteFunction which populates | // Need to write after the above call to WriteFunction which populates | ||||
// the summary information in the index. | // the summary information in the index. | ||||
if (EmitSummaryIndex) | if (EmitSummaryIndex) | ||||
WritePerModuleGlobalValueSummary(FunctionIndex, M, VE, Stream); | WritePerModuleGlobalValueSummary(FunctionIndex, M, VE, Stream); | ||||
WriteValueSymbolTable(M->getValueSymbolTable(), VE, Stream, | WriteValueSymbolTable(M->getValueSymbolTable(), VE, Stream, | ||||
VSTOffsetPlaceholder, BitcodeStartBit, &FunctionIndex); | VSTOffsetPlaceholder, BitcodeStartBit, &FunctionIndex); | ||||
if (GenerateHash) { | |||||
ditto. tejohnson: ditto. | |||||
writeModuleHash(Stream, Buffer, BlockStartPos); | |||||
} | |||||
Stream.ExitBlock(); | Stream.ExitBlock(); | ||||
} | } | ||||
/// EmitDarwinBCHeader - If generating a bc file on darwin, we have to emit a | /// EmitDarwinBCHeader - If generating a bc file on darwin, we have to emit a | ||||
/// header and trailer to make it compatible with the system archiver. To do | /// header and trailer to make it compatible with the system archiver. To do | ||||
/// this we emit the following header, and then emit a trailer that pads the | /// this we emit the following header, and then emit a trailer that pads the | ||||
/// file out to be a multiple of 16 bytes. | /// file out to be a multiple of 16 bytes. | ||||
/// | /// | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | static void WriteBitcodeHeader(BitstreamWriter &Stream) { | ||||
Stream.Emit(0xE, 4); | Stream.Emit(0xE, 4); | ||||
Stream.Emit(0xD, 4); | Stream.Emit(0xD, 4); | ||||
} | } | ||||
/// WriteBitcodeToFile - Write the specified module to the specified output | /// WriteBitcodeToFile - Write the specified module to the specified output | ||||
/// stream. | /// stream. | ||||
void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out, | void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out, | ||||
bool ShouldPreserveUseListOrder, | bool ShouldPreserveUseListOrder, | ||||
bool EmitSummaryIndex) { | bool EmitSummaryIndex, bool GenerateHash) { | ||||
SmallVector<char, 0> Buffer; | SmallVector<char, 0> Buffer; | ||||
Buffer.reserve(256*1024); | Buffer.reserve(256*1024); | ||||
// If this is darwin or another generic macho target, reserve space for the | // If this is darwin or another generic macho target, reserve space for the | ||||
// header. | // header. | ||||
Triple TT(M->getTargetTriple()); | Triple TT(M->getTargetTriple()); | ||||
if (TT.isOSDarwin() || TT.isOSBinFormatMachO()) | if (TT.isOSDarwin() || TT.isOSBinFormatMachO()) | ||||
Buffer.insert(Buffer.begin(), BWH_HeaderSize, 0); | Buffer.insert(Buffer.begin(), BWH_HeaderSize, 0); | ||||
Show All 9 Lines | // Emit the module into the buffer. | ||||
// Emit the file header. | // Emit the file header. | ||||
WriteBitcodeHeader(Stream); | WriteBitcodeHeader(Stream); | ||||
WriteIdentificationBlock(M, Stream); | WriteIdentificationBlock(M, Stream); | ||||
// Emit the module. | // Emit the module. | ||||
WriteModule(M, Stream, ShouldPreserveUseListOrder, BitcodeStartBit, | WriteModule(M, Stream, ShouldPreserveUseListOrder, BitcodeStartBit, | ||||
EmitSummaryIndex); | EmitSummaryIndex, GenerateHash, Buffer); | ||||
} | } | ||||
if (TT.isOSDarwin() || TT.isOSBinFormatMachO()) | if (TT.isOSDarwin() || TT.isOSBinFormatMachO()) | ||||
EmitDarwinBCHeaderAndTrailer(Buffer, TT); | EmitDarwinBCHeaderAndTrailer(Buffer, TT); | ||||
// Write the generated bitstream to "Out". | // Write the generated bitstream to "Out". | ||||
Out.write((char*)&Buffer.front(), Buffer.size()); | Out.write((char*)&Buffer.front(), Buffer.size()); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 49 Lines • Show Last 20 Lines |
What is the added VBR8 here and in the 6-bit case below? I don't see anything else being written. And it isn't in the 8-bit case above.