aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/Bitcode/BitReaderTest.cpp
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2014-08-01 21:11:34 +0000
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2014-08-01 21:11:34 +0000
commit908d809b81dc0394b37ee4f2a407701f1e8d0945 (patch)
tree83e490b909942b73d83fbfd6e726383de57a4d2e /llvm/unittests/Bitcode/BitReaderTest.cpp
parent2e7e989d715e514c9083a9d70416d8af99f7abec (diff)
downloadllvm-908d809b81dc0394b37ee4f2a407701f1e8d0945.zip
llvm-908d809b81dc0394b37ee4f2a407701f1e8d0945.tar.gz
llvm-908d809b81dc0394b37ee4f2a407701f1e8d0945.tar.bz2
BitcodeReader: Fix some BlockAddress forward reference corner cases
`BlockAddress`es are interesting in that they can reference basic blocks from *outside* the block's function. Since basic blocks are not global values, this presents particular challenges for lazy parsing. One corner case was found in PR11677 and fixed in r147425. In that case, a global variable references a block address. It's necessary to load the relevant function to resolve the forward reference before doing anything with the module. By inspection, I found (and have fixed here) two other cases: - An instruction from one function references a block address from another function, and only the first function is lazily loaded. I fixed this the same way as PR11677: by eagerly loading the referenced function. - A function whose block address is taken is dematerialized, leaving invalid references to it. I fixed this by refusing to dematerialize functions whose block addresses are taken (if you have to load it, you can't unload it). llvm-svn: 214559
Diffstat (limited to 'llvm/unittests/Bitcode/BitReaderTest.cpp')
-rw-r--r--llvm/unittests/Bitcode/BitReaderTest.cpp68
1 files changed, 68 insertions, 0 deletions
diff --git a/llvm/unittests/Bitcode/BitReaderTest.cpp b/llvm/unittests/Bitcode/BitReaderTest.cpp
index 144853d..8331527 100644
--- a/llvm/unittests/Bitcode/BitReaderTest.cpp
+++ b/llvm/unittests/Bitcode/BitReaderTest.cpp
@@ -70,6 +70,74 @@ TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677
" unreachable\n"
"}\n");
EXPECT_FALSE(verifyModule(*M, &dbgs()));
+
+ // Try (and fail) to dematerialize @func.
+ M->getFunction("func")->Dematerialize();
+ EXPECT_FALSE(M->getFunction("func")->empty());
+}
+
+TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) {
+ SmallString<1024> Mem;
+
+ LLVMContext Context;
+ std::unique_ptr<Module> M = getLazyModuleFromAssembly(
+ Context, Mem, "define i8* @before() {\n"
+ " ret i8* blockaddress(@func, %bb)\n"
+ "}\n"
+ "define void @other() {\n"
+ " unreachable\n"
+ "}\n"
+ "define void @func() {\n"
+ " unreachable\n"
+ "bb:\n"
+ " unreachable\n"
+ "}\n");
+ EXPECT_TRUE(M->getFunction("before")->empty());
+ EXPECT_TRUE(M->getFunction("func")->empty());
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+
+ // Materialize @before, pulling in @func.
+ EXPECT_FALSE(M->getFunction("before")->Materialize());
+ EXPECT_FALSE(M->getFunction("func")->empty());
+ EXPECT_TRUE(M->getFunction("other")->empty());
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+
+ // Try (and fail) to dematerialize @func.
+ M->getFunction("func")->Dematerialize();
+ EXPECT_FALSE(M->getFunction("func")->empty());
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+}
+
+TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) {
+ SmallString<1024> Mem;
+
+ LLVMContext Context;
+ std::unique_ptr<Module> M = getLazyModuleFromAssembly(
+ Context, Mem, "define void @func() {\n"
+ " unreachable\n"
+ "bb:\n"
+ " unreachable\n"
+ "}\n"
+ "define void @other() {\n"
+ " unreachable\n"
+ "}\n"
+ "define i8* @after() {\n"
+ " ret i8* blockaddress(@func, %bb)\n"
+ "}\n");
+ EXPECT_TRUE(M->getFunction("after")->empty());
+ EXPECT_TRUE(M->getFunction("func")->empty());
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+
+ // Materialize @after, pulling in @func.
+ EXPECT_FALSE(M->getFunction("after")->Materialize());
+ EXPECT_FALSE(M->getFunction("func")->empty());
+ EXPECT_TRUE(M->getFunction("other")->empty());
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+
+ // Try (and fail) to dematerialize @func.
+ M->getFunction("func")->Dematerialize();
+ EXPECT_FALSE(M->getFunction("func")->empty());
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
}
} // end namespace