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