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/Transforms/Instrumentation.h" 18b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/DenseMap.h" 1936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/ADT/Hashing.h" 20b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/STLExtras.h" 2106cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/ADT/Statistic.h" 22b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/StringExtras.h" 23b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/StringMap.h" 24b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include "llvm/ADT/UniqueVector.h" 2536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/DebugInfo.h" 2636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/DebugLoc.h" 270b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/IRBuilder.h" 2836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/InstIterator.h" 290b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Instructions.h" 3036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/IntrinsicInst.h" 310b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Module.h" 32d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Pass.h" 33a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky#include "llvm/Support/CommandLine.h" 3406cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Support/Debug.h" 3539c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling#include "llvm/Support/FileSystem.h" 36a11c3e25015a62c817e60ec4f955a7f3f3bb6c67Rafael Espindola#include "llvm/Support/Path.h" 3706cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Support/raw_ostream.h" 3806cb8ed00696eb14d1b831921452e50ec0568ea2Chandler Carruth#include "llvm/Transforms/Utils/ModuleUtils.h" 39c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky#include <algorithm> 40dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include <memory> 41b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include <string> 42b1928704201034c785a26296a49f69355eb56a05Nick Lewycky#include <utility> 43b1928704201034c785a26296a49f69355eb56a05Nick Lewyckyusing namespace llvm; 44b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 45dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define DEBUG_TYPE "insert-gcov-profiling" 46dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 47a204ef3168c8804808c716115ba915c89d8849b9Nick Lewyckystatic cl::opt<std::string> 48a204ef3168c8804808c716115ba915c89d8849b9Nick LewyckyDefaultGCOVVersion("default-gcov-version", cl::init("402*"), cl::Hidden, 49a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky cl::ValueRequired); 504c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarstatic cl::opt<bool> DefaultExitBlockBeforeBody("gcov-exit-block-before-body", 514c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar cl::init(false), cl::Hidden); 52a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky 53a204ef3168c8804808c716115ba915c89d8849b9Nick LewyckyGCOVOptions GCOVOptions::getDefault() { 54a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky GCOVOptions Options; 55a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky Options.EmitNotes = true; 56a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky Options.EmitData = true; 57a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky Options.UseCfgChecksum = false; 58a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky Options.NoRedZone = false; 59a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky Options.FunctionNamesInData = true; 604c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Options.ExitBlockBeforeBody = DefaultExitBlockBeforeBody; 61a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky 62a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky if (DefaultGCOVVersion.size() != 4) { 63a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky llvm::report_fatal_error(std::string("Invalid -default-gcov-version: ") + 64a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky DefaultGCOVVersion); 65a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky } 66a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky memcpy(Options.Version, DefaultGCOVVersion.c_str(), 4); 67a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky return Options; 68a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky} 69a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky 70b1928704201034c785a26296a49f69355eb56a05Nick Lewyckynamespace { 7136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines class GCOVFunction; 7236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 73b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVProfiler : public ModulePass { 74b1928704201034c785a26296a49f69355eb56a05Nick Lewycky public: 75b1928704201034c785a26296a49f69355eb56a05Nick Lewycky static char ID; 764c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar GCOVProfiler() : GCOVProfiler(GCOVOptions::getDefault()) {} 774c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar GCOVProfiler(const GCOVOptions &Opts) : ModulePass(ID), Options(Opts) { 78a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky assert((Options.EmitNotes || Options.EmitData) && 79a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky "GCOVProfiler asked to do nothing?"); 80a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky ReversedVersion[0] = Options.Version[3]; 81a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky ReversedVersion[1] = Options.Version[2]; 82a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky ReversedVersion[2] = Options.Version[1]; 83a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky ReversedVersion[3] = Options.Version[0]; 84a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky ReversedVersion[4] = '\0'; 85b1928704201034c785a26296a49f69355eb56a05Nick Lewycky initializeGCOVProfilerPass(*PassRegistry::getPassRegistry()); 86b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 874c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar const char *getPassName() const override { 884c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar return "GCOV Profiler"; 894c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar } 904c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar 914c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar private: 9236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool runOnModule(Module &M) override; 93269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky 9464a0a33307723957bf2f15e3181a290853c6f833Nick Lewycky // Create the .gcno files for the Module based on DebugInfo. 9564a0a33307723957bf2f15e3181a290853c6f833Nick Lewycky void emitProfileNotes(); 96b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 970c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky // Modify the program to track transitions along edges and call into the 980c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky // profiling runtime to emit .gcda files when run. 99f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel bool emitProfileArcs(); 1000c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky 101b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Get pointers to the functions in the runtime library. 102b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *getStartFileFunc(); 10377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Constant *getIncrementIndirectCounterFunc(); 104b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *getEmitFunctionFunc(); 105b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *getEmitArcsFunc(); 106f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu Constant *getSummaryInfoFunc(); 10718764716861243c58a711a92190624dc2f6aafc9Bill Wendling Constant *getDeleteWriteoutFunctionListFunc(); 108d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling Constant *getDeleteFlushFunctionListFunc(); 109b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *getEndFileFunc(); 110b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 1111790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky // Create or retrieve an i32 state value that is used to represent the 1121790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky // pred block number for certain non-trivial edges. 1131790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GlobalVariable *getEdgeStateValue(); 1141790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 1151790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky // Produce a table of pointers to counters, by predecessor and successor 1161790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky // block number. 1171790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GlobalVariable *buildEdgeLookupTable(Function *F, 1181790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GlobalVariable *Counter, 11964a0a33307723957bf2f15e3181a290853c6f833Nick Lewycky const UniqueVector<BasicBlock *>&Preds, 12064a0a33307723957bf2f15e3181a290853c6f833Nick Lewycky const UniqueVector<BasicBlock*>&Succs); 1211790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 122b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Add the function to write out all our counters to the global destructor 123b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // list. 124d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling Function *insertCounterWriteout(ArrayRef<std::pair<GlobalVariable*, 125d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling MDNode*> >); 126d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling Function *insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> >); 12777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling void insertIndirectCounterIncrement(); 128b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 1296948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar std::string mangleName(const DICompileUnit *CU, const char *NewStem); 130269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky 131a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky GCOVOptions Options; 132a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky 133a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky // Reversed, NUL-terminated copy of Options.Version. 13436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines char ReversedVersion[5]; 13536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Checksum, produced by hash of EdgeDestinations 13636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SmallVector<uint32_t, 4> FileChecksums; 137a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky 1381790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky Module *M; 139b1928704201034c785a26296a49f69355eb56a05Nick Lewycky LLVMContext *Ctx; 140dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines SmallVector<std::unique_ptr<GCOVFunction>, 16> Funcs; 141cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar DenseMap<DISubprogram *, Function *> FnMap; 142b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 143b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 144b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 145b1928704201034c785a26296a49f69355eb56a05Nick Lewyckychar GCOVProfiler::ID = 0; 146b1928704201034c785a26296a49f69355eb56a05Nick LewyckyINITIALIZE_PASS(GCOVProfiler, "insert-gcov-profiling", 147b1928704201034c785a26296a49f69355eb56a05Nick Lewycky "Insert instrumentation for GCOV profiling", false, false) 148b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 149a204ef3168c8804808c716115ba915c89d8849b9Nick LewyckyModulePass *llvm::createGCOVProfilerPass(const GCOVOptions &Options) { 150a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky return new GCOVProfiler(Options); 151a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky} 152b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 1536948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstatic StringRef getFunctionName(const DISubprogram *SP) { 1540c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar if (!SP->getLinkageName().empty()) 1550c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar return SP->getLinkageName(); 1560c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar return SP->getName(); 1575d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky} 1585d22d02fac5ef25414c0fdd843b0fabba4998d6eNick Lewycky 159b1928704201034c785a26296a49f69355eb56a05Nick Lewyckynamespace { 160b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVRecord { 161b1928704201034c785a26296a49f69355eb56a05Nick Lewycky protected: 162d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper static const char *const LinesTag; 163d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper static const char *const FunctionTag; 164d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper static const char *const BlockTag; 165d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper static const char *const EdgeTag; 166b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 1670c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar GCOVRecord() = default; 168b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 1691790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky void writeBytes(const char *Bytes, int Size) { 1701790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky os->write(Bytes, Size); 171b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 172b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 1731790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky void write(uint32_t i) { 1741790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky writeBytes(reinterpret_cast<char*>(&i), 4); 175b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 176b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 177b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Returns the length measured in 4-byte blocks that will be used to 178b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // represent this string in a GCOV file 179619850cb3161733e9284ff3bf9a68d1a3b76f0b4Craig Topper static unsigned lengthOfGCOVString(StringRef s) { 180b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // A GCOV string is a length, followed by a NUL, then between 0 and 3 NULs 18117df2c3240837b4382898ead8c3ead407a338520Nick Lewycky // padding out to the next 4-byte word. The length is measured in 4-byte 18217df2c3240837b4382898ead8c3ead407a338520Nick Lewycky // words including padding, not bytes of actual string. 183d363ff334d796c7f3df834d928a10d88ed758454Nick Lewycky return (s.size() / 4) + 1; 184b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 185b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 1861790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky void writeGCOVString(StringRef s) { 1871790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky uint32_t Len = lengthOfGCOVString(s); 1881790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(Len); 1891790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky writeBytes(s.data(), s.size()); 190b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 191b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Write 1 to 4 bytes of NUL padding. 1927a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky assert((unsigned)(4 - (s.size() % 4)) > 0); 1937a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky assert((unsigned)(4 - (s.size() % 4)) <= 4); 1947a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky writeBytes("\0\0\0\0", 4 - (s.size() % 4)); 195b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 196b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 197b1928704201034c785a26296a49f69355eb56a05Nick Lewycky raw_ostream *os; 198b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 199d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper const char *const GCOVRecord::LinesTag = "\0\0\x45\x01"; 200d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper const char *const GCOVRecord::FunctionTag = "\0\0\0\1"; 201d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper const char *const GCOVRecord::BlockTag = "\0\0\x41\x01"; 202d6d6a97c3c41395dfed46572b69fb6a5d67a5a8bCraig Topper const char *const GCOVRecord::EdgeTag = "\0\0\x43\x01"; 203b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 204b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVFunction; 205b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVBlock; 206b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 207b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Constructed only by requesting it from a GCOVBlock, this object stores a 20816c19a155c65fd41865562fe4e678ef32728510bDevang Patel // list of line numbers and a single filename, representing lines that belong 20916c19a155c65fd41865562fe4e678ef32728510bDevang Patel // to the block. 210b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVLines : public GCOVRecord { 211b1928704201034c785a26296a49f69355eb56a05Nick Lewycky public: 2121790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky void addLine(uint32_t Line) { 213c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines assert(Line != 0 && "Line zero is not a valid real line number."); 2141790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky Lines.push_back(Line); 215b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 216b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 217619850cb3161733e9284ff3bf9a68d1a3b76f0b4Craig Topper uint32_t length() const { 218bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky // Here 2 = 1 for string length + 1 for '0' id#. 21916c19a155c65fd41865562fe4e678ef32728510bDevang Patel return lengthOfGCOVString(Filename) + 2 + Lines.size(); 220b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 221b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 22216c19a155c65fd41865562fe4e678ef32728510bDevang Patel void writeOut() { 22316c19a155c65fd41865562fe4e678ef32728510bDevang Patel write(0); 22416c19a155c65fd41865562fe4e678ef32728510bDevang Patel writeGCOVString(Filename); 22516c19a155c65fd41865562fe4e678ef32728510bDevang Patel for (int i = 0, e = Lines.size(); i != e; ++i) 22616c19a155c65fd41865562fe4e678ef32728510bDevang Patel write(Lines[i]); 22716c19a155c65fd41865562fe4e678ef32728510bDevang Patel } 228b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 22936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines GCOVLines(StringRef F, raw_ostream *os) 23016c19a155c65fd41865562fe4e678ef32728510bDevang Patel : Filename(F) { 231b1928704201034c785a26296a49f69355eb56a05Nick Lewycky this->os = os; 232b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 233b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 234680018ff8965610b3f1c976b0be1dfd45116b218Devang Patel private: 23516c19a155c65fd41865562fe4e678ef32728510bDevang Patel StringRef Filename; 2361790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky SmallVector<uint32_t, 32> Lines; 237b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 238b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 239c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky 240b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Represent a basic block in GCOV. Each block has a unique number in the 241b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // function, number of lines belonging to each block, and a set of edges to 242b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // other blocks. 243b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVBlock : public GCOVRecord { 244b1928704201034c785a26296a49f69355eb56a05Nick Lewycky public: 24568155d31cd0175be89e26ee68387cb411fca537bDevang Patel GCOVLines &getFile(StringRef Filename) { 2461790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GCOVLines *&Lines = LinesByFile[Filename]; 2471790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky if (!Lines) { 24816c19a155c65fd41865562fe4e678ef32728510bDevang Patel Lines = new GCOVLines(Filename, os); 249b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 2501790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return *Lines; 251b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 252b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 2531790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky void addEdge(GCOVBlock &Successor) { 2541790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky OutEdges.push_back(&Successor); 255b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 256b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 2571790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky void writeOut() { 2581790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky uint32_t Len = 3; 259c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky SmallVector<StringMapEntry<GCOVLines *> *, 32> SortedLinesByFile; 2601790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky for (StringMap<GCOVLines *>::iterator I = LinesByFile.begin(), 2611790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky E = LinesByFile.end(); I != E; ++I) { 26216c19a155c65fd41865562fe4e678ef32728510bDevang Patel Len += I->second->length(); 263c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky SortedLinesByFile.push_back(&*I); 264b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 265b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 2661790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky writeBytes(LinesTag, 4); 2671790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(Len); 2681790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(Number); 269c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky 27036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::sort(SortedLinesByFile.begin(), SortedLinesByFile.end(), 27136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines [](StringMapEntry<GCOVLines *> *LHS, 27236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines StringMapEntry<GCOVLines *> *RHS) { 27336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return LHS->getKey() < RHS->getKey(); 27436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines }); 2756227d5c690504c7ada5780c00a635b282c46e275Craig Topper for (SmallVectorImpl<StringMapEntry<GCOVLines *> *>::iterator 276c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky I = SortedLinesByFile.begin(), E = SortedLinesByFile.end(); 27736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines I != E; ++I) 278c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky (*I)->getValue()->writeOut(); 2791790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(0); 2801790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(0); 281b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 282b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 283b1928704201034c785a26296a49f69355eb56a05Nick Lewycky ~GCOVBlock() { 2841790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky DeleteContainerSeconds(LinesByFile); 285b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 286b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 287ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines GCOVBlock(const GCOVBlock &RHS) : GCOVRecord(RHS), Number(RHS.Number) { 288ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // Only allow copy before edges and lines have been added. After that, 289ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // there are inter-block pointers (eg: edges) that won't take kindly to 290ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines // blocks being copied or moved around. 291ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines assert(LinesByFile.empty()); 292ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines assert(OutEdges.empty()); 293ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines } 294ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 295b1928704201034c785a26296a49f69355eb56a05Nick Lewycky private: 296b1928704201034c785a26296a49f69355eb56a05Nick Lewycky friend class GCOVFunction; 297b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 2981790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GCOVBlock(uint32_t Number, raw_ostream *os) 2991790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky : Number(Number) { 300b1928704201034c785a26296a49f69355eb56a05Nick Lewycky this->os = os; 301b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 302b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 3031790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky uint32_t Number; 3041790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky StringMap<GCOVLines *> LinesByFile; 3051790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky SmallVector<GCOVBlock *, 4> OutEdges; 306b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 307b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 308b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // A function has a unique identifier, a checksum (we leave as zero) and a 309b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // set of blocks and a map of edges between blocks. This is the only GCOV 310b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // object users can construct, the blocks and lines will be rooted here. 311b1928704201034c785a26296a49f69355eb56a05Nick Lewycky class GCOVFunction : public GCOVRecord { 312b1928704201034c785a26296a49f69355eb56a05Nick Lewycky public: 313cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar GCOVFunction(const DISubprogram *SP, Function *F, raw_ostream *os, 314cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar uint32_t Ident, bool UseCfgChecksum, bool ExitBlockBeforeBody) 315ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines : SP(SP), Ident(Ident), UseCfgChecksum(UseCfgChecksum), CfgChecksum(0), 316ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines ReturnBlock(1, os) { 317b1928704201034c785a26296a49f69355eb56a05Nick Lewycky this->os = os; 318b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 31936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines DEBUG(dbgs() << "Function: " << getFunctionName(SP) << "\n"); 320ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 321b1928704201034c785a26296a49f69355eb56a05Nick Lewycky uint32_t i = 0; 322ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines for (auto &BB : *F) { 3234c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar // Skip index 1 if it's assigned to the ReturnBlock. 3244c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (i == 1 && ExitBlockBeforeBody) 3254c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ++i; 3264c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Blocks.insert(std::make_pair(&BB, GCOVBlock(i++, os))); 327b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 3284c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (!ExitBlockBeforeBody) 3294c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar ReturnBlock.Number = i; 3301790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 33136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::string FunctionNameAndLine; 33236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines raw_string_ostream FNLOS(FunctionNameAndLine); 3330c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar FNLOS << getFunctionName(SP) << SP->getLine(); 33436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines FNLOS.flush(); 33536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines FuncChecksum = hash_value(FunctionNameAndLine); 336b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 337b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 3381790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GCOVBlock &getBlock(BasicBlock *BB) { 339ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return Blocks.find(BB)->second; 340b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 341b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 3421790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GCOVBlock &getReturnBlock() { 343ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines return ReturnBlock; 344a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky } 345a4c4c0e1298f4dd9791eff2bae857e7be6d0ab56Nick Lewycky 34636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::string getEdgeDestinations() { 34736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::string EdgeDestinations; 34836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines raw_string_ostream EDOS(EdgeDestinations); 34936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Function *F = Blocks.begin()->first->getParent(); 350cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar for (BasicBlock &I : *F) { 351cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar GCOVBlock &Block = getBlock(&I); 35236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines for (int i = 0, e = Block.OutEdges.size(); i != e; ++i) 35336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines EDOS << Block.OutEdges[i]->Number; 35436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 35536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return EdgeDestinations; 35636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 35736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 35836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t getFuncChecksum() { 35936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines return FuncChecksum; 36036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 36136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 36236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void setCfgChecksum(uint32_t Checksum) { 36336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines CfgChecksum = Checksum; 36436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 36536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 3661790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky void writeOut() { 36736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines writeBytes(FunctionTag, 4); 36836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t BlockLen = 1 + 1 + 1 + lengthOfGCOVString(getFunctionName(SP)) + 3690c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar 1 + lengthOfGCOVString(SP->getFilename()) + 1; 37036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (UseCfgChecksum) 37136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ++BlockLen; 37236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines write(BlockLen); 37336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines write(Ident); 37436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines write(FuncChecksum); 37536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (UseCfgChecksum) 37636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines write(CfgChecksum); 37736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines writeGCOVString(getFunctionName(SP)); 3780c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar writeGCOVString(SP->getFilename()); 3790c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar write(SP->getLine()); 38036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 381b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Emit count of blocks. 3821790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky writeBytes(BlockTag, 4); 3831790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(Blocks.size() + 1); 3841790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky for (int i = 0, e = Blocks.size() + 1; i != e; ++i) { 3851790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(0); // No flags on our blocks. 386b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 387bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky DEBUG(dbgs() << Blocks.size() << " blocks.\n"); 388b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 389b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Emit edges between blocks. 390c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky if (Blocks.empty()) return; 391c4e6b540f05932eea37ca10b6c1fded522777954Nick Lewycky Function *F = Blocks.begin()->first->getParent(); 392cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar for (BasicBlock &I : *F) { 393cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar GCOVBlock &Block = getBlock(&I); 3941790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky if (Block.OutEdges.empty()) continue; 3951790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 3961790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky writeBytes(EdgeTag, 4); 3971790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(Block.OutEdges.size() * 2 + 1); 3981790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(Block.Number); 3991790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky for (int i = 0, e = Block.OutEdges.size(); i != e; ++i) { 400bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky DEBUG(dbgs() << Block.Number << " -> " << Block.OutEdges[i]->Number 401bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky << "\n"); 4021790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(Block.OutEdges[i]->Number); 4031790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky write(0); // no flags 404b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 405b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 406b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 407b1928704201034c785a26296a49f69355eb56a05Nick Lewycky // Emit lines for each block. 408cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar for (BasicBlock &I : *F) 409cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar getBlock(&I).writeOut(); 410b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 411b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 412b1928704201034c785a26296a49f69355eb56a05Nick Lewycky private: 4136948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar const DISubprogram *SP; 41436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t Ident; 41536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t FuncChecksum; 41636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool UseCfgChecksum; 41736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t CfgChecksum; 418ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines DenseMap<BasicBlock *, GCOVBlock> Blocks; 419ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines GCOVBlock ReturnBlock; 420b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 421b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 422b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 4236948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainarstd::string GCOVProfiler::mangleName(const DICompileUnit *CU, 4246948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar const char *NewStem) { 425269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky if (NamedMDNode *GCov = M->getNamedMetadata("llvm.gcov")) { 426269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky for (int i = 0, e = GCov->getNumOperands(); i != e; ++i) { 427269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky MDNode *N = GCov->getOperand(i); 428269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky if (N->getNumOperands() != 2) continue; 429fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky MDString *GCovFile = dyn_cast<MDString>(N->getOperand(0)); 430269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky MDNode *CompileUnit = dyn_cast<MDNode>(N->getOperand(1)); 431fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky if (!GCovFile || !CompileUnit) continue; 432fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky if (CompileUnit == CU) { 4336e5190c193f6267893daf6943af88e95039e739cBill Wendling SmallString<128> Filename = GCovFile->getString(); 4346e5190c193f6267893daf6943af88e95039e739cBill Wendling sys::path::replace_extension(Filename, NewStem); 4356e5190c193f6267893daf6943af88e95039e739cBill Wendling return Filename.str(); 436fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky } 437269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky } 438269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky } 439fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky 4400c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar SmallString<128> Filename = CU->getFilename(); 441fcf74ed5a2bc10570dec2084a2db1f6580b1210dNick Lewycky sys::path::replace_extension(Filename, NewStem); 44239c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling StringRef FName = sys::path::filename(Filename); 44339c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling SmallString<128> CurPath; 44439c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling if (sys::fs::current_path(CurPath)) return FName; 4450c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar sys::path::append(CurPath, FName); 44639c41c3c93e0d223792acb093adce21a714b01c6Bill Wendling return CurPath.str(); 447269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky} 448269687fa350c1aa044bc063c64362a04ecabaa33Nick Lewycky 4490c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewyckybool GCOVProfiler::runOnModule(Module &M) { 4501790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky this->M = &M; 4510c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky Ctx = &M.getContext(); 4520c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky 453cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar FnMap.clear(); 454cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar for (Function &F : M) { 455cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar if (DISubprogram *SP = F.getSubprogram()) 456cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar FnMap[SP] = &F; 457cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar } 458cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 459a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky if (Options.EmitNotes) emitProfileNotes(); 460a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky if (Options.EmitData) return emitProfileArcs(); 461a61e52c9b7cf874b46cef687c1c4627a35952542Nick Lewycky return false; 4620c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky} 4630c4de8a4eb5fd6437b571611794ef84427fc4755Nick Lewycky 464dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic bool functionHasLines(Function *F) { 465dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // Check whether this function actually has any source lines. Not only 466dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // do these waste space, they also can crash gcov. 467dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 468dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines for (BasicBlock::iterator I = BB->begin(), IE = BB->end(); 469dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines I != IE; ++I) { 470c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // Debug intrinsic locations correspond to the location of the 471c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // declaration, not necessarily any statements or expressions. 472c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (isa<DbgInfoIntrinsic>(I)) continue; 473c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 474dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines const DebugLoc &Loc = I->getDebugLoc(); 4750c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar if (!Loc) 4760c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar continue; 477c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 478c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // Artificial lines such as calls to the global constructors. 4794c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar if (Loc.getLine() == 0) continue; 480c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 481c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines return true; 482dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 483dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 484dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return false; 485dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines} 486dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 48764a0a33307723957bf2f15e3181a290853c6f833Nick Lewyckyvoid GCOVProfiler::emitProfileNotes() { 488f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); 489bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky if (!CU_Nodes) return; 490bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 491bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { 492bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky // Each compile unit gets its own .gcno file. This means that whether we run 493bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky // this pass over the original .o's as they're produced, or run it after 494bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky // LTO, we'll generate the same .gcno files. 495bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 4966948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(i)); 49737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines std::error_code EC; 49837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines raw_fd_ostream out(mangleName(CU, "gcno"), EC, sys::fs::F_None); 49936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::string EdgeDestinations; 500bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 50137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines unsigned FunctionIdent = 0; 5020c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar for (auto *SP : CU->getSubprograms()) { 503cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar Function *F = FnMap[SP]; 504bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky if (!F) continue; 505dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!functionHasLines(F)) continue; 50636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 50736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // gcov expects every function to start with an entry block that has a 50836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // single successor, so split the entry block to make sure of that. 50936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines BasicBlock &EntryBlock = F->getEntryBlock(); 51036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines BasicBlock::iterator It = EntryBlock.begin(); 51136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines while (isa<AllocaInst>(*It) || isa<DbgInfoIntrinsic>(*It)) 51236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ++It; 51336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines EntryBlock.splitBasicBlock(It); 51436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 515cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar Funcs.push_back(make_unique<GCOVFunction>(SP, F, &out, FunctionIdent++, 5164c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Options.UseCfgChecksum, 5174c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar Options.ExitBlockBeforeBody)); 518dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines GCOVFunction &Func = *Funcs.back(); 519bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 520bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 521cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar GCOVBlock &Block = Func.getBlock(&*BB); 522bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky TerminatorInst *TI = BB->getTerminator(); 523bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky if (int successors = TI->getNumSuccessors()) { 524bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky for (int i = 0; i != successors; ++i) { 525dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Block.addEdge(Func.getBlock(TI->getSuccessor(i))); 526f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 527bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky } else if (isa<ReturnInst>(TI)) { 528dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Block.addEdge(Func.getReturnBlock()); 529bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky } 530bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 531bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky uint32_t Line = 0; 532bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky for (BasicBlock::iterator I = BB->begin(), IE = BB->end(); 533bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky I != IE; ++I) { 534c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // Debug intrinsic locations correspond to the location of the 535c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // declaration, not necessarily any statements or expressions. 536c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (isa<DbgInfoIntrinsic>(I)) continue; 537c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 538bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky const DebugLoc &Loc = I->getDebugLoc(); 5390c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar if (!Loc) 5400c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar continue; 541c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 542c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines // Artificial lines such as calls to the global constructors. 543c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines if (Loc.getLine() == 0) continue; 544c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines 545bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky if (Line == Loc.getLine()) continue; 546bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky Line = Loc.getLine(); 5470c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar if (SP != getDISubprogram(Loc.getScope())) 5480c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar continue; 549bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky 5500c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar GCOVLines &Lines = Block.getFile(SP->getFilename()); 551bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky Lines.addLine(Loc.getLine()); 552b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 553b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 554dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines EdgeDestinations += Func.getEdgeDestinations(); 555b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 55636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 55736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines FileChecksums.push_back(hash_value(EdgeDestinations)); 55836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines out.write("oncg", 4); 55936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines out.write(ReversedVersion, 4); 56036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines out.write(reinterpret_cast<char*>(&FileChecksums.back()), 4); 56136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 562dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines for (auto &Func : Funcs) { 56336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Func->setCfgChecksum(FileChecksums.back()); 56436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Func->writeOut(); 56536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 56636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 567bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky out.write("\0\0\0\0\0\0\0\0", 8); // EOF 568bba40db07234cef7867b45c67f50632e684cbb15Nick Lewycky out.close(); 569b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 570b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 571b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 572f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patelbool GCOVProfiler::emitProfileArcs() { 573f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); 574f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (!CU_Nodes) return false; 575f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel 57636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines bool Result = false; 57777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling bool InsertIndCounterIncrCode = false; 578f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { 5796948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(i)); 580f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> CountersBySP; 5810c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar for (auto *SP : CU->getSubprograms()) { 582cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar Function *F = FnMap[SP]; 583f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (!F) continue; 584dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!functionHasLines(F)) continue; 585f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (!Result) Result = true; 586f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel unsigned Edges = 0; 587f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 588f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel TerminatorInst *TI = BB->getTerminator(); 589f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (isa<ReturnInst>(TI)) 590f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel ++Edges; 591f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel else 592f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Edges += TI->getNumSuccessors(); 593f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 59436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 595f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel ArrayType *CounterTy = 5961790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky ArrayType::get(Type::getInt64Ty(*Ctx), Edges); 597f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel GlobalVariable *Counters = 5981790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky new GlobalVariable(*M, CounterTy, false, 599b1928704201034c785a26296a49f69355eb56a05Nick Lewycky GlobalValue::InternalLinkage, 6001790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky Constant::getNullValue(CounterTy), 601ce718ff9f42c7da092eaa01dd0242e8d5ba84713Hans Wennborg "__llvm_gcov_ctr"); 6020c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar CountersBySP.push_back(std::make_pair(Counters, SP)); 60336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 604f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel UniqueVector<BasicBlock *> ComplexEdgePreds; 605f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel UniqueVector<BasicBlock *> ComplexEdgeSuccs; 60636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 607f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel unsigned Edge = 0; 608f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 609f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel TerminatorInst *TI = BB->getTerminator(); 610f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors(); 611f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (Successors) { 612f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (Successors == 1) { 613cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar IRBuilder<> Builder(&*BB->getFirstInsertionPt()); 614f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0, 615f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Edge); 616f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Value *Count = Builder.CreateLoad(Counter); 617bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Count = Builder.CreateAdd(Count, Builder.getInt64(1)); 618f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Builder.CreateStore(Count, Counter); 619f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } else if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { 620f675b3c6444af3e2f547b050eedb8a12584110efBill Wendling IRBuilder<> Builder(BI); 621bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Value *Sel = Builder.CreateSelect(BI->getCondition(), 622bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Builder.getInt64(Edge), 623bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Builder.getInt64(Edge + 1)); 624f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel SmallVector<Value *, 2> Idx; 625bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Idx.push_back(Builder.getInt64(0)); 626f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Idx.push_back(Sel); 6270c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar Value *Counter = Builder.CreateInBoundsGEP(Counters->getValueType(), 6280c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar Counters, Idx); 629f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Value *Count = Builder.CreateLoad(Counter); 630bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Count = Builder.CreateAdd(Count, Builder.getInt64(1)); 631f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Builder.CreateStore(Count, Counter); 632f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } else { 633cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar ComplexEdgePreds.insert(&*BB); 634f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel for (int i = 0; i != Successors; ++i) 635f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel ComplexEdgeSuccs.insert(TI->getSuccessor(i)); 636f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 637f675b3c6444af3e2f547b050eedb8a12584110efBill Wendling 638f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Edge += Successors; 639b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 640b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 64136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 642f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (!ComplexEdgePreds.empty()) { 643f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel GlobalVariable *EdgeTable = 6441790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky buildEdgeLookupTable(F, Counters, 6451790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky ComplexEdgePreds, ComplexEdgeSuccs); 646f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel GlobalVariable *EdgeState = getEdgeStateValue(); 64736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 648f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) { 649cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar IRBuilder<> Builder(&*ComplexEdgePreds[i + 1]->getFirstInsertionPt()); 650bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Builder.CreateStore(Builder.getInt32(i), EdgeState); 651f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 652f675b3c6444af3e2f547b050eedb8a12584110efBill Wendling 653f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) { 654f675b3c6444af3e2f547b050eedb8a12584110efBill Wendling // Call runtime to perform increment. 655cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar IRBuilder<> Builder(&*ComplexEdgeSuccs[i + 1]->getFirstInsertionPt()); 656f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel Value *CounterPtrArray = 6571790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0, 6581790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky i * ComplexEdgePreds.size()); 659c7a884040e4ec7795515978a94803894ad08c4caBill Wendling 660c7a884040e4ec7795515978a94803894ad08c4caBill Wendling // Build code to increment the counter. 66177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling InsertIndCounterIncrCode = true; 6626948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall(getIncrementIndirectCounterFunc(), 6636948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {EdgeState, CounterPtrArray}); 664f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 665b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 666b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 6674a8fefaf8303f30514bc2a40d840a1709dae65cfBill Wendling 668d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling Function *WriteoutF = insertCounterWriteout(CountersBySP); 669d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling Function *FlushF = insertFlush(CountersBySP); 670d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 671d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling // Create a small bit of code that registers the "__llvm_gcov_writeout" to 67218764716861243c58a711a92190624dc2f6aafc9Bill Wendling // be executed at exit and the "__llvm_gcov_flush" function to be executed 67318764716861243c58a711a92190624dc2f6aafc9Bill Wendling // when "__gcov_flush" is called. 674d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 675d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling Function *F = Function::Create(FTy, GlobalValue::InternalLinkage, 676d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling "__llvm_gcov_init", M); 677d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling F->setUnnamedAddr(true); 678d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling F->setLinkage(GlobalValue::InternalLinkage); 679d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling F->addFnAttr(Attribute::NoInline); 680d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling if (Options.NoRedZone) 681d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling F->addFnAttr(Attribute::NoRedZone); 682d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 683d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F); 684d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling IRBuilder<> Builder(BB); 685d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 686d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 6878640c6a5227b75666e02424e2181289692138348Bill Wendling Type *Params[] = { 6888640c6a5227b75666e02424e2181289692138348Bill Wendling PointerType::get(FTy, 0), 6898640c6a5227b75666e02424e2181289692138348Bill Wendling PointerType::get(FTy, 0) 6908640c6a5227b75666e02424e2181289692138348Bill Wendling }; 6918640c6a5227b75666e02424e2181289692138348Bill Wendling FTy = FunctionType::get(Builder.getVoidTy(), Params, false); 6928640c6a5227b75666e02424e2181289692138348Bill Wendling 693d7da59004fc9262f33c96ad2736b36ff1235ce7bYuchen Wu // Initialize the environment and register the local writeout and flush 6948640c6a5227b75666e02424e2181289692138348Bill Wendling // functions. 6958640c6a5227b75666e02424e2181289692138348Bill Wendling Constant *GCOVInit = M->getOrInsertFunction("llvm_gcov_init", FTy); 6966948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall(GCOVInit, {WriteoutF, FlushF}); 697d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling Builder.CreateRetVoid(); 698d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 699d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling appendToGlobalCtors(*M, F, 0); 700b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 70177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 70277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling if (InsertIndCounterIncrCode) 70377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling insertIndirectCounterIncrement(); 70477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 705f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel return Result; 706b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 707b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 7081790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky// All edges with successors that aren't branches are "complex", because it 7091790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky// requires complex logic to pick which counter to update. 7101790c9cbb6714e81eab1412909a2320acaecc43bNick LewyckyGlobalVariable *GCOVProfiler::buildEdgeLookupTable( 7111790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky Function *F, 7121790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GlobalVariable *Counters, 7131790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky const UniqueVector<BasicBlock *> &Preds, 7141790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky const UniqueVector<BasicBlock *> &Succs) { 7151790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky // TODO: support invoke, threads. We rely on the fact that nothing can modify 7161790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky // the whole-Module pred edge# between the time we set it and the time we next 7171790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky // read it. Threads and invoke make this untrue. 7181790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 7191790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky // emit [(succs * preds) x i64*], logically [succ x [pred x i64*]]. 7209e6ee16b1814268897965b81e82a74ef39173ee1Benjamin Kramer size_t TableSize = Succs.size() * Preds.size(); 721db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner Type *Int64PtrTy = Type::getInt64PtrTy(*Ctx); 7229e6ee16b1814268897965b81e82a74ef39173ee1Benjamin Kramer ArrayType *EdgeTableTy = ArrayType::get(Int64PtrTy, TableSize); 7231790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 72436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::unique_ptr<Constant * []> EdgeTable(new Constant *[TableSize]); 7251790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky Constant *NullValue = Constant::getNullValue(Int64PtrTy); 7269e6ee16b1814268897965b81e82a74ef39173ee1Benjamin Kramer for (size_t i = 0; i != TableSize; ++i) 7271790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky EdgeTable[i] = NullValue; 7281790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 7291790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky unsigned Edge = 0; 7301790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 7311790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky TerminatorInst *TI = BB->getTerminator(); 7321790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors(); 7337a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efeNick Lewycky if (Successors > 1 && !isa<BranchInst>(TI) && !isa<ReturnInst>(TI)) { 7341790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky for (int i = 0; i != Successors; ++i) { 7351790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky BasicBlock *Succ = TI->getSuccessor(i); 736bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky IRBuilder<> Builder(Succ); 737bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0, 7381790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky Edge + i); 739cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar EdgeTable[((Succs.idFor(Succ) - 1) * Preds.size()) + 740cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar (Preds.idFor(&*BB) - 1)] = cast<Constant>(Counter); 7411790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 7421790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 7431790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky Edge += Successors; 7441790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 7451790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 7461790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GlobalVariable *EdgeTableGV = 7471790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky new GlobalVariable( 7481790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky *M, EdgeTableTy, true, GlobalValue::InternalLinkage, 74937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ConstantArray::get(EdgeTableTy, 75037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines makeArrayRef(&EdgeTable[0],TableSize)), 7511790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky "__llvm_gcda_edge_table"); 7521790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky EdgeTableGV->setUnnamedAddr(true); 7531790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return EdgeTableGV; 7541790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky} 7551790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 756b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getStartFileFunc() { 757d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky Type *Args[] = { 758d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky Type::getInt8PtrTy(*Ctx), // const char *orig_filename 759d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky Type::getInt8PtrTy(*Ctx), // const char version[4] 76036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Type::getInt32Ty(*Ctx), // uint32_t checksum 761d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky }; 762d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false); 7631790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return M->getOrInsertFunction("llvm_gcda_start_file", FTy); 7641790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky} 7651790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 76677b19134104c3e96424dc010f2b69c3faf580e68Bill WendlingConstant *GCOVProfiler::getIncrementIndirectCounterFunc() { 76777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Type *Int32Ty = Type::getInt32Ty(*Ctx); 768c7a884040e4ec7795515978a94803894ad08c4caBill Wendling Type *Int64Ty = Type::getInt64Ty(*Ctx); 76977b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Type *Args[] = { 770b8bce928f4ffdf50eff69334f3e25b27848536b6Micah Villmow Int32Ty->getPointerTo(), // uint32_t *predecessor 771b8bce928f4ffdf50eff69334f3e25b27848536b6Micah Villmow Int64Ty->getPointerTo()->getPointerTo() // uint64_t **counters 77277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling }; 77377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false); 77477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling return M->getOrInsertFunction("__llvm_gcov_indirect_counter_increment", FTy); 775b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 776b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 777b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getEmitFunctionFunc() { 77836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Type *Args[] = { 7795409a188328d9de3755febc23558d4fc1797d04eNick Lewycky Type::getInt32Ty(*Ctx), // uint32_t ident 7805409a188328d9de3755febc23558d4fc1797d04eNick Lewycky Type::getInt8PtrTy(*Ctx), // const char *function_name 78136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Type::getInt32Ty(*Ctx), // uint32_t func_checksum 78217d2f776011cba33f7f5afb03c8066d35dbf8afcNick Lewycky Type::getInt8Ty(*Ctx), // uint8_t use_extra_checksum 78336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Type::getInt32Ty(*Ctx), // uint32_t cfg_checksum 7845409a188328d9de3755febc23558d4fc1797d04eNick Lewycky }; 785c7a884040e4ec7795515978a94803894ad08c4caBill Wendling FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false); 7861790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return M->getOrInsertFunction("llvm_gcda_emit_function", FTy); 787b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 788b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 789b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getEmitArcsFunc() { 7905fdd6c8793462549e3593890ec61573da06e3346Jay Foad Type *Args[] = { 791b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Type::getInt32Ty(*Ctx), // uint32_t num_counters 792b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Type::getInt64PtrTy(*Ctx), // uint64_t *counters 793b1928704201034c785a26296a49f69355eb56a05Nick Lewycky }; 794d9686a98b8145010516c44a3a5b9b96bf934b9acNick Lewycky FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false); 7951790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy); 796b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 797b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 798f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen WuConstant *GCOVProfiler::getSummaryInfoFunc() { 799f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 800f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu return M->getOrInsertFunction("llvm_gcda_summary_info", FTy); 801f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu} 802f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu 80318764716861243c58a711a92190624dc2f6aafc9Bill WendlingConstant *GCOVProfiler::getDeleteWriteoutFunctionListFunc() { 80418764716861243c58a711a92190624dc2f6aafc9Bill Wendling FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 80518764716861243c58a711a92190624dc2f6aafc9Bill Wendling return M->getOrInsertFunction("llvm_delete_writeout_function_list", FTy); 80618764716861243c58a711a92190624dc2f6aafc9Bill Wendling} 80718764716861243c58a711a92190624dc2f6aafc9Bill Wendling 808d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill WendlingConstant *GCOVProfiler::getDeleteFlushFunctionListFunc() { 809d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 810d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling return M->getOrInsertFunction("llvm_delete_flush_function_list", FTy); 811d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling} 812d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 813b1928704201034c785a26296a49f69355eb56a05Nick LewyckyConstant *GCOVProfiler::getEndFileFunc() { 814db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 8151790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return M->getOrInsertFunction("llvm_gcda_end_file", FTy); 816b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 817b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 8181790c9cbb6714e81eab1412909a2320acaecc43bNick LewyckyGlobalVariable *GCOVProfiler::getEdgeStateValue() { 8191790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GlobalVariable *GV = M->getGlobalVariable("__llvm_gcov_global_state_pred"); 8201790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky if (!GV) { 8211790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GV = new GlobalVariable(*M, Type::getInt32Ty(*Ctx), false, 8221790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GlobalValue::InternalLinkage, 8231790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky ConstantInt::get(Type::getInt32Ty(*Ctx), 8241790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky 0xffffffff), 8251790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky "__llvm_gcov_global_state_pred"); 8261790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky GV->setUnnamedAddr(true); 8271790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky } 8281790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky return GV; 8291790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky} 830b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 831d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill WendlingFunction *GCOVProfiler::insertCounterWriteout( 83221b742ffce7bec3d71e09c7c6d901a756d55feb3Bill Wendling ArrayRef<std::pair<GlobalVariable *, MDNode *> > CountersBySP) { 833253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling FunctionType *WriteoutFTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 834253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling Function *WriteoutF = M->getFunction("__llvm_gcov_writeout"); 835253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling if (!WriteoutF) 836253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling WriteoutF = Function::Create(WriteoutFTy, GlobalValue::InternalLinkage, 837253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling "__llvm_gcov_writeout", M); 838b1928704201034c785a26296a49f69355eb56a05Nick Lewycky WriteoutF->setUnnamedAddr(true); 839034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling WriteoutF->addFnAttr(Attribute::NoInline); 840a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky if (Options.NoRedZone) 841034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling WriteoutF->addFnAttr(Attribute::NoRedZone); 842253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling 843253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", WriteoutF); 8441790c9cbb6714e81eab1412909a2320acaecc43bNick Lewycky IRBuilder<> Builder(BB); 845b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 846b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *StartFile = getStartFileFunc(); 847b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *EmitFunction = getEmitFunctionFunc(); 848b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *EmitArcs = getEmitArcsFunc(); 849f42264e7e4cb947bcd1ff7dd48fd0ba4e9fbbf9fYuchen Wu Constant *SummaryInfo = getSummaryInfoFunc(); 850b1928704201034c785a26296a49f69355eb56a05Nick Lewycky Constant *EndFile = getEndFileFunc(); 851b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 852f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); 853f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel if (CU_Nodes) { 854f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { 8556948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(i)); 856f2a2806baf3763d551a9f361124b608b2eed66faBill Wendling std::string FilenameGcda = mangleName(CU, "gcda"); 85736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t CfgChecksum = FileChecksums.empty() ? 0 : FileChecksums[i]; 8586948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall(StartFile, 8596948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {Builder.CreateGlobalStringPtr(FilenameGcda), 86036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Builder.CreateGlobalStringPtr(ReversedVersion), 8616948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.getInt32(CfgChecksum)}); 8628fa6dc431deb7a9aadc23ec0a7bdcb2d02330972Nick Lewycky for (unsigned j = 0, e = CountersBySP.size(); j != e; ++j) { 8636948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar auto *SP = cast_or_null<DISubprogram>(CountersBySP[j].second); 86436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines uint32_t FuncChecksum = Funcs.empty() ? 0 : Funcs[j]->getFuncChecksum(); 8656948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall( 8666948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar EmitFunction, 8676948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar {Builder.getInt32(j), 8686948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Options.FunctionNamesInData 8696948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar ? Builder.CreateGlobalStringPtr(getFunctionName(SP)) 8706948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar : Constant::getNullValue(Builder.getInt8PtrTy()), 8716948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.getInt32(FuncChecksum), 8726948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.getInt8(Options.UseCfgChecksum), 8736948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.getInt32(CfgChecksum)}); 87417d2f776011cba33f7f5afb03c8066d35dbf8afcNick Lewycky 8758fa6dc431deb7a9aadc23ec0a7bdcb2d02330972Nick Lewycky GlobalVariable *GV = CountersBySP[j].first; 876f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel unsigned Arcs = 877b1928704201034c785a26296a49f69355eb56a05Nick Lewycky cast<ArrayType>(GV->getType()->getElementType())->getNumElements(); 8786948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall(EmitArcs, {Builder.getInt32(Arcs), 8796948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateConstGEP2_64(GV, 0, 0)}); 880f6d3a4c7c4d14ad7a4e07e9f80f94f73651960d8Devang Patel } 8816948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall(SummaryInfo, {}); 8826948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall(EndFile, {}); 883b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 884b1928704201034c785a26296a49f69355eb56a05Nick Lewycky } 885b1928704201034c785a26296a49f69355eb56a05Nick Lewycky 8864a8fefaf8303f30514bc2a40d840a1709dae65cfBill Wendling Builder.CreateRetVoid(); 887d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling return WriteoutF; 888b1928704201034c785a26296a49f69355eb56a05Nick Lewycky} 88977b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 89077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendlingvoid GCOVProfiler::insertIndirectCounterIncrement() { 89177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Function *Fn = 89277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling cast<Function>(GCOVProfiler::getIncrementIndirectCounterFunc()); 89377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Fn->setUnnamedAddr(true); 89477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Fn->setLinkage(GlobalValue::InternalLinkage); 895034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling Fn->addFnAttr(Attribute::NoInline); 896a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky if (Options.NoRedZone) 897034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling Fn->addFnAttr(Attribute::NoRedZone); 89877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 89977b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling // Create basic blocks for function. 90077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", Fn); 90177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling IRBuilder<> Builder(BB); 90277b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 90377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling BasicBlock *PredNotNegOne = BasicBlock::Create(*Ctx, "", Fn); 90477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling BasicBlock *CounterEnd = BasicBlock::Create(*Ctx, "", Fn); 90577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling BasicBlock *Exit = BasicBlock::Create(*Ctx, "exit", Fn); 90677b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 90777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling // uint32_t pred = *predecessor; 90877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling // if (pred == 0xffffffff) return; 909cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar Argument *Arg = &*Fn->arg_begin(); 91077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Arg->setName("predecessor"); 91177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Value *Pred = Builder.CreateLoad(Arg, "pred"); 912bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Value *Cond = Builder.CreateICmpEQ(Pred, Builder.getInt32(0xffffffff)); 91377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling BranchInst::Create(Exit, PredNotNegOne, Cond, BB); 91477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 91577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Builder.SetInsertPoint(PredNotNegOne); 91677b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 91777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling // uint64_t *counter = counters[pred]; 91877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling // if (!counter) return; 919bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Value *ZExtPred = Builder.CreateZExt(Pred, Builder.getInt64Ty()); 920cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar Arg = &*std::next(Fn->arg_begin()); 92177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Arg->setName("counters"); 9220c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar Value *GEP = Builder.CreateGEP(Type::getInt64PtrTy(*Ctx), Arg, ZExtPred); 92377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Value *Counter = Builder.CreateLoad(GEP, "counter"); 92458591b1647e0f1f213e5acd7bfa87c226ced0033Nick Lewycky Cond = Builder.CreateICmpEQ(Counter, 92558591b1647e0f1f213e5acd7bfa87c226ced0033Nick Lewycky Constant::getNullValue( 92658591b1647e0f1f213e5acd7bfa87c226ced0033Nick Lewycky Builder.getInt64Ty()->getPointerTo())); 92777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Builder.CreateCondBr(Cond, Exit, CounterEnd); 92877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 92977b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling // ++*counter; 93077b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Builder.SetInsertPoint(CounterEnd); 93177b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Value *Add = Builder.CreateAdd(Builder.CreateLoad(Counter), 932bd2d1245e7db11b58b52c5b36fe76925683aaea5Nick Lewycky Builder.getInt64(1)); 93377b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Builder.CreateStore(Add, Counter); 93477b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Builder.CreateBr(Exit); 93577b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling 93677b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling // Fill in the exit block. 93777b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Builder.SetInsertPoint(Exit); 93877b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling Builder.CreateRetVoid(); 93977b19134104c3e96424dc010f2b69c3faf580e68Bill Wendling} 940253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling 941d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill WendlingFunction *GCOVProfiler:: 942253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill WendlinginsertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) { 943253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 944d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling Function *FlushF = M->getFunction("__llvm_gcov_flush"); 945253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling if (!FlushF) 946253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling FlushF = Function::Create(FTy, GlobalValue::InternalLinkage, 947d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling "__llvm_gcov_flush", M); 948253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling else 949253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling FlushF->setLinkage(GlobalValue::InternalLinkage); 950253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling FlushF->setUnnamedAddr(true); 951034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling FlushF->addFnAttr(Attribute::NoInline); 952a204ef3168c8804808c716115ba915c89d8849b9Nick Lewycky if (Options.NoRedZone) 953034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling FlushF->addFnAttr(Attribute::NoRedZone); 954253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling 955253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", FlushF); 956253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling 957253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling // Write out the current counters. 958253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling Constant *WriteoutF = M->getFunction("__llvm_gcov_writeout"); 959253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling assert(WriteoutF && "Need to create the writeout function first!"); 960253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling 961253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling IRBuilder<> Builder(Entry); 9626948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar Builder.CreateCall(WriteoutF, {}); 963253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling 964032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling // Zero out the counters. 965032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling for (ArrayRef<std::pair<GlobalVariable *, MDNode *> >::iterator 966032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling I = CountersBySP.begin(), E = CountersBySP.end(); 967032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling I != E; ++I) { 968032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling GlobalVariable *GV = I->first; 969032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling Constant *Null = Constant::getNullValue(GV->getType()->getElementType()); 970ec3fc2eac0e9203dd1094b9ce458e8c1b42b832fBill Wendling Builder.CreateStore(Null, GV); 971032dbee2a9d401ee05beb648465f21168e279bdaBill Wendling } 972253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling 973253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling Type *RetTy = FlushF->getReturnType(); 974253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling if (RetTy == Type::getVoidTy(*Ctx)) 975253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling Builder.CreateRetVoid(); 976253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling else if (RetTy->isIntegerTy()) 977d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling // Used if __llvm_gcov_flush was implicitly declared. 978253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling Builder.CreateRet(ConstantInt::get(RetTy, 0)); 979253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling else 980d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling report_fatal_error("invalid return type for __llvm_gcov_flush"); 981d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling 982d195eb6b83c2f3c70c9d1a59e26e8d6d2a3d38d3Bill Wendling return FlushF; 983253353c9cf1ff16d9c30a89c2fb96160ac5a9d65Bill Wendling} 984