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