void writeFunctionLevelValueSymbolTable(const ValueSymbolTable &VST);
void writeGlobalValueSymbolTable(
DenseMap<const Function *, uint64_t> &FunctionToBitcodeIndex);
- void writeUseList(UseListOrder &&Order);
- void writeUseListBlock(const Function *F);
void writeFunction(const Function &F);
void writeBlockInfo();
Stream->Emit(0xD, 4);
}
-dxil::BitcodeWriter::~BitcodeWriter() { assert(WroteStrtab); }
+dxil::BitcodeWriter::~BitcodeWriter() { }
/// Write the specified module to the specified output stream.
void dxil::WriteDXILToFile(const Module &M, raw_ostream &Out) {
BitcodeWriter Writer(Buffer, dyn_cast<raw_fd_stream>(&Out));
Writer.writeModule(M);
- Writer.writeSymtab();
- Writer.writeStrtab();
// Write the generated bitstream to "Out".
if (!Buffer.empty())
Stream->ExitBlock();
}
-void BitcodeWriter::writeSymtab() {
- assert(!WroteStrtab && !WroteSymtab);
-
- // If any module has module-level inline asm, we will require a registered asm
- // parser for the target so that we can create an accurate symbol table for
- // the module.
- for (Module *M : Mods) {
- if (M->getModuleInlineAsm().empty())
- continue;
- }
-
- WroteSymtab = true;
- SmallVector<char, 0> Symtab;
- // The irsymtab::build function may be unable to create a symbol table if the
- // module is malformed (e.g. it contains an invalid alias). Writing a symbol
- // table is not required for correctness, but we still want to be able to
- // write malformed modules to bitcode files, so swallow the error.
- if (Error E = irsymtab::build(Mods, Symtab, StrtabBuilder, Alloc)) {
- consumeError(std::move(E));
- return;
- }
-
- writeBlob(bitc::SYMTAB_BLOCK_ID, bitc::SYMTAB_BLOB,
- {Symtab.data(), Symtab.size()});
-}
-
-void BitcodeWriter::writeStrtab() {
- assert(!WroteStrtab);
-
- std::vector<char> Strtab;
- StrtabBuilder.finalizeInOrder();
- Strtab.resize(StrtabBuilder.getSize());
- StrtabBuilder.write((uint8_t *)Strtab.data());
-
- writeBlob(bitc::STRTAB_BLOCK_ID, bitc::STRTAB_BLOB,
- {Strtab.data(), Strtab.size()});
-
- WroteStrtab = true;
-}
-
-void BitcodeWriter::copyStrtab(StringRef Strtab) {
- writeBlob(bitc::STRTAB_BLOCK_ID, bitc::STRTAB_BLOB, Strtab);
- WroteStrtab = true;
-}
-
void BitcodeWriter::writeModule(const Module &M) {
- assert(!WroteStrtab);
// The Mods vector is used by irsymtab::build, which requires non-const
// Modules in case it needs to materialize metadata. But the bitcode writer
Stream.ExitBlock();
}
-void DXILBitcodeWriter::writeUseList(UseListOrder &&Order) {
- assert(Order.Shuffle.size() >= 2 && "Shuffle too small");
- unsigned Code;
- if (isa<BasicBlock>(Order.V))
- Code = bitc::USELIST_CODE_BB;
- else
- Code = bitc::USELIST_CODE_DEFAULT;
-
- SmallVector<uint64_t, 64> Record(Order.Shuffle.begin(), Order.Shuffle.end());
- Record.push_back(VE.getValueID(Order.V));
- Stream.EmitRecord(Code, Record);
-}
-
-void DXILBitcodeWriter::writeUseListBlock(const Function *F) {
- auto hasMore = [&]() {
- return !VE.UseListOrders.empty() && VE.UseListOrders.back().F == F;
- };
- if (!hasMore())
- // Nothing to do.
- return;
-
- Stream.EnterSubblock(bitc::USELIST_BLOCK_ID, 3);
- while (hasMore()) {
- writeUseList(std::move(VE.UseListOrders.back()));
- VE.UseListOrders.pop_back();
- }
- Stream.ExitBlock();
-}
-
/// Emit a function body to the module stream.
void DXILBitcodeWriter::writeFunction(const Function &F) {
Stream.EnterSubblock(bitc::FUNCTION_BLOCK_ID, 4);
if (NeedsMetadataAttachment)
writeFunctionMetadataAttachment(F);
- writeUseListBlock(&F);
VE.purgeFunction();
Stream.ExitBlock();
}
// function level table.
writeFunctionLevelValueSymbolTable(M.getValueSymbolTable());
- // Emit module-level use-lists.
- writeUseListBlock(nullptr);
-
// Emit function bodies.
for (const Function &F : M)
if (!F.isDeclaration())
// string table.
BumpPtrAllocator Alloc;
- bool WroteStrtab = false, WroteSymtab = false;
-
void writeBlob(unsigned Block, unsigned Record, StringRef Blob);
std::vector<Module *> Mods;
~BitcodeWriter();
- /// Attempt to write a symbol table to the bitcode file. This must be called
- /// at most once after all modules have been written.
- ///
- /// A reader does not require a symbol table to interpret a bitcode file;
- /// the symbol table is needed only to improve link-time performance. So
- /// this function may decide not to write a symbol table. It may so decide
- /// if, for example, the target is unregistered or the IR is malformed.
- void writeSymtab();
-
- /// Write the bitcode file's string table. This must be called exactly once
- /// after all modules and the optional symbol table have been written.
- void writeStrtab();
-
- /// Copy the string table for another module into this bitcode file. This
- /// should be called after copying the module itself into the bitcode file.
- void copyStrtab(StringRef Strtab);
-
/// Write the specified module to the buffer specified at construction time.
void writeModule(const Module &M);
};