xref: /llvm-project/llvm/unittests/Bitcode/BitReaderTest.cpp (revision 028eb5a3f823c25e6c3040d300910e23ed69e788)
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/ADT/STLExtras.h"
12 #include "llvm/AsmParser/Parser.h"
13 #include "llvm/Bitcode/BitstreamReader.h"
14 #include "llvm/Bitcode/BitstreamWriter.h"
15 #include "llvm/Bitcode/ReaderWriter.h"
16 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/Instructions.h"
18 #include "llvm/IR/LLVMContext.h"
19 #include "llvm/IR/Module.h"
20 #include "llvm/IR/Verifier.h"
21 #include "llvm/Support/Debug.h"
22 #include "llvm/Support/MemoryBuffer.h"
23 #include "llvm/Support/SourceMgr.h"
24 #include "gtest/gtest.h"
25 
26 using namespace llvm;
27 
28 namespace {
29 
30 std::unique_ptr<Module> parseAssembly(LLVMContext &Context,
31                                       const char *Assembly) {
32   SMDiagnostic Error;
33   std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context);
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 (!M)
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(Context, Assembly), Mem);
56   std::unique_ptr<MemoryBuffer> Buffer =
57       MemoryBuffer::getMemBuffer(Mem.str(), "test", false);
58   ErrorOr<std::unique_ptr<Module>> ModuleOrErr =
59       getLazyBitcodeModule(std::move(Buffer), Context);
60   return std::move(ModuleOrErr.get());
61 }
62 
63 // Tests that lazy evaluation can parse functions out of order.
64 TEST(BitReaderTest, MaterializeFunctionsOutOfOrder) {
65   SmallString<1024> Mem;
66   LLVMContext Context;
67   std::unique_ptr<Module> M = getLazyModuleFromAssembly(
68       Context, Mem, "define void @f() {\n"
69                     "  unreachable\n"
70                     "}\n"
71                     "define void @g() {\n"
72                     "  unreachable\n"
73                     "}\n"
74                     "define void @h() {\n"
75                     "  unreachable\n"
76                     "}\n"
77                     "define void @j() {\n"
78                     "  unreachable\n"
79                     "}\n");
80   EXPECT_FALSE(verifyModule(*M, &dbgs()));
81 
82   Function *F = M->getFunction("f");
83   Function *G = M->getFunction("g");
84   Function *H = M->getFunction("h");
85   Function *J = M->getFunction("j");
86 
87   // Initially all functions are not materialized (no basic blocks).
88   EXPECT_TRUE(F->empty());
89   EXPECT_TRUE(G->empty());
90   EXPECT_TRUE(H->empty());
91   EXPECT_TRUE(J->empty());
92   EXPECT_FALSE(verifyModule(*M, &dbgs()));
93 
94   // Materialize h.
95   H->materialize();
96   EXPECT_TRUE(F->empty());
97   EXPECT_TRUE(G->empty());
98   EXPECT_FALSE(H->empty());
99   EXPECT_TRUE(J->empty());
100   EXPECT_FALSE(verifyModule(*M, &dbgs()));
101 
102   // Materialize g.
103   G->materialize();
104   EXPECT_TRUE(F->empty());
105   EXPECT_FALSE(G->empty());
106   EXPECT_FALSE(H->empty());
107   EXPECT_TRUE(J->empty());
108   EXPECT_FALSE(verifyModule(*M, &dbgs()));
109 
110   // Materialize j.
111   J->materialize();
112   EXPECT_TRUE(F->empty());
113   EXPECT_FALSE(G->empty());
114   EXPECT_FALSE(H->empty());
115   EXPECT_FALSE(J->empty());
116   EXPECT_FALSE(verifyModule(*M, &dbgs()));
117 
118   // Materialize f.
119   F->materialize();
120   EXPECT_FALSE(F->empty());
121   EXPECT_FALSE(G->empty());
122   EXPECT_FALSE(H->empty());
123   EXPECT_FALSE(J->empty());
124   EXPECT_FALSE(verifyModule(*M, &dbgs()));
125 }
126 
127 TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677
128   SmallString<1024> Mem;
129 
130   LLVMContext Context;
131   std::unique_ptr<Module> M = getLazyModuleFromAssembly(
132       Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n"
133                     "define void @func() {\n"
134                     "  unreachable\n"
135                     "bb:\n"
136                     "  unreachable\n"
137                     "}\n");
138   EXPECT_FALSE(verifyModule(*M, &dbgs()));
139   EXPECT_FALSE(M->getFunction("func")->empty());
140 }
141 
142 TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) {
143   SmallString<1024> Mem;
144 
145   LLVMContext Context;
146   std::unique_ptr<Module> M = getLazyModuleFromAssembly(
147       Context, Mem, "define i8* @before() {\n"
148                     "  ret i8* blockaddress(@func, %bb)\n"
149                     "}\n"
150                     "define void @other() {\n"
151                     "  unreachable\n"
152                     "}\n"
153                     "define void @func() {\n"
154                     "  unreachable\n"
155                     "bb:\n"
156                     "  unreachable\n"
157                     "}\n");
158   EXPECT_TRUE(M->getFunction("before")->empty());
159   EXPECT_TRUE(M->getFunction("func")->empty());
160   EXPECT_FALSE(verifyModule(*M, &dbgs()));
161 
162   // Materialize @before, pulling in @func.
163   EXPECT_FALSE(M->getFunction("before")->materialize());
164   EXPECT_FALSE(M->getFunction("func")->empty());
165   EXPECT_TRUE(M->getFunction("other")->empty());
166   EXPECT_FALSE(verifyModule(*M, &dbgs()));
167 }
168 
169 TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) {
170   SmallString<1024> Mem;
171 
172   LLVMContext Context;
173   std::unique_ptr<Module> M = getLazyModuleFromAssembly(
174       Context, Mem, "define void @func() {\n"
175                     "  unreachable\n"
176                     "bb:\n"
177                     "  unreachable\n"
178                     "}\n"
179                     "define void @other() {\n"
180                     "  unreachable\n"
181                     "}\n"
182                     "define i8* @after() {\n"
183                     "  ret i8* blockaddress(@func, %bb)\n"
184                     "}\n");
185   EXPECT_TRUE(M->getFunction("after")->empty());
186   EXPECT_TRUE(M->getFunction("func")->empty());
187   EXPECT_FALSE(verifyModule(*M, &dbgs()));
188 
189   // Materialize @after, pulling in @func.
190   EXPECT_FALSE(M->getFunction("after")->materialize());
191   EXPECT_FALSE(M->getFunction("func")->empty());
192   EXPECT_TRUE(M->getFunction("other")->empty());
193   EXPECT_FALSE(verifyModule(*M, &dbgs()));
194 }
195 
196 } // end namespace
197