1 //===- GCOVProfiling.cpp - Insert edge counters for gcov profiling --------===// 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 // This pass implements GCOV-style profiling. When this pass is run it emits 10 // "gcno" files next to the existing source, and instruments the code that runs 11 // to records the edges between blocks that run and emit a complementary "gcda" 12 // file on exit. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "llvm/ADT/DenseMap.h" 17 #include "llvm/ADT/Hashing.h" 18 #include "llvm/ADT/STLExtras.h" 19 #include "llvm/ADT/Sequence.h" 20 #include "llvm/ADT/Statistic.h" 21 #include "llvm/ADT/StringExtras.h" 22 #include "llvm/ADT/StringMap.h" 23 #include "llvm/Analysis/EHPersonalities.h" 24 #include "llvm/Analysis/TargetLibraryInfo.h" 25 #include "llvm/IR/CFG.h" 26 #include "llvm/IR/DebugInfo.h" 27 #include "llvm/IR/DebugLoc.h" 28 #include "llvm/IR/IRBuilder.h" 29 #include "llvm/IR/InstIterator.h" 30 #include "llvm/IR/Instructions.h" 31 #include "llvm/IR/IntrinsicInst.h" 32 #include "llvm/IR/Module.h" 33 #include "llvm/Pass.h" 34 #include "llvm/Support/CommandLine.h" 35 #include "llvm/Support/Debug.h" 36 #include "llvm/Support/FileSystem.h" 37 #include "llvm/Support/Path.h" 38 #include "llvm/Support/Regex.h" 39 #include "llvm/Support/raw_ostream.h" 40 #include "llvm/Transforms/Instrumentation.h" 41 #include "llvm/Transforms/Instrumentation/GCOVProfiler.h" 42 #include "llvm/Transforms/Utils/ModuleUtils.h" 43 #include <algorithm> 44 #include <memory> 45 #include <string> 46 #include <utility> 47 using namespace llvm; 48 49 #define DEBUG_TYPE "insert-gcov-profiling" 50 51 static cl::opt<std::string> 52 DefaultGCOVVersion("default-gcov-version", cl::init("402*"), cl::Hidden, 53 cl::ValueRequired); 54 static cl::opt<bool> DefaultExitBlockBeforeBody("gcov-exit-block-before-body", 55 cl::init(false), cl::Hidden); 56 57 GCOVOptions GCOVOptions::getDefault() { 58 GCOVOptions Options; 59 Options.EmitNotes = true; 60 Options.EmitData = true; 61 Options.UseCfgChecksum = false; 62 Options.NoRedZone = false; 63 Options.FunctionNamesInData = true; 64 Options.ExitBlockBeforeBody = DefaultExitBlockBeforeBody; 65 66 if (DefaultGCOVVersion.size() != 4) { 67 llvm::report_fatal_error(std::string("Invalid -default-gcov-version: ") + 68 DefaultGCOVVersion); 69 } 70 memcpy(Options.Version, DefaultGCOVVersion.c_str(), 4); 71 return Options; 72 } 73 74 namespace { 75 class GCOVFunction; 76 77 class GCOVProfiler { 78 public: 79 GCOVProfiler() : GCOVProfiler(GCOVOptions::getDefault()) {} 80 GCOVProfiler(const GCOVOptions &Opts) : Options(Opts) { 81 assert((Options.EmitNotes || Options.EmitData) && 82 "GCOVProfiler asked to do nothing?"); 83 ReversedVersion[0] = Options.Version[3]; 84 ReversedVersion[1] = Options.Version[2]; 85 ReversedVersion[2] = Options.Version[1]; 86 ReversedVersion[3] = Options.Version[0]; 87 ReversedVersion[4] = '\0'; 88 } 89 bool 90 runOnModule(Module &M, 91 std::function<const TargetLibraryInfo &(Function &F)> GetTLI); 92 93 private: 94 // Create the .gcno files for the Module based on DebugInfo. 95 void emitProfileNotes(); 96 97 // Modify the program to track transitions along edges and call into the 98 // profiling runtime to emit .gcda files when run. 99 bool emitProfileArcs(); 100 101 bool isFunctionInstrumented(const Function &F); 102 std::vector<Regex> createRegexesFromString(StringRef RegexesStr); 103 static bool doesFilenameMatchARegex(StringRef Filename, 104 std::vector<Regex> &Regexes); 105 106 // Get pointers to the functions in the runtime library. 107 FunctionCallee getStartFileFunc(const TargetLibraryInfo *TLI); 108 FunctionCallee getEmitFunctionFunc(const TargetLibraryInfo *TLI); 109 FunctionCallee getEmitArcsFunc(const TargetLibraryInfo *TLI); 110 FunctionCallee getSummaryInfoFunc(); 111 FunctionCallee getEndFileFunc(); 112 113 // Add the function to write out all our counters to the global destructor 114 // list. 115 Function * 116 insertCounterWriteout(ArrayRef<std::pair<GlobalVariable *, MDNode *>>); 117 Function *insertFlush(ArrayRef<std::pair<GlobalVariable *, MDNode *>>); 118 119 void AddFlushBeforeForkAndExec(); 120 121 enum class GCovFileType { GCNO, GCDA }; 122 std::string mangleName(const DICompileUnit *CU, GCovFileType FileType); 123 124 GCOVOptions Options; 125 126 // Reversed, NUL-terminated copy of Options.Version. 127 char ReversedVersion[5]; 128 // Checksum, produced by hash of EdgeDestinations 129 SmallVector<uint32_t, 4> FileChecksums; 130 131 Module *M; 132 std::function<const TargetLibraryInfo &(Function &F)> GetTLI; 133 LLVMContext *Ctx; 134 SmallVector<std::unique_ptr<GCOVFunction>, 16> Funcs; 135 std::vector<Regex> FilterRe; 136 std::vector<Regex> ExcludeRe; 137 StringMap<bool> InstrumentedFiles; 138 }; 139 140 class GCOVProfilerLegacyPass : public ModulePass { 141 public: 142 static char ID; 143 GCOVProfilerLegacyPass() 144 : GCOVProfilerLegacyPass(GCOVOptions::getDefault()) {} 145 GCOVProfilerLegacyPass(const GCOVOptions &Opts) 146 : ModulePass(ID), Profiler(Opts) { 147 initializeGCOVProfilerLegacyPassPass(*PassRegistry::getPassRegistry()); 148 } 149 StringRef getPassName() const override { return "GCOV Profiler"; } 150 151 bool runOnModule(Module &M) override { 152 return Profiler.runOnModule(M, [this](Function &F) -> TargetLibraryInfo & { 153 return getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F); 154 }); 155 } 156 157 void getAnalysisUsage(AnalysisUsage &AU) const override { 158 AU.addRequired<TargetLibraryInfoWrapperPass>(); 159 } 160 161 private: 162 GCOVProfiler Profiler; 163 }; 164 } 165 166 char GCOVProfilerLegacyPass::ID = 0; 167 INITIALIZE_PASS_BEGIN( 168 GCOVProfilerLegacyPass, "insert-gcov-profiling", 169 "Insert instrumentation for GCOV profiling", false, false) 170 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) 171 INITIALIZE_PASS_END( 172 GCOVProfilerLegacyPass, "insert-gcov-profiling", 173 "Insert instrumentation for GCOV profiling", false, false) 174 175 ModulePass *llvm::createGCOVProfilerPass(const GCOVOptions &Options) { 176 return new GCOVProfilerLegacyPass(Options); 177 } 178 179 static StringRef getFunctionName(const DISubprogram *SP) { 180 if (!SP->getLinkageName().empty()) 181 return SP->getLinkageName(); 182 return SP->getName(); 183 } 184 185 /// Extract a filename for a DISubprogram. 186 /// 187 /// Prefer relative paths in the coverage notes. Clang also may split 188 /// up absolute paths into a directory and filename component. When 189 /// the relative path doesn't exist, reconstruct the absolute path. 190 static SmallString<128> getFilename(const DISubprogram *SP) { 191 SmallString<128> Path; 192 StringRef RelPath = SP->getFilename(); 193 if (sys::fs::exists(RelPath)) 194 Path = RelPath; 195 else 196 sys::path::append(Path, SP->getDirectory(), SP->getFilename()); 197 return Path; 198 } 199 200 namespace { 201 class GCOVRecord { 202 protected: 203 static const char *const LinesTag; 204 static const char *const FunctionTag; 205 static const char *const BlockTag; 206 static const char *const EdgeTag; 207 208 GCOVRecord() = default; 209 210 void writeBytes(const char *Bytes, int Size) { 211 os->write(Bytes, Size); 212 } 213 214 void write(uint32_t i) { 215 writeBytes(reinterpret_cast<char*>(&i), 4); 216 } 217 218 // Returns the length measured in 4-byte blocks that will be used to 219 // represent this string in a GCOV file 220 static unsigned lengthOfGCOVString(StringRef s) { 221 // A GCOV string is a length, followed by a NUL, then between 0 and 3 NULs 222 // padding out to the next 4-byte word. The length is measured in 4-byte 223 // words including padding, not bytes of actual string. 224 return (s.size() / 4) + 1; 225 } 226 227 void writeGCOVString(StringRef s) { 228 uint32_t Len = lengthOfGCOVString(s); 229 write(Len); 230 writeBytes(s.data(), s.size()); 231 232 // Write 1 to 4 bytes of NUL padding. 233 assert((unsigned)(4 - (s.size() % 4)) > 0); 234 assert((unsigned)(4 - (s.size() % 4)) <= 4); 235 writeBytes("\0\0\0\0", 4 - (s.size() % 4)); 236 } 237 238 raw_ostream *os; 239 }; 240 const char *const GCOVRecord::LinesTag = "\0\0\x45\x01"; 241 const char *const GCOVRecord::FunctionTag = "\0\0\0\1"; 242 const char *const GCOVRecord::BlockTag = "\0\0\x41\x01"; 243 const char *const GCOVRecord::EdgeTag = "\0\0\x43\x01"; 244 245 class GCOVFunction; 246 class GCOVBlock; 247 248 // Constructed only by requesting it from a GCOVBlock, this object stores a 249 // list of line numbers and a single filename, representing lines that belong 250 // to the block. 251 class GCOVLines : public GCOVRecord { 252 public: 253 void addLine(uint32_t Line) { 254 assert(Line != 0 && "Line zero is not a valid real line number."); 255 Lines.push_back(Line); 256 } 257 258 uint32_t length() const { 259 // Here 2 = 1 for string length + 1 for '0' id#. 260 return lengthOfGCOVString(Filename) + 2 + Lines.size(); 261 } 262 263 void writeOut() { 264 write(0); 265 writeGCOVString(Filename); 266 for (int i = 0, e = Lines.size(); i != e; ++i) 267 write(Lines[i]); 268 } 269 270 GCOVLines(StringRef F, raw_ostream *os) 271 : Filename(F) { 272 this->os = os; 273 } 274 275 private: 276 std::string Filename; 277 SmallVector<uint32_t, 32> Lines; 278 }; 279 280 281 // Represent a basic block in GCOV. Each block has a unique number in the 282 // function, number of lines belonging to each block, and a set of edges to 283 // other blocks. 284 class GCOVBlock : public GCOVRecord { 285 public: 286 GCOVLines &getFile(StringRef Filename) { 287 return LinesByFile.try_emplace(Filename, Filename, os).first->second; 288 } 289 290 void addEdge(GCOVBlock &Successor) { 291 OutEdges.push_back(&Successor); 292 } 293 294 void writeOut() { 295 uint32_t Len = 3; 296 SmallVector<StringMapEntry<GCOVLines> *, 32> SortedLinesByFile; 297 for (auto &I : LinesByFile) { 298 Len += I.second.length(); 299 SortedLinesByFile.push_back(&I); 300 } 301 302 writeBytes(LinesTag, 4); 303 write(Len); 304 write(Number); 305 306 llvm::sort(SortedLinesByFile, [](StringMapEntry<GCOVLines> *LHS, 307 StringMapEntry<GCOVLines> *RHS) { 308 return LHS->getKey() < RHS->getKey(); 309 }); 310 for (auto &I : SortedLinesByFile) 311 I->getValue().writeOut(); 312 write(0); 313 write(0); 314 } 315 316 GCOVBlock(const GCOVBlock &RHS) : GCOVRecord(RHS), Number(RHS.Number) { 317 // Only allow copy before edges and lines have been added. After that, 318 // there are inter-block pointers (eg: edges) that won't take kindly to 319 // blocks being copied or moved around. 320 assert(LinesByFile.empty()); 321 assert(OutEdges.empty()); 322 } 323 324 private: 325 friend class GCOVFunction; 326 327 GCOVBlock(uint32_t Number, raw_ostream *os) 328 : Number(Number) { 329 this->os = os; 330 } 331 332 uint32_t Number; 333 StringMap<GCOVLines> LinesByFile; 334 SmallVector<GCOVBlock *, 4> OutEdges; 335 }; 336 337 // A function has a unique identifier, a checksum (we leave as zero) and a 338 // set of blocks and a map of edges between blocks. This is the only GCOV 339 // object users can construct, the blocks and lines will be rooted here. 340 class GCOVFunction : public GCOVRecord { 341 public: 342 GCOVFunction(const DISubprogram *SP, Function *F, raw_ostream *os, 343 uint32_t Ident, bool UseCfgChecksum, bool ExitBlockBeforeBody) 344 : SP(SP), Ident(Ident), UseCfgChecksum(UseCfgChecksum), CfgChecksum(0), 345 ReturnBlock(1, os) { 346 this->os = os; 347 348 LLVM_DEBUG(dbgs() << "Function: " << getFunctionName(SP) << "\n"); 349 350 uint32_t i = 0; 351 for (auto &BB : *F) { 352 // Skip index 1 if it's assigned to the ReturnBlock. 353 if (i == 1 && ExitBlockBeforeBody) 354 ++i; 355 Blocks.insert(std::make_pair(&BB, GCOVBlock(i++, os))); 356 } 357 if (!ExitBlockBeforeBody) 358 ReturnBlock.Number = i; 359 360 std::string FunctionNameAndLine; 361 raw_string_ostream FNLOS(FunctionNameAndLine); 362 FNLOS << getFunctionName(SP) << SP->getLine(); 363 FNLOS.flush(); 364 FuncChecksum = hash_value(FunctionNameAndLine); 365 } 366 367 GCOVBlock &getBlock(BasicBlock *BB) { 368 return Blocks.find(BB)->second; 369 } 370 371 GCOVBlock &getReturnBlock() { 372 return ReturnBlock; 373 } 374 375 std::string getEdgeDestinations() { 376 std::string EdgeDestinations; 377 raw_string_ostream EDOS(EdgeDestinations); 378 Function *F = Blocks.begin()->first->getParent(); 379 for (BasicBlock &I : *F) { 380 GCOVBlock &Block = getBlock(&I); 381 for (int i = 0, e = Block.OutEdges.size(); i != e; ++i) 382 EDOS << Block.OutEdges[i]->Number; 383 } 384 return EdgeDestinations; 385 } 386 387 uint32_t getFuncChecksum() { 388 return FuncChecksum; 389 } 390 391 void setCfgChecksum(uint32_t Checksum) { 392 CfgChecksum = Checksum; 393 } 394 395 void writeOut() { 396 writeBytes(FunctionTag, 4); 397 SmallString<128> Filename = getFilename(SP); 398 uint32_t BlockLen = 1 + 1 + 1 + lengthOfGCOVString(getFunctionName(SP)) + 399 1 + lengthOfGCOVString(Filename) + 1; 400 if (UseCfgChecksum) 401 ++BlockLen; 402 write(BlockLen); 403 write(Ident); 404 write(FuncChecksum); 405 if (UseCfgChecksum) 406 write(CfgChecksum); 407 writeGCOVString(getFunctionName(SP)); 408 writeGCOVString(Filename); 409 write(SP->getLine()); 410 411 // Emit count of blocks. 412 writeBytes(BlockTag, 4); 413 write(Blocks.size() + 1); 414 for (int i = 0, e = Blocks.size() + 1; i != e; ++i) { 415 write(0); // No flags on our blocks. 416 } 417 LLVM_DEBUG(dbgs() << Blocks.size() << " blocks.\n"); 418 419 // Emit edges between blocks. 420 if (Blocks.empty()) return; 421 Function *F = Blocks.begin()->first->getParent(); 422 for (BasicBlock &I : *F) { 423 GCOVBlock &Block = getBlock(&I); 424 if (Block.OutEdges.empty()) continue; 425 426 writeBytes(EdgeTag, 4); 427 write(Block.OutEdges.size() * 2 + 1); 428 write(Block.Number); 429 for (int i = 0, e = Block.OutEdges.size(); i != e; ++i) { 430 LLVM_DEBUG(dbgs() << Block.Number << " -> " 431 << Block.OutEdges[i]->Number << "\n"); 432 write(Block.OutEdges[i]->Number); 433 write(0); // no flags 434 } 435 } 436 437 // Emit lines for each block. 438 for (BasicBlock &I : *F) 439 getBlock(&I).writeOut(); 440 } 441 442 private: 443 const DISubprogram *SP; 444 uint32_t Ident; 445 uint32_t FuncChecksum; 446 bool UseCfgChecksum; 447 uint32_t CfgChecksum; 448 DenseMap<BasicBlock *, GCOVBlock> Blocks; 449 GCOVBlock ReturnBlock; 450 }; 451 } 452 453 // RegexesStr is a string containing differents regex separated by a semi-colon. 454 // For example "foo\..*$;bar\..*$". 455 std::vector<Regex> GCOVProfiler::createRegexesFromString(StringRef RegexesStr) { 456 std::vector<Regex> Regexes; 457 while (!RegexesStr.empty()) { 458 std::pair<StringRef, StringRef> HeadTail = RegexesStr.split(';'); 459 if (!HeadTail.first.empty()) { 460 Regex Re(HeadTail.first); 461 std::string Err; 462 if (!Re.isValid(Err)) { 463 Ctx->emitError(Twine("Regex ") + HeadTail.first + 464 " is not valid: " + Err); 465 } 466 Regexes.emplace_back(std::move(Re)); 467 } 468 RegexesStr = HeadTail.second; 469 } 470 return Regexes; 471 } 472 473 bool GCOVProfiler::doesFilenameMatchARegex(StringRef Filename, 474 std::vector<Regex> &Regexes) { 475 for (Regex &Re : Regexes) { 476 if (Re.match(Filename)) { 477 return true; 478 } 479 } 480 return false; 481 } 482 483 bool GCOVProfiler::isFunctionInstrumented(const Function &F) { 484 if (FilterRe.empty() && ExcludeRe.empty()) { 485 return true; 486 } 487 SmallString<128> Filename = getFilename(F.getSubprogram()); 488 auto It = InstrumentedFiles.find(Filename); 489 if (It != InstrumentedFiles.end()) { 490 return It->second; 491 } 492 493 SmallString<256> RealPath; 494 StringRef RealFilename; 495 496 // Path can be 497 // /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/*.h so for 498 // such a case we must get the real_path. 499 if (sys::fs::real_path(Filename, RealPath)) { 500 // real_path can fail with path like "foo.c". 501 RealFilename = Filename; 502 } else { 503 RealFilename = RealPath; 504 } 505 506 bool ShouldInstrument; 507 if (FilterRe.empty()) { 508 ShouldInstrument = !doesFilenameMatchARegex(RealFilename, ExcludeRe); 509 } else if (ExcludeRe.empty()) { 510 ShouldInstrument = doesFilenameMatchARegex(RealFilename, FilterRe); 511 } else { 512 ShouldInstrument = doesFilenameMatchARegex(RealFilename, FilterRe) && 513 !doesFilenameMatchARegex(RealFilename, ExcludeRe); 514 } 515 InstrumentedFiles[Filename] = ShouldInstrument; 516 return ShouldInstrument; 517 } 518 519 std::string GCOVProfiler::mangleName(const DICompileUnit *CU, 520 GCovFileType OutputType) { 521 bool Notes = OutputType == GCovFileType::GCNO; 522 523 if (NamedMDNode *GCov = M->getNamedMetadata("llvm.gcov")) { 524 for (int i = 0, e = GCov->getNumOperands(); i != e; ++i) { 525 MDNode *N = GCov->getOperand(i); 526 bool ThreeElement = N->getNumOperands() == 3; 527 if (!ThreeElement && N->getNumOperands() != 2) 528 continue; 529 if (dyn_cast<MDNode>(N->getOperand(ThreeElement ? 2 : 1)) != CU) 530 continue; 531 532 if (ThreeElement) { 533 // These nodes have no mangling to apply, it's stored mangled in the 534 // bitcode. 535 MDString *NotesFile = dyn_cast<MDString>(N->getOperand(0)); 536 MDString *DataFile = dyn_cast<MDString>(N->getOperand(1)); 537 if (!NotesFile || !DataFile) 538 continue; 539 return Notes ? NotesFile->getString() : DataFile->getString(); 540 } 541 542 MDString *GCovFile = dyn_cast<MDString>(N->getOperand(0)); 543 if (!GCovFile) 544 continue; 545 546 SmallString<128> Filename = GCovFile->getString(); 547 sys::path::replace_extension(Filename, Notes ? "gcno" : "gcda"); 548 return Filename.str(); 549 } 550 } 551 552 SmallString<128> Filename = CU->getFilename(); 553 sys::path::replace_extension(Filename, Notes ? "gcno" : "gcda"); 554 StringRef FName = sys::path::filename(Filename); 555 SmallString<128> CurPath; 556 if (sys::fs::current_path(CurPath)) return FName; 557 sys::path::append(CurPath, FName); 558 return CurPath.str(); 559 } 560 561 bool GCOVProfiler::runOnModule( 562 Module &M, std::function<const TargetLibraryInfo &(Function &F)> GetTLI) { 563 this->M = &M; 564 this->GetTLI = std::move(GetTLI); 565 Ctx = &M.getContext(); 566 567 AddFlushBeforeForkAndExec(); 568 569 FilterRe = createRegexesFromString(Options.Filter); 570 ExcludeRe = createRegexesFromString(Options.Exclude); 571 572 if (Options.EmitNotes) emitProfileNotes(); 573 if (Options.EmitData) return emitProfileArcs(); 574 return false; 575 } 576 577 PreservedAnalyses GCOVProfilerPass::run(Module &M, 578 ModuleAnalysisManager &AM) { 579 580 GCOVProfiler Profiler(GCOVOpts); 581 FunctionAnalysisManager &FAM = 582 AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 583 584 if (!Profiler.runOnModule(M, [&](Function &F) -> TargetLibraryInfo & { 585 return FAM.getResult<TargetLibraryAnalysis>(F); 586 })) 587 return PreservedAnalyses::all(); 588 589 return PreservedAnalyses::none(); 590 } 591 592 static bool functionHasLines(Function &F) { 593 // Check whether this function actually has any source lines. Not only 594 // do these waste space, they also can crash gcov. 595 for (auto &BB : F) { 596 for (auto &I : BB) { 597 // Debug intrinsic locations correspond to the location of the 598 // declaration, not necessarily any statements or expressions. 599 if (isa<DbgInfoIntrinsic>(&I)) continue; 600 601 const DebugLoc &Loc = I.getDebugLoc(); 602 if (!Loc) 603 continue; 604 605 // Artificial lines such as calls to the global constructors. 606 if (Loc.getLine() == 0) continue; 607 608 return true; 609 } 610 } 611 return false; 612 } 613 614 static bool isUsingScopeBasedEH(Function &F) { 615 if (!F.hasPersonalityFn()) return false; 616 617 EHPersonality Personality = classifyEHPersonality(F.getPersonalityFn()); 618 return isScopedEHPersonality(Personality); 619 } 620 621 static bool shouldKeepInEntry(BasicBlock::iterator It) { 622 if (isa<AllocaInst>(*It)) return true; 623 if (isa<DbgInfoIntrinsic>(*It)) return true; 624 if (auto *II = dyn_cast<IntrinsicInst>(It)) { 625 if (II->getIntrinsicID() == llvm::Intrinsic::localescape) return true; 626 } 627 628 return false; 629 } 630 631 void GCOVProfiler::AddFlushBeforeForkAndExec() { 632 SmallVector<Instruction *, 2> ForkAndExecs; 633 for (auto &F : M->functions()) { 634 auto *TLI = &GetTLI(F); 635 for (auto &I : instructions(F)) { 636 if (CallInst *CI = dyn_cast<CallInst>(&I)) { 637 if (Function *Callee = CI->getCalledFunction()) { 638 LibFunc LF; 639 if (TLI->getLibFunc(*Callee, LF) && 640 (LF == LibFunc_fork || LF == LibFunc_execl || 641 LF == LibFunc_execle || LF == LibFunc_execlp || 642 LF == LibFunc_execv || LF == LibFunc_execvp || 643 LF == LibFunc_execve || LF == LibFunc_execvpe || 644 LF == LibFunc_execvP)) { 645 ForkAndExecs.push_back(&I); 646 } 647 } 648 } 649 } 650 } 651 652 // We need to split the block after the fork/exec call 653 // because else the counters for the lines after will be 654 // the same as before the call. 655 for (auto I : ForkAndExecs) { 656 IRBuilder<> Builder(I); 657 FunctionType *FTy = FunctionType::get(Builder.getVoidTy(), {}, false); 658 FunctionCallee GCOVFlush = M->getOrInsertFunction("__gcov_flush", FTy); 659 Builder.CreateCall(GCOVFlush); 660 I->getParent()->splitBasicBlock(I); 661 } 662 } 663 664 void GCOVProfiler::emitProfileNotes() { 665 NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); 666 if (!CU_Nodes) return; 667 668 for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { 669 // Each compile unit gets its own .gcno file. This means that whether we run 670 // this pass over the original .o's as they're produced, or run it after 671 // LTO, we'll generate the same .gcno files. 672 673 auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(i)); 674 675 // Skip module skeleton (and module) CUs. 676 if (CU->getDWOId()) 677 continue; 678 679 std::error_code EC; 680 raw_fd_ostream out(mangleName(CU, GCovFileType::GCNO), EC, 681 sys::fs::OF_None); 682 if (EC) { 683 Ctx->emitError(Twine("failed to open coverage notes file for writing: ") + 684 EC.message()); 685 continue; 686 } 687 688 std::string EdgeDestinations; 689 690 unsigned FunctionIdent = 0; 691 for (auto &F : M->functions()) { 692 DISubprogram *SP = F.getSubprogram(); 693 if (!SP) continue; 694 if (!functionHasLines(F) || !isFunctionInstrumented(F)) 695 continue; 696 // TODO: Functions using scope-based EH are currently not supported. 697 if (isUsingScopeBasedEH(F)) continue; 698 699 // gcov expects every function to start with an entry block that has a 700 // single successor, so split the entry block to make sure of that. 701 BasicBlock &EntryBlock = F.getEntryBlock(); 702 BasicBlock::iterator It = EntryBlock.begin(); 703 while (shouldKeepInEntry(It)) 704 ++It; 705 EntryBlock.splitBasicBlock(It); 706 707 Funcs.push_back(std::make_unique<GCOVFunction>(SP, &F, &out, FunctionIdent++, 708 Options.UseCfgChecksum, 709 Options.ExitBlockBeforeBody)); 710 GCOVFunction &Func = *Funcs.back(); 711 712 // Add the function line number to the lines of the entry block 713 // to have a counter for the function definition. 714 uint32_t Line = SP->getLine(); 715 auto Filename = getFilename(SP); 716 Func.getBlock(&EntryBlock).getFile(Filename).addLine(Line); 717 718 for (auto &BB : F) { 719 GCOVBlock &Block = Func.getBlock(&BB); 720 Instruction *TI = BB.getTerminator(); 721 if (int successors = TI->getNumSuccessors()) { 722 for (int i = 0; i != successors; ++i) { 723 Block.addEdge(Func.getBlock(TI->getSuccessor(i))); 724 } 725 } else if (isa<ReturnInst>(TI)) { 726 Block.addEdge(Func.getReturnBlock()); 727 } 728 729 for (auto &I : BB) { 730 // Debug intrinsic locations correspond to the location of the 731 // declaration, not necessarily any statements or expressions. 732 if (isa<DbgInfoIntrinsic>(&I)) continue; 733 734 const DebugLoc &Loc = I.getDebugLoc(); 735 if (!Loc) 736 continue; 737 738 // Artificial lines such as calls to the global constructors. 739 if (Loc.getLine() == 0 || Loc.isImplicitCode()) 740 continue; 741 742 if (Line == Loc.getLine()) continue; 743 Line = Loc.getLine(); 744 if (SP != getDISubprogram(Loc.getScope())) 745 continue; 746 747 GCOVLines &Lines = Block.getFile(Filename); 748 Lines.addLine(Loc.getLine()); 749 } 750 Line = 0; 751 } 752 EdgeDestinations += Func.getEdgeDestinations(); 753 } 754 755 FileChecksums.push_back(hash_value(EdgeDestinations)); 756 out.write("oncg", 4); 757 out.write(ReversedVersion, 4); 758 out.write(reinterpret_cast<char*>(&FileChecksums.back()), 4); 759 760 for (auto &Func : Funcs) { 761 Func->setCfgChecksum(FileChecksums.back()); 762 Func->writeOut(); 763 } 764 765 out.write("\0\0\0\0\0\0\0\0", 8); // EOF 766 out.close(); 767 } 768 } 769 770 bool GCOVProfiler::emitProfileArcs() { 771 NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); 772 if (!CU_Nodes) return false; 773 774 bool Result = false; 775 for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { 776 SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> CountersBySP; 777 for (auto &F : M->functions()) { 778 DISubprogram *SP = F.getSubprogram(); 779 if (!SP) continue; 780 if (!functionHasLines(F) || !isFunctionInstrumented(F)) 781 continue; 782 // TODO: Functions using scope-based EH are currently not supported. 783 if (isUsingScopeBasedEH(F)) continue; 784 if (!Result) Result = true; 785 786 DenseMap<std::pair<BasicBlock *, BasicBlock *>, unsigned> EdgeToCounter; 787 unsigned Edges = 0; 788 for (auto &BB : F) { 789 Instruction *TI = BB.getTerminator(); 790 if (isa<ReturnInst>(TI)) { 791 EdgeToCounter[{&BB, nullptr}] = Edges++; 792 } else { 793 for (BasicBlock *Succ : successors(TI)) { 794 EdgeToCounter[{&BB, Succ}] = Edges++; 795 } 796 } 797 } 798 799 ArrayType *CounterTy = 800 ArrayType::get(Type::getInt64Ty(*Ctx), Edges); 801 GlobalVariable *Counters = 802 new GlobalVariable(*M, CounterTy, false, 803 GlobalValue::InternalLinkage, 804 Constant::getNullValue(CounterTy), 805 "__llvm_gcov_ctr"); 806 CountersBySP.push_back(std::make_pair(Counters, SP)); 807 808 // If a BB has several predecessors, use a PHINode to select 809 // the correct counter. 810 for (auto &BB : F) { 811 const unsigned EdgeCount = 812 std::distance(pred_begin(&BB), pred_end(&BB)); 813 if (EdgeCount) { 814 // The phi node must be at the begin of the BB. 815 IRBuilder<> BuilderForPhi(&*BB.begin()); 816 Type *Int64PtrTy = Type::getInt64PtrTy(*Ctx); 817 PHINode *Phi = BuilderForPhi.CreatePHI(Int64PtrTy, EdgeCount); 818 for (BasicBlock *Pred : predecessors(&BB)) { 819 auto It = EdgeToCounter.find({Pred, &BB}); 820 assert(It != EdgeToCounter.end()); 821 const unsigned Edge = It->second; 822 Value *EdgeCounter = BuilderForPhi.CreateConstInBoundsGEP2_64( 823 Counters->getValueType(), Counters, 0, Edge); 824 Phi->addIncoming(EdgeCounter, Pred); 825 } 826 827 // Skip phis, landingpads. 828 IRBuilder<> Builder(&*BB.getFirstInsertionPt()); 829 Value *Count = Builder.CreateLoad(Builder.getInt64Ty(), Phi); 830 Count = Builder.CreateAdd(Count, Builder.getInt64(1)); 831 Builder.CreateStore(Count, Phi); 832 833 Instruction *TI = BB.getTerminator(); 834 if (isa<ReturnInst>(TI)) { 835 auto It = EdgeToCounter.find({&BB, nullptr}); 836 assert(It != EdgeToCounter.end()); 837 const unsigned Edge = It->second; 838 Value *Counter = Builder.CreateConstInBoundsGEP2_64( 839 Counters->getValueType(), Counters, 0, Edge); 840 Value *Count = Builder.CreateLoad(Builder.getInt64Ty(), Counter); 841 Count = Builder.CreateAdd(Count, Builder.getInt64(1)); 842 Builder.CreateStore(Count, Counter); 843 } 844 } 845 } 846 } 847 848 Function *WriteoutF = insertCounterWriteout(CountersBySP); 849 Function *FlushF = insertFlush(CountersBySP); 850 851 // Create a small bit of code that registers the "__llvm_gcov_writeout" to 852 // be executed at exit and the "__llvm_gcov_flush" function to be executed 853 // when "__gcov_flush" is called. 854 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 855 Function *F = Function::Create(FTy, GlobalValue::InternalLinkage, 856 "__llvm_gcov_init", M); 857 F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); 858 F->setLinkage(GlobalValue::InternalLinkage); 859 F->addFnAttr(Attribute::NoInline); 860 if (Options.NoRedZone) 861 F->addFnAttr(Attribute::NoRedZone); 862 863 BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F); 864 IRBuilder<> Builder(BB); 865 866 FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 867 Type *Params[] = { 868 PointerType::get(FTy, 0), 869 PointerType::get(FTy, 0) 870 }; 871 FTy = FunctionType::get(Builder.getVoidTy(), Params, false); 872 873 // Initialize the environment and register the local writeout and flush 874 // functions. 875 FunctionCallee GCOVInit = M->getOrInsertFunction("llvm_gcov_init", FTy); 876 Builder.CreateCall(GCOVInit, {WriteoutF, FlushF}); 877 Builder.CreateRetVoid(); 878 879 appendToGlobalCtors(*M, F, 0); 880 } 881 882 return Result; 883 } 884 885 FunctionCallee GCOVProfiler::getStartFileFunc(const TargetLibraryInfo *TLI) { 886 Type *Args[] = { 887 Type::getInt8PtrTy(*Ctx), // const char *orig_filename 888 Type::getInt8PtrTy(*Ctx), // const char version[4] 889 Type::getInt32Ty(*Ctx), // uint32_t checksum 890 }; 891 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false); 892 AttributeList AL; 893 if (auto AK = TLI->getExtAttrForI32Param(false)) 894 AL = AL.addParamAttribute(*Ctx, 2, AK); 895 FunctionCallee Res = M->getOrInsertFunction("llvm_gcda_start_file", FTy, AL); 896 return Res; 897 } 898 899 FunctionCallee GCOVProfiler::getEmitFunctionFunc(const TargetLibraryInfo *TLI) { 900 Type *Args[] = { 901 Type::getInt32Ty(*Ctx), // uint32_t ident 902 Type::getInt8PtrTy(*Ctx), // const char *function_name 903 Type::getInt32Ty(*Ctx), // uint32_t func_checksum 904 Type::getInt8Ty(*Ctx), // uint8_t use_extra_checksum 905 Type::getInt32Ty(*Ctx), // uint32_t cfg_checksum 906 }; 907 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false); 908 AttributeList AL; 909 if (auto AK = TLI->getExtAttrForI32Param(false)) { 910 AL = AL.addParamAttribute(*Ctx, 0, AK); 911 AL = AL.addParamAttribute(*Ctx, 2, AK); 912 AL = AL.addParamAttribute(*Ctx, 3, AK); 913 AL = AL.addParamAttribute(*Ctx, 4, AK); 914 } 915 return M->getOrInsertFunction("llvm_gcda_emit_function", FTy); 916 } 917 918 FunctionCallee GCOVProfiler::getEmitArcsFunc(const TargetLibraryInfo *TLI) { 919 Type *Args[] = { 920 Type::getInt32Ty(*Ctx), // uint32_t num_counters 921 Type::getInt64PtrTy(*Ctx), // uint64_t *counters 922 }; 923 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false); 924 AttributeList AL; 925 if (auto AK = TLI->getExtAttrForI32Param(false)) 926 AL = AL.addParamAttribute(*Ctx, 0, AK); 927 return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy, AL); 928 } 929 930 FunctionCallee GCOVProfiler::getSummaryInfoFunc() { 931 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 932 return M->getOrInsertFunction("llvm_gcda_summary_info", FTy); 933 } 934 935 FunctionCallee GCOVProfiler::getEndFileFunc() { 936 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 937 return M->getOrInsertFunction("llvm_gcda_end_file", FTy); 938 } 939 940 Function *GCOVProfiler::insertCounterWriteout( 941 ArrayRef<std::pair<GlobalVariable *, MDNode *> > CountersBySP) { 942 FunctionType *WriteoutFTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 943 Function *WriteoutF = M->getFunction("__llvm_gcov_writeout"); 944 if (!WriteoutF) 945 WriteoutF = Function::Create(WriteoutFTy, GlobalValue::InternalLinkage, 946 "__llvm_gcov_writeout", M); 947 WriteoutF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); 948 WriteoutF->addFnAttr(Attribute::NoInline); 949 if (Options.NoRedZone) 950 WriteoutF->addFnAttr(Attribute::NoRedZone); 951 952 BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", WriteoutF); 953 IRBuilder<> Builder(BB); 954 955 auto *TLI = &GetTLI(*WriteoutF); 956 957 FunctionCallee StartFile = getStartFileFunc(TLI); 958 FunctionCallee EmitFunction = getEmitFunctionFunc(TLI); 959 FunctionCallee EmitArcs = getEmitArcsFunc(TLI); 960 FunctionCallee SummaryInfo = getSummaryInfoFunc(); 961 FunctionCallee EndFile = getEndFileFunc(); 962 963 NamedMDNode *CUNodes = M->getNamedMetadata("llvm.dbg.cu"); 964 if (!CUNodes) { 965 Builder.CreateRetVoid(); 966 return WriteoutF; 967 } 968 969 // Collect the relevant data into a large constant data structure that we can 970 // walk to write out everything. 971 StructType *StartFileCallArgsTy = StructType::create( 972 {Builder.getInt8PtrTy(), Builder.getInt8PtrTy(), Builder.getInt32Ty()}); 973 StructType *EmitFunctionCallArgsTy = StructType::create( 974 {Builder.getInt32Ty(), Builder.getInt8PtrTy(), Builder.getInt32Ty(), 975 Builder.getInt8Ty(), Builder.getInt32Ty()}); 976 StructType *EmitArcsCallArgsTy = StructType::create( 977 {Builder.getInt32Ty(), Builder.getInt64Ty()->getPointerTo()}); 978 StructType *FileInfoTy = 979 StructType::create({StartFileCallArgsTy, Builder.getInt32Ty(), 980 EmitFunctionCallArgsTy->getPointerTo(), 981 EmitArcsCallArgsTy->getPointerTo()}); 982 983 Constant *Zero32 = Builder.getInt32(0); 984 // Build an explicit array of two zeros for use in ConstantExpr GEP building. 985 Constant *TwoZero32s[] = {Zero32, Zero32}; 986 987 SmallVector<Constant *, 8> FileInfos; 988 for (int i : llvm::seq<int>(0, CUNodes->getNumOperands())) { 989 auto *CU = cast<DICompileUnit>(CUNodes->getOperand(i)); 990 991 // Skip module skeleton (and module) CUs. 992 if (CU->getDWOId()) 993 continue; 994 995 std::string FilenameGcda = mangleName(CU, GCovFileType::GCDA); 996 uint32_t CfgChecksum = FileChecksums.empty() ? 0 : FileChecksums[i]; 997 auto *StartFileCallArgs = ConstantStruct::get( 998 StartFileCallArgsTy, {Builder.CreateGlobalStringPtr(FilenameGcda), 999 Builder.CreateGlobalStringPtr(ReversedVersion), 1000 Builder.getInt32(CfgChecksum)}); 1001 1002 SmallVector<Constant *, 8> EmitFunctionCallArgsArray; 1003 SmallVector<Constant *, 8> EmitArcsCallArgsArray; 1004 for (int j : llvm::seq<int>(0, CountersBySP.size())) { 1005 auto *SP = cast_or_null<DISubprogram>(CountersBySP[j].second); 1006 uint32_t FuncChecksum = Funcs.empty() ? 0 : Funcs[j]->getFuncChecksum(); 1007 EmitFunctionCallArgsArray.push_back(ConstantStruct::get( 1008 EmitFunctionCallArgsTy, 1009 {Builder.getInt32(j), 1010 Options.FunctionNamesInData 1011 ? Builder.CreateGlobalStringPtr(getFunctionName(SP)) 1012 : Constant::getNullValue(Builder.getInt8PtrTy()), 1013 Builder.getInt32(FuncChecksum), 1014 Builder.getInt8(Options.UseCfgChecksum), 1015 Builder.getInt32(CfgChecksum)})); 1016 1017 GlobalVariable *GV = CountersBySP[j].first; 1018 unsigned Arcs = cast<ArrayType>(GV->getValueType())->getNumElements(); 1019 EmitArcsCallArgsArray.push_back(ConstantStruct::get( 1020 EmitArcsCallArgsTy, 1021 {Builder.getInt32(Arcs), ConstantExpr::getInBoundsGetElementPtr( 1022 GV->getValueType(), GV, TwoZero32s)})); 1023 } 1024 // Create global arrays for the two emit calls. 1025 int CountersSize = CountersBySP.size(); 1026 assert(CountersSize == (int)EmitFunctionCallArgsArray.size() && 1027 "Mismatched array size!"); 1028 assert(CountersSize == (int)EmitArcsCallArgsArray.size() && 1029 "Mismatched array size!"); 1030 auto *EmitFunctionCallArgsArrayTy = 1031 ArrayType::get(EmitFunctionCallArgsTy, CountersSize); 1032 auto *EmitFunctionCallArgsArrayGV = new GlobalVariable( 1033 *M, EmitFunctionCallArgsArrayTy, /*isConstant*/ true, 1034 GlobalValue::InternalLinkage, 1035 ConstantArray::get(EmitFunctionCallArgsArrayTy, 1036 EmitFunctionCallArgsArray), 1037 Twine("__llvm_internal_gcov_emit_function_args.") + Twine(i)); 1038 auto *EmitArcsCallArgsArrayTy = 1039 ArrayType::get(EmitArcsCallArgsTy, CountersSize); 1040 EmitFunctionCallArgsArrayGV->setUnnamedAddr( 1041 GlobalValue::UnnamedAddr::Global); 1042 auto *EmitArcsCallArgsArrayGV = new GlobalVariable( 1043 *M, EmitArcsCallArgsArrayTy, /*isConstant*/ true, 1044 GlobalValue::InternalLinkage, 1045 ConstantArray::get(EmitArcsCallArgsArrayTy, EmitArcsCallArgsArray), 1046 Twine("__llvm_internal_gcov_emit_arcs_args.") + Twine(i)); 1047 EmitArcsCallArgsArrayGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); 1048 1049 FileInfos.push_back(ConstantStruct::get( 1050 FileInfoTy, 1051 {StartFileCallArgs, Builder.getInt32(CountersSize), 1052 ConstantExpr::getInBoundsGetElementPtr(EmitFunctionCallArgsArrayTy, 1053 EmitFunctionCallArgsArrayGV, 1054 TwoZero32s), 1055 ConstantExpr::getInBoundsGetElementPtr( 1056 EmitArcsCallArgsArrayTy, EmitArcsCallArgsArrayGV, TwoZero32s)})); 1057 } 1058 1059 // If we didn't find anything to actually emit, bail on out. 1060 if (FileInfos.empty()) { 1061 Builder.CreateRetVoid(); 1062 return WriteoutF; 1063 } 1064 1065 // To simplify code, we cap the number of file infos we write out to fit 1066 // easily in a 32-bit signed integer. This gives consistent behavior between 1067 // 32-bit and 64-bit systems without requiring (potentially very slow) 64-bit 1068 // operations on 32-bit systems. It also seems unreasonable to try to handle 1069 // more than 2 billion files. 1070 if ((int64_t)FileInfos.size() > (int64_t)INT_MAX) 1071 FileInfos.resize(INT_MAX); 1072 1073 // Create a global for the entire data structure so we can walk it more 1074 // easily. 1075 auto *FileInfoArrayTy = ArrayType::get(FileInfoTy, FileInfos.size()); 1076 auto *FileInfoArrayGV = new GlobalVariable( 1077 *M, FileInfoArrayTy, /*isConstant*/ true, GlobalValue::InternalLinkage, 1078 ConstantArray::get(FileInfoArrayTy, FileInfos), 1079 "__llvm_internal_gcov_emit_file_info"); 1080 FileInfoArrayGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); 1081 1082 // Create the CFG for walking this data structure. 1083 auto *FileLoopHeader = 1084 BasicBlock::Create(*Ctx, "file.loop.header", WriteoutF); 1085 auto *CounterLoopHeader = 1086 BasicBlock::Create(*Ctx, "counter.loop.header", WriteoutF); 1087 auto *FileLoopLatch = BasicBlock::Create(*Ctx, "file.loop.latch", WriteoutF); 1088 auto *ExitBB = BasicBlock::Create(*Ctx, "exit", WriteoutF); 1089 1090 // We always have at least one file, so just branch to the header. 1091 Builder.CreateBr(FileLoopHeader); 1092 1093 // The index into the files structure is our loop induction variable. 1094 Builder.SetInsertPoint(FileLoopHeader); 1095 PHINode *IV = 1096 Builder.CreatePHI(Builder.getInt32Ty(), /*NumReservedValues*/ 2); 1097 IV->addIncoming(Builder.getInt32(0), BB); 1098 auto *FileInfoPtr = Builder.CreateInBoundsGEP( 1099 FileInfoArrayTy, FileInfoArrayGV, {Builder.getInt32(0), IV}); 1100 auto *StartFileCallArgsPtr = 1101 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 0); 1102 auto *StartFileCall = Builder.CreateCall( 1103 StartFile, 1104 {Builder.CreateLoad(StartFileCallArgsTy->getElementType(0), 1105 Builder.CreateStructGEP(StartFileCallArgsTy, 1106 StartFileCallArgsPtr, 0)), 1107 Builder.CreateLoad(StartFileCallArgsTy->getElementType(1), 1108 Builder.CreateStructGEP(StartFileCallArgsTy, 1109 StartFileCallArgsPtr, 1)), 1110 Builder.CreateLoad(StartFileCallArgsTy->getElementType(2), 1111 Builder.CreateStructGEP(StartFileCallArgsTy, 1112 StartFileCallArgsPtr, 2))}); 1113 if (auto AK = TLI->getExtAttrForI32Param(false)) 1114 StartFileCall->addParamAttr(2, AK); 1115 auto *NumCounters = 1116 Builder.CreateLoad(FileInfoTy->getElementType(1), 1117 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 1)); 1118 auto *EmitFunctionCallArgsArray = 1119 Builder.CreateLoad(FileInfoTy->getElementType(2), 1120 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 2)); 1121 auto *EmitArcsCallArgsArray = 1122 Builder.CreateLoad(FileInfoTy->getElementType(3), 1123 Builder.CreateStructGEP(FileInfoTy, FileInfoPtr, 3)); 1124 auto *EnterCounterLoopCond = 1125 Builder.CreateICmpSLT(Builder.getInt32(0), NumCounters); 1126 Builder.CreateCondBr(EnterCounterLoopCond, CounterLoopHeader, FileLoopLatch); 1127 1128 Builder.SetInsertPoint(CounterLoopHeader); 1129 auto *JV = Builder.CreatePHI(Builder.getInt32Ty(), /*NumReservedValues*/ 2); 1130 JV->addIncoming(Builder.getInt32(0), FileLoopHeader); 1131 auto *EmitFunctionCallArgsPtr = Builder.CreateInBoundsGEP( 1132 EmitFunctionCallArgsTy, EmitFunctionCallArgsArray, JV); 1133 auto *EmitFunctionCall = Builder.CreateCall( 1134 EmitFunction, 1135 {Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(0), 1136 Builder.CreateStructGEP(EmitFunctionCallArgsTy, 1137 EmitFunctionCallArgsPtr, 0)), 1138 Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(1), 1139 Builder.CreateStructGEP(EmitFunctionCallArgsTy, 1140 EmitFunctionCallArgsPtr, 1)), 1141 Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(2), 1142 Builder.CreateStructGEP(EmitFunctionCallArgsTy, 1143 EmitFunctionCallArgsPtr, 2)), 1144 Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(3), 1145 Builder.CreateStructGEP(EmitFunctionCallArgsTy, 1146 EmitFunctionCallArgsPtr, 3)), 1147 Builder.CreateLoad(EmitFunctionCallArgsTy->getElementType(4), 1148 Builder.CreateStructGEP(EmitFunctionCallArgsTy, 1149 EmitFunctionCallArgsPtr, 1150 4))}); 1151 if (auto AK = TLI->getExtAttrForI32Param(false)) { 1152 EmitFunctionCall->addParamAttr(0, AK); 1153 EmitFunctionCall->addParamAttr(2, AK); 1154 EmitFunctionCall->addParamAttr(3, AK); 1155 EmitFunctionCall->addParamAttr(4, AK); 1156 } 1157 auto *EmitArcsCallArgsPtr = 1158 Builder.CreateInBoundsGEP(EmitArcsCallArgsTy, EmitArcsCallArgsArray, JV); 1159 auto *EmitArcsCall = Builder.CreateCall( 1160 EmitArcs, 1161 {Builder.CreateLoad( 1162 EmitArcsCallArgsTy->getElementType(0), 1163 Builder.CreateStructGEP(EmitArcsCallArgsTy, EmitArcsCallArgsPtr, 0)), 1164 Builder.CreateLoad(EmitArcsCallArgsTy->getElementType(1), 1165 Builder.CreateStructGEP(EmitArcsCallArgsTy, 1166 EmitArcsCallArgsPtr, 1))}); 1167 if (auto AK = TLI->getExtAttrForI32Param(false)) 1168 EmitArcsCall->addParamAttr(0, AK); 1169 auto *NextJV = Builder.CreateAdd(JV, Builder.getInt32(1)); 1170 auto *CounterLoopCond = Builder.CreateICmpSLT(NextJV, NumCounters); 1171 Builder.CreateCondBr(CounterLoopCond, CounterLoopHeader, FileLoopLatch); 1172 JV->addIncoming(NextJV, CounterLoopHeader); 1173 1174 Builder.SetInsertPoint(FileLoopLatch); 1175 Builder.CreateCall(SummaryInfo, {}); 1176 Builder.CreateCall(EndFile, {}); 1177 auto *NextIV = Builder.CreateAdd(IV, Builder.getInt32(1)); 1178 auto *FileLoopCond = 1179 Builder.CreateICmpSLT(NextIV, Builder.getInt32(FileInfos.size())); 1180 Builder.CreateCondBr(FileLoopCond, FileLoopHeader, ExitBB); 1181 IV->addIncoming(NextIV, FileLoopLatch); 1182 1183 Builder.SetInsertPoint(ExitBB); 1184 Builder.CreateRetVoid(); 1185 1186 return WriteoutF; 1187 } 1188 1189 Function *GCOVProfiler:: 1190 insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) { 1191 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 1192 Function *FlushF = M->getFunction("__llvm_gcov_flush"); 1193 if (!FlushF) 1194 FlushF = Function::Create(FTy, GlobalValue::InternalLinkage, 1195 "__llvm_gcov_flush", M); 1196 else 1197 FlushF->setLinkage(GlobalValue::InternalLinkage); 1198 FlushF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); 1199 FlushF->addFnAttr(Attribute::NoInline); 1200 if (Options.NoRedZone) 1201 FlushF->addFnAttr(Attribute::NoRedZone); 1202 1203 BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", FlushF); 1204 1205 // Write out the current counters. 1206 Function *WriteoutF = M->getFunction("__llvm_gcov_writeout"); 1207 assert(WriteoutF && "Need to create the writeout function first!"); 1208 1209 IRBuilder<> Builder(Entry); 1210 Builder.CreateCall(WriteoutF, {}); 1211 1212 // Zero out the counters. 1213 for (const auto &I : CountersBySP) { 1214 GlobalVariable *GV = I.first; 1215 Constant *Null = Constant::getNullValue(GV->getValueType()); 1216 Builder.CreateStore(Null, GV); 1217 } 1218 1219 Type *RetTy = FlushF->getReturnType(); 1220 if (RetTy == Type::getVoidTy(*Ctx)) 1221 Builder.CreateRetVoid(); 1222 else if (RetTy->isIntegerTy()) 1223 // Used if __llvm_gcov_flush was implicitly declared. 1224 Builder.CreateRet(ConstantInt::get(RetTy, 0)); 1225 else 1226 report_fatal_error("invalid return type for __llvm_gcov_flush"); 1227 1228 return FlushF; 1229 } 1230