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 "BitReaderTestCode.h" |
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/IR/Constants.h" |
16 | #include "llvm/IR/InstrTypes.h" |
17 | #include "llvm/IR/LLVMContext.h" |
18 | #include "llvm/IR/Module.h" |
19 | #include "llvm/IR/Verifier.h" |
20 | #include "llvm/Support/Debug.h" |
21 | #include "llvm/Support/Error.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(AsmString: Assembly, Err&: Error, Context); |
34 | |
35 | std::string ErrMsg; |
36 | raw_string_ostream OS(ErrMsg); |
37 | Error.print(ProgName: "" , S&: OS); |
38 | |
39 | // A failure here means that the test itself is buggy. |
40 | if (!M) |
41 | report_fatal_error(reason: 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(M: *Mod, Out&: OS); |
50 | } |
51 | |
52 | static std::unique_ptr<Module> getLazyModuleFromAssembly(LLVMContext &Context, |
53 | SmallString<1024> &Mem, |
54 | const char *Assembly) { |
55 | writeModuleToBuffer(Mod: parseAssembly(Context, Assembly), Buffer&: Mem); |
56 | Expected<std::unique_ptr<Module>> ModuleOrErr = |
57 | getLazyBitcodeModule(Buffer: MemoryBufferRef(Mem.str(), "test" ), Context); |
58 | if (!ModuleOrErr) |
59 | report_fatal_error(reason: "Could not parse bitcode module" ); |
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, Assembly: "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(Name: "f" ); |
83 | Function *G = M->getFunction(Name: "g" ); |
84 | Function *H = M->getFunction(Name: "h" ); |
85 | Function *J = M->getFunction(Name: "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 | ASSERT_FALSE(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 | ASSERT_FALSE(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 | ASSERT_FALSE(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 | ASSERT_FALSE(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, MaterializeFunctionsStrictFP) { |
128 | SmallString<1024> Mem; |
129 | |
130 | LLVMContext Context; |
131 | std::unique_ptr<Module> M = getLazyModuleFromAssembly( |
132 | Context, Mem, Assembly: "define double @foo(double %a) {\n" |
133 | " %result = call double @bar(double %a) strictfp\n" |
134 | " ret double %result\n" |
135 | "}\n" |
136 | "declare double @bar(double)\n" ); |
137 | Function *Foo = M->getFunction(Name: "foo" ); |
138 | ASSERT_FALSE(Foo->materialize()); |
139 | EXPECT_FALSE(Foo->empty()); |
140 | |
141 | for (auto &BB : *Foo) { |
142 | auto It = BB.begin(); |
143 | while (It != BB.end()) { |
144 | Instruction &I = *It; |
145 | ++It; |
146 | |
147 | if (auto *Call = dyn_cast<CallBase>(Val: &I)) { |
148 | EXPECT_FALSE(Call->isStrictFP()); |
149 | EXPECT_TRUE(Call->isNoBuiltin()); |
150 | } |
151 | } |
152 | } |
153 | |
154 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
155 | } |
156 | |
157 | TEST(BitReaderTest, MaterializeConstrainedFPStrictFP) { |
158 | SmallString<1024> Mem; |
159 | |
160 | LLVMContext Context; |
161 | std::unique_ptr<Module> M = getLazyModuleFromAssembly( |
162 | Context, Mem, |
163 | Assembly: "define double @foo(double %a) strictfp {\n" |
164 | " %result = call double @llvm.experimental.constrained.sqrt.f64(double " |
165 | "%a, metadata !\"round.tonearest\", metadata !\"fpexcept.strict\") " |
166 | "strictfp\n" |
167 | " ret double %result\n" |
168 | "}\n" |
169 | "declare double @llvm.experimental.constrained.sqrt.f64(double, " |
170 | "metadata, metadata)\n" ); |
171 | Function *Foo = M->getFunction(Name: "foo" ); |
172 | ASSERT_FALSE(Foo->materialize()); |
173 | EXPECT_FALSE(Foo->empty()); |
174 | |
175 | for (auto &BB : *Foo) { |
176 | auto It = BB.begin(); |
177 | while (It != BB.end()) { |
178 | Instruction &I = *It; |
179 | ++It; |
180 | |
181 | if (auto *Call = dyn_cast<CallBase>(Val: &I)) { |
182 | EXPECT_TRUE(Call->isStrictFP()); |
183 | EXPECT_FALSE(Call->isNoBuiltin()); |
184 | } |
185 | } |
186 | } |
187 | |
188 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
189 | } |
190 | |
191 | TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677 |
192 | SmallString<1024> Mem; |
193 | |
194 | LLVMContext Context; |
195 | std::unique_ptr<Module> M = getLazyModuleFromAssembly( |
196 | Context, Mem, Assembly: "@table = constant i8* blockaddress(@func, %bb)\n" |
197 | "define void @func() {\n" |
198 | " unreachable\n" |
199 | "bb:\n" |
200 | " unreachable\n" |
201 | "}\n" ); |
202 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
203 | EXPECT_FALSE(M->getFunction("func" )->empty()); |
204 | } |
205 | |
206 | TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) { |
207 | SmallString<1024> Mem; |
208 | |
209 | LLVMContext Context; |
210 | std::unique_ptr<Module> M = getLazyModuleFromAssembly( |
211 | Context, Mem, Assembly: "define i8* @before() {\n" |
212 | " ret i8* blockaddress(@func, %bb)\n" |
213 | "}\n" |
214 | "define void @other() {\n" |
215 | " unreachable\n" |
216 | "}\n" |
217 | "define void @func() {\n" |
218 | " unreachable\n" |
219 | "bb:\n" |
220 | " unreachable\n" |
221 | "}\n" ); |
222 | EXPECT_TRUE(M->getFunction("before" )->empty()); |
223 | EXPECT_TRUE(M->getFunction("func" )->empty()); |
224 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
225 | |
226 | // Materialize @before, pulling in @func. |
227 | EXPECT_FALSE(M->getFunction("before" )->materialize()); |
228 | EXPECT_FALSE(M->getFunction("func" )->empty()); |
229 | EXPECT_TRUE(M->getFunction("other" )->empty()); |
230 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
231 | } |
232 | |
233 | TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) { |
234 | SmallString<1024> Mem; |
235 | |
236 | LLVMContext Context; |
237 | std::unique_ptr<Module> M = getLazyModuleFromAssembly( |
238 | Context, Mem, Assembly: "define void @func() {\n" |
239 | " unreachable\n" |
240 | "bb:\n" |
241 | " unreachable\n" |
242 | "}\n" |
243 | "define void @other() {\n" |
244 | " unreachable\n" |
245 | "}\n" |
246 | "define i8* @after() {\n" |
247 | " ret i8* blockaddress(@func, %bb)\n" |
248 | "}\n" ); |
249 | EXPECT_TRUE(M->getFunction("after" )->empty()); |
250 | EXPECT_TRUE(M->getFunction("func" )->empty()); |
251 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
252 | |
253 | // Materialize @after, pulling in @func. |
254 | EXPECT_FALSE(M->getFunction("after" )->materialize()); |
255 | EXPECT_FALSE(M->getFunction("func" )->empty()); |
256 | EXPECT_TRUE(M->getFunction("other" )->empty()); |
257 | EXPECT_FALSE(verifyModule(*M, &dbgs())); |
258 | } |
259 | |
260 | // Helper function to convert type metadata to a string for testing |
261 | static std::string mdToString(Metadata *MD) { |
262 | std::string S; |
263 | if (auto *VMD = dyn_cast<ValueAsMetadata>(Val: MD)) { |
264 | if (VMD->getType()->isPointerTy()) { |
265 | S += "ptr" ; |
266 | return S; |
267 | } |
268 | } |
269 | |
270 | if (auto *TMD = dyn_cast<MDTuple>(Val: MD)) { |
271 | S += "!{" ; |
272 | for (unsigned I = 0; I < TMD->getNumOperands(); I++) { |
273 | if (I != 0) |
274 | S += ", " ; |
275 | S += mdToString(MD: TMD->getOperand(I).get()); |
276 | } |
277 | S += "}" ; |
278 | } else if (auto *SMD = dyn_cast<MDString>(Val: MD)) { |
279 | S += "!'" ; |
280 | S += SMD->getString(); |
281 | S += "'" ; |
282 | } else if (auto *I = mdconst::dyn_extract<ConstantInt>(MD)) { |
283 | S += std::to_string(val: I->getZExtValue()); |
284 | } else if (auto *P = mdconst::dyn_extract<PoisonValue>(MD)) { |
285 | auto *Ty = P->getType(); |
286 | if (Ty->isIntegerTy()) { |
287 | S += "i" ; |
288 | S += std::to_string(val: Ty->getIntegerBitWidth()); |
289 | } else if (Ty->isStructTy()) { |
290 | S += "%" ; |
291 | S += Ty->getStructName(); |
292 | } else { |
293 | llvm_unreachable("unhandled poison metadata" ); |
294 | } |
295 | } else { |
296 | llvm_unreachable("unhandled metadata" ); |
297 | } |
298 | return S; |
299 | } |
300 | |
301 | // Recursively look into a (pointer) type and the the type. |
302 | // For primitive types it's a poison value of the type, for a pointer it's a |
303 | // metadata tuple with the addrspace and the referenced type. For a function, |
304 | // it's a tuple where the first element is the string "function", the second |
305 | // element is the return type or the string "void" and the following elements |
306 | // are the argument types. |
307 | static Metadata *getTypeMetadataEntry(unsigned TypeID, LLVMContext &Context, |
308 | GetTypeByIDTy GetTypeByID, |
309 | GetContainedTypeIDTy GetContainedTypeID) { |
310 | Type *Ty = GetTypeByID(TypeID); |
311 | if (auto *FTy = dyn_cast<FunctionType>(Val: Ty)) { |
312 | // Save the function signature as metadata |
313 | SmallVector<Metadata *> SignatureMD; |
314 | SignatureMD.push_back(Elt: MDString::get(Context, Str: "function" )); |
315 | // Return type |
316 | if (FTy->getReturnType()->isVoidTy()) |
317 | SignatureMD.push_back(Elt: MDString::get(Context, Str: "void" )); |
318 | else |
319 | SignatureMD.push_back(Elt: getTypeMetadataEntry(TypeID: GetContainedTypeID(TypeID, 0), |
320 | Context, GetTypeByID, |
321 | GetContainedTypeID)); |
322 | // Arguments |
323 | for (unsigned I = 0; I != FTy->getNumParams(); ++I) |
324 | SignatureMD.push_back( |
325 | Elt: getTypeMetadataEntry(TypeID: GetContainedTypeID(TypeID, I + 1), Context, |
326 | GetTypeByID, GetContainedTypeID)); |
327 | |
328 | return MDTuple::get(Context, MDs: SignatureMD); |
329 | } |
330 | |
331 | if (!Ty->isPointerTy()) |
332 | return ConstantAsMetadata::get(C: PoisonValue::get(T: Ty)); |
333 | |
334 | // Return !{<addrspace>, <inner>} for pointer |
335 | SmallVector<Metadata *, 2> MD; |
336 | MD.push_back(Elt: ConstantAsMetadata::get(C: ConstantInt::get( |
337 | Ty: Type::getInt32Ty(C&: Context), V: Ty->getPointerAddressSpace()))); |
338 | MD.push_back(Elt: getTypeMetadataEntry(TypeID: GetContainedTypeID(TypeID, 0), Context, |
339 | GetTypeByID, GetContainedTypeID)); |
340 | return MDTuple::get(Context, MDs: MD); |
341 | } |
342 | |
343 | // Test that when reading bitcode with typed pointers and upgrading them to |
344 | // opaque pointers, the type information of function signatures can be extracted |
345 | // and stored in metadata. |
346 | TEST(BitReaderTest, AccessFunctionTypeInfo) { |
347 | StringRef Bitcode(reinterpret_cast<const char *>(AccessFunctionTypeInfoBc), |
348 | sizeof(AccessFunctionTypeInfoBc)); |
349 | |
350 | LLVMContext Context; |
351 | ParserCallbacks Callbacks; |
352 | // Supply a callback that stores the signature of a function into metadata, |
353 | // so that the types behind pointers can be accessed. |
354 | // Each function gets a !types metadata, which is a tuple with one element |
355 | // for a non-void return type and every argument. For primitive types it's |
356 | // a poison value of the type, for a pointer it's a metadata tuple with |
357 | // the addrspace and the referenced type. |
358 | Callbacks.ValueType = [&](Value *V, unsigned TypeID, |
359 | GetTypeByIDTy GetTypeByID, |
360 | GetContainedTypeIDTy GetContainedTypeID) { |
361 | if (auto *F = dyn_cast<Function>(Val: V)) { |
362 | auto *MD = getTypeMetadataEntry(TypeID, Context&: F->getContext(), GetTypeByID, |
363 | GetContainedTypeID); |
364 | F->setMetadata(Kind: "types" , Node: cast<MDNode>(Val: MD)); |
365 | } |
366 | }; |
367 | |
368 | Expected<std::unique_ptr<Module>> ModuleOrErr = |
369 | parseBitcodeFile(Buffer: MemoryBufferRef(Bitcode, "test" ), Context, Callbacks); |
370 | |
371 | if (!ModuleOrErr) |
372 | report_fatal_error(reason: "Could not parse bitcode module" ); |
373 | std::unique_ptr<Module> M = std::move(ModuleOrErr.get()); |
374 | |
375 | EXPECT_EQ(mdToString(M->getFunction("func" )->getMetadata("types" )), |
376 | "!{!'function', !'void'}" ); |
377 | EXPECT_EQ(mdToString(M->getFunction("func_header" )->getMetadata("types" )), |
378 | "!{!'function', i32}" ); |
379 | EXPECT_EQ(mdToString(M->getFunction("ret_ptr" )->getMetadata("types" )), |
380 | "!{!'function', !{0, i8}}" ); |
381 | EXPECT_EQ(mdToString(M->getFunction("ret_and_arg_ptr" )->getMetadata("types" )), |
382 | "!{!'function', !{0, i8}, !{8, i32}}" ); |
383 | EXPECT_EQ(mdToString(M->getFunction("double_ptr" )->getMetadata("types" )), |
384 | "!{!'function', !{1, i8}, !{2, !{0, i32}}, !{0, !{0, !{0, i32}}}}" ); |
385 | } |
386 | |
387 | // Test that when reading bitcode with typed pointers and upgrading them to |
388 | // opaque pointers, the type information of pointers in metadata can be |
389 | // extracted and stored in metadata. |
390 | TEST(BitReaderTest, AccessMetadataTypeInfo) { |
391 | StringRef Bitcode(reinterpret_cast<const char *>(AccessMetadataTypeInfoBc), |
392 | sizeof(AccessFunctionTypeInfoBc)); |
393 | |
394 | LLVMContext Context; |
395 | ParserCallbacks Callbacks; |
396 | // Supply a callback that stores types from metadata, |
397 | // so that the types behind pointers can be accessed. |
398 | // Non-pointer entries are ignored. Values with a pointer type are |
399 | // replaced by a metadata tuple with {original value, type md}. We cannot |
400 | // save the metadata outside because after conversion to opaque pointers, |
401 | // entries are not distinguishable anymore (e.g. i32* and i8* are both |
402 | // upgraded to ptr). |
403 | Callbacks.MDType = [&](Metadata **Val, unsigned TypeID, |
404 | GetTypeByIDTy GetTypeByID, |
405 | GetContainedTypeIDTy GetContainedTypeID) { |
406 | auto *OrigVal = cast<ValueAsMetadata>(Val: *Val); |
407 | if (OrigVal->getType()->isPointerTy()) { |
408 | // Ignore function references, their signature can be saved like |
409 | // in the test above |
410 | if (!isa<Function>(Val: OrigVal->getValue())) { |
411 | SmallVector<Metadata *> Tuple; |
412 | Tuple.push_back(Elt: OrigVal); |
413 | Tuple.push_back(Elt: getTypeMetadataEntry(TypeID: GetContainedTypeID(TypeID, 0), |
414 | Context&: OrigVal->getContext(), GetTypeByID, |
415 | GetContainedTypeID)); |
416 | *Val = MDTuple::get(Context&: OrigVal->getContext(), MDs: Tuple); |
417 | } |
418 | } |
419 | }; |
420 | |
421 | Expected<std::unique_ptr<Module>> ModuleOrErr = |
422 | parseBitcodeFile(Buffer: MemoryBufferRef(Bitcode, "test" ), Context, Callbacks); |
423 | |
424 | if (!ModuleOrErr) |
425 | report_fatal_error(reason: "Could not parse bitcode module" ); |
426 | std::unique_ptr<Module> M = std::move(ModuleOrErr.get()); |
427 | |
428 | EXPECT_EQ( |
429 | mdToString(M->getNamedMetadata("md" )->getOperand(0)), |
430 | "!{2, !{ptr, %dx.types.f32}, ptr, !{ptr, !{!'function', !'void'}}}" ); |
431 | EXPECT_EQ(mdToString(M->getNamedMetadata("md2" )->getOperand(0)), |
432 | "!{!{ptr, !{!'function', !{0, i8}, !{2, !{0, i32}}}}, !{ptr, !{0, " |
433 | "!{0, i32}}}}" ); |
434 | } |
435 | |
436 | } // end namespace |
437 | |