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