• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/InstrTypes.h"
15 #include "llvm/IR/LLVMContext.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/IR/Verifier.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/Error.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 
parseAssembly(LLVMContext & Context,const char * Assembly)28 std::unique_ptr<Module> parseAssembly(LLVMContext &Context,
29                                       const char *Assembly) {
30   SMDiagnostic Error;
31   std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context);
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 
writeModuleToBuffer(std::unique_ptr<Module> Mod,SmallVectorImpl<char> & Buffer)44 static void writeModuleToBuffer(std::unique_ptr<Module> Mod,
45                                 SmallVectorImpl<char> &Buffer) {
46   raw_svector_ostream OS(Buffer);
47   WriteBitcodeToFile(*Mod, OS);
48 }
49 
getLazyModuleFromAssembly(LLVMContext & Context,SmallString<1024> & Mem,const char * Assembly)50 static std::unique_ptr<Module> getLazyModuleFromAssembly(LLVMContext &Context,
51                                                          SmallString<1024> &Mem,
52                                                          const char *Assembly) {
53   writeModuleToBuffer(parseAssembly(Context, Assembly), Mem);
54   Expected<std::unique_ptr<Module>> ModuleOrErr =
55       getLazyBitcodeModule(MemoryBufferRef(Mem.str(), "test"), Context);
56   if (!ModuleOrErr)
57     report_fatal_error("Could not parse bitcode module");
58   return std::move(ModuleOrErr.get());
59 }
60 
61 // Tests that lazy evaluation can parse functions out of order.
TEST(BitReaderTest,MaterializeFunctionsOutOfOrder)62 TEST(BitReaderTest, MaterializeFunctionsOutOfOrder) {
63   SmallString<1024> Mem;
64   LLVMContext Context;
65   std::unique_ptr<Module> M = getLazyModuleFromAssembly(
66       Context, Mem, "define void @f() {\n"
67                     "  unreachable\n"
68                     "}\n"
69                     "define void @g() {\n"
70                     "  unreachable\n"
71                     "}\n"
72                     "define void @h() {\n"
73                     "  unreachable\n"
74                     "}\n"
75                     "define void @j() {\n"
76                     "  unreachable\n"
77                     "}\n");
78   EXPECT_FALSE(verifyModule(*M, &dbgs()));
79 
80   Function *F = M->getFunction("f");
81   Function *G = M->getFunction("g");
82   Function *H = M->getFunction("h");
83   Function *J = M->getFunction("j");
84 
85   // Initially all functions are not materialized (no basic blocks).
86   EXPECT_TRUE(F->empty());
87   EXPECT_TRUE(G->empty());
88   EXPECT_TRUE(H->empty());
89   EXPECT_TRUE(J->empty());
90   EXPECT_FALSE(verifyModule(*M, &dbgs()));
91 
92   // Materialize h.
93   ASSERT_FALSE(H->materialize());
94   EXPECT_TRUE(F->empty());
95   EXPECT_TRUE(G->empty());
96   EXPECT_FALSE(H->empty());
97   EXPECT_TRUE(J->empty());
98   EXPECT_FALSE(verifyModule(*M, &dbgs()));
99 
100   // Materialize g.
101   ASSERT_FALSE(G->materialize());
102   EXPECT_TRUE(F->empty());
103   EXPECT_FALSE(G->empty());
104   EXPECT_FALSE(H->empty());
105   EXPECT_TRUE(J->empty());
106   EXPECT_FALSE(verifyModule(*M, &dbgs()));
107 
108   // Materialize j.
109   ASSERT_FALSE(J->materialize());
110   EXPECT_TRUE(F->empty());
111   EXPECT_FALSE(G->empty());
112   EXPECT_FALSE(H->empty());
113   EXPECT_FALSE(J->empty());
114   EXPECT_FALSE(verifyModule(*M, &dbgs()));
115 
116   // Materialize f.
117   ASSERT_FALSE(F->materialize());
118   EXPECT_FALSE(F->empty());
119   EXPECT_FALSE(G->empty());
120   EXPECT_FALSE(H->empty());
121   EXPECT_FALSE(J->empty());
122   EXPECT_FALSE(verifyModule(*M, &dbgs()));
123 }
124 
TEST(BitReaderTest,MaterializeFunctionsStrictFP)125 TEST(BitReaderTest, MaterializeFunctionsStrictFP) {
126   SmallString<1024> Mem;
127 
128   LLVMContext Context;
129   std::unique_ptr<Module> M = getLazyModuleFromAssembly(
130       Context, Mem, "define double @foo(double %a) {\n"
131                     "  %result = call double @bar(double %a) strictfp\n"
132                     "  ret double %result\n"
133                     "}\n"
134                     "declare double @bar(double)\n");
135   Function *Foo = M->getFunction("foo");
136   ASSERT_FALSE(Foo->materialize());
137   EXPECT_FALSE(Foo->empty());
138 
139   for (auto &BB : *Foo) {
140     auto It = BB.begin();
141     while (It != BB.end()) {
142       Instruction &I = *It;
143       ++It;
144 
145       if (auto *Call = dyn_cast<CallBase>(&I)) {
146         EXPECT_FALSE(Call->isStrictFP());
147         EXPECT_TRUE(Call->isNoBuiltin());
148       }
149     }
150   }
151 
152   EXPECT_FALSE(verifyModule(*M, &dbgs()));
153 }
154 
TEST(BitReaderTest,MaterializeConstrainedFPStrictFP)155 TEST(BitReaderTest, MaterializeConstrainedFPStrictFP) {
156   SmallString<1024> Mem;
157 
158   LLVMContext Context;
159   std::unique_ptr<Module> M = getLazyModuleFromAssembly(
160       Context, Mem,
161       "define double @foo(double %a) {\n"
162       "  %result = call double @llvm.experimental.constrained.sqrt.f64(double "
163       "%a, metadata !\"round.tonearest\", metadata !\"fpexcept.strict\") "
164       "strictfp\n"
165       "  ret double %result\n"
166       "}\n"
167       "declare double @llvm.experimental.constrained.sqrt.f64(double, "
168       "metadata, metadata)\n");
169   Function *Foo = M->getFunction("foo");
170   ASSERT_FALSE(Foo->materialize());
171   EXPECT_FALSE(Foo->empty());
172 
173   for (auto &BB : *Foo) {
174     auto It = BB.begin();
175     while (It != BB.end()) {
176       Instruction &I = *It;
177       ++It;
178 
179       if (auto *Call = dyn_cast<CallBase>(&I)) {
180         EXPECT_TRUE(Call->isStrictFP());
181         EXPECT_FALSE(Call->isNoBuiltin());
182       }
183     }
184   }
185 
186   EXPECT_FALSE(verifyModule(*M, &dbgs()));
187 }
188 
TEST(BitReaderTest,MaterializeFunctionsForBlockAddr)189 TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677
190   SmallString<1024> Mem;
191 
192   LLVMContext Context;
193   std::unique_ptr<Module> M = getLazyModuleFromAssembly(
194       Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n"
195                     "define void @func() {\n"
196                     "  unreachable\n"
197                     "bb:\n"
198                     "  unreachable\n"
199                     "}\n");
200   EXPECT_FALSE(verifyModule(*M, &dbgs()));
201   EXPECT_FALSE(M->getFunction("func")->empty());
202 }
203 
TEST(BitReaderTest,MaterializeFunctionsForBlockAddrInFunctionBefore)204 TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) {
205   SmallString<1024> Mem;
206 
207   LLVMContext Context;
208   std::unique_ptr<Module> M = getLazyModuleFromAssembly(
209       Context, Mem, "define i8* @before() {\n"
210                     "  ret i8* blockaddress(@func, %bb)\n"
211                     "}\n"
212                     "define void @other() {\n"
213                     "  unreachable\n"
214                     "}\n"
215                     "define void @func() {\n"
216                     "  unreachable\n"
217                     "bb:\n"
218                     "  unreachable\n"
219                     "}\n");
220   EXPECT_TRUE(M->getFunction("before")->empty());
221   EXPECT_TRUE(M->getFunction("func")->empty());
222   EXPECT_FALSE(verifyModule(*M, &dbgs()));
223 
224   // Materialize @before, pulling in @func.
225   EXPECT_FALSE(M->getFunction("before")->materialize());
226   EXPECT_FALSE(M->getFunction("func")->empty());
227   EXPECT_TRUE(M->getFunction("other")->empty());
228   EXPECT_FALSE(verifyModule(*M, &dbgs()));
229 }
230 
TEST(BitReaderTest,MaterializeFunctionsForBlockAddrInFunctionAfter)231 TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) {
232   SmallString<1024> Mem;
233 
234   LLVMContext Context;
235   std::unique_ptr<Module> M = getLazyModuleFromAssembly(
236       Context, Mem, "define void @func() {\n"
237                     "  unreachable\n"
238                     "bb:\n"
239                     "  unreachable\n"
240                     "}\n"
241                     "define void @other() {\n"
242                     "  unreachable\n"
243                     "}\n"
244                     "define i8* @after() {\n"
245                     "  ret i8* blockaddress(@func, %bb)\n"
246                     "}\n");
247   EXPECT_TRUE(M->getFunction("after")->empty());
248   EXPECT_TRUE(M->getFunction("func")->empty());
249   EXPECT_FALSE(verifyModule(*M, &dbgs()));
250 
251   // Materialize @after, pulling in @func.
252   EXPECT_FALSE(M->getFunction("after")->materialize());
253   EXPECT_FALSE(M->getFunction("func")->empty());
254   EXPECT_TRUE(M->getFunction("other")->empty());
255   EXPECT_FALSE(verifyModule(*M, &dbgs()));
256 }
257 
258 } // end namespace
259