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