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