1 //===- llvm/unittest/Bitcode/BitReaderTest.cpp - Tests for BitReader ------===// 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 10 #include "llvm/ADT/SmallString.h" 11 #include "llvm/Bitcode/BitstreamWriter.h" 12 #include "llvm/Bitcode/ReaderWriter.h" 13 #include "llvm/AsmParser/Parser.h" 14 #include "llvm/IR/Constants.h" 15 #include "llvm/IR/Instructions.h" 16 #include "llvm/IR/LLVMContext.h" 17 #include "llvm/IR/Module.h" 18 #include "llvm/IR/Verifier.h" 19 #include "llvm/Support/Debug.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(const char *Assembly) { 29 auto M = make_unique<Module>("Module", getGlobalContext()); 30 31 SMDiagnostic Error; 32 bool Parsed = 33 ParseAssemblyString(Assembly, M.get(), Error, M->getContext()) == M.get(); 34 35 std::string ErrMsg; 36 raw_string_ostream OS(ErrMsg); 37 Error.print("", OS); 38 39 // A failure here means that the test itself is buggy. 40 if (!Parsed) 41 report_fatal_error(OS.str().c_str()); 42 43 return M; 44 } 45 46 static void writeModuleToBuffer(std::unique_ptr<Module> Mod, 47 SmallVectorImpl<char> &Buffer) { 48 raw_svector_ostream OS(Buffer); 49 WriteBitcodeToFile(Mod.get(), OS); 50 } 51 52 static std::unique_ptr<Module> getLazyModuleFromAssembly(LLVMContext &Context, 53 SmallString<1024> &Mem, 54 const char *Assembly) { 55 writeModuleToBuffer(parseAssembly(Assembly), Mem); 56 MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(Mem.str(), "test", false); 57 ErrorOr<Module *> ModuleOrErr = getLazyBitcodeModule(Buffer, Context); 58 return std::unique_ptr<Module>(ModuleOrErr.get()); 59 } 60 61 TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677 62 SmallString<1024> Mem; 63 64 LLVMContext Context; 65 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 66 Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n" 67 "define void @func() {\n" 68 " unreachable\n" 69 "bb:\n" 70 " unreachable\n" 71 "}\n"); 72 EXPECT_FALSE(verifyModule(*M, &dbgs())); 73 74 // Try (and fail) to dematerialize @func. 75 M->getFunction("func")->Dematerialize(); 76 EXPECT_FALSE(M->getFunction("func")->empty()); 77 } 78 79 TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) { 80 SmallString<1024> Mem; 81 82 LLVMContext Context; 83 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 84 Context, Mem, "define i8* @before() {\n" 85 " ret i8* blockaddress(@func, %bb)\n" 86 "}\n" 87 "define void @other() {\n" 88 " unreachable\n" 89 "}\n" 90 "define void @func() {\n" 91 " unreachable\n" 92 "bb:\n" 93 " unreachable\n" 94 "}\n"); 95 EXPECT_TRUE(M->getFunction("before")->empty()); 96 EXPECT_TRUE(M->getFunction("func")->empty()); 97 EXPECT_FALSE(verifyModule(*M, &dbgs())); 98 99 // Materialize @before, pulling in @func. 100 EXPECT_FALSE(M->getFunction("before")->Materialize()); 101 EXPECT_FALSE(M->getFunction("func")->empty()); 102 EXPECT_TRUE(M->getFunction("other")->empty()); 103 EXPECT_FALSE(verifyModule(*M, &dbgs())); 104 105 // Try (and fail) to dematerialize @func. 106 M->getFunction("func")->Dematerialize(); 107 EXPECT_FALSE(M->getFunction("func")->empty()); 108 EXPECT_FALSE(verifyModule(*M, &dbgs())); 109 } 110 111 TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) { 112 SmallString<1024> Mem; 113 114 LLVMContext Context; 115 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 116 Context, Mem, "define void @func() {\n" 117 " unreachable\n" 118 "bb:\n" 119 " unreachable\n" 120 "}\n" 121 "define void @other() {\n" 122 " unreachable\n" 123 "}\n" 124 "define i8* @after() {\n" 125 " ret i8* blockaddress(@func, %bb)\n" 126 "}\n"); 127 EXPECT_TRUE(M->getFunction("after")->empty()); 128 EXPECT_TRUE(M->getFunction("func")->empty()); 129 EXPECT_FALSE(verifyModule(*M, &dbgs())); 130 131 // Materialize @after, pulling in @func. 132 EXPECT_FALSE(M->getFunction("after")->Materialize()); 133 EXPECT_FALSE(M->getFunction("func")->empty()); 134 EXPECT_TRUE(M->getFunction("other")->empty()); 135 EXPECT_FALSE(verifyModule(*M, &dbgs())); 136 137 // Try (and fail) to dematerialize @func. 138 M->getFunction("func")->Dematerialize(); 139 EXPECT_FALSE(M->getFunction("func")->empty()); 140 EXPECT_FALSE(verifyModule(*M, &dbgs())); 141 } 142 143 } // end namespace 144