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 SMDiagnostic Error; 30 std::unique_ptr<Module> M = 31 parseAssemblyString(Assembly, Error, getGlobalContext()); 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.get(), OS); 48 } 49 50 static std::unique_ptr<Module> getLazyModuleFromAssembly(LLVMContext &Context, 51 SmallString<1024> &Mem, 52 const char *Assembly) { 53 writeModuleToBuffer(parseAssembly(Assembly), Mem); 54 std::unique_ptr<MemoryBuffer> Buffer = 55 MemoryBuffer::getMemBuffer(Mem.str(), "test", false); 56 ErrorOr<Module *> ModuleOrErr = 57 getLazyBitcodeModule(std::move(Buffer), Context); 58 return std::unique_ptr<Module>(ModuleOrErr.get()); 59 } 60 61 TEST(BitReaderTest, DematerializeFunctionPreservesLinkageType) { 62 SmallString<1024> Mem; 63 64 LLVMContext Context; 65 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 66 Context, Mem, "define internal i32 @func() {\n" 67 "ret i32 0\n" 68 "}\n"); 69 70 EXPECT_FALSE(verifyModule(*M, &dbgs())); 71 72 M->getFunction("func")->materialize(); 73 EXPECT_FALSE(M->getFunction("func")->empty()); 74 EXPECT_TRUE(M->getFunction("func")->getLinkage() == 75 GlobalValue::InternalLinkage); 76 77 // Check that the linkage type is preserved after dematerialization. 78 M->getFunction("func")->Dematerialize(); 79 EXPECT_TRUE(M->getFunction("func")->empty()); 80 EXPECT_TRUE(M->getFunction("func")->getLinkage() == 81 GlobalValue::InternalLinkage); 82 EXPECT_FALSE(verifyModule(*M, &dbgs())); 83 } 84 85 TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677 86 SmallString<1024> Mem; 87 88 LLVMContext Context; 89 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 90 Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n" 91 "define void @func() {\n" 92 " unreachable\n" 93 "bb:\n" 94 " unreachable\n" 95 "}\n"); 96 EXPECT_FALSE(verifyModule(*M, &dbgs())); 97 98 // Try (and fail) to dematerialize @func. 99 M->getFunction("func")->Dematerialize(); 100 EXPECT_FALSE(M->getFunction("func")->empty()); 101 } 102 103 TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) { 104 SmallString<1024> Mem; 105 106 LLVMContext Context; 107 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 108 Context, Mem, "define i8* @before() {\n" 109 " ret i8* blockaddress(@func, %bb)\n" 110 "}\n" 111 "define void @other() {\n" 112 " unreachable\n" 113 "}\n" 114 "define void @func() {\n" 115 " unreachable\n" 116 "bb:\n" 117 " unreachable\n" 118 "}\n"); 119 EXPECT_TRUE(M->getFunction("before")->empty()); 120 EXPECT_TRUE(M->getFunction("func")->empty()); 121 EXPECT_FALSE(verifyModule(*M, &dbgs())); 122 123 // Materialize @before, pulling in @func. 124 EXPECT_FALSE(M->getFunction("before")->materialize()); 125 EXPECT_FALSE(M->getFunction("func")->empty()); 126 EXPECT_TRUE(M->getFunction("other")->empty()); 127 EXPECT_FALSE(verifyModule(*M, &dbgs())); 128 129 // Try (and fail) to dematerialize @func. 130 M->getFunction("func")->Dematerialize(); 131 EXPECT_FALSE(M->getFunction("func")->empty()); 132 EXPECT_FALSE(verifyModule(*M, &dbgs())); 133 } 134 135 TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) { 136 SmallString<1024> Mem; 137 138 LLVMContext Context; 139 std::unique_ptr<Module> M = getLazyModuleFromAssembly( 140 Context, Mem, "define void @func() {\n" 141 " unreachable\n" 142 "bb:\n" 143 " unreachable\n" 144 "}\n" 145 "define void @other() {\n" 146 " unreachable\n" 147 "}\n" 148 "define i8* @after() {\n" 149 " ret i8* blockaddress(@func, %bb)\n" 150 "}\n"); 151 EXPECT_TRUE(M->getFunction("after")->empty()); 152 EXPECT_TRUE(M->getFunction("func")->empty()); 153 EXPECT_FALSE(verifyModule(*M, &dbgs())); 154 155 // Materialize @after, pulling in @func. 156 EXPECT_FALSE(M->getFunction("after")->materialize()); 157 EXPECT_FALSE(M->getFunction("func")->empty()); 158 EXPECT_TRUE(M->getFunction("other")->empty()); 159 EXPECT_FALSE(verifyModule(*M, &dbgs())); 160 161 // Try (and fail) to dematerialize @func. 162 M->getFunction("func")->Dematerialize(); 163 EXPECT_FALSE(M->getFunction("func")->empty()); 164 EXPECT_FALSE(verifyModule(*M, &dbgs())); 165 } 166 167 } // end namespace 168