1 //===- llvm/unittest/Bitcode/BitReaderTest.cpp - Tests for BitReader ------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ADT/STLExtras.h" 10 #include "llvm/ADT/SmallString.h" 11 #include "llvm/AsmParser/Parser.h" 12 #include "llvm/Bitcode/BitcodeReader.h" 13 #include "llvm/Bitcode/BitcodeWriter.h" 14 #include "llvm/IR/LLVMContext.h" 15 #include "llvm/IR/Module.h" 16 #include "llvm/IR/Verifier.h" 17 #include "llvm/Support/Debug.h" 18 #include "llvm/Support/Error.h" 19 #include "llvm/Support/MemoryBuffer.h" 20 #include "llvm/Support/SourceMgr.h" 21 #include "gtest/gtest.h" 22 23 using namespace llvm; 24 25 namespace { 26 27 std::unique_ptr<Module> parseAssembly(LLVMContext &Context, 28 const char *Assembly) { 29 SMDiagnostic Error; 30 std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context); 31 32 std::string ErrMsg; 33 raw_string_ostream OS(ErrMsg); 34 Error.print("", OS); 35 36 // A failure here means that the test itself is buggy. 37 if (!M) 38 report_fatal_error(OS.str().c_str()); 39 40 return M; 41 } 42 43 static void writeModuleToBuffer(std::unique_ptr<Module> Mod, 44 SmallVectorImpl<char> &Buffer) { 45 raw_svector_ostream OS(Buffer); 46 WriteBitcodeToFile(*Mod, OS); 47 } 48 49 static std::unique_ptr<Module> getLazyModuleFromAssembly(LLVMContext &Context, 50 SmallString<1024> &Mem, 51 const char *Assembly) { 52 writeModuleToBuffer(parseAssembly(Context, Assembly), Mem); 53 Expected<std::unique_ptr<Module>> ModuleOrErr = 54 getLazyBitcodeModule(MemoryBufferRef(Mem.str(), "test"), Context); 55 if (!ModuleOrErr) 56 report_fatal_error("Could not parse bitcode module"); 57 return std::move(ModuleOrErr.get()); 58 } 59 60 // Tests that lazy evaluation can parse functions out of order. 61 TEST(BitReaderTest, MaterializeFunctionsOutOfOrder) { 62 SmallString<1024> Mem; 63 LLVMContext Context; 64 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 65 Context, Mem, "define void @f() {\n" 66 " unreachable\n" 67 "}\n" 68 "define void @g() {\n" 69 " unreachable\n" 70 "}\n" 71 "define void @h() {\n" 72 " unreachable\n" 73 "}\n" 74 "define void @j() {\n" 75 " unreachable\n" 76 "}\n"); 77 EXPECT_FALSE(verifyModule(*M, &dbgs())); 78 79 Function *F = M->getFunction("f"); 80 Function *G = M->getFunction("g"); 81 Function *H = M->getFunction("h"); 82 Function *J = M->getFunction("j"); 83 84 // Initially all functions are not materialized (no basic blocks). 85 EXPECT_TRUE(F->empty()); 86 EXPECT_TRUE(G->empty()); 87 EXPECT_TRUE(H->empty()); 88 EXPECT_TRUE(J->empty()); 89 EXPECT_FALSE(verifyModule(*M, &dbgs())); 90 91 // Materialize h. 92 ASSERT_FALSE(H->materialize()); 93 EXPECT_TRUE(F->empty()); 94 EXPECT_TRUE(G->empty()); 95 EXPECT_FALSE(H->empty()); 96 EXPECT_TRUE(J->empty()); 97 EXPECT_FALSE(verifyModule(*M, &dbgs())); 98 99 // Materialize g. 100 ASSERT_FALSE(G->materialize()); 101 EXPECT_TRUE(F->empty()); 102 EXPECT_FALSE(G->empty()); 103 EXPECT_FALSE(H->empty()); 104 EXPECT_TRUE(J->empty()); 105 EXPECT_FALSE(verifyModule(*M, &dbgs())); 106 107 // Materialize j. 108 ASSERT_FALSE(J->materialize()); 109 EXPECT_TRUE(F->empty()); 110 EXPECT_FALSE(G->empty()); 111 EXPECT_FALSE(H->empty()); 112 EXPECT_FALSE(J->empty()); 113 EXPECT_FALSE(verifyModule(*M, &dbgs())); 114 115 // Materialize f. 116 ASSERT_FALSE(F->materialize()); 117 EXPECT_FALSE(F->empty()); 118 EXPECT_FALSE(G->empty()); 119 EXPECT_FALSE(H->empty()); 120 EXPECT_FALSE(J->empty()); 121 EXPECT_FALSE(verifyModule(*M, &dbgs())); 122 } 123 124 TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677 125 SmallString<1024> Mem; 126 127 LLVMContext Context; 128 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 129 Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n" 130 "define void @func() {\n" 131 " unreachable\n" 132 "bb:\n" 133 " unreachable\n" 134 "}\n"); 135 EXPECT_FALSE(verifyModule(*M, &dbgs())); 136 EXPECT_FALSE(M->getFunction("func")->empty()); 137 } 138 139 TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) { 140 SmallString<1024> Mem; 141 142 LLVMContext Context; 143 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 144 Context, Mem, "define i8* @before() {\n" 145 " ret i8* blockaddress(@func, %bb)\n" 146 "}\n" 147 "define void @other() {\n" 148 " unreachable\n" 149 "}\n" 150 "define void @func() {\n" 151 " unreachable\n" 152 "bb:\n" 153 " unreachable\n" 154 "}\n"); 155 EXPECT_TRUE(M->getFunction("before")->empty()); 156 EXPECT_TRUE(M->getFunction("func")->empty()); 157 EXPECT_FALSE(verifyModule(*M, &dbgs())); 158 159 // Materialize @before, pulling in @func. 160 EXPECT_FALSE(M->getFunction("before")->materialize()); 161 EXPECT_FALSE(M->getFunction("func")->empty()); 162 EXPECT_TRUE(M->getFunction("other")->empty()); 163 EXPECT_FALSE(verifyModule(*M, &dbgs())); 164 } 165 166 TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) { 167 SmallString<1024> Mem; 168 169 LLVMContext Context; 170 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 171 Context, Mem, "define void @func() {\n" 172 " unreachable\n" 173 "bb:\n" 174 " unreachable\n" 175 "}\n" 176 "define void @other() {\n" 177 " unreachable\n" 178 "}\n" 179 "define i8* @after() {\n" 180 " ret i8* blockaddress(@func, %bb)\n" 181 "}\n"); 182 EXPECT_TRUE(M->getFunction("after")->empty()); 183 EXPECT_TRUE(M->getFunction("func")->empty()); 184 EXPECT_FALSE(verifyModule(*M, &dbgs())); 185 186 // Materialize @after, pulling in @func. 187 EXPECT_FALSE(M->getFunction("after")->materialize()); 188 EXPECT_FALSE(M->getFunction("func")->empty()); 189 EXPECT_TRUE(M->getFunction("other")->empty()); 190 EXPECT_FALSE(verifyModule(*M, &dbgs())); 191 } 192 193 } // end namespace 194