aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Bitcode/Reader/BitcodeReader.cpp')
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp37
1 files changed, 37 insertions, 0 deletions
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.