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