Fix auto-upgrade of TBAA tags in Bitcode Reader

If TBAA is on an intrinsic and it gets upgraded, it'll delete the call
instruction that we collected in a vector. Even if we were to use
WeakVH, it'll drop the TBAA and we'll hit the assert on the upgrade
path.

r263673 gave a shot to make sure the TBAA upgrade happens before
intrinsics upgrade, but failed to account for all cases.

Instead of collecting instructions in a vector, this patch makes it
just upgrade the TBAA on the fly, because metadata are always
already loaded at this point.

Differential Revision: https://reviews.llvm.org/D24533

llvm-svn: 281549
This commit is contained in:
Mehdi Amini
2016-09-14 22:29:59 +00:00
parent 8d22e6c27b
commit e470927187
7 changed files with 71 additions and 36 deletions

View File

@@ -257,8 +257,6 @@ class BitcodeReader : public GVMaterializer {
std::vector<std::pair<Function*, unsigned> > FunctionPrologues;
std::vector<std::pair<Function*, unsigned> > FunctionPersonalityFns;
SmallVector<Instruction*, 64> InstsWithTBAATag;
bool HasSeenOldLoopTags = false;
/// The set of attributes by index. Index zero in the file is for null, and
@@ -4425,11 +4423,11 @@ std::error_code BitcodeReader::parseMetadataAttachment(Function &F) {
if (HasSeenOldLoopTags && I->second == LLVMContext::MD_loop)
MD = upgradeInstructionLoopAttachment(*MD);
Inst->setMetadata(I->second, MD);
if (I->second == LLVMContext::MD_tbaa) {
InstsWithTBAATag.push_back(Inst);
continue;
assert(!MD->isTemporary() && "should load MDs before attachments");
MD = UpgradeTBAANode(*MD);
}
Inst->setMetadata(I->second, MD);
}
break;
}
@@ -5842,11 +5840,6 @@ std::error_code BitcodeReader::materializeModule() {
if (!BasicBlockFwdRefs.empty())
return error("Never resolved function from blockaddress");
// Upgrading intrinsic calls before TBAA can cause TBAA metadata to be lost,
// to prevent this instructions with TBAA tags should be upgraded first.
for (unsigned I = 0, E = InstsWithTBAATag.size(); I < E; I++)
UpgradeInstWithTBAATag(InstsWithTBAATag[I]);
// Upgrade any intrinsic calls that slipped through (should not happen!) and
// delete the old functions to clean up. We can't do this unless the entire
// module is materialized because there could always be another function body