1b1928704201034c785a26296a49f69355eb56a05Nick Lewycky//===- GCOVProfiling.cpp - Insert edge counters for gcov profiling --------===// 2b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// 3b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// The LLVM Compiler Infrastructure 4b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// 5b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// This file is distributed under the University of Illinois Open Source 6b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// License. See LICENSE.TXT for details. 7b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// 8b1928704201034c785a26296a49f69355eb56a05Nick Lewycky//===----------------------------------------------------------------------===// 9b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// 10b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// This pass implements GCOV-style profiling. When this pass is run it emits 11b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// "gcno" files next to the existing source, and instruments the code that runs 12b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// to records the edges between blocks that run and emit a complementary "gcda" 13b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// file on exit. 14b1928704201034c785a26296a49f69355eb56a05Nick Lewycky// 15b1928704201034c785a26296a49f69355eb56a05Nick Lewycky//===----------------------------------------------------------------------===// 16b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 17b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/DenseMap.h" 1836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/ADT/Hashing.h" 19b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/STLExtras.h" 2006cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/ADT/Statistic.h" 21b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/StringExtras.h" 22b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/StringMap.h" 23b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/UniqueVector.h" 2436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/DebugInfo.h" 2536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/DebugLoc.h" 260b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/IRBuilder.h" 2736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/InstIterator.h" 280b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Instructions.h" 2936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/IntrinsicInst.h" 300b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Module.h" 31d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Pass.h" 32a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky#include "llvm/Support/CommandLine.h" 3306cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Support/Debug.h" 3439c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling#include "llvm/Support/FileSystem.h" 35a11c3e25015a62c817e60ec4f955a7f3f3bb6c67Rafael Espindola#include "llvm/Support/Path.h" 3606cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Support/raw_ostream.h" 37de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Transforms/GCOVProfiler.h" 38de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Transforms/Instrumentation.h" 3906cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Transforms/Utils/ModuleUtils.h" 40c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky#include <algorithm> 41dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include <memory> 42b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include <string> 43b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include <utility> 44b1928704201034c785a26296a49f69355eb56a05Nick Lewyckyusing namespace llvm; 45b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 46dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define DEBUG_TYPE "insert-gcov-profiling" 47dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 48a204ef3168c8804808c716115ba915c89d8849b9Nick Lewyckystatic cl::opt<std::string> 49a204ef3168c8804808c716115ba915c89d8849b9Nick LewyckyDefaultGCOVVersion("default-gcov-version", cl::init("402*"), cl::Hidden, 50a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky cl::ValueRequired); 514c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<bool> DefaultExitBlockBeforeBody("gcov-exit-block-before-body", 524c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::init(false), cl::Hidden); 53a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky 54a204ef3168c8804808c716115ba915c89d8849b9Nick LewyckyGCOVOptions GCOVOptions::getDefault() { 55a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky GCOVOptions Options; 56a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky Options.EmitNotes = true; 57a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky Options.EmitData = true; 58a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky Options.UseCfgChecksum = false; 59a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky Options.NoRedZone = false; 60a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky Options.FunctionNamesInData = true; 614c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Options.ExitBlockBeforeBody = DefaultExitBlockBeforeBody; 62a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky 63a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky if (DefaultGCOVVersion.size() != 4) { 64a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky llvm::report_fatal_error(std::string("Invalid -default-gcov-version: ") + 65a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky DefaultGCOVVersion); 66a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky } 67a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky memcpy(Options.Version, DefaultGCOVVersion.c_str(), 4); 68a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky return Options; 69a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky} 70a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky 71b1928704201034c785a26296a49f69355eb56a05Nick Lewyckynamespace { 72de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarclass GCOVFunction; 73de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 74de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarclass GCOVProfiler { 75de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarpublic: 76de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GCOVProfiler() : GCOVProfiler(GCOVOptions::getDefault()) {} 77de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GCOVProfiler(const GCOVOptions &Opts) : Options(Opts) { 78de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar assert((Options.EmitNotes || Options.EmitData) && 79de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "GCOVProfiler asked to do nothing?"); 80de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ReversedVersion[0] = Options.Version[3]; 81de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ReversedVersion[1] = Options.Version[2]; 82de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ReversedVersion[2] = Options.Version[1]; 83de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ReversedVersion[3] = Options.Version[0]; 84de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ReversedVersion[4] = '\0'; 85de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 86de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar bool runOnModule(Module &M); 87de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 88de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarprivate: 89de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Create the .gcno files for the Module based on DebugInfo. 90de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar void emitProfileNotes(); 91de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 92de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Modify the program to track transitions along edges and call into the 93de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // profiling runtime to emit .gcda files when run. 94de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar bool emitProfileArcs(); 95de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 96de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Get pointers to the functions in the runtime library. 97de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Constant *getStartFileFunc(); 98de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Constant *getIncrementIndirectCounterFunc(); 99de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Constant *getEmitFunctionFunc(); 100de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Constant *getEmitArcsFunc(); 101de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Constant *getSummaryInfoFunc(); 102de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Constant *getEndFileFunc(); 103de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 104de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Create or retrieve an i32 state value that is used to represent the 105de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // pred block number for certain non-trivial edges. 106de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GlobalVariable *getEdgeStateValue(); 107de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 108de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Produce a table of pointers to counters, by predecessor and successor 109de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // block number. 110de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GlobalVariable *buildEdgeLookupTable(Function *F, GlobalVariable *Counter, 111de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const UniqueVector<BasicBlock *> &Preds, 112de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const UniqueVector<BasicBlock *> &Succs); 113de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 114de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Add the function to write out all our counters to the global destructor 115de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // list. 116de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Function * 117de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar insertCounterWriteout(ArrayRef<std::pair<GlobalVariable *, MDNode *>>); 118de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Function *insertFlush(ArrayRef<std::pair<GlobalVariable *, MDNode *>>); 119de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar void insertIndirectCounterIncrement(); 120de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 121de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::string mangleName(const DICompileUnit *CU, const char *NewStem); 12236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 123de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GCOVOptions Options; 1244c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 125de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Reversed, NUL-terminated copy of Options.Version. 126de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar char ReversedVersion[5]; 127de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Checksum, produced by hash of EdgeDestinations 128de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SmallVector<uint32_t, 4> FileChecksums; 129de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 130de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Module *M; 131de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar LLVMContext *Ctx; 132de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SmallVector<std::unique_ptr<GCOVFunction>, 16> Funcs; 133de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}; 134de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 135de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarclass GCOVProfilerLegacyPass : public ModulePass { 136de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarpublic: 137de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar static char ID; 138de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GCOVProfilerLegacyPass() 139de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar : GCOVProfilerLegacyPass(GCOVOptions::getDefault()) {} 140de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GCOVProfilerLegacyPass(const GCOVOptions &Opts) 141de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar : ModulePass(ID), Profiler(Opts) { 142de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar initializeGCOVProfilerLegacyPassPass(*PassRegistry::getPassRegistry()); 143de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 144de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const char *getPassName() const override { return "GCOV Profiler"; } 145de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 146de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar bool runOnModule(Module &M) override { return Profiler.runOnModule(M); } 147de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 148de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarprivate: 149de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GCOVProfiler Profiler; 150de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}; 151b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 152b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 153de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarchar GCOVProfilerLegacyPass::ID = 0; 154de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarINITIALIZE_PASS(GCOVProfilerLegacyPass, "insert-gcov-profiling", 155b1928704201034c785a26296a49f69355eb56a05Nick Lewycky "Insert instrumentation for GCOV profiling", false, false) 156b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 157a204ef3168c8804808c716115ba915c89d8849b9Nick LewyckyModulePass *llvm::createGCOVProfilerPass(const GCOVOptions &Options) { 158de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return new GCOVProfilerLegacyPass(Options); 159a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky} 160b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 1616948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstatic StringRef getFunctionName(const DISubprogram *SP) { 1620c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar if (!SP->getLinkageName().empty()) 1630c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar return SP->getLinkageName(); 1640c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar return SP->getName(); 1655d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky} 1665d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky 167b1928704201034c785a26296a49f69355eb56a05Nick Lewyckynamespace { 168b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVRecord { 169b1928704201034c785a26296a49f69355eb56a05Nick Lewycky protected: 170d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper static const char *const LinesTag; 171d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper static const char *const FunctionTag; 172d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper static const char *const BlockTag; 173d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper static const char *const EdgeTag; 174b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 1750c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar GCOVRecord() = default; 176b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 1771790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky void writeBytes(const char *Bytes, int Size) { 1781790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky os->write(Bytes, Size); 179b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 180b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 1811790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky void write(uint32_t i) { 1821790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky writeBytes(reinterpret_cast<char*>(&i), 4); 183b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 184b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 185b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Returns the length measured in 4-byte blocks that will be used to 186b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // represent this string in a GCOV file 187619850cb3161733e9284ff3bf9a68d1a3b76f0b4Craig Topper static unsigned lengthOfGCOVString(StringRef s) { 188b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // A GCOV string is a length, followed by a NUL, then between 0 and 3 NULs 18917df2c3240837b4382898ead8c3ead407a338520Nick Lewycky // padding out to the next 4-byte word. The length is measured in 4-byte 19017df2c3240837b4382898ead8c3ead407a338520Nick Lewycky // words including padding, not bytes of actual string. 191d363ff334d796c7f3df834d928a10d88ed758454Nick Lewycky return (s.size() / 4) + 1; 192b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 193b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 1941790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky void writeGCOVString(StringRef s) { 1951790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky uint32_t Len = lengthOfGCOVString(s); 1961790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(Len); 1971790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky writeBytes(s.data(), s.size()); 198b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 199b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Write 1 to 4 bytes of NUL padding. 2007a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky assert((unsigned)(4 - (s.size() % 4)) > 0); 2017a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky assert((unsigned)(4 - (s.size() % 4)) <= 4); 2027a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky writeBytes("\0\0\0\0", 4 - (s.size() % 4)); 203b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 204b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 205b1928704201034c785a26296a49f69355eb56a05Nick Lewycky raw_ostream *os; 206b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 207d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper const char *const GCOVRecord::LinesTag = "\0\0\x45\x01"; 208d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper const char *const GCOVRecord::FunctionTag = "\0\0\0\1"; 209d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper const char *const GCOVRecord::BlockTag = "\0\0\x41\x01"; 210d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper const char *const GCOVRecord::EdgeTag = "\0\0\x43\x01"; 211b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 212b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVFunction; 213b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVBlock; 214b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 215b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Constructed only by requesting it from a GCOVBlock, this object stores a 21616c19a155c65fd41865562fe4e678ef32728510bDevang Patel // list of line numbers and a single filename, representing lines that belong 21716c19a155c65fd41865562fe4e678ef32728510bDevang Patel // to the block. 218b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVLines : public GCOVRecord { 219b1928704201034c785a26296a49f69355eb56a05Nick Lewycky public: 2201790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky void addLine(uint32_t Line) { 221c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines assert(Line != 0 && "Line zero is not a valid real line number."); 2221790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky Lines.push_back(Line); 223b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 224b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 225619850cb3161733e9284ff3bf9a68d1a3b76f0b4Craig Topper uint32_t length() const { 226bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky // Here 2 = 1 for string length + 1 for '0' id#. 22716c19a155c65fd41865562fe4e678ef32728510bDevang Patel return lengthOfGCOVString(Filename) + 2 + Lines.size(); 228b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 229b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 23016c19a155c65fd41865562fe4e678ef32728510bDevang Patel void writeOut() { 23116c19a155c65fd41865562fe4e678ef32728510bDevang Patel write(0); 23216c19a155c65fd41865562fe4e678ef32728510bDevang Patel writeGCOVString(Filename); 23316c19a155c65fd41865562fe4e678ef32728510bDevang Patel for (int i = 0, e = Lines.size(); i != e; ++i) 23416c19a155c65fd41865562fe4e678ef32728510bDevang Patel write(Lines[i]); 23516c19a155c65fd41865562fe4e678ef32728510bDevang Patel } 236b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 23736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines GCOVLines(StringRef F, raw_ostream *os) 23816c19a155c65fd41865562fe4e678ef32728510bDevang Patel : Filename(F) { 239b1928704201034c785a26296a49f69355eb56a05Nick Lewycky this->os = os; 240b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 241b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 242680018ff8965610b3f1c976b0be1dfd45116b218Devang Patel private: 24316c19a155c65fd41865562fe4e678ef32728510bDevang Patel StringRef Filename; 2441790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky SmallVector<uint32_t, 32> Lines; 245b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 246b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 247c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky 248b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Represent a basic block in GCOV. Each block has a unique number in the 249b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // function, number of lines belonging to each block, and a set of edges to 250b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // other blocks. 251b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVBlock : public GCOVRecord { 252b1928704201034c785a26296a49f69355eb56a05Nick Lewycky public: 25368155d31cd0175be89e26ee68387cb411fca537bDevang Patel GCOVLines &getFile(StringRef Filename) { 2541790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GCOVLines *&Lines = LinesByFile[Filename]; 2551790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky if (!Lines) { 25616c19a155c65fd41865562fe4e678ef32728510bDevang Patel Lines = new GCOVLines(Filename, os); 257b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 2581790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return *Lines; 259b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 260b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 2611790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky void addEdge(GCOVBlock &Successor) { 2621790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky OutEdges.push_back(&Successor); 263b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 264b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 2651790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky void writeOut() { 2661790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky uint32_t Len = 3; 267c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky SmallVector<StringMapEntry<GCOVLines *> *, 32> SortedLinesByFile; 268de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto &I : LinesByFile) { 269de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Len += I.second->length(); 270de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SortedLinesByFile.push_back(&I); 271b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 272b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 2731790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky writeBytes(LinesTag, 4); 2741790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(Len); 2751790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(Number); 276c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky 27736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::sort(SortedLinesByFile.begin(), SortedLinesByFile.end(), 27836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines [](StringMapEntry<GCOVLines *> *LHS, 27936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringMapEntry<GCOVLines *> *RHS) { 28036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return LHS->getKey() < RHS->getKey(); 28136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines }); 282de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto &I : SortedLinesByFile) 283de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar I->getValue()->writeOut(); 2841790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(0); 2851790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(0); 286b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 287b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 288b1928704201034c785a26296a49f69355eb56a05Nick Lewycky ~GCOVBlock() { 2891790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky DeleteContainerSeconds(LinesByFile); 290b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 291b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 292ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines GCOVBlock(const GCOVBlock &RHS) : GCOVRecord(RHS), Number(RHS.Number) { 293ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Only allow copy before edges and lines have been added. After that, 294ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // there are inter-block pointers (eg: edges) that won't take kindly to 295ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // blocks being copied or moved around. 296ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines assert(LinesByFile.empty()); 297ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines assert(OutEdges.empty()); 298ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 299ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 300b1928704201034c785a26296a49f69355eb56a05Nick Lewycky private: 301b1928704201034c785a26296a49f69355eb56a05Nick Lewycky friend class GCOVFunction; 302b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 3031790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GCOVBlock(uint32_t Number, raw_ostream *os) 3041790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky : Number(Number) { 305b1928704201034c785a26296a49f69355eb56a05Nick Lewycky this->os = os; 306b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 307b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 3081790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky uint32_t Number; 3091790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky StringMap<GCOVLines *> LinesByFile; 3101790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky SmallVector<GCOVBlock *, 4> OutEdges; 311b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 312b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 313b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // A function has a unique identifier, a checksum (we leave as zero) and a 314b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // set of blocks and a map of edges between blocks. This is the only GCOV 315b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // object users can construct, the blocks and lines will be rooted here. 316b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVFunction : public GCOVRecord { 317b1928704201034c785a26296a49f69355eb56a05Nick Lewycky public: 318f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar GCOVFunction(const DISubprogram *SP, Function *F, raw_ostream *os, 319f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar uint32_t Ident, bool UseCfgChecksum, bool ExitBlockBeforeBody) 320ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines : SP(SP), Ident(Ident), UseCfgChecksum(UseCfgChecksum), CfgChecksum(0), 321ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines ReturnBlock(1, os) { 322b1928704201034c785a26296a49f69355eb56a05Nick Lewycky this->os = os; 323b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 32436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DEBUG(dbgs() << "Function: " << getFunctionName(SP) << "\n"); 325ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 326b1928704201034c785a26296a49f69355eb56a05Nick Lewycky uint32_t i = 0; 327ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines for (auto &BB : *F) { 3284c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // Skip index 1 if it's assigned to the ReturnBlock. 3294c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (i == 1 && ExitBlockBeforeBody) 3304c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ++i; 3314c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Blocks.insert(std::make_pair(&BB, GCOVBlock(i++, os))); 332b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 3334c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (!ExitBlockBeforeBody) 3344c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ReturnBlock.Number = i; 3351790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 33636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::string FunctionNameAndLine; 33736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines raw_string_ostream FNLOS(FunctionNameAndLine); 3380c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar FNLOS << getFunctionName(SP) << SP->getLine(); 33936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines FNLOS.flush(); 34036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines FuncChecksum = hash_value(FunctionNameAndLine); 341b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 342b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 3431790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GCOVBlock &getBlock(BasicBlock *BB) { 344ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return Blocks.find(BB)->second; 345b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 346b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 3471790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GCOVBlock &getReturnBlock() { 348ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return ReturnBlock; 349a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky } 350a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky 35136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::string getEdgeDestinations() { 35236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::string EdgeDestinations; 35336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines raw_string_ostream EDOS(EdgeDestinations); 35436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Function *F = Blocks.begin()->first->getParent(); 355f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar for (BasicBlock &I : *F) { 356f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar GCOVBlock &Block = getBlock(&I); 35736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (int i = 0, e = Block.OutEdges.size(); i != e; ++i) 35836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines EDOS << Block.OutEdges[i]->Number; 35936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 36036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EdgeDestinations; 36136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 36236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 36336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t getFuncChecksum() { 36436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return FuncChecksum; 36536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 36636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 36736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void setCfgChecksum(uint32_t Checksum) { 36836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CfgChecksum = Checksum; 36936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 37036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 3711790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky void writeOut() { 37236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines writeBytes(FunctionTag, 4); 37336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t BlockLen = 1 + 1 + 1 + lengthOfGCOVString(getFunctionName(SP)) + 3740c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar 1 + lengthOfGCOVString(SP->getFilename()) + 1; 37536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (UseCfgChecksum) 37636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ++BlockLen; 37736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines write(BlockLen); 37836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines write(Ident); 37936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines write(FuncChecksum); 38036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (UseCfgChecksum) 38136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines write(CfgChecksum); 38236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines writeGCOVString(getFunctionName(SP)); 3830c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar writeGCOVString(SP->getFilename()); 3840c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar write(SP->getLine()); 38536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 386b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Emit count of blocks. 3871790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky writeBytes(BlockTag, 4); 3881790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(Blocks.size() + 1); 3891790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky for (int i = 0, e = Blocks.size() + 1; i != e; ++i) { 3901790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(0); // No flags on our blocks. 391b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 392bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky DEBUG(dbgs() << Blocks.size() << " blocks.\n"); 393b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 394b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Emit edges between blocks. 395c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky if (Blocks.empty()) return; 396c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky Function *F = Blocks.begin()->first->getParent(); 397f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar for (BasicBlock &I : *F) { 398f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar GCOVBlock &Block = getBlock(&I); 3991790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky if (Block.OutEdges.empty()) continue; 4001790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 4011790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky writeBytes(EdgeTag, 4); 4021790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(Block.OutEdges.size() * 2 + 1); 4031790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(Block.Number); 4041790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky for (int i = 0, e = Block.OutEdges.size(); i != e; ++i) { 405bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky DEBUG(dbgs() << Block.Number << " -> " << Block.OutEdges[i]->Number 406bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky << "\n"); 4071790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(Block.OutEdges[i]->Number); 4081790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(0); // no flags 409b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 410b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 411b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 412b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Emit lines for each block. 413f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar for (BasicBlock &I : *F) 414f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar getBlock(&I).writeOut(); 415b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 416b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 417b1928704201034c785a26296a49f69355eb56a05Nick Lewycky private: 4186948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar const DISubprogram *SP; 41936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t Ident; 42036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t FuncChecksum; 42136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool UseCfgChecksum; 42236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t CfgChecksum; 423ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines DenseMap<BasicBlock *, GCOVBlock> Blocks; 424ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines GCOVBlock ReturnBlock; 425b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 426b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 427b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 4286948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstd::string GCOVProfiler::mangleName(const DICompileUnit *CU, 4296948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar const char *NewStem) { 430269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky if (NamedMDNode *GCov = M->getNamedMetadata("llvm.gcov")) { 431269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky for (int i = 0, e = GCov->getNumOperands(); i != e; ++i) { 432269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky MDNode *N = GCov->getOperand(i); 433269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky if (N->getNumOperands() != 2) continue; 434fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky MDString *GCovFile = dyn_cast<MDString>(N->getOperand(0)); 435269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky MDNode *CompileUnit = dyn_cast<MDNode>(N->getOperand(1)); 436fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky if (!GCovFile || !CompileUnit) continue; 437fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky if (CompileUnit == CU) { 4386e5190c193f6267893daf6943af88e95039e739cBill Wendling SmallString<128> Filename = GCovFile->getString(); 4396e5190c193f6267893daf6943af88e95039e739cBill Wendling sys::path::replace_extension(Filename, NewStem); 4406e5190c193f6267893daf6943af88e95039e739cBill Wendling return Filename.str(); 441fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky } 442269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky } 443269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky } 444fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky 4450c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar SmallString<128> Filename = CU->getFilename(); 446fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky sys::path::replace_extension(Filename, NewStem); 44739c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling StringRef FName = sys::path::filename(Filename); 44839c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling SmallString<128> CurPath; 44939c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling if (sys::fs::current_path(CurPath)) return FName; 4500c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar sys::path::append(CurPath, FName); 45139c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling return CurPath.str(); 452269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky} 453269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky 4540c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewyckybool GCOVProfiler::runOnModule(Module &M) { 4551790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky this->M = &M; 4560c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky Ctx = &M.getContext(); 4570c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky 458a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky if (Options.EmitNotes) emitProfileNotes(); 459a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky if (Options.EmitData) return emitProfileArcs(); 460a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky return false; 4610c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky} 4620c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky 463de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarPreservedAnalyses GCOVProfilerPass::run(Module &M, 464de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar AnalysisManager<Module> &AM) { 465de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 466de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GCOVProfiler Profiler(GCOVOpts); 467de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 468de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!Profiler.runOnModule(M)) 469de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return PreservedAnalyses::all(); 470de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 471de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return PreservedAnalyses::none(); 472de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 473de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 474de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic bool functionHasLines(Function &F) { 475dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // Check whether this function actually has any source lines. Not only 476dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // do these waste space, they also can crash gcov. 477de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto &BB : F) { 478de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto &I : BB) { 479c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // Debug intrinsic locations correspond to the location of the 480c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // declaration, not necessarily any statements or expressions. 481de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (isa<DbgInfoIntrinsic>(&I)) continue; 482c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 483de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const DebugLoc &Loc = I.getDebugLoc(); 4840c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar if (!Loc) 4850c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar continue; 486c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 487c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // Artificial lines such as calls to the global constructors. 4884c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (Loc.getLine() == 0) continue; 489c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 490c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines return true; 491dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 492dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 493dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return false; 494dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines} 495dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 49664a0a33307723957bf2f15e3181a290853c6f833Nick Lewyckyvoid GCOVProfiler::emitProfileNotes() { 497f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); 498bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky if (!CU_Nodes) return; 499bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 500bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { 501bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky // Each compile unit gets its own .gcno file. This means that whether we run 502bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky // this pass over the original .o's as they're produced, or run it after 503bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky // LTO, we'll generate the same .gcno files. 504bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 5056948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(i)); 506de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 507de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Skip module skeleton (and module) CUs. 508de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (CU->getDWOId()) 509de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar continue; 510de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 51137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines std::error_code EC; 51237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines raw_fd_ostream out(mangleName(CU, "gcno"), EC, sys::fs::F_None); 51336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::string EdgeDestinations; 514bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 51537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines unsigned FunctionIdent = 0; 516de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto &F : M->functions()) { 517de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DISubprogram *SP = F.getSubprogram(); 518de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!SP) continue; 519dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!functionHasLines(F)) continue; 52036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 52136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // gcov expects every function to start with an entry block that has a 52236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // single successor, so split the entry block to make sure of that. 523de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar BasicBlock &EntryBlock = F.getEntryBlock(); 52436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines BasicBlock::iterator It = EntryBlock.begin(); 52536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines while (isa<AllocaInst>(*It) || isa<DbgInfoIntrinsic>(*It)) 52636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ++It; 52736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines EntryBlock.splitBasicBlock(It); 52836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 529de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Funcs.push_back(make_unique<GCOVFunction>(SP, &F, &out, FunctionIdent++, 5304c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Options.UseCfgChecksum, 5314c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Options.ExitBlockBeforeBody)); 532dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines GCOVFunction &Func = *Funcs.back(); 533bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 534de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto &BB : F) { 535de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GCOVBlock &Block = Func.getBlock(&BB); 536de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TerminatorInst *TI = BB.getTerminator(); 537bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky if (int successors = TI->getNumSuccessors()) { 538bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky for (int i = 0; i != successors; ++i) { 539dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Block.addEdge(Func.getBlock(TI->getSuccessor(i))); 540f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 541bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky } else if (isa<ReturnInst>(TI)) { 542dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Block.addEdge(Func.getReturnBlock()); 543bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky } 544bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 545bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky uint32_t Line = 0; 546de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto &I : BB) { 547c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // Debug intrinsic locations correspond to the location of the 548c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // declaration, not necessarily any statements or expressions. 549de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (isa<DbgInfoIntrinsic>(&I)) continue; 550c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 551de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const DebugLoc &Loc = I.getDebugLoc(); 5520c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar if (!Loc) 5530c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar continue; 554c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 555c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // Artificial lines such as calls to the global constructors. 556c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (Loc.getLine() == 0) continue; 557c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 558bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky if (Line == Loc.getLine()) continue; 559bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky Line = Loc.getLine(); 5600c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar if (SP != getDISubprogram(Loc.getScope())) 5610c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar continue; 562bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 5630c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar GCOVLines &Lines = Block.getFile(SP->getFilename()); 564bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky Lines.addLine(Loc.getLine()); 565b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 566b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 567dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines EdgeDestinations += Func.getEdgeDestinations(); 568b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 56936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 57036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines FileChecksums.push_back(hash_value(EdgeDestinations)); 57136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines out.write("oncg", 4); 57236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines out.write(ReversedVersion, 4); 57336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines out.write(reinterpret_cast<char*>(&FileChecksums.back()), 4); 57436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 575dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines for (auto &Func : Funcs) { 57636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Func->setCfgChecksum(FileChecksums.back()); 57736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Func->writeOut(); 57836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 57936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 580bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky out.write("\0\0\0\0\0\0\0\0", 8); // EOF 581bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky out.close(); 582b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 583b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 584b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 585f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patelbool GCOVProfiler::emitProfileArcs() { 586f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); 587f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (!CU_Nodes) return false; 588f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel 58936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool Result = false; 59077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling bool InsertIndCounterIncrCode = false; 591f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { 592f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> CountersBySP; 593de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto &F : M->functions()) { 594de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar DISubprogram *SP = F.getSubprogram(); 595de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!SP) continue; 596dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!functionHasLines(F)) continue; 597f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (!Result) Result = true; 598f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel unsigned Edges = 0; 599de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto &BB : F) { 600de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TerminatorInst *TI = BB.getTerminator(); 601f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (isa<ReturnInst>(TI)) 602f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel ++Edges; 603f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel else 604f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Edges += TI->getNumSuccessors(); 605f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 60636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 607f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel ArrayType *CounterTy = 6081790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky ArrayType::get(Type::getInt64Ty(*Ctx), Edges); 609f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel GlobalVariable *Counters = 6101790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky new GlobalVariable(*M, CounterTy, false, 611b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GlobalValue::InternalLinkage, 6121790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky Constant::getNullValue(CounterTy), 613ce718ff9f42c7da092eaa01dd0242e8d5ba84713Hans Wennborg "__llvm_gcov_ctr"); 6140c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar CountersBySP.push_back(std::make_pair(Counters, SP)); 61536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 616f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel UniqueVector<BasicBlock *> ComplexEdgePreds; 617f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel UniqueVector<BasicBlock *> ComplexEdgeSuccs; 61836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 619f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel unsigned Edge = 0; 620de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (auto &BB : F) { 621de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TerminatorInst *TI = BB.getTerminator(); 622f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors(); 623f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (Successors) { 624f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (Successors == 1) { 625de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar IRBuilder<> Builder(&*BB.getFirstInsertionPt()); 626f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0, 627f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Edge); 628f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Value *Count = Builder.CreateLoad(Counter); 629bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Count = Builder.CreateAdd(Count, Builder.getInt64(1)); 630f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Builder.CreateStore(Count, Counter); 631f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } else if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { 632f675b3c6444af3e2f547b050eedb8a12584110efBill Wendling IRBuilder<> Builder(BI); 633bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Value *Sel = Builder.CreateSelect(BI->getCondition(), 634bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Builder.getInt64(Edge), 635bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Builder.getInt64(Edge + 1)); 636de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Value *Counter = Builder.CreateInBoundsGEP( 637de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Counters->getValueType(), Counters, {Builder.getInt64(0), Sel}); 638f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Value *Count = Builder.CreateLoad(Counter); 639bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Count = Builder.CreateAdd(Count, Builder.getInt64(1)); 640f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Builder.CreateStore(Count, Counter); 641f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } else { 642de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ComplexEdgePreds.insert(&BB); 643f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel for (int i = 0; i != Successors; ++i) 644f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel ComplexEdgeSuccs.insert(TI->getSuccessor(i)); 645f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 646f675b3c6444af3e2f547b050eedb8a12584110efBill Wendling 647f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Edge += Successors; 648b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 649b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 65036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 651f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (!ComplexEdgePreds.empty()) { 652f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel GlobalVariable *EdgeTable = 653de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar buildEdgeLookupTable(&F, Counters, 6541790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky ComplexEdgePreds, ComplexEdgeSuccs); 655f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel GlobalVariable *EdgeState = getEdgeStateValue(); 65636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 657f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) { 658f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar IRBuilder<> Builder(&*ComplexEdgePreds[i + 1]->getFirstInsertionPt()); 659bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Builder.CreateStore(Builder.getInt32(i), EdgeState); 660f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 661f675b3c6444af3e2f547b050eedb8a12584110efBill Wendling 662f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) { 663f675b3c6444af3e2f547b050eedb8a12584110efBill Wendling // Call runtime to perform increment. 664f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar IRBuilder<> Builder(&*ComplexEdgeSuccs[i + 1]->getFirstInsertionPt()); 665f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Value *CounterPtrArray = 6661790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0, 6671790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky i * ComplexEdgePreds.size()); 668c7a884040e4ec7795515978a94803894ad08c4caBill Wendling 669c7a884040e4ec7795515978a94803894ad08c4caBill Wendling // Build code to increment the counter. 67077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling InsertIndCounterIncrCode = true; 6716948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall(getIncrementIndirectCounterFunc(), 6726948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {EdgeState, CounterPtrArray}); 673f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 674b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 675b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 6764a8fefaf8303f30514bc2a40d840a1709dae65cfBill Wendling 677d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling Function *WriteoutF = insertCounterWriteout(CountersBySP); 678d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling Function *FlushF = insertFlush(CountersBySP); 679d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 680d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling // Create a small bit of code that registers the "__llvm_gcov_writeout" to 68118764716861243c58a711a92190624dc2f6aafc9Bill Wendling // be executed at exit and the "__llvm_gcov_flush" function to be executed 68218764716861243c58a711a92190624dc2f6aafc9Bill Wendling // when "__gcov_flush" is called. 683d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 684d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling Function *F = Function::Create(FTy, GlobalValue::InternalLinkage, 685d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling "__llvm_gcov_init", M); 686de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); 687d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling F->setLinkage(GlobalValue::InternalLinkage); 688d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling F->addFnAttr(Attribute::NoInline); 689d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling if (Options.NoRedZone) 690d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling F->addFnAttr(Attribute::NoRedZone); 691d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 692d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F); 693d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling IRBuilder<> Builder(BB); 694d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 695d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 6968640c6a5227b75666e02424e2181289692138348Bill Wendling Type *Params[] = { 6978640c6a5227b75666e02424e2181289692138348Bill Wendling PointerType::get(FTy, 0), 6988640c6a5227b75666e02424e2181289692138348Bill Wendling PointerType::get(FTy, 0) 6998640c6a5227b75666e02424e2181289692138348Bill Wendling }; 7008640c6a5227b75666e02424e2181289692138348Bill Wendling FTy = FunctionType::get(Builder.getVoidTy(), Params, false); 7018640c6a5227b75666e02424e2181289692138348Bill Wendling 702d7da59004fc9262f33c96ad2736b36ff1235ce7bYuchen Wu // Initialize the environment and register the local writeout and flush 7038640c6a5227b75666e02424e2181289692138348Bill Wendling // functions. 7048640c6a5227b75666e02424e2181289692138348Bill Wendling Constant *GCOVInit = M->getOrInsertFunction("llvm_gcov_init", FTy); 7056948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall(GCOVInit, {WriteoutF, FlushF}); 706d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling Builder.CreateRetVoid(); 707d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 708d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling appendToGlobalCtors(*M, F, 0); 709b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 71077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 71177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling if (InsertIndCounterIncrCode) 71277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling insertIndirectCounterIncrement(); 71377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 714f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel return Result; 715b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 716b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 7171790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky// All edges with successors that aren't branches are "complex", because it 7181790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky// requires complex logic to pick which counter to update. 7191790c9cbb6714e81eab1412909a2320acaecc43bNick LewyckyGlobalVariable *GCOVProfiler::buildEdgeLookupTable( 7201790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky Function *F, 7211790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GlobalVariable *Counters, 7221790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky const UniqueVector<BasicBlock *> &Preds, 7231790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky const UniqueVector<BasicBlock *> &Succs) { 7241790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky // TODO: support invoke, threads. We rely on the fact that nothing can modify 7251790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky // the whole-Module pred edge# between the time we set it and the time we next 7261790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky // read it. Threads and invoke make this untrue. 7271790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 7281790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky // emit [(succs * preds) x i64*], logically [succ x [pred x i64*]]. 7299e6ee16b1814268897965b81e82a74ef39173ee1Benjamin Kramer size_t TableSize = Succs.size() * Preds.size(); 730db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner Type *Int64PtrTy = Type::getInt64PtrTy(*Ctx); 7319e6ee16b1814268897965b81e82a74ef39173ee1Benjamin Kramer ArrayType *EdgeTableTy = ArrayType::get(Int64PtrTy, TableSize); 7321790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 73336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::unique_ptr<Constant * []> EdgeTable(new Constant *[TableSize]); 7341790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky Constant *NullValue = Constant::getNullValue(Int64PtrTy); 7359e6ee16b1814268897965b81e82a74ef39173ee1Benjamin Kramer for (size_t i = 0; i != TableSize; ++i) 7361790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky EdgeTable[i] = NullValue; 7371790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 7381790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky unsigned Edge = 0; 739de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (BasicBlock &BB : *F) { 740de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TerminatorInst *TI = BB.getTerminator(); 7411790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors(); 7427a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky if (Successors > 1 && !isa<BranchInst>(TI) && !isa<ReturnInst>(TI)) { 7431790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky for (int i = 0; i != Successors; ++i) { 7441790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky BasicBlock *Succ = TI->getSuccessor(i); 745bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky IRBuilder<> Builder(Succ); 746bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0, 7471790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky Edge + i); 748f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar EdgeTable[((Succs.idFor(Succ) - 1) * Preds.size()) + 749de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar (Preds.idFor(&BB) - 1)] = cast<Constant>(Counter); 7501790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 7511790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 7521790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky Edge += Successors; 7531790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 7541790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 7551790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GlobalVariable *EdgeTableGV = 7561790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky new GlobalVariable( 7571790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky *M, EdgeTableTy, true, GlobalValue::InternalLinkage, 75837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ConstantArray::get(EdgeTableTy, 75937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines makeArrayRef(&EdgeTable[0],TableSize)), 7601790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky "__llvm_gcda_edge_table"); 761de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar EdgeTableGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); 7621790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return EdgeTableGV; 7631790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky} 7641790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 765b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getStartFileFunc() { 766d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky Type *Args[] = { 767d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky Type::getInt8PtrTy(*Ctx), // const char *orig_filename 768d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky Type::getInt8PtrTy(*Ctx), // const char version[4] 76936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Type::getInt32Ty(*Ctx), // uint32_t checksum 770d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky }; 771d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false); 7721790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return M->getOrInsertFunction("llvm_gcda_start_file", FTy); 7731790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky} 7741790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 77577b19134104c3e96424dc010f2b69c3faf580e68Bill WendlingConstant *GCOVProfiler::getIncrementIndirectCounterFunc() { 77677b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Type *Int32Ty = Type::getInt32Ty(*Ctx); 777c7a884040e4ec7795515978a94803894ad08c4caBill Wendling Type *Int64Ty = Type::getInt64Ty(*Ctx); 77877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Type *Args[] = { 779b8bce928f4ffdf50eff69334f3e25b27848536b6Micah Villmow Int32Ty->getPointerTo(), // uint32_t *predecessor 780b8bce928f4ffdf50eff69334f3e25b27848536b6Micah Villmow Int64Ty->getPointerTo()->getPointerTo() // uint64_t **counters 78177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling }; 78277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false); 78377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling return M->getOrInsertFunction("__llvm_gcov_indirect_counter_increment", FTy); 784b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 785b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 786b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getEmitFunctionFunc() { 78736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Type *Args[] = { 7885409a188328d9de3755febc23558d4fc1797d04eNick Lewycky Type::getInt32Ty(*Ctx), // uint32_t ident 7895409a188328d9de3755febc23558d4fc1797d04eNick Lewycky Type::getInt8PtrTy(*Ctx), // const char *function_name 79036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Type::getInt32Ty(*Ctx), // uint32_t func_checksum 79117d2f776011cba33f7f5afb03c8066d35dbf8afcNick Lewycky Type::getInt8Ty(*Ctx), // uint8_t use_extra_checksum 79236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Type::getInt32Ty(*Ctx), // uint32_t cfg_checksum 7935409a188328d9de3755febc23558d4fc1797d04eNick Lewycky }; 794c7a884040e4ec7795515978a94803894ad08c4caBill Wendling FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false); 7951790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return M->getOrInsertFunction("llvm_gcda_emit_function", FTy); 796b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 797b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 798b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getEmitArcsFunc() { 7995fdd6c8793462549e3593890ec61573da06e3346Jay Foad Type *Args[] = { 800b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Type::getInt32Ty(*Ctx), // uint32_t num_counters 801b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Type::getInt64PtrTy(*Ctx), // uint64_t *counters 802b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 803d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false); 8041790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy); 805b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 806b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 807f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen WuConstant *GCOVProfiler::getSummaryInfoFunc() { 808f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 809f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu return M->getOrInsertFunction("llvm_gcda_summary_info", FTy); 810f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu} 811f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu 812b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getEndFileFunc() { 813db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 8141790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return M->getOrInsertFunction("llvm_gcda_end_file", FTy); 815b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 816b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 8171790c9cbb6714e81eab1412909a2320acaecc43bNick LewyckyGlobalVariable *GCOVProfiler::getEdgeStateValue() { 8181790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GlobalVariable *GV = M->getGlobalVariable("__llvm_gcov_global_state_pred"); 8191790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky if (!GV) { 8201790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GV = new GlobalVariable(*M, Type::getInt32Ty(*Ctx), false, 8211790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GlobalValue::InternalLinkage, 8221790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky ConstantInt::get(Type::getInt32Ty(*Ctx), 8231790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 0xffffffff), 8241790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky "__llvm_gcov_global_state_pred"); 825de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); 8261790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 8271790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return GV; 8281790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky} 829b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 830d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill WendlingFunction *GCOVProfiler::insertCounterWriteout( 83121b742ffce7bec3d71e09c7c6d901a756d55feb3Bill Wendling ArrayRef<std::pair<GlobalVariable *, MDNode *> > CountersBySP) { 832253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling FunctionType *WriteoutFTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 833253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling Function *WriteoutF = M->getFunction("__llvm_gcov_writeout"); 834253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling if (!WriteoutF) 835253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling WriteoutF = Function::Create(WriteoutFTy, GlobalValue::InternalLinkage, 836253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling "__llvm_gcov_writeout", M); 837de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar WriteoutF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); 838034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling WriteoutF->addFnAttr(Attribute::NoInline); 839a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky if (Options.NoRedZone) 840034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling WriteoutF->addFnAttr(Attribute::NoRedZone); 841253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling 842253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", WriteoutF); 8431790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky IRBuilder<> Builder(BB); 844b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 845b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *StartFile = getStartFileFunc(); 846b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *EmitFunction = getEmitFunctionFunc(); 847b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *EmitArcs = getEmitArcsFunc(); 848f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu Constant *SummaryInfo = getSummaryInfoFunc(); 849b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *EndFile = getEndFileFunc(); 850b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 851f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); 852f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (CU_Nodes) { 853f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { 8546948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(i)); 855de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 856de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Skip module skeleton (and module) CUs. 857de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (CU->getDWOId()) 858de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar continue; 859de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 860f2a2806baf3763d551a9f361124b608b2eed66faBill Wendling std::string FilenameGcda = mangleName(CU, "gcda"); 86136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t CfgChecksum = FileChecksums.empty() ? 0 : FileChecksums[i]; 8626948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall(StartFile, 8636948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {Builder.CreateGlobalStringPtr(FilenameGcda), 86436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Builder.CreateGlobalStringPtr(ReversedVersion), 8656948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.getInt32(CfgChecksum)}); 8668fa6dc431deb7a9aadc23ec0a7bdcb2d02330972Nick Lewycky for (unsigned j = 0, e = CountersBySP.size(); j != e; ++j) { 8676948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar auto *SP = cast_or_null<DISubprogram>(CountersBySP[j].second); 86836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t FuncChecksum = Funcs.empty() ? 0 : Funcs[j]->getFuncChecksum(); 8696948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall( 8706948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar EmitFunction, 8716948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {Builder.getInt32(j), 8726948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Options.FunctionNamesInData 8736948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar ? Builder.CreateGlobalStringPtr(getFunctionName(SP)) 8746948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar : Constant::getNullValue(Builder.getInt8PtrTy()), 8756948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.getInt32(FuncChecksum), 8766948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.getInt8(Options.UseCfgChecksum), 8776948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.getInt32(CfgChecksum)}); 87817d2f776011cba33f7f5afb03c8066d35dbf8afcNick Lewycky 8798fa6dc431deb7a9aadc23ec0a7bdcb2d02330972Nick Lewycky GlobalVariable *GV = CountersBySP[j].first; 880f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel unsigned Arcs = 881de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar cast<ArrayType>(GV->getValueType())->getNumElements(); 8826948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall(EmitArcs, {Builder.getInt32(Arcs), 8836948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateConstGEP2_64(GV, 0, 0)}); 884f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 8856948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall(SummaryInfo, {}); 8866948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall(EndFile, {}); 887b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 888b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 889b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 8904a8fefaf8303f30514bc2a40d840a1709dae65cfBill Wendling Builder.CreateRetVoid(); 891d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling return WriteoutF; 892b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 89377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 89477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendlingvoid GCOVProfiler::insertIndirectCounterIncrement() { 89577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Function *Fn = 89677b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling cast<Function>(GCOVProfiler::getIncrementIndirectCounterFunc()); 897de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Fn->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); 89877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Fn->setLinkage(GlobalValue::InternalLinkage); 899034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling Fn->addFnAttr(Attribute::NoInline); 900a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky if (Options.NoRedZone) 901034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling Fn->addFnAttr(Attribute::NoRedZone); 90277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 90377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling // Create basic blocks for function. 90477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", Fn); 90577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling IRBuilder<> Builder(BB); 90677b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 90777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling BasicBlock *PredNotNegOne = BasicBlock::Create(*Ctx, "", Fn); 90877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling BasicBlock *CounterEnd = BasicBlock::Create(*Ctx, "", Fn); 90977b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling BasicBlock *Exit = BasicBlock::Create(*Ctx, "exit", Fn); 91077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 91177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling // uint32_t pred = *predecessor; 91277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling // if (pred == 0xffffffff) return; 913f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Argument *Arg = &*Fn->arg_begin(); 91477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Arg->setName("predecessor"); 91577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Value *Pred = Builder.CreateLoad(Arg, "pred"); 916bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Value *Cond = Builder.CreateICmpEQ(Pred, Builder.getInt32(0xffffffff)); 91777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling BranchInst::Create(Exit, PredNotNegOne, Cond, BB); 91877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 91977b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Builder.SetInsertPoint(PredNotNegOne); 92077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 92177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling // uint64_t *counter = counters[pred]; 92277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling // if (!counter) return; 923bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Value *ZExtPred = Builder.CreateZExt(Pred, Builder.getInt64Ty()); 924f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar Arg = &*std::next(Fn->arg_begin()); 92577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Arg->setName("counters"); 9260c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar Value *GEP = Builder.CreateGEP(Type::getInt64PtrTy(*Ctx), Arg, ZExtPred); 92777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Value *Counter = Builder.CreateLoad(GEP, "counter"); 92858591b1647e0f1f213e5acd7bfa87c226ced0033Nick Lewycky Cond = Builder.CreateICmpEQ(Counter, 92958591b1647e0f1f213e5acd7bfa87c226ced0033Nick Lewycky Constant::getNullValue( 93058591b1647e0f1f213e5acd7bfa87c226ced0033Nick Lewycky Builder.getInt64Ty()->getPointerTo())); 93177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Builder.CreateCondBr(Cond, Exit, CounterEnd); 93277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 93377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling // ++*counter; 93477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Builder.SetInsertPoint(CounterEnd); 93577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Value *Add = Builder.CreateAdd(Builder.CreateLoad(Counter), 936bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Builder.getInt64(1)); 93777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Builder.CreateStore(Add, Counter); 93877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Builder.CreateBr(Exit); 93977b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 94077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling // Fill in the exit block. 94177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Builder.SetInsertPoint(Exit); 94277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Builder.CreateRetVoid(); 94377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling} 944253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling 945d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill WendlingFunction *GCOVProfiler:: 946253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill WendlinginsertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) { 947253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 948d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling Function *FlushF = M->getFunction("__llvm_gcov_flush"); 949253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling if (!FlushF) 950253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling FlushF = Function::Create(FTy, GlobalValue::InternalLinkage, 951d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling "__llvm_gcov_flush", M); 952253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling else 953253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling FlushF->setLinkage(GlobalValue::InternalLinkage); 954de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar FlushF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); 955034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling FlushF->addFnAttr(Attribute::NoInline); 956a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky if (Options.NoRedZone) 957034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling FlushF->addFnAttr(Attribute::NoRedZone); 958253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling 959253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", FlushF); 960253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling 961253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling // Write out the current counters. 962253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling Constant *WriteoutF = M->getFunction("__llvm_gcov_writeout"); 963253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling assert(WriteoutF && "Need to create the writeout function first!"); 964253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling 965253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling IRBuilder<> Builder(Entry); 9666948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall(WriteoutF, {}); 967253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling 968032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling // Zero out the counters. 969de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (const auto &I : CountersBySP) { 970de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar GlobalVariable *GV = I.first; 971de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Constant *Null = Constant::getNullValue(GV->getValueType()); 972ec3fc2eac0e9203dd1094b9ce458e8c1b42b832fBill Wendling Builder.CreateStore(Null, GV); 973032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling } 974253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling 975253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling Type *RetTy = FlushF->getReturnType(); 976253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling if (RetTy == Type::getVoidTy(*Ctx)) 977253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling Builder.CreateRetVoid(); 978253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling else if (RetTy->isIntegerTy()) 979d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling // Used if __llvm_gcov_flush was implicitly declared. 980253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling Builder.CreateRet(ConstantInt::get(RetTy, 0)); 981253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling else 982d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling report_fatal_error("invalid return type for __llvm_gcov_flush"); 983d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 984d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling return FlushF; 985253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling} 986