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 27using namespace llvm; 28 29namespace { 30 31class CloneInstruction : public ::testing::Test { 32protected: 33 void SetUp() override { V = nullptr; } 34 35 template <typename T> 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 43 void eraseClones() { 44 DeleteContainerPointers(Clones); 45 } 46 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 60TEST_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 130TEST_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 144TEST_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 154TEST_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 181TEST_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 204class CloneFunc : public ::testing::Test { 205protected: 206 void SetUp() override { 207 SetupModule(); 208 CreateOldFunc(); 209 CreateNewFunc(); 210 SetupFinder(); 211 } 212 213 void TearDown() override { delete Finder; } 214 215 void SetupModule() { 216 M = new Module("", C); 217 } 218 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 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 275 void CreateNewFunc() { 276 ValueToValueMapTy VMap; 277 NewFunc = CloneFunction(OldFunc, VMap, nullptr); 278 } 279 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. 293TEST_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. 299TEST_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. 314TEST_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 351TEST_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 395class CloneModule : public ::testing::Test { 396protected: 397 void SetUp() override { 398 SetupModule(); 399 CreateOldModule(); 400 CreateNewModule(); 401 } 402 403 void SetupModule() { OldM = new Module("", C); } 404 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 436 void CreateNewModule() { NewM = llvm::CloneModule(OldM).release(); } 437 438 LLVMContext C; 439 Module *OldM; 440 Module *NewM; 441}; 442 443TEST_F(CloneModule, Verify) { 444 EXPECT_FALSE(verifyModule(*NewM)); 445} 446 447TEST_F(CloneModule, OldModuleUnchanged) { 448 DebugInfoFinder Finder; 449 Finder.processModule(*OldM); 450 EXPECT_EQ(1U, Finder.subprogram_count()); 451} 452 453TEST_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