diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2017-06-27 23:50:11 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2017-06-27 23:50:11 +0000 |
commit | fdc12501773abc6668775ff4f3b1a9ba3eda9b01 (patch) | |
tree | 0dd0c68c808e61c2514d475c4c548ee4f68c1f15 | |
parent | 0293dd1939a041b4f51e5541e2a5d765aa6718f8 (diff) |
Bitcode: Write the irsymtab to disk.
Differential Revision: https://reviews.llvm.org/D33973
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306487 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/Bitcode/BitcodeWriter.h | 20 | ||||
-rw-r--r-- | include/llvm/Bitcode/LLVMBitCodes.h | 8 | ||||
-rw-r--r-- | lib/Bitcode/Writer/BitcodeWriter.cpp | 44 | ||||
-rw-r--r-- | lib/Object/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp | 2 | ||||
-rw-r--r-- | test/Bitcode/thinlto-alias.ll | 2 | ||||
-rw-r--r-- | test/Bitcode/thinlto-function-summary-callgraph-pgo.ll | 2 | ||||
-rw-r--r-- | test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll | 2 | ||||
-rw-r--r-- | test/Bitcode/thinlto-function-summary-callgraph-sample-profile-summary.ll | 2 | ||||
-rw-r--r-- | test/Bitcode/thinlto-function-summary-callgraph.ll | 2 | ||||
-rw-r--r-- | test/Bitcode/thinlto-function-summary-refgraph.ll | 2 | ||||
-rw-r--r-- | test/Bitcode/thinlto-function-summary.ll | 2 | ||||
-rw-r--r-- | test/Object/X86/irsymtab-asm.ll | 17 | ||||
-rw-r--r-- | test/Object/X86/irsymtab-bad-alias.ll | 15 | ||||
-rw-r--r-- | test/Object/X86/irsymtab.ll | 20 | ||||
-rw-r--r-- | test/ThinLTO/X86/autoupgrade.ll | 2 | ||||
-rw-r--r-- | tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp | 6 |
17 files changed, 138 insertions, 11 deletions
diff --git a/include/llvm/Bitcode/BitcodeWriter.h b/include/llvm/Bitcode/BitcodeWriter.h index 7c3c4b2e0cb..f8b7fb341e8 100644 --- a/include/llvm/Bitcode/BitcodeWriter.h +++ b/include/llvm/Bitcode/BitcodeWriter.h @@ -28,18 +28,34 @@ namespace llvm { std::unique_ptr<BitstreamWriter> Stream; StringTableBuilder StrtabBuilder{StringTableBuilder::RAW}; - bool WroteStrtab = false; + + // Owns any strings created by the irsymtab writer until we create the + // string table. + BumpPtrAllocator Alloc; + + bool WroteStrtab = false, WroteSymtab = false; void writeBlob(unsigned Block, unsigned Record, StringRef Blob); + std::vector<Module *> Mods; + public: /// Create a BitcodeWriter that writes to Buffer. BitcodeWriter(SmallVectorImpl<char> &Buffer); ~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 have been written. + /// 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 diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 4e3e177cac8..5435e48ff42 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -22,7 +22,7 @@ namespace llvm { namespace bitc { -// The only top-level block types are MODULE, IDENTIFICATION and STRTAB. +// The only top-level block types are MODULE, IDENTIFICATION, STRTAB and SYMTAB. enum BlockIDs { // Blocks MODULE_BLOCK_ID = FIRST_APPLICATION_BLOCKID, @@ -57,6 +57,8 @@ enum BlockIDs { STRTAB_BLOCK_ID, FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID, + + SYMTAB_BLOCK_ID, }; /// Identification block contains a string that describes the producer details, @@ -571,6 +573,10 @@ enum StrtabCodes { STRTAB_BLOB = 1, }; +enum SymtabCodes { + SYMTAB_BLOB = 1, +}; + } // End bitc namespace } // End llvm namespace diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index feeba31908a..b2b1ea6de37 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -29,10 +29,12 @@ #include "llvm/IR/UseListOrder.h" #include "llvm/IR/ValueSymbolTable.h" #include "llvm/MC/StringTableBuilder.h" +#include "llvm/Object/IRSymtab.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Program.h" #include "llvm/Support/SHA1.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" #include <cctype> #include <map> @@ -3820,6 +3822,38 @@ void BitcodeWriter::writeBlob(unsigned Block, unsigned Record, StringRef Blob) { 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; + + std::string Err; + const Triple TT(M->getTargetTriple()); + const Target *T = TargetRegistry::lookupTarget(TT.str(), Err); + if (!T || !T->hasMCAsmParser()) + return; + } + + 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); @@ -3843,6 +3877,15 @@ void BitcodeWriter::writeModule(const Module *M, bool ShouldPreserveUseListOrder, const ModuleSummaryIndex *Index, bool GenerateHash, ModuleHash *ModHash) { + 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 + // requires that the module is materialized, so we can cast to non-const here, + // after checking that it is in fact materialized. + assert(M->isMaterialized()); + Mods.push_back(const_cast<Module *>(M)); + ModuleBitcodeWriter ModuleWriter(M, Buffer, StrtabBuilder, *Stream, ShouldPreserveUseListOrder, Index, GenerateHash, ModHash); @@ -3875,6 +3918,7 @@ void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out, BitcodeWriter Writer(Buffer); Writer.writeModule(M, ShouldPreserveUseListOrder, Index, GenerateHash, ModHash); + Writer.writeSymtab(); Writer.writeStrtab(); if (TT.isOSDarwin() || TT.isOSBinFormatMachO()) diff --git a/lib/Object/CMakeLists.txt b/lib/Object/CMakeLists.txt index 1d08a9efd8b..fd5e7707c54 100644 --- a/lib/Object/CMakeLists.txt +++ b/lib/Object/CMakeLists.txt @@ -27,4 +27,5 @@ add_llvm_library(LLVMObject DEPENDS intrinsics_gen + llvm_vcsrevision_h ) diff --git a/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp index 802f470ffe1..8d494fe9cde 100644 --- a/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ b/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -371,6 +371,7 @@ void splitAndWriteThinLTOBitcode( /*GenerateHash=*/true, &ModHash); W.writeModule(MergedM.get(), /*ShouldPreserveUseListOrder=*/false, &MergedMIndex); + W.writeSymtab(); W.writeStrtab(); OS << Buffer; @@ -385,6 +386,7 @@ void splitAndWriteThinLTOBitcode( /*GenerateHash=*/false, &ModHash); W2.writeModule(MergedM.get(), /*ShouldPreserveUseListOrder=*/false, &MergedMIndex); + W2.writeSymtab(); W2.writeStrtab(); *ThinLinkOS << Buffer; } diff --git a/test/Bitcode/thinlto-alias.ll b/test/Bitcode/thinlto-alias.ll index 2c235f0620e..81fbb767ba9 100644 --- a/test/Bitcode/thinlto-alias.ll +++ b/test/Bitcode/thinlto-alias.ll @@ -18,7 +18,7 @@ ; CHECK-NEXT: </GLOBALVAL_SUMMARY_BLOCK> ; CHECK: <STRTAB_BLOCK -; CHECK-NEXT: blob data = 'mainanalias' +; CHECK-NEXT: blob data = 'mainanalias{{.*}}' ; COMBINED: <GLOBALVAL_SUMMARY_BLOCK ; COMBINED-NEXT: <VERSION diff --git a/test/Bitcode/thinlto-function-summary-callgraph-pgo.ll b/test/Bitcode/thinlto-function-summary-callgraph-pgo.ll index 7f9d6d95f50..ef5fb36d8e0 100644 --- a/test/Bitcode/thinlto-function-summary-callgraph-pgo.ll +++ b/test/Bitcode/thinlto-function-summary-callgraph-pgo.ll @@ -20,7 +20,7 @@ ; CHECK-NEXT: <PERMODULE_PROFILE {{.*}} op4=1 op5=2/> ; CHECK-NEXT: </GLOBALVAL_SUMMARY_BLOCK> ; CHECK: <STRTAB_BLOCK -; CHECK-NEXT: blob data = 'mainfunc' +; CHECK-NEXT: blob data = 'mainfunc{{.*}}' ; COMBINED: <GLOBALVAL_SUMMARY_BLOCK ; COMBINED-NEXT: <VERSION diff --git a/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll b/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll index b64d5bd52bf..a4d259add60 100644 --- a/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll +++ b/test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll @@ -33,7 +33,7 @@ ; CHECK-NEXT: </GLOBALVAL_SUMMARY_BLOCK> ; CHECK: <STRTAB_BLOCK -; CHECK-NEXT: blob data = 'hot_functionhot1hot2hot3hot4coldnone1none2none3' +; CHECK-NEXT: blob data = 'hot_functionhot1hot2hot3hot4coldnone1none2none3{{.*}}' ; COMBINED: <GLOBALVAL_SUMMARY_BLOCK ; COMBINED-NEXT: <VERSION diff --git a/test/Bitcode/thinlto-function-summary-callgraph-sample-profile-summary.ll b/test/Bitcode/thinlto-function-summary-callgraph-sample-profile-summary.ll index 875f397646a..b62090efe20 100644 --- a/test/Bitcode/thinlto-function-summary-callgraph-sample-profile-summary.ll +++ b/test/Bitcode/thinlto-function-summary-callgraph-sample-profile-summary.ll @@ -33,7 +33,7 @@ ; CHECK-NEXT: </GLOBALVAL_SUMMARY_BLOCK> ; CHECK: <STRTAB_BLOCK -; CHECK-NEXT: blob data = 'hot_functionhot1hot2hot3hot4coldnone1none2none3' +; CHECK-NEXT: blob data = 'hot_functionhot1hot2hot3hot4coldnone1none2none3{{.*}}' ; COMBINED: <GLOBALVAL_SUMMARY_BLOCK ; COMBINED-NEXT: <VERSION diff --git a/test/Bitcode/thinlto-function-summary-callgraph.ll b/test/Bitcode/thinlto-function-summary-callgraph.ll index 566f3a077e7..749909badd9 100644 --- a/test/Bitcode/thinlto-function-summary-callgraph.ll +++ b/test/Bitcode/thinlto-function-summary-callgraph.ll @@ -21,7 +21,7 @@ ; CHECK-NEXT: <PERMODULE {{.*}} op3=1 ; CHECK-NEXT: </GLOBALVAL_SUMMARY_BLOCK> ; CHECK: <STRTAB_BLOCK -; CHECK-NEXT: blob data = 'undefinedglobmainfunc' +; CHECK-NEXT: blob data = 'undefinedglobmainfunc{{.*}}' ; COMBINED: <GLOBALVAL_SUMMARY_BLOCK diff --git a/test/Bitcode/thinlto-function-summary-refgraph.ll b/test/Bitcode/thinlto-function-summary-refgraph.ll index b52fce79179..47a44b78922 100644 --- a/test/Bitcode/thinlto-function-summary-refgraph.ll +++ b/test/Bitcode/thinlto-function-summary-refgraph.ll @@ -62,7 +62,7 @@ ; CHECK: </GLOBALVAL_SUMMARY_BLOCK> ; CHECK: <STRTAB_BLOCK -; CHECK-NEXT: blob data = 'barglobalvarfuncfunc2foofunc3WXYZllvm.ctpop.i8main' +; CHECK-NEXT: blob data = 'barglobalvarfuncfunc2foofunc3WXYZllvm.ctpop.i8main{{.*}}' ; ModuleID = 'thinlto-function-summary-refgraph.ll' target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/test/Bitcode/thinlto-function-summary.ll b/test/Bitcode/thinlto-function-summary.ll index 6b8bfbb292c..5922a8b3c4d 100644 --- a/test/Bitcode/thinlto-function-summary.ll +++ b/test/Bitcode/thinlto-function-summary.ll @@ -24,7 +24,7 @@ ; BC-NEXT: <ALIAS {{.*}} op0=5 op1=0 op2=3 ; BC-NEXT: </GLOBALVAL_SUMMARY_BLOCK ; BC: <STRTAB_BLOCK -; BC-NEXT: blob data = 'hfoobaranon.{{................................}}.0variadicf' +; BC-NEXT: blob data = 'hfoobaranon.{{................................}}.0variadicf{{.*}}' ; RUN: opt -name-anon-globals -module-summary < %s | llvm-dis | FileCheck %s diff --git a/test/Object/X86/irsymtab-asm.ll b/test/Object/X86/irsymtab-asm.ll new file mode 100644 index 00000000000..487dc37b657 --- /dev/null +++ b/test/Object/X86/irsymtab-asm.ll @@ -0,0 +1,17 @@ +; Check that we correctly handle the case where we have inline asm and the +; target is not registered. In this case we shouldn't emit an irsymtab. + +; RUN: llvm-as -o %t %s +; RUN: llvm-bcanalyzer -dump %t | FileCheck --check-prefix=AS %s + +; AS-NOT: <SYMTAB_BLOCK + +; RUN: opt -o %t2 %s +; RUN: llvm-bcanalyzer -dump %t2 | FileCheck --check-prefix=OPT %s + +; OPT: <SYMTAB_BLOCK + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +module asm "ret" diff --git a/test/Object/X86/irsymtab-bad-alias.ll b/test/Object/X86/irsymtab-bad-alias.ll new file mode 100644 index 00000000000..c54436d5921 --- /dev/null +++ b/test/Object/X86/irsymtab-bad-alias.ll @@ -0,0 +1,15 @@ +; Check that we do not create an irsymtab for modules with malformed IR. + +; RUN: opt -o %t %s +; RUN: llvm-bcanalyzer -dump %t | FileCheck %s + +; CHECK-NOT: <SYMTAB_BLOCK + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@g1 = global i32 1 +@g2 = global i32 2 + +@a = alias i32, inttoptr(i32 sub (i32 ptrtoint (i32* @g1 to i32), + i32 ptrtoint (i32* @g2 to i32)) to i32*) diff --git a/test/Object/X86/irsymtab.ll b/test/Object/X86/irsymtab.ll new file mode 100644 index 00000000000..7a202f77507 --- /dev/null +++ b/test/Object/X86/irsymtab.ll @@ -0,0 +1,20 @@ +; RUN: env LLVM_OVERRIDE_PRODUCER=producer opt -o %t %s +; RUN: llvm-bcanalyzer -dump -show-binary-blobs %t | FileCheck --check-prefix=BCA %s + +; BCA: <SYMTAB_BLOCK +; Version stored at offset 0. +; BCA-NEXT: <BLOB abbrevid=4/> blob data = '\x00\x00\x00\x00\x06\x00\x00\x00\x08\x00\x00\x00D\x00\x00\x00\x01\x00\x00\x00P\x00\x00\x00\x00\x00\x00\x00P\x00\x00\x00\x02\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x0E\x00\x00\x00\x18\x00\x00\x00&\x00\x00\x00\x0B\x00\x00\x001\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\xFF\xFF\xFF\xFF\x00$\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\x03\x00\x00\x00\xFF\xFF\xFF\xFF\x08$\x00\x00' +; BCA-NEXT: </SYMTAB_BLOCK> +; BCA-NEXT: <STRTAB_BLOCK +; BCA-NEXT: <BLOB abbrevid=4/> blob data = 'foobarproducerx86_64-unknown-linux-gnuirsymtab.ll' +; BCA-NEXT: </STRTAB_BLOCK> + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" +source_filename = "irsymtab.ll" + +define void @foo() { + ret void +} + +declare void @bar() diff --git a/test/ThinLTO/X86/autoupgrade.ll b/test/ThinLTO/X86/autoupgrade.ll index cbbe833d262..2188d031c43 100644 --- a/test/ThinLTO/X86/autoupgrade.ll +++ b/test/ThinLTO/X86/autoupgrade.ll @@ -10,7 +10,7 @@ ; RUN: | llvm-bcanalyzer -dump | FileCheck %s ; CHECK: <STRTAB_BLOCK -; CHECK-NEXT: blob data = 'mainglobalfunc1llvm.invariant.start.p0i8' +; CHECK-NEXT: blob data = 'mainglobalfunc1llvm.invariant.start.p0i8{{.*}}' target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.11.0" diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp index 22bc6f7043e..528247c2dbc 100644 --- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -125,6 +125,7 @@ static const char *GetBlockName(unsigned BlockID, return "FULL_LTO_GLOBALVAL_SUMMARY_BLOCK"; case bitc::MODULE_STRTAB_BLOCK_ID: return "MODULE_STRTAB_BLOCK"; case bitc::STRTAB_BLOCK_ID: return "STRTAB_BLOCK"; + case bitc::SYMTAB_BLOCK_ID: return "SYMTAB_BLOCK"; } } @@ -393,6 +394,11 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID, default: return nullptr; case bitc::STRTAB_BLOB: return "BLOB"; } + case bitc::SYMTAB_BLOCK_ID: + switch(CodeID) { + default: return nullptr; + case bitc::SYMTAB_BLOB: return "BLOB"; + } } #undef STRINGIFY_CODE } |