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/InstrTypes.h" 15 #include "llvm/IR/LLVMContext.h" 16 #include "llvm/IR/Module.h" 17 #include "llvm/IR/Verifier.h" 18 #include "llvm/Support/Debug.h" 19 #include "llvm/Support/Error.h" 20 #include "llvm/Support/MemoryBuffer.h" 21 #include "llvm/Support/SourceMgr.h" 22 #include "gtest/gtest.h" 23 24 using namespace llvm; 25 26 namespace { 27 28 std::unique_ptr<Module> parseAssembly(LLVMContext &Context, 29 const char *Assembly) { 30 SMDiagnostic Error; 31 std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context); 32 33 std::string ErrMsg; 34 raw_string_ostream OS(ErrMsg); 35 Error.print("", OS); 36 37 // A failure here means that the test itself is buggy. 38 if (!M) 39 report_fatal_error(OS.str().c_str()); 40 41 return M; 42 } 43 44 static void writeModuleToBuffer(std::unique_ptr<Module> Mod, 45 SmallVectorImpl<char> &Buffer) { 46 raw_svector_ostream OS(Buffer); 47 WriteBitcodeToFile(*Mod, OS); 48 } 49 50 static std::unique_ptr<Module> getLazyModuleFromAssembly(LLVMContext &Context, 51 SmallString<1024> &Mem, 52 const char *Assembly) { 53 writeModuleToBuffer(parseAssembly(Context, Assembly), Mem); 54 Expected<std::unique_ptr<Module>> ModuleOrErr = 55 getLazyBitcodeModule(MemoryBufferRef(Mem.str(), "test"), Context); 56 if (!ModuleOrErr) 57 report_fatal_error("Could not parse bitcode module"); 58 return std::move(ModuleOrErr.get()); 59 } 60 61 // Tests that lazy evaluation can parse functions out of order. 62 TEST(BitReaderTest, MaterializeFunctionsOutOfOrder) { 63 SmallString<1024> Mem; 64 LLVMContext Context; 65 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 66 Context, Mem, "define void @f() {\n" 67 " unreachable\n" 68 "}\n" 69 "define void @g() {\n" 70 " unreachable\n" 71 "}\n" 72 "define void @h() {\n" 73 " unreachable\n" 74 "}\n" 75 "define void @j() {\n" 76 " unreachable\n" 77 "}\n"); 78 EXPECT_FALSE(verifyModule(*M, &dbgs())); 79 80 Function *F = M->getFunction("f"); 81 Function *G = M->getFunction("g"); 82 Function *H = M->getFunction("h"); 83 Function *J = M->getFunction("j"); 84 85 // Initially all functions are not materialized (no basic blocks). 86 EXPECT_TRUE(F->empty()); 87 EXPECT_TRUE(G->empty()); 88 EXPECT_TRUE(H->empty()); 89 EXPECT_TRUE(J->empty()); 90 EXPECT_FALSE(verifyModule(*M, &dbgs())); 91 92 // Materialize h. 93 ASSERT_FALSE(H->materialize()); 94 EXPECT_TRUE(F->empty()); 95 EXPECT_TRUE(G->empty()); 96 EXPECT_FALSE(H->empty()); 97 EXPECT_TRUE(J->empty()); 98 EXPECT_FALSE(verifyModule(*M, &dbgs())); 99 100 // Materialize g. 101 ASSERT_FALSE(G->materialize()); 102 EXPECT_TRUE(F->empty()); 103 EXPECT_FALSE(G->empty()); 104 EXPECT_FALSE(H->empty()); 105 EXPECT_TRUE(J->empty()); 106 EXPECT_FALSE(verifyModule(*M, &dbgs())); 107 108 // Materialize j. 109 ASSERT_FALSE(J->materialize()); 110 EXPECT_TRUE(F->empty()); 111 EXPECT_FALSE(G->empty()); 112 EXPECT_FALSE(H->empty()); 113 EXPECT_FALSE(J->empty()); 114 EXPECT_FALSE(verifyModule(*M, &dbgs())); 115 116 // Materialize f. 117 ASSERT_FALSE(F->materialize()); 118 EXPECT_FALSE(F->empty()); 119 EXPECT_FALSE(G->empty()); 120 EXPECT_FALSE(H->empty()); 121 EXPECT_FALSE(J->empty()); 122 EXPECT_FALSE(verifyModule(*M, &dbgs())); 123 } 124 125 TEST(BitReaderTest, MaterializeFunctionsStrictFP) { 126 SmallString<1024> Mem; 127 128 LLVMContext Context; 129 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 130 Context, Mem, "define double @foo(double %a) {\n" 131 " %result = call double @bar(double %a) strictfp\n" 132 " ret double %result\n" 133 "}\n" 134 "declare double @bar(double)\n"); 135 Function *Foo = M->getFunction("foo"); 136 ASSERT_FALSE(Foo->materialize()); 137 EXPECT_FALSE(Foo->empty()); 138 139 for (auto &BB : *Foo) { 140 auto It = BB.begin(); 141 while (It != BB.end()) { 142 Instruction &I = *It; 143 ++It; 144 145 if (auto *Call = dyn_cast<CallBase>(&I)) { 146 EXPECT_FALSE(Call->isStrictFP()); 147 EXPECT_TRUE(Call->isNoBuiltin()); 148 } 149 } 150 } 151 152 EXPECT_FALSE(verifyModule(*M, &dbgs())); 153 } 154 155 TEST(BitReaderTest, MaterializeConstrainedFPStrictFP) { 156 SmallString<1024> Mem; 157 158 LLVMContext Context; 159 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 160 Context, Mem, 161 "define double @foo(double %a) {\n" 162 " %result = call double @llvm.experimental.constrained.sqrt.f64(double " 163 "%a, metadata !\"round.tonearest\", metadata !\"fpexcept.strict\") " 164 "strictfp\n" 165 " ret double %result\n" 166 "}\n" 167 "declare double @llvm.experimental.constrained.sqrt.f64(double, " 168 "metadata, metadata)\n"); 169 Function *Foo = M->getFunction("foo"); 170 ASSERT_FALSE(Foo->materialize()); 171 EXPECT_FALSE(Foo->empty()); 172 173 for (auto &BB : *Foo) { 174 auto It = BB.begin(); 175 while (It != BB.end()) { 176 Instruction &I = *It; 177 ++It; 178 179 if (auto *Call = dyn_cast<CallBase>(&I)) { 180 EXPECT_TRUE(Call->isStrictFP()); 181 EXPECT_FALSE(Call->isNoBuiltin()); 182 } 183 } 184 } 185 186 EXPECT_FALSE(verifyModule(*M, &dbgs())); 187 } 188 189 TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677 190 SmallString<1024> Mem; 191 192 LLVMContext Context; 193 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 194 Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n" 195 "define void @func() {\n" 196 " unreachable\n" 197 "bb:\n" 198 " unreachable\n" 199 "}\n"); 200 EXPECT_FALSE(verifyModule(*M, &dbgs())); 201 EXPECT_FALSE(M->getFunction("func")->empty()); 202 } 203 204 TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) { 205 SmallString<1024> Mem; 206 207 LLVMContext Context; 208 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 209 Context, Mem, "define i8* @before() {\n" 210 " ret i8* blockaddress(@func, %bb)\n" 211 "}\n" 212 "define void @other() {\n" 213 " unreachable\n" 214 "}\n" 215 "define void @func() {\n" 216 " unreachable\n" 217 "bb:\n" 218 " unreachable\n" 219 "}\n"); 220 EXPECT_TRUE(M->getFunction("before")->empty()); 221 EXPECT_TRUE(M->getFunction("func")->empty()); 222 EXPECT_FALSE(verifyModule(*M, &dbgs())); 223 224 // Materialize @before, pulling in @func. 225 EXPECT_FALSE(M->getFunction("before")->materialize()); 226 EXPECT_FALSE(M->getFunction("func")->empty()); 227 EXPECT_TRUE(M->getFunction("other")->empty()); 228 EXPECT_FALSE(verifyModule(*M, &dbgs())); 229 } 230 231 TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) { 232 SmallString<1024> Mem; 233 234 LLVMContext Context; 235 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 236 Context, Mem, "define void @func() {\n" 237 " unreachable\n" 238 "bb:\n" 239 " unreachable\n" 240 "}\n" 241 "define void @other() {\n" 242 " unreachable\n" 243 "}\n" 244 "define i8* @after() {\n" 245 " ret i8* blockaddress(@func, %bb)\n" 246 "}\n"); 247 EXPECT_TRUE(M->getFunction("after")->empty()); 248 EXPECT_TRUE(M->getFunction("func")->empty()); 249 EXPECT_FALSE(verifyModule(*M, &dbgs())); 250 251 // Materialize @after, pulling in @func. 252 EXPECT_FALSE(M->getFunction("after")->materialize()); 253 EXPECT_FALSE(M->getFunction("func")->empty()); 254 EXPECT_TRUE(M->getFunction("other")->empty()); 255 EXPECT_FALSE(verifyModule(*M, &dbgs())); 256 } 257 258 } // end namespace 259