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/IR/Module.h"
11 #include "gtest/gtest.h"
12 using namespace llvm;
13 
14 namespace {
15 
16 TEST(FunctionTest, hasLazyArguments) {
17   LLVMContext C;
18 
19   Type *ArgTypes[] = {Type::getInt8Ty(C), Type::getInt32Ty(C)};
20   FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), ArgTypes, false);
21 
22   // Functions start out with lazy arguments.
23   std::unique_ptr<Function> F(
24       Function::Create(FTy, GlobalValue::ExternalLinkage, "F"));
25   EXPECT_TRUE(F->hasLazyArguments());
26 
27   // Checking for empty or size shouldn't force arguments to be instantiated.
28   EXPECT_FALSE(F->arg_empty());
29   EXPECT_TRUE(F->hasLazyArguments());
30   EXPECT_EQ(2u, F->arg_size());
31   EXPECT_TRUE(F->hasLazyArguments());
32 
33   // The argument list should be populated at first access.
34   (void)F->arg_begin();
35   EXPECT_FALSE(F->hasLazyArguments());
36 }
37 
38 TEST(FunctionTest, stealArgumentListFrom) {
39   LLVMContext C;
40 
41   Type *ArgTypes[] = {Type::getInt8Ty(C), Type::getInt32Ty(C)};
42   FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), ArgTypes, false);
43   std::unique_ptr<Function> F1(
44       Function::Create(FTy, GlobalValue::ExternalLinkage, "F1"));
45   std::unique_ptr<Function> F2(
46       Function::Create(FTy, GlobalValue::ExternalLinkage, "F1"));
47   EXPECT_TRUE(F1->hasLazyArguments());
48   EXPECT_TRUE(F2->hasLazyArguments());
49 
50   // Steal arguments before they've been accessed.  Nothing should change; both
51   // functions should still have lazy arguments.
52   //
53   //   steal(empty); drop (empty)
54   F1->stealArgumentListFrom(*F2);
55   EXPECT_TRUE(F1->hasLazyArguments());
56   EXPECT_TRUE(F2->hasLazyArguments());
57 
58   // Save arguments from F1 for later assertions.  F1 won't have lazy arguments
59   // anymore.
60   SmallVector<Argument *, 4> Args;
61   for (Argument &A : F1->args())
62     Args.push_back(&A);
63   EXPECT_EQ(2u, Args.size());
64   EXPECT_FALSE(F1->hasLazyArguments());
65 
66   // Steal arguments from F1 to F2.  F1's arguments should be lazy again.
67   //
68   //   steal(real); drop (empty)
69   F2->stealArgumentListFrom(*F1);
70   EXPECT_TRUE(F1->hasLazyArguments());
71   EXPECT_FALSE(F2->hasLazyArguments());
72   unsigned I = 0;
73   for (Argument &A : F2->args()) {
74     EXPECT_EQ(Args[I], &A);
75     I++;
76   }
77   EXPECT_EQ(2u, I);
78 
79   // Check that arguments in F1 don't have pointer equality with the saved ones.
80   // This also instantiates F1's arguments.
81   I = 0;
82   for (Argument &A : F1->args()) {
83     EXPECT_NE(Args[I], &A);
84     I++;
85   }
86   EXPECT_EQ(2u, I);
87   EXPECT_FALSE(F1->hasLazyArguments());
88   EXPECT_FALSE(F2->hasLazyArguments());
89 
90   // Steal back from F2.  F2's arguments should be lazy again.
91   //
92   //   steal(real); drop (real)
93   F1->stealArgumentListFrom(*F2);
94   EXPECT_FALSE(F1->hasLazyArguments());
95   EXPECT_TRUE(F2->hasLazyArguments());
96   I = 0;
97   for (Argument &A : F1->args()) {
98     EXPECT_EQ(Args[I], &A);
99     I++;
100   }
101   EXPECT_EQ(2u, I);
102 
103   // Steal from F2 a second time.  Now both functions should have lazy
104   // arguments.
105   //
106   //   steal(empty); drop (real)
107   F1->stealArgumentListFrom(*F2);
108   EXPECT_TRUE(F1->hasLazyArguments());
109   EXPECT_TRUE(F2->hasLazyArguments());
110 }
111 
112 // Test setting and removing section information
113 TEST(FunctionTest, setSection) {
114   LLVMContext C;
115   Module M("test", C);
116 
117   llvm::Function *F =
118       Function::Create(llvm::FunctionType::get(llvm::Type::getVoidTy(C), false),
119                        llvm::GlobalValue::ExternalLinkage, "F", &M);
120 
121   F->setSection(".text.test");
122   EXPECT_TRUE(F->getSection() == ".text.test");
123   EXPECT_TRUE(F->hasSection());
124   F->setSection("");
125   EXPECT_FALSE(F->hasSection());
126   F->setSection(".text.test");
127   F->setSection(".text.test2");
128   EXPECT_TRUE(F->getSection() == ".text.test2");
129   EXPECT_TRUE(F->hasSection());
130 }
131 
132 TEST(FunctionTest, GetPointerAlignment) {
133   LLVMContext Context;
134   Type *VoidType(Type::getVoidTy(Context));
135   FunctionType *FuncType(FunctionType::get(VoidType, false));
136   std::unique_ptr<Function> Func(Function::Create(
137       FuncType, GlobalValue::ExternalLinkage));
138   EXPECT_EQ(0U, Func->getPointerAlignment(DataLayout("")));
139   EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fi8")));
140   EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fn8")));
141   EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fi16")));
142   EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fn16")));
143   EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fi32")));
144   EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn32")));
145 
146   Func->setAlignment(4U);
147 
148   EXPECT_EQ(0U, Func->getPointerAlignment(DataLayout("")));
149   EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fi8")));
150   EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn8")));
151   EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fi16")));
152   EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn16")));
153   EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fi32")));
154   EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn32")));
155 }
156 
157 } // end namespace
158