1//===- FunctionTest.cpp - Function unit tests -----------------------------===//
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/IR/Function.h"
10#include "llvm/AsmParser/Parser.h"
11#include "llvm/IR/Module.h"
12#include "llvm/Support/SourceMgr.h"
13#include "gtest/gtest.h"
14using namespace llvm;
15
16namespace {
17
18static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
19 SMDiagnostic Err;
20 std::unique_ptr<Module> Mod = parseAssemblyString(AsmString: IR, Err, Context&: C);
21 if (!Mod)
22 Err.print(ProgName: "InstructionsTests", S&: errs());
23 return Mod;
24}
25
26static BasicBlock *getBBWithName(Function *F, StringRef Name) {
27 auto It = find_if(
28 Range&: *F, P: [&Name](const BasicBlock &BB) { return BB.getName() == Name; });
29 assert(It != F->end() && "Not found!");
30 return &*It;
31}
32
33TEST(FunctionTest, hasLazyArguments) {
34 LLVMContext C;
35
36 Type *ArgTypes[] = {Type::getInt8Ty(C), Type::getInt32Ty(C)};
37 FunctionType *FTy = FunctionType::get(Result: Type::getVoidTy(C), Params: ArgTypes, isVarArg: false);
38
39 // Functions start out with lazy arguments.
40 std::unique_ptr<Function> F(
41 Function::Create(Ty: FTy, Linkage: GlobalValue::ExternalLinkage, N: "F"));
42 EXPECT_TRUE(F->hasLazyArguments());
43
44 // Checking for empty or size shouldn't force arguments to be instantiated.
45 EXPECT_FALSE(F->arg_empty());
46 EXPECT_TRUE(F->hasLazyArguments());
47 EXPECT_EQ(2u, F->arg_size());
48 EXPECT_TRUE(F->hasLazyArguments());
49
50 // The argument list should be populated at first access.
51 (void)F->arg_begin();
52 EXPECT_FALSE(F->hasLazyArguments());
53
54 // Checking that getArg gets the arguments from F1 in the correct order.
55 unsigned i = 0;
56 for (Argument &A : F->args()) {
57 EXPECT_EQ(&A, F->getArg(i));
58 ++i;
59 }
60 EXPECT_FALSE(F->hasLazyArguments());
61}
62
63TEST(FunctionTest, stealArgumentListFrom) {
64 LLVMContext C;
65
66 Type *ArgTypes[] = {Type::getInt8Ty(C), Type::getInt32Ty(C)};
67 FunctionType *FTy = FunctionType::get(Result: Type::getVoidTy(C), Params: ArgTypes, isVarArg: false);
68 std::unique_ptr<Function> F1(
69 Function::Create(Ty: FTy, Linkage: GlobalValue::ExternalLinkage, N: "F1"));
70 std::unique_ptr<Function> F2(
71 Function::Create(Ty: FTy, Linkage: GlobalValue::ExternalLinkage, N: "F1"));
72 EXPECT_TRUE(F1->hasLazyArguments());
73 EXPECT_TRUE(F2->hasLazyArguments());
74
75 // Steal arguments before they've been accessed. Nothing should change; both
76 // functions should still have lazy arguments.
77 //
78 // steal(empty); drop (empty)
79 F1->stealArgumentListFrom(Src&: *F2);
80 EXPECT_TRUE(F1->hasLazyArguments());
81 EXPECT_TRUE(F2->hasLazyArguments());
82
83 // Save arguments from F1 for later assertions. F1 won't have lazy arguments
84 // anymore.
85 SmallVector<Argument *, 4> Args;
86 for (Argument &A : F1->args())
87 Args.push_back(Elt: &A);
88 EXPECT_EQ(2u, Args.size());
89 EXPECT_FALSE(F1->hasLazyArguments());
90
91 // Steal arguments from F1 to F2. F1's arguments should be lazy again.
92 //
93 // steal(real); drop (empty)
94 F2->stealArgumentListFrom(Src&: *F1);
95 EXPECT_TRUE(F1->hasLazyArguments());
96 EXPECT_FALSE(F2->hasLazyArguments());
97 unsigned I = 0;
98 for (Argument &A : F2->args()) {
99 EXPECT_EQ(Args[I], &A);
100 I++;
101 }
102 EXPECT_EQ(2u, I);
103
104 // Check that arguments in F1 don't have pointer equality with the saved ones.
105 // This also instantiates F1's arguments.
106 I = 0;
107 for (Argument &A : F1->args()) {
108 EXPECT_NE(Args[I], &A);
109 I++;
110 }
111 EXPECT_EQ(2u, I);
112 EXPECT_FALSE(F1->hasLazyArguments());
113 EXPECT_FALSE(F2->hasLazyArguments());
114
115 // Steal back from F2. F2's arguments should be lazy again.
116 //
117 // steal(real); drop (real)
118 F1->stealArgumentListFrom(Src&: *F2);
119 EXPECT_FALSE(F1->hasLazyArguments());
120 EXPECT_TRUE(F2->hasLazyArguments());
121 I = 0;
122 for (Argument &A : F1->args()) {
123 EXPECT_EQ(Args[I], &A);
124 I++;
125 }
126 EXPECT_EQ(2u, I);
127
128 // Steal from F2 a second time. Now both functions should have lazy
129 // arguments.
130 //
131 // steal(empty); drop (real)
132 F1->stealArgumentListFrom(Src&: *F2);
133 EXPECT_TRUE(F1->hasLazyArguments());
134 EXPECT_TRUE(F2->hasLazyArguments());
135}
136
137// Test setting and removing section information
138TEST(FunctionTest, setSection) {
139 LLVMContext C;
140 Module M("test", C);
141
142 llvm::Function *F =
143 Function::Create(Ty: llvm::FunctionType::get(Result: llvm::Type::getVoidTy(C), isVarArg: false),
144 Linkage: llvm::GlobalValue::ExternalLinkage, N: "F", M: &M);
145
146 F->setSection(".text.test");
147 EXPECT_TRUE(F->getSection() == ".text.test");
148 EXPECT_TRUE(F->hasSection());
149 F->setSection("");
150 EXPECT_FALSE(F->hasSection());
151 F->setSection(".text.test");
152 F->setSection(".text.test2");
153 EXPECT_TRUE(F->getSection() == ".text.test2");
154 EXPECT_TRUE(F->hasSection());
155}
156
157TEST(FunctionTest, GetPointerAlignment) {
158 LLVMContext Context;
159 Type *VoidType(Type::getVoidTy(C&: Context));
160 FunctionType *FuncType(FunctionType::get(Result: VoidType, isVarArg: false));
161 std::unique_ptr<Function> Func(Function::Create(
162 Ty: FuncType, Linkage: GlobalValue::ExternalLinkage));
163 EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("")));
164 EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("Fi8")));
165 EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("Fn8")));
166 EXPECT_EQ(Align(2), Func->getPointerAlignment(DataLayout("Fi16")));
167 EXPECT_EQ(Align(2), Func->getPointerAlignment(DataLayout("Fn16")));
168 EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fi32")));
169 EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn32")));
170
171 Func->setAlignment(Align(4));
172
173 EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("")));
174 EXPECT_EQ(Align(1), Func->getPointerAlignment(DataLayout("Fi8")));
175 EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn8")));
176 EXPECT_EQ(Align(2), Func->getPointerAlignment(DataLayout("Fi16")));
177 EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn16")));
178 EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fi32")));
179 EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn32")));
180}
181
182TEST(FunctionTest, InsertBasicBlockAt) {
183 LLVMContext C;
184 std::unique_ptr<Module> M = parseIR(C, IR: R"(
185define void @foo(i32 %a, i32 %b) {
186foo_bb0:
187 ret void
188}
189
190define void @bar() {
191bar_bb0:
192 br label %bar_bb1
193bar_bb1:
194 br label %bar_bb2
195bar_bb2:
196 ret void
197}
198)");
199 Function *FooF = M->getFunction(Name: "foo");
200 BasicBlock *FooBB0 = getBBWithName(F: FooF, Name: "foo_bb0");
201
202 Function *BarF = M->getFunction(Name: "bar");
203 BasicBlock *BarBB0 = getBBWithName(F: BarF, Name: "bar_bb0");
204 BasicBlock *BarBB1 = getBBWithName(F: BarF, Name: "bar_bb1");
205 BasicBlock *BarBB2 = getBBWithName(F: BarF, Name: "bar_bb2");
206
207 // Insert foo_bb0 into bar() at the very top.
208 FooBB0->removeFromParent();
209 auto It = BarF->insert(Position: BarF->begin(), BB: FooBB0);
210 EXPECT_EQ(BarBB0->getPrevNode(), FooBB0);
211 EXPECT_EQ(It, FooBB0->getIterator());
212
213 // Insert foo_bb0 into bar() at the very end.
214 FooBB0->removeFromParent();
215 It = BarF->insert(Position: BarF->end(), BB: FooBB0);
216 EXPECT_EQ(FooBB0->getPrevNode(), BarBB2);
217 EXPECT_EQ(FooBB0->getNextNode(), nullptr);
218 EXPECT_EQ(It, FooBB0->getIterator());
219
220 // Insert foo_bb0 into bar() just before bar_bb0.
221 FooBB0->removeFromParent();
222 It = BarF->insert(Position: BarBB0->getIterator(), BB: FooBB0);
223 EXPECT_EQ(FooBB0->getPrevNode(), nullptr);
224 EXPECT_EQ(FooBB0->getNextNode(), BarBB0);
225 EXPECT_EQ(It, FooBB0->getIterator());
226
227 // Insert foo_bb0 into bar() just before bar_bb1.
228 FooBB0->removeFromParent();
229 It = BarF->insert(Position: BarBB1->getIterator(), BB: FooBB0);
230 EXPECT_EQ(FooBB0->getPrevNode(), BarBB0);
231 EXPECT_EQ(FooBB0->getNextNode(), BarBB1);
232 EXPECT_EQ(It, FooBB0->getIterator());
233
234 // Insert foo_bb0 into bar() just before bar_bb2.
235 FooBB0->removeFromParent();
236 It = BarF->insert(Position: BarBB2->getIterator(), BB: FooBB0);
237 EXPECT_EQ(FooBB0->getPrevNode(), BarBB1);
238 EXPECT_EQ(FooBB0->getNextNode(), BarBB2);
239 EXPECT_EQ(It, FooBB0->getIterator());
240}
241
242TEST(FunctionTest, SpliceOneBB) {
243 LLVMContext Ctx;
244 std::unique_ptr<Module> M = parseIR(C&: Ctx, IR: R"(
245 define void @from() {
246 from_bb1:
247 br label %from_bb2
248 from_bb2:
249 br label %from_bb3
250 from_bb3:
251 ret void
252 }
253 define void @to() {
254 to_bb1:
255 br label %to_bb2
256 to_bb2:
257 br label %to_bb3
258 to_bb3:
259 ret void
260 }
261)");
262 Function *FromF = M->getFunction(Name: "from");
263 BasicBlock *FromBB1 = getBBWithName(F: FromF, Name: "from_bb1");
264 BasicBlock *FromBB2 = getBBWithName(F: FromF, Name: "from_bb2");
265 BasicBlock *FromBB3 = getBBWithName(F: FromF, Name: "from_bb3");
266
267 Function *ToF = M->getFunction(Name: "to");
268 BasicBlock *ToBB1 = getBBWithName(F: ToF, Name: "to_bb1");
269 BasicBlock *ToBB2 = getBBWithName(F: ToF, Name: "to_bb2");
270 BasicBlock *ToBB3 = getBBWithName(F: ToF, Name: "to_bb3");
271
272 // Move from_bb2 before to_bb1.
273 ToF->splice(ToIt: ToBB1->getIterator(), FromF, FromIt: FromBB2->getIterator());
274 EXPECT_EQ(FromF->size(), 2u);
275 EXPECT_EQ(ToF->size(), 4u);
276
277 auto It = FromF->begin();
278 EXPECT_EQ(&*It++, FromBB1);
279 EXPECT_EQ(&*It++, FromBB3);
280
281 It = ToF->begin();
282 EXPECT_EQ(&*It++, FromBB2);
283 EXPECT_EQ(&*It++, ToBB1);
284 EXPECT_EQ(&*It++, ToBB2);
285 EXPECT_EQ(&*It++, ToBB3);
286
287 // Cleanup to avoid "Uses remain when a value is destroyed!".
288 FromF->splice(ToIt: FromBB3->getIterator(), FromF: ToF, FromIt: FromBB2->getIterator());
289}
290
291TEST(FunctionTest, SpliceOneBBWhenFromIsSameAsTo) {
292 LLVMContext Ctx;
293 std::unique_ptr<Module> M = parseIR(C&: Ctx, IR: R"(
294 define void @fromto() {
295 bb1:
296 br label %bb2
297 bb2:
298 ret void
299 }
300)");
301 Function *F = M->getFunction(Name: "fromto");
302 BasicBlock *BB1 = getBBWithName(F, Name: "bb1");
303 BasicBlock *BB2 = getBBWithName(F, Name: "bb2");
304
305 // According to ilist's splice() a single-element splice where dst == src
306 // should be a noop.
307 F->splice(ToIt: BB1->getIterator(), FromF: F, FromIt: BB1->getIterator());
308
309 auto It = F->begin();
310 EXPECT_EQ(&*It++, BB1);
311 EXPECT_EQ(&*It++, BB2);
312 EXPECT_EQ(F->size(), 2u);
313}
314
315TEST(FunctionTest, SpliceLastBB) {
316 LLVMContext Ctx;
317 std::unique_ptr<Module> M = parseIR(C&: Ctx, IR: R"(
318 define void @from() {
319 from_bb1:
320 br label %from_bb2
321 from_bb2:
322 br label %from_bb3
323 from_bb3:
324 ret void
325 }
326 define void @to() {
327 to_bb1:
328 br label %to_bb2
329 to_bb2:
330 br label %to_bb3
331 to_bb3:
332 ret void
333 }
334)");
335
336 Function *FromF = M->getFunction(Name: "from");
337 BasicBlock *FromBB1 = getBBWithName(F: FromF, Name: "from_bb1");
338 BasicBlock *FromBB2 = getBBWithName(F: FromF, Name: "from_bb2");
339 BasicBlock *FromBB3 = getBBWithName(F: FromF, Name: "from_bb3");
340
341 Function *ToF = M->getFunction(Name: "to");
342 BasicBlock *ToBB1 = getBBWithName(F: ToF, Name: "to_bb1");
343 BasicBlock *ToBB2 = getBBWithName(F: ToF, Name: "to_bb2");
344 BasicBlock *ToBB3 = getBBWithName(F: ToF, Name: "to_bb3");
345
346 // Move from_bb2 before to_bb1.
347 auto ToMove = FromBB2->getIterator();
348 ToF->splice(ToIt: ToBB1->getIterator(), FromF, FromBeginIt: ToMove, FromEndIt: std::next(x: ToMove));
349
350 EXPECT_EQ(FromF->size(), 2u);
351 auto It = FromF->begin();
352 EXPECT_EQ(&*It++, FromBB1);
353 EXPECT_EQ(&*It++, FromBB3);
354
355 EXPECT_EQ(ToF->size(), 4u);
356 It = ToF->begin();
357 EXPECT_EQ(&*It++, FromBB2);
358 EXPECT_EQ(&*It++, ToBB1);
359 EXPECT_EQ(&*It++, ToBB2);
360 EXPECT_EQ(&*It++, ToBB3);
361
362 // Cleanup to avoid "Uses remain when a value is destroyed!".
363 FromF->splice(ToIt: FromBB3->getIterator(), FromF: ToF, FromIt: ToMove);
364}
365
366TEST(FunctionTest, SpliceBBRange) {
367 LLVMContext Ctx;
368 std::unique_ptr<Module> M = parseIR(C&: Ctx, IR: R"(
369 define void @from() {
370 from_bb1:
371 br label %from_bb2
372 from_bb2:
373 br label %from_bb3
374 from_bb3:
375 ret void
376 }
377 define void @to() {
378 to_bb1:
379 br label %to_bb2
380 to_bb2:
381 br label %to_bb3
382 to_bb3:
383 ret void
384 }
385)");
386
387 Function *FromF = M->getFunction(Name: "from");
388 BasicBlock *FromBB1 = getBBWithName(F: FromF, Name: "from_bb1");
389 BasicBlock *FromBB2 = getBBWithName(F: FromF, Name: "from_bb2");
390 BasicBlock *FromBB3 = getBBWithName(F: FromF, Name: "from_bb3");
391
392 Function *ToF = M->getFunction(Name: "to");
393 BasicBlock *ToBB1 = getBBWithName(F: ToF, Name: "to_bb1");
394 BasicBlock *ToBB2 = getBBWithName(F: ToF, Name: "to_bb2");
395 BasicBlock *ToBB3 = getBBWithName(F: ToF, Name: "to_bb3");
396
397 // Move all BBs from @from to @to.
398 ToF->splice(ToIt: ToBB2->getIterator(), FromF, FromBeginIt: FromF->begin(), FromEndIt: FromF->end());
399
400 EXPECT_EQ(FromF->size(), 0u);
401
402 EXPECT_EQ(ToF->size(), 6u);
403 auto It = ToF->begin();
404 EXPECT_EQ(&*It++, ToBB1);
405 EXPECT_EQ(&*It++, FromBB1);
406 EXPECT_EQ(&*It++, FromBB2);
407 EXPECT_EQ(&*It++, FromBB3);
408 EXPECT_EQ(&*It++, ToBB2);
409 EXPECT_EQ(&*It++, ToBB3);
410}
411
412#ifdef EXPENSIVE_CHECKS
413TEST(FunctionTest, SpliceEndBeforeBegin) {
414 LLVMContext Ctx;
415 std::unique_ptr<Module> M = parseIR(Ctx, R"(
416 define void @from() {
417 from_bb1:
418 br label %from_bb2
419 from_bb2:
420 br label %from_bb3
421 from_bb3:
422 ret void
423 }
424 define void @to() {
425 to_bb1:
426 br label %to_bb2
427 to_bb2:
428 br label %to_bb3
429 to_bb3:
430 ret void
431 }
432)");
433
434 Function *FromF = M->getFunction("from");
435 BasicBlock *FromBB1 = getBBWithName(FromF, "from_bb1");
436 BasicBlock *FromBB2 = getBBWithName(FromF, "from_bb2");
437
438 Function *ToF = M->getFunction("to");
439 BasicBlock *ToBB2 = getBBWithName(ToF, "to_bb2");
440
441 EXPECT_DEATH(ToF->splice(ToBB2->getIterator(), FromF, FromBB2->getIterator(),
442 FromBB1->getIterator()),
443 "FromBeginIt not before FromEndIt!");
444}
445#endif //EXPENSIVE_CHECKS
446
447TEST(FunctionTest, EraseBBs) {
448 LLVMContext Ctx;
449 std::unique_ptr<Module> M = parseIR(C&: Ctx, IR: R"(
450 define void @foo() {
451 bb1:
452 br label %bb2
453 bb2:
454 br label %bb3
455 bb3:
456 br label %bb4
457 bb4:
458 br label %bb5
459 bb5:
460 ret void
461 }
462)");
463
464 Function *F = M->getFunction(Name: "foo");
465 BasicBlock *BB1 = getBBWithName(F, Name: "bb1");
466 BasicBlock *BB2 = getBBWithName(F, Name: "bb2");
467 BasicBlock *BB3 = getBBWithName(F, Name: "bb3");
468 BasicBlock *BB4 = getBBWithName(F, Name: "bb4");
469 BasicBlock *BB5 = getBBWithName(F, Name: "bb5");
470 EXPECT_EQ(F->size(), 5u);
471
472 // Erase BB2.
473 BB1->getTerminator()->eraseFromParent();
474 auto It = F->erase(FromIt: BB2->getIterator(), ToIt: std::next(x: BB2->getIterator()));
475 EXPECT_EQ(F->size(), 4u);
476 // Check that the iterator returned matches the node after the erased one.
477 EXPECT_EQ(It, BB3->getIterator());
478
479 It = F->begin();
480 EXPECT_EQ(&*It++, BB1);
481 EXPECT_EQ(&*It++, BB3);
482 EXPECT_EQ(&*It++, BB4);
483 EXPECT_EQ(&*It++, BB5);
484
485 // Erase all BBs.
486 It = F->erase(FromIt: F->begin(), ToIt: F->end());
487 EXPECT_EQ(F->size(), 0u);
488}
489} // end namespace
490

source code of llvm/unittests/IR/FunctionTest.cpp