summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2017-06-27 23:50:11 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2017-06-27 23:50:11 +0000
commitfdc12501773abc6668775ff4f3b1a9ba3eda9b01 (patch)
tree0dd0c68c808e61c2514d475c4c548ee4f68c1f15
parent0293dd1939a041b4f51e5541e2a5d765aa6718f8 (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.h20
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h8
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp44
-rw-r--r--lib/Object/CMakeLists.txt1
-rw-r--r--lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp2
-rw-r--r--test/Bitcode/thinlto-alias.ll2
-rw-r--r--test/Bitcode/thinlto-function-summary-callgraph-pgo.ll2
-rw-r--r--test/Bitcode/thinlto-function-summary-callgraph-profile-summary.ll2
-rw-r--r--test/Bitcode/thinlto-function-summary-callgraph-sample-profile-summary.ll2
-rw-r--r--test/Bitcode/thinlto-function-summary-callgraph.ll2
-rw-r--r--test/Bitcode/thinlto-function-summary-refgraph.ll2
-rw-r--r--test/Bitcode/thinlto-function-summary.ll2
-rw-r--r--test/Object/X86/irsymtab-asm.ll17
-rw-r--r--test/Object/X86/irsymtab-bad-alias.ll15
-rw-r--r--test/Object/X86/irsymtab.ll20
-rw-r--r--test/ThinLTO/X86/autoupgrade.ll2
-rw-r--r--tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp6
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
}