| Chandler Carruth | e517273 | 2012-01-02 09:19:48 +0000 | [diff] [blame] | 1 | //===- llvm/unittest/Bitcode/BitReaderTest.cpp - Tests for BitReader ------===// |
| Rafael Espindola | b799346 | 2012-01-02 07:49:53 +0000 | [diff] [blame] | 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| Rafael Espindola | 456baad | 2015-06-17 01:15:47 +0000 | [diff] [blame] | 10 | #include "llvm/ADT/STLExtras.h" |
| Teresa Johnson | ad17679 | 2016-11-11 05:34:58 +0000 | [diff] [blame] | 11 | #include "llvm/ADT/SmallString.h" |
| Chandler Carruth | d990388 | 2015-01-14 11:23:27 +0000 | [diff] [blame] | 12 | #include "llvm/AsmParser/Parser.h" |
| Teresa Johnson | ad17679 | 2016-11-11 05:34:58 +0000 | [diff] [blame] | 13 | #include "llvm/Bitcode/BitcodeReader.h" |
| 14 | #include "llvm/Bitcode/BitcodeWriter.h" |
| Derek Schuff | b4c1c28 | 2015-08-03 18:01:50 +0000 | [diff] [blame] | 15 | #include "llvm/Bitcode/BitstreamReader.h" |
| Rafael Espindola | b799346 | 2012-01-02 07:49:53 +0000 | [diff] [blame] | 16 | #include "llvm/Bitcode/BitstreamWriter.h" |
| Chandler Carruth | 9fb823b | 2013-01-02 11:36:10 +0000 | [diff] [blame] | 17 | #include "llvm/IR/Constants.h" |
| 18 | #include "llvm/IR/Instructions.h" |
| 19 | #include "llvm/IR/LLVMContext.h" |
| 20 | #include "llvm/IR/Module.h" |
| Chandler Carruth | 5ad5f15 | 2014-01-13 09:26:24 +0000 | [diff] [blame] | 21 | #include "llvm/IR/Verifier.h" |
| Duncan P. N. Exon Smith | 7a2990c | 2014-08-01 21:01:04 +0000 | [diff] [blame] | 22 | #include "llvm/Support/Debug.h" |
| Peter Collingbourne | 7f00d0a | 2016-11-09 17:49:19 +0000 | [diff] [blame] | 23 | #include "llvm/Support/Error.h" |
| Rafael Espindola | b799346 | 2012-01-02 07:49:53 +0000 | [diff] [blame] | 24 | #include "llvm/Support/MemoryBuffer.h" |
| Duncan P. N. Exon Smith | 7a2990c | 2014-08-01 21:01:04 +0000 | [diff] [blame] | 25 | #include "llvm/Support/SourceMgr.h" |
| Rafael Espindola | b799346 | 2012-01-02 07:49:53 +0000 | [diff] [blame] | 26 | #include "gtest/gtest.h" |
| 27 | |
| Duncan P. N. Exon Smith | 7a2990c | 2014-08-01 21:01:04 +0000 | [diff] [blame] | 28 | using namespace llvm; |
| 29 | |
| Rafael Espindola | b799346 | 2012-01-02 07:49:53 +0000 | [diff] [blame] | 30 | namespace { |
| 31 | |
| Mehdi Amini | 03b42e4 | 2016-04-14 21:59:01 +0000 | [diff] [blame] | 32 | std::unique_ptr<Module> parseAssembly(LLVMContext &Context, |
| 33 | const char *Assembly) { |
| Duncan P. N. Exon Smith | 7a2990c | 2014-08-01 21:01:04 +0000 | [diff] [blame] | 34 | SMDiagnostic Error; |
| Mehdi Amini | 03b42e4 | 2016-04-14 21:59:01 +0000 | [diff] [blame] | 35 | std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context); |
| Rafael Espindola | b799346 | 2012-01-02 07:49:53 +0000 | [diff] [blame] | 36 | |
| Duncan P. N. Exon Smith | 7a2990c | 2014-08-01 21:01:04 +0000 | [diff] [blame] | 37 | std::string ErrMsg; |
| 38 | raw_string_ostream OS(ErrMsg); |
| 39 | Error.print("", OS); |
| Rafael Espindola | b799346 | 2012-01-02 07:49:53 +0000 | [diff] [blame] | 40 | |
| Duncan P. N. Exon Smith | 7a2990c | 2014-08-01 21:01:04 +0000 | [diff] [blame] | 41 | // A failure here means that the test itself is buggy. |
| Rafael Espindola | 11c07d7 | 2014-08-19 16:58:54 +0000 | [diff] [blame] | 42 | if (!M) |
| Duncan P. N. Exon Smith | 7a2990c | 2014-08-01 21:01:04 +0000 | [diff] [blame] | 43 | report_fatal_error(OS.str().c_str()); |
| Rafael Espindola | b799346 | 2012-01-02 07:49:53 +0000 | [diff] [blame] | 44 | |
| Duncan P. N. Exon Smith | 7a2990c | 2014-08-01 21:01:04 +0000 | [diff] [blame] | 45 | return M; |
| Rafael Espindola | b799346 | 2012-01-02 07:49:53 +0000 | [diff] [blame] | 46 | } |
| 47 | |
| Duncan P. N. Exon Smith | 7a2990c | 2014-08-01 21:01:04 +0000 | [diff] [blame] | 48 | static void writeModuleToBuffer(std::unique_ptr<Module> Mod, |
| 49 | SmallVectorImpl<char> &Buffer) { |
| Daniel Dunbar | 5fa5ecf | 2012-02-29 20:30:56 +0000 | [diff] [blame] | 50 | raw_svector_ostream OS(Buffer); |
| NAKAMURA Takumi | 508baf7 | 2013-01-23 08:33:13 +0000 | [diff] [blame] | 51 | WriteBitcodeToFile(Mod.get(), OS); |
| Rafael Espindola | b799346 | 2012-01-02 07:49:53 +0000 | [diff] [blame] | 52 | } |
| 53 | |
| Duncan P. N. Exon Smith | 7a2990c | 2014-08-01 21:01:04 +0000 | [diff] [blame] | 54 | static std::unique_ptr<Module> getLazyModuleFromAssembly(LLVMContext &Context, |
| 55 | SmallString<1024> &Mem, |
| 56 | const char *Assembly) { |
| Mehdi Amini | 03b42e4 | 2016-04-14 21:59:01 +0000 | [diff] [blame] | 57 | writeModuleToBuffer(parseAssembly(Context, Assembly), Mem); |
| Peter Collingbourne | d9445c4 | 2016-11-13 07:00:17 +0000 | [diff] [blame] | 58 | Expected<std::unique_ptr<Module>> ModuleOrErr = |
| Peter Collingbourne | e2dcf7c | 2016-11-08 06:03:43 +0000 | [diff] [blame] | 59 | getLazyBitcodeModule(MemoryBufferRef(Mem.str(), "test"), Context); |
| Peter Collingbourne | d9445c4 | 2016-11-13 07:00:17 +0000 | [diff] [blame] | 60 | if (!ModuleOrErr) |
| 61 | report_fatal_error("Could not parse bitcode module"); |
| Rafael Espindola | dcd1dca | 2015-06-16 22:27:55 +0000 | [diff] [blame] | 62 | return std::move(ModuleOrErr.get()); |
| Rafael Espindola | b799346 | 2012-01-02 07:49:53 +0000 | [diff] [blame] | 63 | } |
| Chandler Carruth | e517273 | 2012-01-02 09:19:48 +0000 | [diff] [blame] | 64 | |
| Derek Schuff | 5d8dfd3 | 2015-05-06 16:52:35 +0000 | [diff] [blame] | 65 | // Tests that lazy evaluation can parse functions out of order. |
| 66 | TEST(BitReaderTest, MaterializeFunctionsOutOfOrder) { |
| 67 | SmallString<1024> Mem; |
| 68 | LLVMContext Context; |
| 69 | std::unique_ptr<Module> M = getLazyModuleFromAssembly( |
| 70 | Context, Mem, "define void @f() {\n" |
| 71 | " unreachable\n" |
| 72 | "}\n" |
| 73 | "define void @g() {\n" |
| 74 | " unreachable\n" |
| 75 | "}\n" |
| 76 | "define void @h() {\n" |
| 77 | " unreachable\n" |
| 78 | "}\n" |
| 79 | "define void @j() {\n" |
| 80 | " unreachable\n" |
| 81 | "}\n"); |
| 82 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
| 83 | |
| 84 | Function *F = M->getFunction("f"); |
| 85 | Function *G = M->getFunction("g"); |
| 86 | Function *H = M->getFunction("h"); |
| 87 | Function *J = M->getFunction("j"); |
| 88 | |
| 89 | // Initially all functions are not materialized (no basic blocks). |
| 90 | EXPECT_TRUE(F->empty()); |
| 91 | EXPECT_TRUE(G->empty()); |
| 92 | EXPECT_TRUE(H->empty()); |
| 93 | EXPECT_TRUE(J->empty()); |
| 94 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
| 95 | |
| 96 | // Materialize h. |
| Peter Collingbourne | 7f00d0a | 2016-11-09 17:49:19 +0000 | [diff] [blame] | 97 | ASSERT_FALSE(H->materialize()); |
| Derek Schuff | 5d8dfd3 | 2015-05-06 16:52:35 +0000 | [diff] [blame] | 98 | EXPECT_TRUE(F->empty()); |
| 99 | EXPECT_TRUE(G->empty()); |
| 100 | EXPECT_FALSE(H->empty()); |
| 101 | EXPECT_TRUE(J->empty()); |
| 102 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
| 103 | |
| 104 | // Materialize g. |
| Peter Collingbourne | 7f00d0a | 2016-11-09 17:49:19 +0000 | [diff] [blame] | 105 | ASSERT_FALSE(G->materialize()); |
| Derek Schuff | 5d8dfd3 | 2015-05-06 16:52:35 +0000 | [diff] [blame] | 106 | EXPECT_TRUE(F->empty()); |
| 107 | EXPECT_FALSE(G->empty()); |
| 108 | EXPECT_FALSE(H->empty()); |
| 109 | EXPECT_TRUE(J->empty()); |
| 110 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
| 111 | |
| 112 | // Materialize j. |
| Peter Collingbourne | 7f00d0a | 2016-11-09 17:49:19 +0000 | [diff] [blame] | 113 | ASSERT_FALSE(J->materialize()); |
| Derek Schuff | 5d8dfd3 | 2015-05-06 16:52:35 +0000 | [diff] [blame] | 114 | EXPECT_TRUE(F->empty()); |
| 115 | EXPECT_FALSE(G->empty()); |
| 116 | EXPECT_FALSE(H->empty()); |
| 117 | EXPECT_FALSE(J->empty()); |
| 118 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
| 119 | |
| 120 | // Materialize f. |
| Peter Collingbourne | 7f00d0a | 2016-11-09 17:49:19 +0000 | [diff] [blame] | 121 | ASSERT_FALSE(F->materialize()); |
| Derek Schuff | 5d8dfd3 | 2015-05-06 16:52:35 +0000 | [diff] [blame] | 122 | EXPECT_FALSE(F->empty()); |
| 123 | EXPECT_FALSE(G->empty()); |
| 124 | EXPECT_FALSE(H->empty()); |
| 125 | EXPECT_FALSE(J->empty()); |
| 126 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
| 127 | } |
| 128 | |
| Duncan P. N. Exon Smith | 7a2990c | 2014-08-01 21:01:04 +0000 | [diff] [blame] | 129 | TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677 |
| 130 | SmallString<1024> Mem; |
| 131 | |
| 132 | LLVMContext Context; |
| 133 | std::unique_ptr<Module> M = getLazyModuleFromAssembly( |
| 134 | Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n" |
| 135 | "define void @func() {\n" |
| 136 | " unreachable\n" |
| 137 | "bb:\n" |
| 138 | " unreachable\n" |
| 139 | "}\n"); |
| 140 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
| Peter Collingbourne | 028eb5a | 2016-11-02 00:08:19 +0000 | [diff] [blame] | 141 | EXPECT_FALSE(M->getFunction("func")->empty()); |
| Duncan P. N. Exon Smith | 908d809 | 2014-08-01 21:11:34 +0000 | [diff] [blame] | 142 | } |
| 143 | |
| 144 | TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) { |
| 145 | SmallString<1024> Mem; |
| 146 | |
| 147 | LLVMContext Context; |
| 148 | std::unique_ptr<Module> M = getLazyModuleFromAssembly( |
| 149 | Context, Mem, "define i8* @before() {\n" |
| 150 | " ret i8* blockaddress(@func, %bb)\n" |
| 151 | "}\n" |
| 152 | "define void @other() {\n" |
| 153 | " unreachable\n" |
| 154 | "}\n" |
| 155 | "define void @func() {\n" |
| 156 | " unreachable\n" |
| 157 | "bb:\n" |
| 158 | " unreachable\n" |
| 159 | "}\n"); |
| 160 | EXPECT_TRUE(M->getFunction("before")->empty()); |
| 161 | EXPECT_TRUE(M->getFunction("func")->empty()); |
| 162 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
| 163 | |
| 164 | // Materialize @before, pulling in @func. |
| Rafael Espindola | 5a52e6d | 2014-10-24 22:50:48 +0000 | [diff] [blame] | 165 | EXPECT_FALSE(M->getFunction("before")->materialize()); |
| Duncan P. N. Exon Smith | 908d809 | 2014-08-01 21:11:34 +0000 | [diff] [blame] | 166 | EXPECT_FALSE(M->getFunction("func")->empty()); |
| 167 | EXPECT_TRUE(M->getFunction("other")->empty()); |
| 168 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
| Duncan P. N. Exon Smith | 908d809 | 2014-08-01 21:11:34 +0000 | [diff] [blame] | 169 | } |
| 170 | |
| 171 | TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) { |
| 172 | SmallString<1024> Mem; |
| 173 | |
| 174 | LLVMContext Context; |
| 175 | std::unique_ptr<Module> M = getLazyModuleFromAssembly( |
| 176 | Context, Mem, "define void @func() {\n" |
| 177 | " unreachable\n" |
| 178 | "bb:\n" |
| 179 | " unreachable\n" |
| 180 | "}\n" |
| 181 | "define void @other() {\n" |
| 182 | " unreachable\n" |
| 183 | "}\n" |
| 184 | "define i8* @after() {\n" |
| 185 | " ret i8* blockaddress(@func, %bb)\n" |
| 186 | "}\n"); |
| 187 | EXPECT_TRUE(M->getFunction("after")->empty()); |
| 188 | EXPECT_TRUE(M->getFunction("func")->empty()); |
| 189 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
| 190 | |
| 191 | // Materialize @after, pulling in @func. |
| Rafael Espindola | 5a52e6d | 2014-10-24 22:50:48 +0000 | [diff] [blame] | 192 | EXPECT_FALSE(M->getFunction("after")->materialize()); |
| Duncan P. N. Exon Smith | 908d809 | 2014-08-01 21:11:34 +0000 | [diff] [blame] | 193 | EXPECT_FALSE(M->getFunction("func")->empty()); |
| 194 | EXPECT_TRUE(M->getFunction("other")->empty()); |
| 195 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
| Rafael Espindola | b799346 | 2012-01-02 07:49:53 +0000 | [diff] [blame] | 196 | } |
| Duncan P. N. Exon Smith | 7a2990c | 2014-08-01 21:01:04 +0000 | [diff] [blame] | 197 | |
| 198 | } // end namespace |