1 //===- Cloning.cpp - Unit tests for the Cloner ----------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Transforms/Utils/Cloning.h" 10 #include "llvm/ADT/STLExtras.h" 11 #include "llvm/ADT/SmallPtrSet.h" 12 #include "llvm/Analysis/AliasAnalysis.h" 13 #include "llvm/Analysis/DomTreeUpdater.h" 14 #include "llvm/Analysis/LoopInfo.h" 15 #include "llvm/AsmParser/Parser.h" 16 #include "llvm/IR/Argument.h" 17 #include "llvm/IR/Constant.h" 18 #include "llvm/IR/DIBuilder.h" 19 #include "llvm/IR/DebugInfo.h" 20 #include "llvm/IR/Function.h" 21 #include "llvm/IR/IRBuilder.h" 22 #include "llvm/IR/InstIterator.h" 23 #include "llvm/IR/Instructions.h" 24 #include "llvm/IR/IntrinsicInst.h" 25 #include "llvm/IR/LLVMContext.h" 26 #include "llvm/IR/Module.h" 27 #include "llvm/IR/Verifier.h" 28 #include "llvm/Support/SourceMgr.h" 29 #include "gtest/gtest.h" 30 31 using namespace llvm; 32 33 namespace { 34 35 class CloneInstruction : public ::testing::Test { 36 protected: 37 void SetUp() override { V = nullptr; } 38 39 template <typename T> 40 T *clone(T *V1) { 41 Value *V2 = V1->clone(); 42 Orig.insert(V1); 43 Clones.insert(V2); 44 return cast<T>(V2); 45 } 46 47 void eraseClones() { 48 for (Value *V : Clones) 49 V->deleteValue(); 50 Clones.clear(); 51 } 52 53 void TearDown() override { 54 eraseClones(); 55 for (Value *V : Orig) 56 V->deleteValue(); 57 Orig.clear(); 58 if (V) 59 V->deleteValue(); 60 } 61 62 SmallPtrSet<Value *, 4> Orig; // Erase on exit 63 SmallPtrSet<Value *, 4> Clones; // Erase in eraseClones 64 65 LLVMContext context; 66 Value *V; 67 }; 68 69 TEST_F(CloneInstruction, OverflowBits) { 70 V = new Argument(Type::getInt32Ty(context)); 71 72 BinaryOperator *Add = BinaryOperator::Create(Instruction::Add, V, V); 73 BinaryOperator *Sub = BinaryOperator::Create(Instruction::Sub, V, V); 74 BinaryOperator *Mul = BinaryOperator::Create(Instruction::Mul, V, V); 75 76 BinaryOperator *AddClone = this->clone(Add); 77 BinaryOperator *SubClone = this->clone(Sub); 78 BinaryOperator *MulClone = this->clone(Mul); 79 80 EXPECT_FALSE(AddClone->hasNoUnsignedWrap()); 81 EXPECT_FALSE(AddClone->hasNoSignedWrap()); 82 EXPECT_FALSE(SubClone->hasNoUnsignedWrap()); 83 EXPECT_FALSE(SubClone->hasNoSignedWrap()); 84 EXPECT_FALSE(MulClone->hasNoUnsignedWrap()); 85 EXPECT_FALSE(MulClone->hasNoSignedWrap()); 86 87 eraseClones(); 88 89 Add->setHasNoUnsignedWrap(); 90 Sub->setHasNoUnsignedWrap(); 91 Mul->setHasNoUnsignedWrap(); 92 93 AddClone = this->clone(Add); 94 SubClone = this->clone(Sub); 95 MulClone = this->clone(Mul); 96 97 EXPECT_TRUE(AddClone->hasNoUnsignedWrap()); 98 EXPECT_FALSE(AddClone->hasNoSignedWrap()); 99 EXPECT_TRUE(SubClone->hasNoUnsignedWrap()); 100 EXPECT_FALSE(SubClone->hasNoSignedWrap()); 101 EXPECT_TRUE(MulClone->hasNoUnsignedWrap()); 102 EXPECT_FALSE(MulClone->hasNoSignedWrap()); 103 104 eraseClones(); 105 106 Add->setHasNoSignedWrap(); 107 Sub->setHasNoSignedWrap(); 108 Mul->setHasNoSignedWrap(); 109 110 AddClone = this->clone(Add); 111 SubClone = this->clone(Sub); 112 MulClone = this->clone(Mul); 113 114 EXPECT_TRUE(AddClone->hasNoUnsignedWrap()); 115 EXPECT_TRUE(AddClone->hasNoSignedWrap()); 116 EXPECT_TRUE(SubClone->hasNoUnsignedWrap()); 117 EXPECT_TRUE(SubClone->hasNoSignedWrap()); 118 EXPECT_TRUE(MulClone->hasNoUnsignedWrap()); 119 EXPECT_TRUE(MulClone->hasNoSignedWrap()); 120 121 eraseClones(); 122 123 Add->setHasNoUnsignedWrap(false); 124 Sub->setHasNoUnsignedWrap(false); 125 Mul->setHasNoUnsignedWrap(false); 126 127 AddClone = this->clone(Add); 128 SubClone = this->clone(Sub); 129 MulClone = this->clone(Mul); 130 131 EXPECT_FALSE(AddClone->hasNoUnsignedWrap()); 132 EXPECT_TRUE(AddClone->hasNoSignedWrap()); 133 EXPECT_FALSE(SubClone->hasNoUnsignedWrap()); 134 EXPECT_TRUE(SubClone->hasNoSignedWrap()); 135 EXPECT_FALSE(MulClone->hasNoUnsignedWrap()); 136 EXPECT_TRUE(MulClone->hasNoSignedWrap()); 137 } 138 139 TEST_F(CloneInstruction, Inbounds) { 140 V = new Argument(PointerType::get(context, 0)); 141 142 Constant *Z = Constant::getNullValue(Type::getInt32Ty(context)); 143 std::vector<Value *> ops; 144 ops.push_back(Z); 145 GetElementPtrInst *GEP = 146 GetElementPtrInst::Create(Type::getInt32Ty(context), V, ops); 147 EXPECT_FALSE(this->clone(GEP)->isInBounds()); 148 149 GEP->setIsInBounds(); 150 EXPECT_TRUE(this->clone(GEP)->isInBounds()); 151 } 152 153 TEST_F(CloneInstruction, Exact) { 154 V = new Argument(Type::getInt32Ty(context)); 155 156 BinaryOperator *SDiv = BinaryOperator::Create(Instruction::SDiv, V, V); 157 EXPECT_FALSE(this->clone(SDiv)->isExact()); 158 159 SDiv->setIsExact(true); 160 EXPECT_TRUE(this->clone(SDiv)->isExact()); 161 } 162 163 TEST_F(CloneInstruction, Attributes) { 164 Type *ArgTy1[] = {PointerType::get(context, 0)}; 165 FunctionType *FT1 = 166 FunctionType::get(Type::getVoidTy(context), ArgTy1, false); 167 168 Function *F1 = Function::Create(FT1, Function::ExternalLinkage); 169 BasicBlock *BB = BasicBlock::Create(context, "", F1); 170 IRBuilder<> Builder(BB); 171 Builder.CreateRetVoid(); 172 173 Function *F2 = Function::Create(FT1, Function::ExternalLinkage); 174 175 Argument *A = &*F1->arg_begin(); 176 A->addAttr( 177 Attribute::getWithCaptureInfo(A->getContext(), CaptureInfo::none())); 178 179 SmallVector<ReturnInst*, 4> Returns; 180 ValueToValueMapTy VMap; 181 VMap[A] = UndefValue::get(A->getType()); 182 183 CloneFunctionInto(F2, F1, VMap, CloneFunctionChangeType::LocalChangesOnly, 184 Returns); 185 EXPECT_FALSE(F2->arg_begin()->hasNoCaptureAttr()); 186 187 delete F1; 188 delete F2; 189 } 190 191 TEST_F(CloneInstruction, CallingConvention) { 192 Type *ArgTy1[] = {PointerType::get(context, 0)}; 193 FunctionType *FT1 = 194 FunctionType::get(Type::getVoidTy(context), ArgTy1, false); 195 196 Function *F1 = Function::Create(FT1, Function::ExternalLinkage); 197 F1->setCallingConv(CallingConv::Cold); 198 BasicBlock *BB = BasicBlock::Create(context, "", F1); 199 IRBuilder<> Builder(BB); 200 Builder.CreateRetVoid(); 201 202 Function *F2 = Function::Create(FT1, Function::ExternalLinkage); 203 204 SmallVector<ReturnInst*, 4> Returns; 205 ValueToValueMapTy VMap; 206 VMap[&*F1->arg_begin()] = &*F2->arg_begin(); 207 208 CloneFunctionInto(F2, F1, VMap, CloneFunctionChangeType::LocalChangesOnly, 209 Returns); 210 EXPECT_EQ(CallingConv::Cold, F2->getCallingConv()); 211 212 delete F1; 213 delete F2; 214 } 215 216 TEST_F(CloneInstruction, DuplicateInstructionsToSplit) { 217 Type *ArgTy1[] = {PointerType::get(context, 0)}; 218 FunctionType *FT = FunctionType::get(Type::getVoidTy(context), ArgTy1, false); 219 V = new Argument(Type::getInt32Ty(context)); 220 221 Function *F = Function::Create(FT, Function::ExternalLinkage); 222 223 BasicBlock *BB1 = BasicBlock::Create(context, "", F); 224 IRBuilder<> Builder1(BB1); 225 226 BasicBlock *BB2 = BasicBlock::Create(context, "", F); 227 IRBuilder<> Builder2(BB2); 228 229 Builder1.CreateBr(BB2); 230 231 Instruction *AddInst = cast<Instruction>(Builder2.CreateAdd(V, V)); 232 Instruction *MulInst = cast<Instruction>(Builder2.CreateMul(AddInst, V)); 233 Instruction *SubInst = cast<Instruction>(Builder2.CreateSub(MulInst, V)); 234 Builder2.CreateRetVoid(); 235 236 // Dummy DTU. 237 ValueToValueMapTy Mapping; 238 DomTreeUpdater DTU(DomTreeUpdater::UpdateStrategy::Lazy); 239 auto Split = 240 DuplicateInstructionsInSplitBetween(BB2, BB1, SubInst, Mapping, DTU); 241 242 EXPECT_TRUE(Split); 243 EXPECT_EQ(Mapping.size(), 2u); 244 EXPECT_TRUE(Mapping.find(AddInst) != Mapping.end()); 245 EXPECT_TRUE(Mapping.find(MulInst) != Mapping.end()); 246 247 auto AddSplit = dyn_cast<Instruction>(Mapping[AddInst]); 248 EXPECT_TRUE(AddSplit); 249 EXPECT_EQ(AddSplit->getOperand(0), V); 250 EXPECT_EQ(AddSplit->getOperand(1), V); 251 EXPECT_EQ(AddSplit->getParent(), Split); 252 253 auto MulSplit = dyn_cast<Instruction>(Mapping[MulInst]); 254 EXPECT_TRUE(MulSplit); 255 EXPECT_EQ(MulSplit->getOperand(0), AddSplit); 256 EXPECT_EQ(MulSplit->getOperand(1), V); 257 EXPECT_EQ(MulSplit->getParent(), Split); 258 259 EXPECT_EQ(AddSplit->getNextNode(), MulSplit); 260 EXPECT_EQ(MulSplit->getNextNode(), Split->getTerminator()); 261 262 delete F; 263 } 264 265 TEST_F(CloneInstruction, DuplicateInstructionsToSplitBlocksEq1) { 266 Type *ArgTy1[] = {PointerType::get(context, 0)}; 267 FunctionType *FT = FunctionType::get(Type::getVoidTy(context), ArgTy1, false); 268 V = new Argument(Type::getInt32Ty(context)); 269 270 Function *F = Function::Create(FT, Function::ExternalLinkage); 271 272 BasicBlock *BB1 = BasicBlock::Create(context, "", F); 273 IRBuilder<> Builder1(BB1); 274 275 BasicBlock *BB2 = BasicBlock::Create(context, "", F); 276 IRBuilder<> Builder2(BB2); 277 278 Builder1.CreateBr(BB2); 279 280 Instruction *AddInst = cast<Instruction>(Builder2.CreateAdd(V, V)); 281 Instruction *MulInst = cast<Instruction>(Builder2.CreateMul(AddInst, V)); 282 Instruction *SubInst = cast<Instruction>(Builder2.CreateSub(MulInst, V)); 283 Builder2.CreateBr(BB2); 284 285 // Dummy DTU. 286 DomTreeUpdater DTU(DomTreeUpdater::UpdateStrategy::Lazy); 287 ValueToValueMapTy Mapping; 288 auto Split = DuplicateInstructionsInSplitBetween( 289 BB2, BB2, BB2->getTerminator(), Mapping, DTU); 290 291 EXPECT_TRUE(Split); 292 EXPECT_EQ(Mapping.size(), 3u); 293 EXPECT_TRUE(Mapping.find(AddInst) != Mapping.end()); 294 EXPECT_TRUE(Mapping.find(MulInst) != Mapping.end()); 295 EXPECT_TRUE(Mapping.find(SubInst) != Mapping.end()); 296 297 auto AddSplit = dyn_cast<Instruction>(Mapping[AddInst]); 298 EXPECT_TRUE(AddSplit); 299 EXPECT_EQ(AddSplit->getOperand(0), V); 300 EXPECT_EQ(AddSplit->getOperand(1), V); 301 EXPECT_EQ(AddSplit->getParent(), Split); 302 303 auto MulSplit = dyn_cast<Instruction>(Mapping[MulInst]); 304 EXPECT_TRUE(MulSplit); 305 EXPECT_EQ(MulSplit->getOperand(0), AddSplit); 306 EXPECT_EQ(MulSplit->getOperand(1), V); 307 EXPECT_EQ(MulSplit->getParent(), Split); 308 309 auto SubSplit = dyn_cast<Instruction>(Mapping[SubInst]); 310 EXPECT_EQ(MulSplit->getNextNode(), SubSplit); 311 EXPECT_EQ(SubSplit->getNextNode(), Split->getTerminator()); 312 EXPECT_EQ(Split->getSingleSuccessor(), BB2); 313 EXPECT_EQ(BB2->getSingleSuccessor(), Split); 314 315 delete F; 316 } 317 318 TEST_F(CloneInstruction, DuplicateInstructionsToSplitBlocksEq2) { 319 Type *ArgTy1[] = {PointerType::get(context, 0)}; 320 FunctionType *FT = FunctionType::get(Type::getVoidTy(context), ArgTy1, false); 321 V = new Argument(Type::getInt32Ty(context)); 322 323 Function *F = Function::Create(FT, Function::ExternalLinkage); 324 325 BasicBlock *BB1 = BasicBlock::Create(context, "", F); 326 IRBuilder<> Builder1(BB1); 327 328 BasicBlock *BB2 = BasicBlock::Create(context, "", F); 329 IRBuilder<> Builder2(BB2); 330 331 Builder1.CreateBr(BB2); 332 333 Instruction *AddInst = cast<Instruction>(Builder2.CreateAdd(V, V)); 334 Instruction *MulInst = cast<Instruction>(Builder2.CreateMul(AddInst, V)); 335 Instruction *SubInst = cast<Instruction>(Builder2.CreateSub(MulInst, V)); 336 Builder2.CreateBr(BB2); 337 338 // Dummy DTU. 339 DomTreeUpdater DTU(DomTreeUpdater::UpdateStrategy::Lazy); 340 ValueToValueMapTy Mapping; 341 auto Split = 342 DuplicateInstructionsInSplitBetween(BB2, BB2, SubInst, Mapping, DTU); 343 344 EXPECT_TRUE(Split); 345 EXPECT_EQ(Mapping.size(), 2u); 346 EXPECT_TRUE(Mapping.find(AddInst) != Mapping.end()); 347 EXPECT_TRUE(Mapping.find(MulInst) != Mapping.end()); 348 349 auto AddSplit = dyn_cast<Instruction>(Mapping[AddInst]); 350 EXPECT_TRUE(AddSplit); 351 EXPECT_EQ(AddSplit->getOperand(0), V); 352 EXPECT_EQ(AddSplit->getOperand(1), V); 353 EXPECT_EQ(AddSplit->getParent(), Split); 354 355 auto MulSplit = dyn_cast<Instruction>(Mapping[MulInst]); 356 EXPECT_TRUE(MulSplit); 357 EXPECT_EQ(MulSplit->getOperand(0), AddSplit); 358 EXPECT_EQ(MulSplit->getOperand(1), V); 359 EXPECT_EQ(MulSplit->getParent(), Split); 360 EXPECT_EQ(MulSplit->getNextNode(), Split->getTerminator()); 361 EXPECT_EQ(Split->getSingleSuccessor(), BB2); 362 EXPECT_EQ(BB2->getSingleSuccessor(), Split); 363 364 delete F; 365 } 366 367 static void runWithLoopInfoAndDominatorTree( 368 Module &M, StringRef FuncName, 369 function_ref<void(Function &F, LoopInfo &LI, DominatorTree &DT)> Test) { 370 auto *F = M.getFunction(FuncName); 371 ASSERT_NE(F, nullptr) << "Could not find " << FuncName; 372 373 DominatorTree DT(*F); 374 LoopInfo LI(DT); 375 376 Test(*F, LI, DT); 377 } 378 379 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) { 380 SMDiagnostic Err; 381 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C); 382 if (!Mod) 383 Err.print("CloneLoop", errs()); 384 return Mod; 385 } 386 387 TEST(CloneLoop, CloneLoopNest) { 388 // Parse the module. 389 LLVMContext Context; 390 391 std::unique_ptr<Module> M = parseIR( 392 Context, 393 R"(define void @foo(i32* %A, i32 %ub) { 394 entry: 395 %guardcmp = icmp slt i32 0, %ub 396 br i1 %guardcmp, label %for.outer.preheader, label %for.end 397 for.outer.preheader: 398 br label %for.outer 399 for.outer: 400 %j = phi i32 [ 0, %for.outer.preheader ], [ %inc.outer, %for.outer.latch ] 401 br i1 %guardcmp, label %for.inner.preheader, label %for.outer.latch 402 for.inner.preheader: 403 br label %for.inner 404 for.inner: 405 %i = phi i32 [ 0, %for.inner.preheader ], [ %inc, %for.inner ] 406 %idxprom = sext i32 %i to i64 407 %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom 408 store i32 %i, i32* %arrayidx, align 4 409 %inc = add nsw i32 %i, 1 410 %cmp = icmp slt i32 %inc, %ub 411 br i1 %cmp, label %for.inner, label %for.inner.exit 412 for.inner.exit: 413 br label %for.outer.latch 414 for.outer.latch: 415 %inc.outer = add nsw i32 %j, 1 416 %cmp.outer = icmp slt i32 %inc.outer, %ub 417 br i1 %cmp.outer, label %for.outer, label %for.outer.exit 418 for.outer.exit: 419 br label %for.end 420 for.end: 421 ret void 422 })" 423 ); 424 425 runWithLoopInfoAndDominatorTree( 426 *M, "foo", [&](Function &F, LoopInfo &LI, DominatorTree &DT) { 427 Function::iterator FI = F.begin(); 428 // First basic block is entry - skip it. 429 BasicBlock *Preheader = &*(++FI); 430 BasicBlock *Header = &*(++FI); 431 assert(Header->getName() == "for.outer"); 432 Loop *L = LI.getLoopFor(Header); 433 EXPECT_NE(L, nullptr); 434 EXPECT_EQ(Header, L->getHeader()); 435 EXPECT_EQ(Preheader, L->getLoopPreheader()); 436 437 ValueToValueMapTy VMap; 438 SmallVector<BasicBlock *, 4> ClonedLoopBlocks; 439 Loop *NewLoop = cloneLoopWithPreheader(Preheader, Preheader, L, VMap, 440 "", &LI, &DT, ClonedLoopBlocks); 441 EXPECT_NE(NewLoop, nullptr); 442 EXPECT_EQ(NewLoop->getSubLoops().size(), 1u); 443 Loop::block_iterator BI = NewLoop->block_begin(); 444 EXPECT_TRUE((*BI)->getName().starts_with("for.outer")); 445 EXPECT_TRUE((*(++BI))->getName().starts_with("for.inner.preheader")); 446 EXPECT_TRUE((*(++BI))->getName().starts_with("for.inner")); 447 EXPECT_TRUE((*(++BI))->getName().starts_with("for.inner.exit")); 448 EXPECT_TRUE((*(++BI))->getName().starts_with("for.outer.latch")); 449 }); 450 } 451 452 class CloneFunc : public ::testing::Test { 453 protected: 454 void SetUp() override { 455 SetupModule(); 456 CreateOldFunc(); 457 CreateNewFunc(); 458 SetupFinder(); 459 } 460 461 void TearDown() override { delete Finder; } 462 463 void SetupModule() { 464 M = new Module("", C); 465 } 466 467 void CreateOldFunc() { 468 FunctionType* FuncType = FunctionType::get(Type::getVoidTy(C), false); 469 OldFunc = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", M); 470 CreateOldFunctionBodyAndDI(); 471 } 472 473 void CreateOldFunctionBodyAndDI() { 474 DIBuilder DBuilder(*M); 475 IRBuilder<> IBuilder(C); 476 477 // Function DI 478 auto *File = DBuilder.createFile("filename.c", "/file/dir/"); 479 DITypeRefArray ParamTypes = DBuilder.getOrCreateTypeArray({}); 480 DISubroutineType *FuncType = 481 DBuilder.createSubroutineType(ParamTypes); 482 auto *CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99, 483 DBuilder.createFile("filename.c", 484 "/file/dir"), 485 "CloneFunc", false, "", 0); 486 487 auto *Subprogram = DBuilder.createFunction( 488 CU, "f", "f", File, 4, FuncType, 3, DINode::FlagZero, 489 DISubprogram::SPFlagLocalToUnit | DISubprogram::SPFlagDefinition); 490 OldFunc->setSubprogram(Subprogram); 491 492 // Function body 493 BasicBlock* Entry = BasicBlock::Create(C, "", OldFunc); 494 IBuilder.SetInsertPoint(Entry); 495 DebugLoc Loc = DILocation::get(Subprogram->getContext(), 3, 2, Subprogram); 496 IBuilder.SetCurrentDebugLocation(Loc); 497 AllocaInst* Alloca = IBuilder.CreateAlloca(IntegerType::getInt32Ty(C)); 498 IBuilder.SetCurrentDebugLocation( 499 DILocation::get(Subprogram->getContext(), 4, 2, Subprogram)); 500 Value* AllocaContent = IBuilder.getInt32(1); 501 Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca); 502 IBuilder.SetCurrentDebugLocation( 503 DILocation::get(Subprogram->getContext(), 5, 2, Subprogram)); 504 505 // Create a local variable around the alloca 506 auto *IntType = DBuilder.createBasicType("int", 32, dwarf::DW_ATE_signed); 507 auto *E = DBuilder.createExpression(); 508 auto *Variable = 509 DBuilder.createAutoVariable(Subprogram, "x", File, 5, IntType, true); 510 auto *DL = DILocation::get(Subprogram->getContext(), 5, 0, Subprogram); 511 DBuilder.insertDeclare(Alloca, Variable, E, DL, Store); 512 DBuilder.insertDbgValueIntrinsic(AllocaContent, Variable, E, DL, Entry); 513 // Also create an inlined variable. 514 // Create a distinct struct type that we should not duplicate during 515 // cloning). 516 auto *StructType = DICompositeType::getDistinct( 517 C, dwarf::DW_TAG_structure_type, "some_struct", nullptr, 0, nullptr, 518 nullptr, 32, 32, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr); 519 auto *InlinedSP = DBuilder.createFunction( 520 CU, "inlined", "inlined", File, 8, FuncType, 9, DINode::FlagZero, 521 DISubprogram::SPFlagLocalToUnit | DISubprogram::SPFlagDefinition); 522 auto *InlinedVar = 523 DBuilder.createAutoVariable(InlinedSP, "inlined", File, 5, StructType, true); 524 auto *Scope = DBuilder.createLexicalBlock( 525 DBuilder.createLexicalBlockFile(InlinedSP, File), File, 1, 1); 526 auto InlinedDL = DILocation::get( 527 Subprogram->getContext(), 9, 4, Scope, 528 DILocation::get(Subprogram->getContext(), 5, 2, Subprogram)); 529 IBuilder.SetCurrentDebugLocation(InlinedDL); 530 DBuilder.insertDeclare(Alloca, InlinedVar, E, InlinedDL, Store); 531 IBuilder.CreateStore(IBuilder.getInt32(2), Alloca); 532 // Finalize the debug info. 533 DBuilder.finalize(); 534 IBuilder.CreateRetVoid(); 535 536 // Create another, empty, compile unit. 537 DIBuilder DBuilder2(*M); 538 DBuilder2.createCompileUnit(dwarf::DW_LANG_C99, 539 DBuilder.createFile("extra.c", "/file/dir"), 540 "CloneFunc", false, "", 0); 541 DBuilder2.finalize(); 542 } 543 544 void CreateNewFunc() { 545 ValueToValueMapTy VMap; 546 NewFunc = CloneFunction(OldFunc, VMap, nullptr); 547 } 548 549 void SetupFinder() { 550 Finder = new DebugInfoFinder(); 551 Finder->processModule(*M); 552 } 553 554 LLVMContext C; 555 Function* OldFunc; 556 Function* NewFunc; 557 Module* M; 558 DebugInfoFinder* Finder; 559 }; 560 561 // Test that a new, distinct function was created. 562 TEST_F(CloneFunc, NewFunctionCreated) { 563 EXPECT_NE(OldFunc, NewFunc); 564 } 565 566 // Test that a new subprogram entry was added and is pointing to the new 567 // function, while the original subprogram still points to the old one. 568 TEST_F(CloneFunc, Subprogram) { 569 EXPECT_FALSE(verifyModule(*M, &errs())); 570 EXPECT_EQ(3U, Finder->subprogram_count()); 571 EXPECT_NE(NewFunc->getSubprogram(), OldFunc->getSubprogram()); 572 } 573 574 // Test that instructions in the old function still belong to it in the 575 // metadata, while instruction in the new function belong to the new one. 576 TEST_F(CloneFunc, InstructionOwnership) { 577 EXPECT_FALSE(verifyModule(*M)); 578 579 inst_iterator OldIter = inst_begin(OldFunc); 580 inst_iterator OldEnd = inst_end(OldFunc); 581 inst_iterator NewIter = inst_begin(NewFunc); 582 inst_iterator NewEnd = inst_end(NewFunc); 583 while (OldIter != OldEnd && NewIter != NewEnd) { 584 Instruction& OldI = *OldIter; 585 Instruction& NewI = *NewIter; 586 EXPECT_NE(&OldI, &NewI); 587 588 EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata()); 589 if (OldI.hasMetadata()) { 590 const DebugLoc& OldDL = OldI.getDebugLoc(); 591 const DebugLoc& NewDL = NewI.getDebugLoc(); 592 593 // Verify that the debug location data is the same 594 EXPECT_EQ(OldDL.getLine(), NewDL.getLine()); 595 EXPECT_EQ(OldDL.getCol(), NewDL.getCol()); 596 597 // But that they belong to different functions 598 auto *OldSubprogram = cast<DISubprogram>(OldDL.getInlinedAtScope()); 599 auto *NewSubprogram = cast<DISubprogram>(NewDL.getInlinedAtScope()); 600 EXPECT_EQ(OldFunc->getSubprogram(), OldSubprogram); 601 EXPECT_EQ(NewFunc->getSubprogram(), NewSubprogram); 602 } 603 604 ++OldIter; 605 ++NewIter; 606 } 607 EXPECT_EQ(OldEnd, OldIter); 608 EXPECT_EQ(NewEnd, NewIter); 609 } 610 611 // Test that the arguments for debug intrinsics in the new function were 612 // properly cloned 613 TEST_F(CloneFunc, DebugIntrinsics) { 614 EXPECT_FALSE(verifyModule(*M)); 615 616 inst_iterator OldIter = inst_begin(OldFunc); 617 inst_iterator OldEnd = inst_end(OldFunc); 618 inst_iterator NewIter = inst_begin(NewFunc); 619 inst_iterator NewEnd = inst_end(NewFunc); 620 while (OldIter != OldEnd && NewIter != NewEnd) { 621 Instruction& OldI = *OldIter; 622 Instruction& NewI = *NewIter; 623 if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) { 624 DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI); 625 EXPECT_TRUE(NewIntrin); 626 627 // Old address must belong to the old function 628 EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())-> 629 getParent()->getParent()); 630 // New address must belong to the new function 631 EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())-> 632 getParent()->getParent()); 633 634 if (OldIntrin->getDebugLoc()->getInlinedAt()) { 635 // Inlined variable should refer to the same DILocalVariable as in the 636 // Old Function 637 EXPECT_EQ(OldIntrin->getVariable(), NewIntrin->getVariable()); 638 } else { 639 // Old variable must belong to the old function. 640 EXPECT_EQ(OldFunc->getSubprogram(), 641 cast<DISubprogram>(OldIntrin->getVariable()->getScope())); 642 // New variable must belong to the new function. 643 EXPECT_EQ(NewFunc->getSubprogram(), 644 cast<DISubprogram>(NewIntrin->getVariable()->getScope())); 645 } 646 } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) { 647 DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI); 648 EXPECT_TRUE(NewIntrin); 649 650 if (!OldIntrin->getDebugLoc()->getInlinedAt()) { 651 // Old variable must belong to the old function. 652 EXPECT_EQ(OldFunc->getSubprogram(), 653 cast<DISubprogram>(OldIntrin->getVariable()->getScope())); 654 // New variable must belong to the new function. 655 EXPECT_EQ(NewFunc->getSubprogram(), 656 cast<DISubprogram>(NewIntrin->getVariable()->getScope())); 657 } 658 } 659 660 ++OldIter; 661 ++NewIter; 662 } 663 } 664 665 static int GetDICompileUnitCount(const Module& M) { 666 if (const auto* LLVM_DBG_CU = M.getNamedMetadata("llvm.dbg.cu")) { 667 return LLVM_DBG_CU->getNumOperands(); 668 } 669 return 0; 670 } 671 672 static bool haveCompileUnitsInCommon(const Module &LHS, const Module &RHS) { 673 const NamedMDNode *LHSCUs = LHS.getNamedMetadata("llvm.dbg.cu"); 674 if (!LHSCUs) 675 return false; 676 677 const NamedMDNode *RHSCUs = RHS.getNamedMetadata("llvm.dbg.cu"); 678 if (!RHSCUs) 679 return false; 680 681 SmallPtrSet<const MDNode *, 8> Found; 682 for (int I = 0, E = LHSCUs->getNumOperands(); I != E; ++I) 683 if (const MDNode *N = LHSCUs->getOperand(I)) 684 Found.insert(N); 685 686 for (int I = 0, E = RHSCUs->getNumOperands(); I != E; ++I) 687 if (const MDNode *N = RHSCUs->getOperand(I)) 688 if (Found.count(N)) 689 return true; 690 691 return false; 692 } 693 694 TEST(CloneFunction, CloneEmptyFunction) { 695 StringRef ImplAssembly = R"( 696 define void @foo() { 697 ret void 698 } 699 declare void @bar() 700 )"; 701 702 LLVMContext Context; 703 SMDiagnostic Error; 704 705 auto ImplModule = parseAssemblyString(ImplAssembly, Error, Context); 706 EXPECT_TRUE(ImplModule != nullptr); 707 auto *ImplFunction = ImplModule->getFunction("foo"); 708 EXPECT_TRUE(ImplFunction != nullptr); 709 auto *DeclFunction = ImplModule->getFunction("bar"); 710 EXPECT_TRUE(DeclFunction != nullptr); 711 712 ValueToValueMapTy VMap; 713 SmallVector<ReturnInst *, 8> Returns; 714 ClonedCodeInfo CCI; 715 CloneFunctionInto(ImplFunction, DeclFunction, VMap, 716 CloneFunctionChangeType::GlobalChanges, Returns, "", &CCI); 717 718 EXPECT_FALSE(verifyModule(*ImplModule, &errs())); 719 EXPECT_FALSE(CCI.ContainsCalls); 720 EXPECT_FALSE(CCI.ContainsDynamicAllocas); 721 } 722 723 TEST(CloneFunction, CloneFunctionWithInalloca) { 724 StringRef ImplAssembly = R"( 725 declare void @a(i32* inalloca(i32)) 726 define void @foo() { 727 %a = alloca inalloca i32 728 call void @a(i32* inalloca(i32) %a) 729 ret void 730 } 731 declare void @bar() 732 )"; 733 734 LLVMContext Context; 735 SMDiagnostic Error; 736 737 auto ImplModule = parseAssemblyString(ImplAssembly, Error, Context); 738 EXPECT_TRUE(ImplModule != nullptr); 739 auto *ImplFunction = ImplModule->getFunction("foo"); 740 EXPECT_TRUE(ImplFunction != nullptr); 741 auto *DeclFunction = ImplModule->getFunction("bar"); 742 EXPECT_TRUE(DeclFunction != nullptr); 743 744 ValueToValueMapTy VMap; 745 SmallVector<ReturnInst *, 8> Returns; 746 ClonedCodeInfo CCI; 747 CloneFunctionInto(DeclFunction, ImplFunction, VMap, 748 CloneFunctionChangeType::GlobalChanges, Returns, "", &CCI); 749 750 EXPECT_FALSE(verifyModule(*ImplModule, &errs())); 751 EXPECT_TRUE(CCI.ContainsCalls); 752 EXPECT_TRUE(CCI.ContainsDynamicAllocas); 753 } 754 755 TEST(CloneFunction, CloneFunctionWithSubprograms) { 756 // Tests that the debug info is duplicated correctly when a DISubprogram 757 // happens to be one of the operands of the DISubprogram that is being cloned. 758 // In general, operands of "test" that are distinct should be duplicated, 759 // but in this case "my_operator" should not be duplicated. If it is 760 // duplicated, the metadata in the llvm.dbg.declare could end up with 761 // different duplicates. 762 StringRef ImplAssembly = R"( 763 declare void @llvm.dbg.declare(metadata, metadata, metadata) 764 765 define void @test() !dbg !5 { 766 call void @llvm.dbg.declare(metadata i8* undef, metadata !4, metadata !DIExpression()), !dbg !6 767 ret void 768 } 769 770 declare void @cloned() 771 772 !llvm.dbg.cu = !{!0} 773 !llvm.module.flags = !{!2} 774 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1) 775 !1 = !DIFile(filename: "test.cpp", directory: "") 776 !2 = !{i32 1, !"Debug Info Version", i32 3} 777 !3 = distinct !DISubprogram(name: "my_operator", scope: !1, unit: !0, retainedNodes: !{!4}) 778 !4 = !DILocalVariable(name: "awaitables", scope: !3) 779 !5 = distinct !DISubprogram(name: "test", scope: !3, unit: !0) 780 !6 = !DILocation(line: 55, column: 15, scope: !3, inlinedAt: !7) 781 !7 = distinct !DILocation(line: 73, column: 14, scope: !5) 782 )"; 783 784 LLVMContext Context; 785 SMDiagnostic Error; 786 787 auto ImplModule = parseAssemblyString(ImplAssembly, Error, Context); 788 EXPECT_TRUE(ImplModule != nullptr); 789 auto *OldFunc = ImplModule->getFunction("test"); 790 EXPECT_TRUE(OldFunc != nullptr); 791 auto *NewFunc = ImplModule->getFunction("cloned"); 792 EXPECT_TRUE(NewFunc != nullptr); 793 794 ValueToValueMapTy VMap; 795 SmallVector<ReturnInst *, 8> Returns; 796 ClonedCodeInfo CCI; 797 CloneFunctionInto(NewFunc, OldFunc, VMap, 798 CloneFunctionChangeType::GlobalChanges, Returns, "", &CCI); 799 800 // This fails if the scopes in the llvm.dbg.declare variable and location 801 // aren't the same. 802 EXPECT_FALSE(verifyModule(*ImplModule, &errs())); 803 } 804 805 TEST(CloneFunction, CloneFunctionWithInlinedSubprograms) { 806 StringRef ImplAssembly = R"( 807 declare void @llvm.dbg.declare(metadata, metadata, metadata) 808 809 define void @test() !dbg !3 { 810 call void @llvm.dbg.declare(metadata i8* undef, metadata !5, metadata !DIExpression()), !dbg !7 811 ret void 812 } 813 814 declare void @cloned() 815 816 !llvm.dbg.cu = !{!0} 817 !llvm.module.flags = !{!2} 818 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1) 819 !1 = !DIFile(filename: "test.cpp", directory: "") 820 !2 = !{i32 1, !"Debug Info Version", i32 3} 821 !3 = distinct !DISubprogram(name: "test", scope: !0, unit: !0) 822 !4 = distinct !DISubprogram(name: "inlined", scope: !0, unit: !0, retainedNodes: !{!5}) 823 !5 = !DILocalVariable(name: "awaitables", scope: !4) 824 !6 = distinct !DILexicalBlock(scope: !4, file: !1, line: 1) 825 !7 = !DILocation(line: 1, scope: !6, inlinedAt: !8) 826 !8 = !DILocation(line: 10, scope: !3) 827 )"; 828 829 LLVMContext Context; 830 SMDiagnostic Error; 831 832 auto ImplModule = parseAssemblyString(ImplAssembly, Error, Context); 833 EXPECT_TRUE(ImplModule != nullptr); 834 auto *Func = ImplModule->getFunction("test"); 835 EXPECT_TRUE(Func != nullptr); 836 auto *ClonedFunc = ImplModule->getFunction("cloned"); 837 EXPECT_TRUE(ClonedFunc != nullptr); 838 839 ValueToValueMapTy VMap; 840 SmallVector<ReturnInst *, 8> Returns; 841 ClonedCodeInfo CCI; 842 CloneFunctionInto(ClonedFunc, Func, VMap, 843 CloneFunctionChangeType::GlobalChanges, Returns, "", &CCI); 844 845 EXPECT_FALSE(verifyModule(*ImplModule, &errs())); 846 847 // Check that DILexicalBlock of inlined function was not cloned. 848 auto DbgDeclareI = Func->begin()->begin()->getDbgRecordRange().begin(); 849 auto ClonedDbgDeclareI = 850 ClonedFunc->begin()->begin()->getDbgRecordRange().begin(); 851 const DebugLoc &DbgLoc = DbgDeclareI->getDebugLoc(); 852 const DebugLoc &ClonedDbgLoc = ClonedDbgDeclareI->getDebugLoc(); 853 EXPECT_NE(DbgLoc.get(), ClonedDbgLoc.get()); 854 EXPECT_EQ(cast<DILexicalBlock>(DbgLoc.getScope()), 855 cast<DILexicalBlock>(ClonedDbgLoc.getScope())); 856 } 857 858 TEST(CloneFunction, CloneFunctionToDifferentModule) { 859 StringRef ImplAssembly = R"( 860 define void @foo() { 861 ret void, !dbg !5 862 } 863 864 !llvm.module.flags = !{!0} 865 !llvm.dbg.cu = !{!2, !6} 866 !0 = !{i32 1, !"Debug Info Version", i32 3} 867 !1 = distinct !DISubprogram(unit: !2) 868 !2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3) 869 !3 = !DIFile(filename: "foo.c", directory: "/tmp") 870 !4 = distinct !DISubprogram(unit: !2) 871 !5 = !DILocation(line: 4, scope: !1) 872 !6 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3) 873 )"; 874 StringRef DeclAssembly = R"( 875 declare void @foo() 876 )"; 877 878 LLVMContext Context; 879 SMDiagnostic Error; 880 881 auto ImplModule = parseAssemblyString(ImplAssembly, Error, Context); 882 EXPECT_TRUE(ImplModule != nullptr); 883 // DICompileUnits: !2, !6. Only !2 is reachable from @foo(). 884 EXPECT_TRUE(GetDICompileUnitCount(*ImplModule) == 2); 885 auto* ImplFunction = ImplModule->getFunction("foo"); 886 EXPECT_TRUE(ImplFunction != nullptr); 887 888 auto DeclModule = parseAssemblyString(DeclAssembly, Error, Context); 889 EXPECT_TRUE(DeclModule != nullptr); 890 // No DICompileUnits defined here. 891 EXPECT_TRUE(GetDICompileUnitCount(*DeclModule) == 0); 892 auto* DeclFunction = DeclModule->getFunction("foo"); 893 EXPECT_TRUE(DeclFunction != nullptr); 894 895 ValueToValueMapTy VMap; 896 VMap[ImplFunction] = DeclFunction; 897 // No args to map 898 SmallVector<ReturnInst*, 8> Returns; 899 CloneFunctionInto(DeclFunction, ImplFunction, VMap, 900 CloneFunctionChangeType::DifferentModule, Returns); 901 902 EXPECT_FALSE(verifyModule(*ImplModule, &errs())); 903 EXPECT_FALSE(verifyModule(*DeclModule, &errs())); 904 // DICompileUnit !2 shall be cloned into DeclModule. 905 EXPECT_TRUE(GetDICompileUnitCount(*DeclModule) == 1); 906 EXPECT_FALSE(haveCompileUnitsInCommon(*ImplModule, *DeclModule)); 907 } 908 909 class CloneModule : public ::testing::Test { 910 protected: 911 void SetUp() override { 912 SetupModule(); 913 CreateOldModule(); 914 CreateNewModule(); 915 } 916 917 void SetupModule() { OldM = new Module("", C); } 918 919 void CreateOldModule() { 920 auto *CD = OldM->getOrInsertComdat("comdat"); 921 CD->setSelectionKind(Comdat::ExactMatch); 922 923 auto GV = new GlobalVariable( 924 *OldM, Type::getInt32Ty(C), false, GlobalValue::ExternalLinkage, 925 ConstantInt::get(Type::getInt32Ty(C), 1), "gv"); 926 GV->addMetadata(LLVMContext::MD_type, *MDNode::get(C, {})); 927 GV->setComdat(CD); 928 929 // Add ifuncs 930 { 931 const unsigned AddrSpace = 123; 932 auto *FuncPtrTy = PointerType::get(C, AddrSpace); 933 auto *FuncTy = FunctionType::get(FuncPtrTy, false); 934 935 auto *ResolverF = Function::Create(FuncTy, GlobalValue::PrivateLinkage, 936 AddrSpace, "resolver", OldM); 937 BasicBlock *ResolverBody = BasicBlock::Create(C, "", ResolverF); 938 ReturnInst::Create(C, ConstantPointerNull::get(FuncPtrTy), ResolverBody); 939 940 GlobalIFunc *GI = GlobalIFunc::create(FuncTy, AddrSpace, 941 GlobalValue::LinkOnceODRLinkage, 942 "an_ifunc", ResolverF, OldM); 943 GI->setVisibility(GlobalValue::ProtectedVisibility); 944 } 945 946 { 947 // Add an empty compile unit first that isn't otherwise referenced, to 948 // confirm that compile units get cloned in the correct order. 949 DIBuilder EmptyBuilder(*OldM); 950 auto *File = EmptyBuilder.createFile("empty.c", "/file/dir/"); 951 (void)EmptyBuilder.createCompileUnit(dwarf::DW_LANG_C99, File, 952 "EmptyUnit", false, "", 0); 953 EmptyBuilder.finalize(); 954 } 955 956 DIBuilder DBuilder(*OldM); 957 IRBuilder<> IBuilder(C); 958 959 auto *FuncType = FunctionType::get(Type::getVoidTy(C), false); 960 auto *PersFn = Function::Create(FuncType, GlobalValue::ExternalLinkage, 961 "persfn", OldM); 962 auto *F = 963 Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", OldM); 964 F->setPersonalityFn(PersFn); 965 F->setComdat(CD); 966 967 // Create debug info 968 auto *File = DBuilder.createFile("filename.c", "/file/dir/"); 969 DITypeRefArray ParamTypes = DBuilder.getOrCreateTypeArray({}); 970 DISubroutineType *DFuncType = DBuilder.createSubroutineType(ParamTypes); 971 auto *CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99, 972 DBuilder.createFile("filename.c", 973 "/file/dir"), 974 "CloneModule", false, "", 0); 975 // Function DI 976 auto *Subprogram = DBuilder.createFunction( 977 CU, "f", "f", File, 4, DFuncType, 3, DINode::FlagZero, 978 DISubprogram::SPFlagLocalToUnit | DISubprogram::SPFlagDefinition); 979 F->setSubprogram(Subprogram); 980 981 // Create and assign DIGlobalVariableExpression to gv 982 auto GVExpression = DBuilder.createGlobalVariableExpression( 983 Subprogram, "gv", "gv", File, 1, DBuilder.createNullPtrType(), false); 984 GV->addDebugInfo(GVExpression); 985 986 // DIGlobalVariableExpression not attached to any global variable 987 auto Expr = DBuilder.createExpression( 988 ArrayRef<uint64_t>{dwarf::DW_OP_constu, 42U, dwarf::DW_OP_stack_value}); 989 990 DBuilder.createGlobalVariableExpression( 991 Subprogram, "unattached", "unattached", File, 1, 992 DBuilder.createNullPtrType(), false, true, Expr); 993 994 auto *Entry = BasicBlock::Create(C, "", F); 995 IBuilder.SetInsertPoint(Entry); 996 IBuilder.CreateRetVoid(); 997 998 auto *G = 999 Function::Create(FuncType, GlobalValue::ExternalLinkage, "g", OldM); 1000 G->addMetadata(LLVMContext::MD_type, *MDNode::get(C, {})); 1001 1002 // Finalize the debug info 1003 DBuilder.finalize(); 1004 } 1005 1006 void CreateNewModule() { NewM = llvm::CloneModule(*OldM).release(); } 1007 1008 LLVMContext C; 1009 Module *OldM; 1010 Module *NewM; 1011 }; 1012 1013 TEST_F(CloneModule, Verify) { 1014 // Confirm the old module is (still) valid. 1015 EXPECT_FALSE(verifyModule(*OldM, &errs())); 1016 1017 // Check the new module. 1018 EXPECT_FALSE(verifyModule(*NewM, &errs())); 1019 } 1020 1021 TEST_F(CloneModule, OldModuleUnchanged) { 1022 DebugInfoFinder Finder; 1023 Finder.processModule(*OldM); 1024 EXPECT_EQ(1U, Finder.subprogram_count()); 1025 } 1026 1027 TEST_F(CloneModule, Subprogram) { 1028 Function *NewF = NewM->getFunction("f"); 1029 DISubprogram *SP = NewF->getSubprogram(); 1030 EXPECT_TRUE(SP != nullptr); 1031 EXPECT_EQ(SP->getName(), "f"); 1032 EXPECT_EQ(SP->getFile()->getFilename(), "filename.c"); 1033 EXPECT_EQ(SP->getLine(), (unsigned)4); 1034 } 1035 1036 TEST_F(CloneModule, FunctionDeclarationMetadata) { 1037 Function *NewF = NewM->getFunction("g"); 1038 EXPECT_NE(nullptr, NewF->getMetadata(LLVMContext::MD_type)); 1039 } 1040 1041 TEST_F(CloneModule, GlobalMetadata) { 1042 GlobalVariable *NewGV = NewM->getGlobalVariable("gv"); 1043 EXPECT_NE(nullptr, NewGV->getMetadata(LLVMContext::MD_type)); 1044 } 1045 1046 TEST_F(CloneModule, GlobalDebugInfo) { 1047 GlobalVariable *NewGV = NewM->getGlobalVariable("gv"); 1048 EXPECT_TRUE(NewGV != nullptr); 1049 1050 // Find debug info expression assigned to global 1051 SmallVector<DIGlobalVariableExpression *, 1> GVs; 1052 NewGV->getDebugInfo(GVs); 1053 EXPECT_EQ(GVs.size(), 1U); 1054 1055 DIGlobalVariableExpression *GVExpr = GVs[0]; 1056 DIGlobalVariable *GV = GVExpr->getVariable(); 1057 EXPECT_TRUE(GV != nullptr); 1058 1059 EXPECT_EQ(GV->getName(), "gv"); 1060 EXPECT_EQ(GV->getLine(), 1U); 1061 1062 // Assert that the scope of the debug info attached to 1063 // global variable matches the cloned function. 1064 DISubprogram *SP = NewM->getFunction("f")->getSubprogram(); 1065 EXPECT_TRUE(SP != nullptr); 1066 EXPECT_EQ(GV->getScope(), SP); 1067 } 1068 1069 TEST_F(CloneModule, CompileUnit) { 1070 // Find DICompileUnit listed in llvm.dbg.cu 1071 auto *NMD = NewM->getNamedMetadata("llvm.dbg.cu"); 1072 EXPECT_TRUE(NMD != nullptr); 1073 EXPECT_EQ(NMD->getNumOperands(), 2U); 1074 EXPECT_FALSE(haveCompileUnitsInCommon(*OldM, *NewM)); 1075 1076 // Check that the empty CU is first, even though it's not referenced except 1077 // from named metadata. 1078 DICompileUnit *EmptyCU = dyn_cast<llvm::DICompileUnit>(NMD->getOperand(0)); 1079 EXPECT_TRUE(EmptyCU != nullptr); 1080 EXPECT_EQ("EmptyUnit", EmptyCU->getProducer()); 1081 1082 // Get the interesting CU. 1083 DICompileUnit *CU = dyn_cast<llvm::DICompileUnit>(NMD->getOperand(1)); 1084 EXPECT_TRUE(CU != nullptr); 1085 EXPECT_EQ("CloneModule", CU->getProducer()); 1086 1087 // Assert this CU is consistent with the cloned function debug info 1088 DISubprogram *SP = NewM->getFunction("f")->getSubprogram(); 1089 EXPECT_TRUE(SP != nullptr); 1090 EXPECT_EQ(SP->getUnit(), CU); 1091 1092 // Check globals listed in CU have the correct scope 1093 DIGlobalVariableExpressionArray GlobalArray = CU->getGlobalVariables(); 1094 EXPECT_EQ(GlobalArray.size(), 2U); 1095 for (DIGlobalVariableExpression *GVExpr : GlobalArray) { 1096 DIGlobalVariable *GV = GVExpr->getVariable(); 1097 EXPECT_EQ(GV->getScope(), SP); 1098 } 1099 } 1100 1101 TEST_F(CloneModule, Comdat) { 1102 GlobalVariable *NewGV = NewM->getGlobalVariable("gv"); 1103 auto *CD = NewGV->getComdat(); 1104 ASSERT_NE(nullptr, CD); 1105 EXPECT_EQ("comdat", CD->getName()); 1106 EXPECT_EQ(Comdat::ExactMatch, CD->getSelectionKind()); 1107 1108 Function *NewF = NewM->getFunction("f"); 1109 EXPECT_EQ(CD, NewF->getComdat()); 1110 } 1111 1112 TEST_F(CloneModule, IFunc) { 1113 ASSERT_EQ(1u, NewM->ifunc_size()); 1114 1115 const GlobalIFunc &IFunc = *NewM->ifunc_begin(); 1116 EXPECT_EQ("an_ifunc", IFunc.getName()); 1117 EXPECT_EQ(GlobalValue::LinkOnceODRLinkage, IFunc.getLinkage()); 1118 EXPECT_EQ(GlobalValue::ProtectedVisibility, IFunc.getVisibility()); 1119 EXPECT_EQ(123u, IFunc.getAddressSpace()); 1120 1121 const Function *Resolver = IFunc.getResolverFunction(); 1122 ASSERT_NE(nullptr, Resolver); 1123 EXPECT_EQ("resolver", Resolver->getName()); 1124 EXPECT_EQ(GlobalValue::PrivateLinkage, Resolver->getLinkage()); 1125 } 1126 1127 TEST_F(CloneModule, CloneDbgLabel) { 1128 LLVMContext Context; 1129 1130 std::unique_ptr<Module> M = parseIR(Context, 1131 R"M( 1132 define void @noop(ptr nocapture noundef writeonly align 4 %dst) local_unnamed_addr !dbg !3 { 1133 entry: 1134 %call = tail call spir_func i64 @foo(i32 noundef 0) 1135 #dbg_label(!11, !12) 1136 store i64 %call, ptr %dst, align 4 1137 ret void 1138 } 1139 1140 declare i64 @foo(i32 noundef) local_unnamed_addr 1141 1142 !llvm.dbg.cu = !{!0} 1143 !llvm.module.flags = !{!2} 1144 1145 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 19.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) 1146 !1 = !DIFile(filename: "<stdin>", directory: "foo") 1147 !2 = !{i32 2, !"Debug Info Version", i32 3} 1148 !3 = distinct !DISubprogram(name: "noop", scope: !4, file: !4, line: 17, type: !5, scopeLine: 17, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9) 1149 !4 = !DIFile(filename: "file", directory: "foo") 1150 !5 = !DISubroutineType(types: !6) 1151 !6 = !{null, !7} 1152 !7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64) 1153 !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) 1154 !9 = !{} 1155 !11 = !DILabel(scope: !3, name: "foo", file: !4, line: 23) 1156 !12 = !DILocation(line: 23, scope: !3) 1157 )M"); 1158 1159 ASSERT_FALSE(verifyModule(*M, &errs())); 1160 auto NewM = llvm::CloneModule(*M); 1161 EXPECT_FALSE(verifyModule(*NewM, &errs())); 1162 } 1163 } // namespace 1164