xref: /aosp_15_r20/external/llvm/unittests/Transforms/Utils/Cloning.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- Cloning.cpp - Unit tests for the Cloner ----------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/Cloning.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallPtrSet.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Argument.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constant.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DIBuilder.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DebugInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IRBuilder.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/InstIterator.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IntrinsicInst.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LLVMContext.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Verifier.h"
25*9880d681SAndroid Build Coastguard Worker #include "gtest/gtest.h"
26*9880d681SAndroid Build Coastguard Worker 
27*9880d681SAndroid Build Coastguard Worker using namespace llvm;
28*9880d681SAndroid Build Coastguard Worker 
29*9880d681SAndroid Build Coastguard Worker namespace {
30*9880d681SAndroid Build Coastguard Worker 
31*9880d681SAndroid Build Coastguard Worker class CloneInstruction : public ::testing::Test {
32*9880d681SAndroid Build Coastguard Worker protected:
SetUp()33*9880d681SAndroid Build Coastguard Worker   void SetUp() override { V = nullptr; }
34*9880d681SAndroid Build Coastguard Worker 
35*9880d681SAndroid Build Coastguard Worker   template <typename T>
clone(T * V1)36*9880d681SAndroid Build Coastguard Worker   T *clone(T *V1) {
37*9880d681SAndroid Build Coastguard Worker     Value *V2 = V1->clone();
38*9880d681SAndroid Build Coastguard Worker     Orig.insert(V1);
39*9880d681SAndroid Build Coastguard Worker     Clones.insert(V2);
40*9880d681SAndroid Build Coastguard Worker     return cast<T>(V2);
41*9880d681SAndroid Build Coastguard Worker   }
42*9880d681SAndroid Build Coastguard Worker 
eraseClones()43*9880d681SAndroid Build Coastguard Worker   void eraseClones() {
44*9880d681SAndroid Build Coastguard Worker     DeleteContainerPointers(Clones);
45*9880d681SAndroid Build Coastguard Worker   }
46*9880d681SAndroid Build Coastguard Worker 
TearDown()47*9880d681SAndroid Build Coastguard Worker   void TearDown() override {
48*9880d681SAndroid Build Coastguard Worker     eraseClones();
49*9880d681SAndroid Build Coastguard Worker     DeleteContainerPointers(Orig);
50*9880d681SAndroid Build Coastguard Worker     delete V;
51*9880d681SAndroid Build Coastguard Worker   }
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker   SmallPtrSet<Value *, 4> Orig;   // Erase on exit
54*9880d681SAndroid Build Coastguard Worker   SmallPtrSet<Value *, 4> Clones; // Erase in eraseClones
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker   LLVMContext context;
57*9880d681SAndroid Build Coastguard Worker   Value *V;
58*9880d681SAndroid Build Coastguard Worker };
59*9880d681SAndroid Build Coastguard Worker 
TEST_F(CloneInstruction,OverflowBits)60*9880d681SAndroid Build Coastguard Worker TEST_F(CloneInstruction, OverflowBits) {
61*9880d681SAndroid Build Coastguard Worker   V = new Argument(Type::getInt32Ty(context));
62*9880d681SAndroid Build Coastguard Worker 
63*9880d681SAndroid Build Coastguard Worker   BinaryOperator *Add = BinaryOperator::Create(Instruction::Add, V, V);
64*9880d681SAndroid Build Coastguard Worker   BinaryOperator *Sub = BinaryOperator::Create(Instruction::Sub, V, V);
65*9880d681SAndroid Build Coastguard Worker   BinaryOperator *Mul = BinaryOperator::Create(Instruction::Mul, V, V);
66*9880d681SAndroid Build Coastguard Worker 
67*9880d681SAndroid Build Coastguard Worker   BinaryOperator *AddClone = this->clone(Add);
68*9880d681SAndroid Build Coastguard Worker   BinaryOperator *SubClone = this->clone(Sub);
69*9880d681SAndroid Build Coastguard Worker   BinaryOperator *MulClone = this->clone(Mul);
70*9880d681SAndroid Build Coastguard Worker 
71*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
72*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(AddClone->hasNoSignedWrap());
73*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
74*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(SubClone->hasNoSignedWrap());
75*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
76*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(MulClone->hasNoSignedWrap());
77*9880d681SAndroid Build Coastguard Worker 
78*9880d681SAndroid Build Coastguard Worker   eraseClones();
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker   Add->setHasNoUnsignedWrap();
81*9880d681SAndroid Build Coastguard Worker   Sub->setHasNoUnsignedWrap();
82*9880d681SAndroid Build Coastguard Worker   Mul->setHasNoUnsignedWrap();
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker   AddClone = this->clone(Add);
85*9880d681SAndroid Build Coastguard Worker   SubClone = this->clone(Sub);
86*9880d681SAndroid Build Coastguard Worker   MulClone = this->clone(Mul);
87*9880d681SAndroid Build Coastguard Worker 
88*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
89*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(AddClone->hasNoSignedWrap());
90*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
91*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(SubClone->hasNoSignedWrap());
92*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
93*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(MulClone->hasNoSignedWrap());
94*9880d681SAndroid Build Coastguard Worker 
95*9880d681SAndroid Build Coastguard Worker   eraseClones();
96*9880d681SAndroid Build Coastguard Worker 
97*9880d681SAndroid Build Coastguard Worker   Add->setHasNoSignedWrap();
98*9880d681SAndroid Build Coastguard Worker   Sub->setHasNoSignedWrap();
99*9880d681SAndroid Build Coastguard Worker   Mul->setHasNoSignedWrap();
100*9880d681SAndroid Build Coastguard Worker 
101*9880d681SAndroid Build Coastguard Worker   AddClone = this->clone(Add);
102*9880d681SAndroid Build Coastguard Worker   SubClone = this->clone(Sub);
103*9880d681SAndroid Build Coastguard Worker   MulClone = this->clone(Mul);
104*9880d681SAndroid Build Coastguard Worker 
105*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
106*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(AddClone->hasNoSignedWrap());
107*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
108*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(SubClone->hasNoSignedWrap());
109*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
110*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(MulClone->hasNoSignedWrap());
111*9880d681SAndroid Build Coastguard Worker 
112*9880d681SAndroid Build Coastguard Worker   eraseClones();
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker   Add->setHasNoUnsignedWrap(false);
115*9880d681SAndroid Build Coastguard Worker   Sub->setHasNoUnsignedWrap(false);
116*9880d681SAndroid Build Coastguard Worker   Mul->setHasNoUnsignedWrap(false);
117*9880d681SAndroid Build Coastguard Worker 
118*9880d681SAndroid Build Coastguard Worker   AddClone = this->clone(Add);
119*9880d681SAndroid Build Coastguard Worker   SubClone = this->clone(Sub);
120*9880d681SAndroid Build Coastguard Worker   MulClone = this->clone(Mul);
121*9880d681SAndroid Build Coastguard Worker 
122*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
123*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(AddClone->hasNoSignedWrap());
124*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
125*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(SubClone->hasNoSignedWrap());
126*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
127*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(MulClone->hasNoSignedWrap());
128*9880d681SAndroid Build Coastguard Worker }
129*9880d681SAndroid Build Coastguard Worker 
TEST_F(CloneInstruction,Inbounds)130*9880d681SAndroid Build Coastguard Worker TEST_F(CloneInstruction, Inbounds) {
131*9880d681SAndroid Build Coastguard Worker   V = new Argument(Type::getInt32PtrTy(context));
132*9880d681SAndroid Build Coastguard Worker 
133*9880d681SAndroid Build Coastguard Worker   Constant *Z = Constant::getNullValue(Type::getInt32Ty(context));
134*9880d681SAndroid Build Coastguard Worker   std::vector<Value *> ops;
135*9880d681SAndroid Build Coastguard Worker   ops.push_back(Z);
136*9880d681SAndroid Build Coastguard Worker   GetElementPtrInst *GEP =
137*9880d681SAndroid Build Coastguard Worker       GetElementPtrInst::Create(Type::getInt32Ty(context), V, ops);
138*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(this->clone(GEP)->isInBounds());
139*9880d681SAndroid Build Coastguard Worker 
140*9880d681SAndroid Build Coastguard Worker   GEP->setIsInBounds();
141*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(this->clone(GEP)->isInBounds());
142*9880d681SAndroid Build Coastguard Worker }
143*9880d681SAndroid Build Coastguard Worker 
TEST_F(CloneInstruction,Exact)144*9880d681SAndroid Build Coastguard Worker TEST_F(CloneInstruction, Exact) {
145*9880d681SAndroid Build Coastguard Worker   V = new Argument(Type::getInt32Ty(context));
146*9880d681SAndroid Build Coastguard Worker 
147*9880d681SAndroid Build Coastguard Worker   BinaryOperator *SDiv = BinaryOperator::Create(Instruction::SDiv, V, V);
148*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(this->clone(SDiv)->isExact());
149*9880d681SAndroid Build Coastguard Worker 
150*9880d681SAndroid Build Coastguard Worker   SDiv->setIsExact(true);
151*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(this->clone(SDiv)->isExact());
152*9880d681SAndroid Build Coastguard Worker }
153*9880d681SAndroid Build Coastguard Worker 
TEST_F(CloneInstruction,Attributes)154*9880d681SAndroid Build Coastguard Worker TEST_F(CloneInstruction, Attributes) {
155*9880d681SAndroid Build Coastguard Worker   Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
156*9880d681SAndroid Build Coastguard Worker   FunctionType *FT1 =  FunctionType::get(Type::getVoidTy(context), ArgTy1, false);
157*9880d681SAndroid Build Coastguard Worker 
158*9880d681SAndroid Build Coastguard Worker   Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
159*9880d681SAndroid Build Coastguard Worker   BasicBlock *BB = BasicBlock::Create(context, "", F1);
160*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder(BB);
161*9880d681SAndroid Build Coastguard Worker   Builder.CreateRetVoid();
162*9880d681SAndroid Build Coastguard Worker 
163*9880d681SAndroid Build Coastguard Worker   Function *F2 = Function::Create(FT1, Function::ExternalLinkage);
164*9880d681SAndroid Build Coastguard Worker 
165*9880d681SAndroid Build Coastguard Worker   Attribute::AttrKind AK[] = { Attribute::NoCapture };
166*9880d681SAndroid Build Coastguard Worker   AttributeSet AS = AttributeSet::get(context, 0, AK);
167*9880d681SAndroid Build Coastguard Worker   Argument *A = &*F1->arg_begin();
168*9880d681SAndroid Build Coastguard Worker   A->addAttr(AS);
169*9880d681SAndroid Build Coastguard Worker 
170*9880d681SAndroid Build Coastguard Worker   SmallVector<ReturnInst*, 4> Returns;
171*9880d681SAndroid Build Coastguard Worker   ValueToValueMapTy VMap;
172*9880d681SAndroid Build Coastguard Worker   VMap[A] = UndefValue::get(A->getType());
173*9880d681SAndroid Build Coastguard Worker 
174*9880d681SAndroid Build Coastguard Worker   CloneFunctionInto(F2, F1, VMap, false, Returns);
175*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(F2->arg_begin()->hasNoCaptureAttr());
176*9880d681SAndroid Build Coastguard Worker 
177*9880d681SAndroid Build Coastguard Worker   delete F1;
178*9880d681SAndroid Build Coastguard Worker   delete F2;
179*9880d681SAndroid Build Coastguard Worker }
180*9880d681SAndroid Build Coastguard Worker 
TEST_F(CloneInstruction,CallingConvention)181*9880d681SAndroid Build Coastguard Worker TEST_F(CloneInstruction, CallingConvention) {
182*9880d681SAndroid Build Coastguard Worker   Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
183*9880d681SAndroid Build Coastguard Worker   FunctionType *FT1 =  FunctionType::get(Type::getVoidTy(context), ArgTy1, false);
184*9880d681SAndroid Build Coastguard Worker 
185*9880d681SAndroid Build Coastguard Worker   Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
186*9880d681SAndroid Build Coastguard Worker   F1->setCallingConv(CallingConv::Cold);
187*9880d681SAndroid Build Coastguard Worker   BasicBlock *BB = BasicBlock::Create(context, "", F1);
188*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder(BB);
189*9880d681SAndroid Build Coastguard Worker   Builder.CreateRetVoid();
190*9880d681SAndroid Build Coastguard Worker 
191*9880d681SAndroid Build Coastguard Worker   Function *F2 = Function::Create(FT1, Function::ExternalLinkage);
192*9880d681SAndroid Build Coastguard Worker 
193*9880d681SAndroid Build Coastguard Worker   SmallVector<ReturnInst*, 4> Returns;
194*9880d681SAndroid Build Coastguard Worker   ValueToValueMapTy VMap;
195*9880d681SAndroid Build Coastguard Worker   VMap[&*F1->arg_begin()] = &*F2->arg_begin();
196*9880d681SAndroid Build Coastguard Worker 
197*9880d681SAndroid Build Coastguard Worker   CloneFunctionInto(F2, F1, VMap, false, Returns);
198*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(CallingConv::Cold, F2->getCallingConv());
199*9880d681SAndroid Build Coastguard Worker 
200*9880d681SAndroid Build Coastguard Worker   delete F1;
201*9880d681SAndroid Build Coastguard Worker   delete F2;
202*9880d681SAndroid Build Coastguard Worker }
203*9880d681SAndroid Build Coastguard Worker 
204*9880d681SAndroid Build Coastguard Worker class CloneFunc : public ::testing::Test {
205*9880d681SAndroid Build Coastguard Worker protected:
SetUp()206*9880d681SAndroid Build Coastguard Worker   void SetUp() override {
207*9880d681SAndroid Build Coastguard Worker     SetupModule();
208*9880d681SAndroid Build Coastguard Worker     CreateOldFunc();
209*9880d681SAndroid Build Coastguard Worker     CreateNewFunc();
210*9880d681SAndroid Build Coastguard Worker     SetupFinder();
211*9880d681SAndroid Build Coastguard Worker   }
212*9880d681SAndroid Build Coastguard Worker 
TearDown()213*9880d681SAndroid Build Coastguard Worker   void TearDown() override { delete Finder; }
214*9880d681SAndroid Build Coastguard Worker 
SetupModule()215*9880d681SAndroid Build Coastguard Worker   void SetupModule() {
216*9880d681SAndroid Build Coastguard Worker     M = new Module("", C);
217*9880d681SAndroid Build Coastguard Worker   }
218*9880d681SAndroid Build Coastguard Worker 
CreateOldFunc()219*9880d681SAndroid Build Coastguard Worker   void CreateOldFunc() {
220*9880d681SAndroid Build Coastguard Worker     FunctionType* FuncType = FunctionType::get(Type::getVoidTy(C), false);
221*9880d681SAndroid Build Coastguard Worker     OldFunc = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", M);
222*9880d681SAndroid Build Coastguard Worker     CreateOldFunctionBodyAndDI();
223*9880d681SAndroid Build Coastguard Worker   }
224*9880d681SAndroid Build Coastguard Worker 
CreateOldFunctionBodyAndDI()225*9880d681SAndroid Build Coastguard Worker   void CreateOldFunctionBodyAndDI() {
226*9880d681SAndroid Build Coastguard Worker     DIBuilder DBuilder(*M);
227*9880d681SAndroid Build Coastguard Worker     IRBuilder<> IBuilder(C);
228*9880d681SAndroid Build Coastguard Worker 
229*9880d681SAndroid Build Coastguard Worker     // Function DI
230*9880d681SAndroid Build Coastguard Worker     auto *File = DBuilder.createFile("filename.c", "/file/dir/");
231*9880d681SAndroid Build Coastguard Worker     DITypeRefArray ParamTypes = DBuilder.getOrCreateTypeArray(None);
232*9880d681SAndroid Build Coastguard Worker     DISubroutineType *FuncType =
233*9880d681SAndroid Build Coastguard Worker         DBuilder.createSubroutineType(ParamTypes);
234*9880d681SAndroid Build Coastguard Worker     auto *CU =
235*9880d681SAndroid Build Coastguard Worker         DBuilder.createCompileUnit(dwarf::DW_LANG_C99, "filename.c",
236*9880d681SAndroid Build Coastguard Worker                                    "/file/dir", "CloneFunc", false, "", 0);
237*9880d681SAndroid Build Coastguard Worker 
238*9880d681SAndroid Build Coastguard Worker     auto *Subprogram = DBuilder.createFunction(
239*9880d681SAndroid Build Coastguard Worker         CU, "f", "f", File, 4, FuncType, true, true, 3, 0, false);
240*9880d681SAndroid Build Coastguard Worker     OldFunc->setSubprogram(Subprogram);
241*9880d681SAndroid Build Coastguard Worker 
242*9880d681SAndroid Build Coastguard Worker     // Function body
243*9880d681SAndroid Build Coastguard Worker     BasicBlock* Entry = BasicBlock::Create(C, "", OldFunc);
244*9880d681SAndroid Build Coastguard Worker     IBuilder.SetInsertPoint(Entry);
245*9880d681SAndroid Build Coastguard Worker     DebugLoc Loc = DebugLoc::get(3, 2, Subprogram);
246*9880d681SAndroid Build Coastguard Worker     IBuilder.SetCurrentDebugLocation(Loc);
247*9880d681SAndroid Build Coastguard Worker     AllocaInst* Alloca = IBuilder.CreateAlloca(IntegerType::getInt32Ty(C));
248*9880d681SAndroid Build Coastguard Worker     IBuilder.SetCurrentDebugLocation(DebugLoc::get(4, 2, Subprogram));
249*9880d681SAndroid Build Coastguard Worker     Value* AllocaContent = IBuilder.getInt32(1);
250*9880d681SAndroid Build Coastguard Worker     Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca);
251*9880d681SAndroid Build Coastguard Worker     IBuilder.SetCurrentDebugLocation(DebugLoc::get(5, 2, Subprogram));
252*9880d681SAndroid Build Coastguard Worker     Instruction* Terminator = IBuilder.CreateRetVoid();
253*9880d681SAndroid Build Coastguard Worker 
254*9880d681SAndroid Build Coastguard Worker     // Create a local variable around the alloca
255*9880d681SAndroid Build Coastguard Worker     auto *IntType =
256*9880d681SAndroid Build Coastguard Worker         DBuilder.createBasicType("int", 32, 0, dwarf::DW_ATE_signed);
257*9880d681SAndroid Build Coastguard Worker     auto *E = DBuilder.createExpression();
258*9880d681SAndroid Build Coastguard Worker     auto *Variable =
259*9880d681SAndroid Build Coastguard Worker         DBuilder.createAutoVariable(Subprogram, "x", File, 5, IntType, true);
260*9880d681SAndroid Build Coastguard Worker     auto *DL = DILocation::get(Subprogram->getContext(), 5, 0, Subprogram);
261*9880d681SAndroid Build Coastguard Worker     DBuilder.insertDeclare(Alloca, Variable, E, DL, Store);
262*9880d681SAndroid Build Coastguard Worker     DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, E, DL,
263*9880d681SAndroid Build Coastguard Worker                                      Terminator);
264*9880d681SAndroid Build Coastguard Worker     // Finalize the debug info
265*9880d681SAndroid Build Coastguard Worker     DBuilder.finalize();
266*9880d681SAndroid Build Coastguard Worker 
267*9880d681SAndroid Build Coastguard Worker 
268*9880d681SAndroid Build Coastguard Worker     // Create another, empty, compile unit
269*9880d681SAndroid Build Coastguard Worker     DIBuilder DBuilder2(*M);
270*9880d681SAndroid Build Coastguard Worker     DBuilder2.createCompileUnit(dwarf::DW_LANG_C99,
271*9880d681SAndroid Build Coastguard Worker         "extra.c", "/file/dir", "CloneFunc", false, "", 0);
272*9880d681SAndroid Build Coastguard Worker     DBuilder2.finalize();
273*9880d681SAndroid Build Coastguard Worker   }
274*9880d681SAndroid Build Coastguard Worker 
CreateNewFunc()275*9880d681SAndroid Build Coastguard Worker   void CreateNewFunc() {
276*9880d681SAndroid Build Coastguard Worker     ValueToValueMapTy VMap;
277*9880d681SAndroid Build Coastguard Worker     NewFunc = CloneFunction(OldFunc, VMap, nullptr);
278*9880d681SAndroid Build Coastguard Worker   }
279*9880d681SAndroid Build Coastguard Worker 
SetupFinder()280*9880d681SAndroid Build Coastguard Worker   void SetupFinder() {
281*9880d681SAndroid Build Coastguard Worker     Finder = new DebugInfoFinder();
282*9880d681SAndroid Build Coastguard Worker     Finder->processModule(*M);
283*9880d681SAndroid Build Coastguard Worker   }
284*9880d681SAndroid Build Coastguard Worker 
285*9880d681SAndroid Build Coastguard Worker   LLVMContext C;
286*9880d681SAndroid Build Coastguard Worker   Function* OldFunc;
287*9880d681SAndroid Build Coastguard Worker   Function* NewFunc;
288*9880d681SAndroid Build Coastguard Worker   Module* M;
289*9880d681SAndroid Build Coastguard Worker   DebugInfoFinder* Finder;
290*9880d681SAndroid Build Coastguard Worker };
291*9880d681SAndroid Build Coastguard Worker 
292*9880d681SAndroid Build Coastguard Worker // Test that a new, distinct function was created.
TEST_F(CloneFunc,NewFunctionCreated)293*9880d681SAndroid Build Coastguard Worker TEST_F(CloneFunc, NewFunctionCreated) {
294*9880d681SAndroid Build Coastguard Worker   EXPECT_NE(OldFunc, NewFunc);
295*9880d681SAndroid Build Coastguard Worker }
296*9880d681SAndroid Build Coastguard Worker 
297*9880d681SAndroid Build Coastguard Worker // Test that a new subprogram entry was added and is pointing to the new
298*9880d681SAndroid Build Coastguard Worker // function, while the original subprogram still points to the old one.
TEST_F(CloneFunc,Subprogram)299*9880d681SAndroid Build Coastguard Worker TEST_F(CloneFunc, Subprogram) {
300*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(verifyModule(*M));
301*9880d681SAndroid Build Coastguard Worker 
302*9880d681SAndroid Build Coastguard Worker   unsigned SubprogramCount = Finder->subprogram_count();
303*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(1U, SubprogramCount);
304*9880d681SAndroid Build Coastguard Worker 
305*9880d681SAndroid Build Coastguard Worker   auto Iter = Finder->subprograms().begin();
306*9880d681SAndroid Build Coastguard Worker   auto *Sub = cast<DISubprogram>(*Iter);
307*9880d681SAndroid Build Coastguard Worker 
308*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(Sub == OldFunc->getSubprogram());
309*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(Sub == NewFunc->getSubprogram());
310*9880d681SAndroid Build Coastguard Worker }
311*9880d681SAndroid Build Coastguard Worker 
312*9880d681SAndroid Build Coastguard Worker // Test that instructions in the old function still belong to it in the
313*9880d681SAndroid Build Coastguard Worker // metadata, while instruction in the new function belong to the new one.
TEST_F(CloneFunc,InstructionOwnership)314*9880d681SAndroid Build Coastguard Worker TEST_F(CloneFunc, InstructionOwnership) {
315*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(verifyModule(*M));
316*9880d681SAndroid Build Coastguard Worker 
317*9880d681SAndroid Build Coastguard Worker   inst_iterator OldIter = inst_begin(OldFunc);
318*9880d681SAndroid Build Coastguard Worker   inst_iterator OldEnd = inst_end(OldFunc);
319*9880d681SAndroid Build Coastguard Worker   inst_iterator NewIter = inst_begin(NewFunc);
320*9880d681SAndroid Build Coastguard Worker   inst_iterator NewEnd = inst_end(NewFunc);
321*9880d681SAndroid Build Coastguard Worker   while (OldIter != OldEnd && NewIter != NewEnd) {
322*9880d681SAndroid Build Coastguard Worker     Instruction& OldI = *OldIter;
323*9880d681SAndroid Build Coastguard Worker     Instruction& NewI = *NewIter;
324*9880d681SAndroid Build Coastguard Worker     EXPECT_NE(&OldI, &NewI);
325*9880d681SAndroid Build Coastguard Worker 
326*9880d681SAndroid Build Coastguard Worker     EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata());
327*9880d681SAndroid Build Coastguard Worker     if (OldI.hasMetadata()) {
328*9880d681SAndroid Build Coastguard Worker       const DebugLoc& OldDL = OldI.getDebugLoc();
329*9880d681SAndroid Build Coastguard Worker       const DebugLoc& NewDL = NewI.getDebugLoc();
330*9880d681SAndroid Build Coastguard Worker 
331*9880d681SAndroid Build Coastguard Worker       // Verify that the debug location data is the same
332*9880d681SAndroid Build Coastguard Worker       EXPECT_EQ(OldDL.getLine(), NewDL.getLine());
333*9880d681SAndroid Build Coastguard Worker       EXPECT_EQ(OldDL.getCol(), NewDL.getCol());
334*9880d681SAndroid Build Coastguard Worker 
335*9880d681SAndroid Build Coastguard Worker       // But that they belong to different functions
336*9880d681SAndroid Build Coastguard Worker       auto *OldSubprogram = cast<DISubprogram>(OldDL.getScope());
337*9880d681SAndroid Build Coastguard Worker       auto *NewSubprogram = cast<DISubprogram>(NewDL.getScope());
338*9880d681SAndroid Build Coastguard Worker       EXPECT_EQ(OldFunc->getSubprogram(), OldSubprogram);
339*9880d681SAndroid Build Coastguard Worker       EXPECT_EQ(NewFunc->getSubprogram(), NewSubprogram);
340*9880d681SAndroid Build Coastguard Worker     }
341*9880d681SAndroid Build Coastguard Worker 
342*9880d681SAndroid Build Coastguard Worker     ++OldIter;
343*9880d681SAndroid Build Coastguard Worker     ++NewIter;
344*9880d681SAndroid Build Coastguard Worker   }
345*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(OldEnd, OldIter);
346*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(NewEnd, NewIter);
347*9880d681SAndroid Build Coastguard Worker }
348*9880d681SAndroid Build Coastguard Worker 
349*9880d681SAndroid Build Coastguard Worker // Test that the arguments for debug intrinsics in the new function were
350*9880d681SAndroid Build Coastguard Worker // properly cloned
TEST_F(CloneFunc,DebugIntrinsics)351*9880d681SAndroid Build Coastguard Worker TEST_F(CloneFunc, DebugIntrinsics) {
352*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(verifyModule(*M));
353*9880d681SAndroid Build Coastguard Worker 
354*9880d681SAndroid Build Coastguard Worker   inst_iterator OldIter = inst_begin(OldFunc);
355*9880d681SAndroid Build Coastguard Worker   inst_iterator OldEnd = inst_end(OldFunc);
356*9880d681SAndroid Build Coastguard Worker   inst_iterator NewIter = inst_begin(NewFunc);
357*9880d681SAndroid Build Coastguard Worker   inst_iterator NewEnd = inst_end(NewFunc);
358*9880d681SAndroid Build Coastguard Worker   while (OldIter != OldEnd && NewIter != NewEnd) {
359*9880d681SAndroid Build Coastguard Worker     Instruction& OldI = *OldIter;
360*9880d681SAndroid Build Coastguard Worker     Instruction& NewI = *NewIter;
361*9880d681SAndroid Build Coastguard Worker     if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) {
362*9880d681SAndroid Build Coastguard Worker       DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI);
363*9880d681SAndroid Build Coastguard Worker       EXPECT_TRUE(NewIntrin);
364*9880d681SAndroid Build Coastguard Worker 
365*9880d681SAndroid Build Coastguard Worker       // Old address must belong to the old function
366*9880d681SAndroid Build Coastguard Worker       EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())->
367*9880d681SAndroid Build Coastguard Worker                          getParent()->getParent());
368*9880d681SAndroid Build Coastguard Worker       // New address must belong to the new function
369*9880d681SAndroid Build Coastguard Worker       EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())->
370*9880d681SAndroid Build Coastguard Worker                          getParent()->getParent());
371*9880d681SAndroid Build Coastguard Worker 
372*9880d681SAndroid Build Coastguard Worker       // Old variable must belong to the old function
373*9880d681SAndroid Build Coastguard Worker       EXPECT_EQ(OldFunc->getSubprogram(),
374*9880d681SAndroid Build Coastguard Worker                 cast<DISubprogram>(OldIntrin->getVariable()->getScope()));
375*9880d681SAndroid Build Coastguard Worker       // New variable must belong to the New function
376*9880d681SAndroid Build Coastguard Worker       EXPECT_EQ(NewFunc->getSubprogram(),
377*9880d681SAndroid Build Coastguard Worker                 cast<DISubprogram>(NewIntrin->getVariable()->getScope()));
378*9880d681SAndroid Build Coastguard Worker     } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) {
379*9880d681SAndroid Build Coastguard Worker       DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI);
380*9880d681SAndroid Build Coastguard Worker       EXPECT_TRUE(NewIntrin);
381*9880d681SAndroid Build Coastguard Worker 
382*9880d681SAndroid Build Coastguard Worker       // Old variable must belong to the old function
383*9880d681SAndroid Build Coastguard Worker       EXPECT_EQ(OldFunc->getSubprogram(),
384*9880d681SAndroid Build Coastguard Worker                 cast<DISubprogram>(OldIntrin->getVariable()->getScope()));
385*9880d681SAndroid Build Coastguard Worker       // New variable must belong to the New function
386*9880d681SAndroid Build Coastguard Worker       EXPECT_EQ(NewFunc->getSubprogram(),
387*9880d681SAndroid Build Coastguard Worker                 cast<DISubprogram>(NewIntrin->getVariable()->getScope()));
388*9880d681SAndroid Build Coastguard Worker     }
389*9880d681SAndroid Build Coastguard Worker 
390*9880d681SAndroid Build Coastguard Worker     ++OldIter;
391*9880d681SAndroid Build Coastguard Worker     ++NewIter;
392*9880d681SAndroid Build Coastguard Worker   }
393*9880d681SAndroid Build Coastguard Worker }
394*9880d681SAndroid Build Coastguard Worker 
395*9880d681SAndroid Build Coastguard Worker class CloneModule : public ::testing::Test {
396*9880d681SAndroid Build Coastguard Worker protected:
SetUp()397*9880d681SAndroid Build Coastguard Worker   void SetUp() override {
398*9880d681SAndroid Build Coastguard Worker     SetupModule();
399*9880d681SAndroid Build Coastguard Worker     CreateOldModule();
400*9880d681SAndroid Build Coastguard Worker     CreateNewModule();
401*9880d681SAndroid Build Coastguard Worker   }
402*9880d681SAndroid Build Coastguard Worker 
SetupModule()403*9880d681SAndroid Build Coastguard Worker   void SetupModule() { OldM = new Module("", C); }
404*9880d681SAndroid Build Coastguard Worker 
CreateOldModule()405*9880d681SAndroid Build Coastguard Worker   void CreateOldModule() {
406*9880d681SAndroid Build Coastguard Worker     DIBuilder DBuilder(*OldM);
407*9880d681SAndroid Build Coastguard Worker     IRBuilder<> IBuilder(C);
408*9880d681SAndroid Build Coastguard Worker 
409*9880d681SAndroid Build Coastguard Worker     auto *FuncType = FunctionType::get(Type::getVoidTy(C), false);
410*9880d681SAndroid Build Coastguard Worker     auto *PersFn = Function::Create(FuncType, GlobalValue::ExternalLinkage,
411*9880d681SAndroid Build Coastguard Worker                                     "persfn", OldM);
412*9880d681SAndroid Build Coastguard Worker     auto *F =
413*9880d681SAndroid Build Coastguard Worker         Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", OldM);
414*9880d681SAndroid Build Coastguard Worker     F->setPersonalityFn(PersFn);
415*9880d681SAndroid Build Coastguard Worker 
416*9880d681SAndroid Build Coastguard Worker     // Create debug info
417*9880d681SAndroid Build Coastguard Worker     auto *File = DBuilder.createFile("filename.c", "/file/dir/");
418*9880d681SAndroid Build Coastguard Worker     DITypeRefArray ParamTypes = DBuilder.getOrCreateTypeArray(None);
419*9880d681SAndroid Build Coastguard Worker     DISubroutineType *DFuncType = DBuilder.createSubroutineType(ParamTypes);
420*9880d681SAndroid Build Coastguard Worker     auto *CU =
421*9880d681SAndroid Build Coastguard Worker         DBuilder.createCompileUnit(dwarf::DW_LANG_C99, "filename.c",
422*9880d681SAndroid Build Coastguard Worker                                    "/file/dir", "CloneModule", false, "", 0);
423*9880d681SAndroid Build Coastguard Worker     // Function DI
424*9880d681SAndroid Build Coastguard Worker     auto *Subprogram = DBuilder.createFunction(CU, "f", "f", File, 4, DFuncType,
425*9880d681SAndroid Build Coastguard Worker                                                true, true, 3, 0, false);
426*9880d681SAndroid Build Coastguard Worker     F->setSubprogram(Subprogram);
427*9880d681SAndroid Build Coastguard Worker 
428*9880d681SAndroid Build Coastguard Worker     auto *Entry = BasicBlock::Create(C, "", F);
429*9880d681SAndroid Build Coastguard Worker     IBuilder.SetInsertPoint(Entry);
430*9880d681SAndroid Build Coastguard Worker     IBuilder.CreateRetVoid();
431*9880d681SAndroid Build Coastguard Worker 
432*9880d681SAndroid Build Coastguard Worker     // Finalize the debug info
433*9880d681SAndroid Build Coastguard Worker     DBuilder.finalize();
434*9880d681SAndroid Build Coastguard Worker   }
435*9880d681SAndroid Build Coastguard Worker 
CreateNewModule()436*9880d681SAndroid Build Coastguard Worker   void CreateNewModule() { NewM = llvm::CloneModule(OldM).release(); }
437*9880d681SAndroid Build Coastguard Worker 
438*9880d681SAndroid Build Coastguard Worker   LLVMContext C;
439*9880d681SAndroid Build Coastguard Worker   Module *OldM;
440*9880d681SAndroid Build Coastguard Worker   Module *NewM;
441*9880d681SAndroid Build Coastguard Worker };
442*9880d681SAndroid Build Coastguard Worker 
TEST_F(CloneModule,Verify)443*9880d681SAndroid Build Coastguard Worker TEST_F(CloneModule, Verify) {
444*9880d681SAndroid Build Coastguard Worker   EXPECT_FALSE(verifyModule(*NewM));
445*9880d681SAndroid Build Coastguard Worker }
446*9880d681SAndroid Build Coastguard Worker 
TEST_F(CloneModule,OldModuleUnchanged)447*9880d681SAndroid Build Coastguard Worker TEST_F(CloneModule, OldModuleUnchanged) {
448*9880d681SAndroid Build Coastguard Worker   DebugInfoFinder Finder;
449*9880d681SAndroid Build Coastguard Worker   Finder.processModule(*OldM);
450*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(1U, Finder.subprogram_count());
451*9880d681SAndroid Build Coastguard Worker }
452*9880d681SAndroid Build Coastguard Worker 
TEST_F(CloneModule,Subprogram)453*9880d681SAndroid Build Coastguard Worker TEST_F(CloneModule, Subprogram) {
454*9880d681SAndroid Build Coastguard Worker   Function *NewF = NewM->getFunction("f");
455*9880d681SAndroid Build Coastguard Worker   DISubprogram *SP = NewF->getSubprogram();
456*9880d681SAndroid Build Coastguard Worker   EXPECT_TRUE(SP != nullptr);
457*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(SP->getName(), "f");
458*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(SP->getFile()->getFilename(), "filename.c");
459*9880d681SAndroid Build Coastguard Worker   EXPECT_EQ(SP->getLine(), (unsigned)4);
460*9880d681SAndroid Build Coastguard Worker }
461*9880d681SAndroid Build Coastguard Worker }
462