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