aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Bitcode
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Bitcode')
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp1
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp37
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp24
3 files changed, 61 insertions, 1 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp
index f291827..4e73f42 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp
@@ -267,6 +267,7 @@ static Optional<const char *> GetCodeName(unsigned CodeID, unsigned BlockID,
STRINGIFY_CODE(FUNC_CODE, INST_STOREATOMIC)
STRINGIFY_CODE(FUNC_CODE, INST_CMPXCHG)
STRINGIFY_CODE(FUNC_CODE, INST_CALLBR)
+ STRINGIFY_CODE(FUNC_CODE, BLOCKADDR_USERS)
}
case bitc::VALUE_SYMTAB_BLOCK_ID:
switch (CodeID) {
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 8a50749..62d9904 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -558,6 +558,13 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer {
DenseMap<Function *, std::vector<BasicBlock *>> BasicBlockFwdRefs;
std::deque<Function *> BasicBlockFwdRefQueue;
+ /// These are Functions that contain BlockAddresses which refer a different
+ /// Function. When parsing the different Function, queue Functions that refer
+ /// to the different Function. Those Functions must be materialized in order
+ /// to resolve their BlockAddress constants before the different Function
+ /// gets moved into another Module.
+ std::vector<Function *> BackwardRefFunctions;
+
/// Indicates that we are using a new encoding for instruction operands where
/// most operands in the current FUNCTION_BLOCK are encoded relative to the
/// instruction number, for a more compact encoding. Some instruction
@@ -881,6 +888,11 @@ Error BitcodeReader::materializeForwardReferencedFunctions() {
}
assert(BasicBlockFwdRefs.empty() && "Function missing from queue");
+ for (Function *F : BackwardRefFunctions)
+ if (Error Err = materialize(F))
+ return Err;
+ BackwardRefFunctions.clear();
+
// Reset state.
WillMaterializeAllForwardRefs = false;
return Error::success();
@@ -4317,6 +4329,31 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
continue;
}
+ case bitc::FUNC_CODE_BLOCKADDR_USERS: // BLOCKADDR_USERS: [vals...]
+ // The record should not be emitted if it's an empty list.
+ if (Record.empty())
+ return error("Invalid record");
+ // When we have the RARE case of a BlockAddress Constant that is not
+ // scoped to the Function it refers to, we need to conservatively
+ // materialize the referred to Function, regardless of whether or not
+ // that Function will ultimately be linked, otherwise users of
+ // BitcodeReader might start splicing out Function bodies such that we
+ // might no longer be able to materialize the BlockAddress since the
+ // BasicBlock (and entire body of the Function) the BlockAddress refers
+ // to may have been moved. In the case that the user of BitcodeReader
+ // decides ultimately not to link the Function body, materializing here
+ // could be considered wasteful, but it's better than a deserialization
+ // failure as described. This keeps BitcodeReader unaware of complex
+ // linkage policy decisions such as those use by LTO, leaving those
+ // decisions "one layer up."
+ for (uint64_t ValID : Record)
+ if (auto *F = dyn_cast<Function>(ValueList[ValID]))
+ BackwardRefFunctions.push_back(F);
+ else
+ return error("Invalid record");
+
+ continue;
+
case bitc::FUNC_CODE_DEBUG_LOC_AGAIN: // DEBUG_LOC_AGAIN
// This record indicates that the last instruction is at the same
// location as the previous instruction with a location.
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index c76294d..79c7685 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
@@ -3359,8 +3360,10 @@ void ModuleBitcodeWriter::writeFunction(
bool NeedsMetadataAttachment = F.hasMetadata();
DILocation *LastDL = nullptr;
+ SmallPtrSet<Function *, 4> BlockAddressUsers;
+
// Finally, emit all the instructions, in order.
- for (const BasicBlock &BB : F)
+ for (const BasicBlock &BB : F) {
for (const Instruction &I : BB) {
writeInstruction(I, InstID, Vals);
@@ -3392,6 +3395,25 @@ void ModuleBitcodeWriter::writeFunction(
LastDL = DL;
}
+ if (BlockAddress *BA = BlockAddress::lookup(&BB)) {
+ for (User *U : BA->users()) {
+ if (auto *I = dyn_cast<Instruction>(U)) {
+ Function *P = I->getParent()->getParent();
+ if (P != &F)
+ BlockAddressUsers.insert(P);
+ }
+ }
+ }
+ }
+
+ if (!BlockAddressUsers.empty()) {
+ SmallVector<uint64_t, 4> Record;
+ Record.reserve(BlockAddressUsers.size());
+ for (Function *F : BlockAddressUsers)
+ Record.push_back(VE.getValueID(F));
+ Stream.EmitRecord(bitc::FUNC_CODE_BLOCKADDR_USERS, Record);
+ }
+
// Emit names for all the instructions etc.
if (auto *Symtab = F.getValueSymbolTable())
writeFunctionLevelValueSymbolTable(*Symtab);