diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 66426c83c66..e5dfa723b04 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1635,11 +1635,14 @@ std::error_code BitcodeReader::ParseConstants() { } else { // Otherwise insert a placeholder and remember it so it can be inserted // when the function is parsed. - BB = BasicBlock::Create(Context); auto &FwdBBs = BasicBlockFwdRefs[Fn]; if (FwdBBs.empty()) BasicBlockFwdRefQueue.push_back(Fn); - FwdBBs.emplace_back(BBID, BB); + if (FwdBBs.size() < BBID + 1) + FwdBBs.resize(BBID + 1); + if (!FwdBBs[BBID]) + FwdBBs[BBID] = BasicBlock::Create(Context); + BB = FwdBBs[BBID]; } V = BlockAddress::get(Fn, BB); break; @@ -2392,24 +2395,19 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) { FunctionBBs[i] = BasicBlock::Create(Context, "", F); } else { auto &BBRefs = BBFRI->second; - std::sort(BBRefs.begin(), BBRefs.end(), - [](const std::pair &LHS, - const std::pair &RHS) { - return LHS.first < RHS.first; - }); - unsigned R = 0, RE = BBRefs.size(); - for (unsigned I = 0, E = FunctionBBs.size(); I != E; ++I) - if (R != RE && BBRefs[R].first == I) { - assert(I != 0 && "Invalid reference to entry block"); - BasicBlock *BB = BBRefs[R++].second; - BB->insertInto(F); - FunctionBBs[I] = BB; + // Check for invalid basic block references. + if (BBRefs.size() > FunctionBBs.size()) + return Error(BitcodeError::InvalidID); + assert(!BBRefs.empty() && "Unexpected empty array"); + assert(!BBRefs.front() && "Invalid reference to entry block"); + for (unsigned I = 0, E = FunctionBBs.size(), RE = BBRefs.size(); I != E; + ++I) + if (I < RE && BBRefs[I]) { + BBRefs[I]->insertInto(F); + FunctionBBs[I] = BBRefs[I]; } else { FunctionBBs[I] = BasicBlock::Create(Context, "", F); } - // Check for invalid basic block references. - if (R != RE) - return Error(BitcodeError::InvalidID); // Erase from the table. BasicBlockFwdRefs.erase(BBFRI); diff --git a/lib/Bitcode/Reader/BitcodeReader.h b/lib/Bitcode/Reader/BitcodeReader.h index 5bbcaf4c614..6d4e0a2dfe9 100644 --- a/lib/Bitcode/Reader/BitcodeReader.h +++ b/lib/Bitcode/Reader/BitcodeReader.h @@ -181,9 +181,9 @@ class BitcodeReader : public GVMaterializer { DenseMap DeferredFunctionInfo; /// These are basic blocks forward-referenced by block addresses. They are - /// inserted lazily into functions when they're loaded. - typedef std::pair BasicBlockRefTy; - DenseMap> BasicBlockFwdRefs; + /// inserted lazily into functions when they're loaded. The basic block ID is + /// its index into the vector. + DenseMap> BasicBlockFwdRefs; std::deque BasicBlockFwdRefQueue; /// UseRelativeIDs - Indicates that we are using a new encoding for diff --git a/test/Bitcode/blockaddress.ll b/test/Bitcode/blockaddress.ll index 305118c83b8..83fae48bf2f 100644 --- a/test/Bitcode/blockaddress.ll +++ b/test/Bitcode/blockaddress.ll @@ -44,3 +44,17 @@ here: end: ret void } + +; Check a blockaddress taken in two separate functions before the referenced +; function. +define i8* @take1() { + ret i8* blockaddress(@taken, %bb) +} +define i8* @take2() { + ret i8* blockaddress(@taken, %bb) +} +define void @taken() { + unreachable +bb: + unreachable +}