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