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