45 #define DEBUG_TYPE "insert-gcov-profiling"
76 GCOVProfiler() : GCOVProfiler(
GCOVOptions::getDefault()) {}
78 assert((Options.EmitNotes || Options.EmitData) &&
79 "GCOVProfiler asked to do nothing?");
80 ReversedVersion[0] = Options.Version[3];
81 ReversedVersion[1] = Options.Version[2];
82 ReversedVersion[2] = Options.Version[1];
83 ReversedVersion[3] = Options.Version[0];
84 ReversedVersion[4] =
'\0';
87 const char *getPassName()
const override {
88 return "GCOV Profiler";
92 bool runOnModule(
Module &M)
override;
95 void emitProfileNotes();
99 bool emitProfileArcs();
103 Constant *getIncrementIndirectCounterFunc();
107 Constant *getDeleteWriteoutFunctionListFunc();
108 Constant *getDeleteFlushFunctionListFunc();
127 void insertIndirectCounterIncrement();
129 std::string mangleName(
const DICompileUnit *CU,
const char *NewStem);
134 char ReversedVersion[5];
146 "Insert instrumentation for GCOV profiling",
false,
false)
149 return new GCOVProfiler(Options);
153 if (!SP->getLinkageName().empty())
154 return SP->getLinkageName();
161 static const char *
const LinesTag;
162 static const char *
const FunctionTag;
163 static const char *
const BlockTag;
164 static const char *
const EdgeTag;
166 GCOVRecord() =
default;
168 void writeBytes(
const char *Bytes,
int Size) {
169 os->write(Bytes, Size);
172 void write(uint32_t i) {
173 writeBytes(reinterpret_cast<char*>(&i), 4);
178 static unsigned lengthOfGCOVString(
StringRef s) {
182 return (s.
size() / 4) + 1;
186 uint32_t Len = lengthOfGCOVString(s);
191 assert((
unsigned)(4 - (s.
size() % 4)) > 0);
192 assert((
unsigned)(4 - (s.
size() % 4)) <= 4);
193 writeBytes(
"\0\0\0\0", 4 - (s.
size() % 4));
198 const char *
const GCOVRecord::LinesTag =
"\0\0\x45\x01";
199 const char *
const GCOVRecord::FunctionTag =
"\0\0\0\1";
200 const char *
const GCOVRecord::BlockTag =
"\0\0\x41\x01";
201 const char *
const GCOVRecord::EdgeTag =
"\0\0\x43\x01";
209 class GCOVLines :
public GCOVRecord {
211 void addLine(uint32_t Line) {
212 assert(Line != 0 &&
"Line zero is not a valid real line number.");
213 Lines.push_back(Line);
216 uint32_t length()
const {
218 return lengthOfGCOVString(Filename) + 2 + Lines.size();
223 writeGCOVString(Filename);
224 for (
int i = 0, e = Lines.size(); i != e; ++i)
245 GCOVLines *&Lines = LinesByFile[Filename];
247 Lines =
new GCOVLines(Filename, os);
253 OutEdges.push_back(&Successor);
260 E = LinesByFile.end();
I != E; ++
I) {
261 Len +=
I->second->length();
265 writeBytes(LinesTag, 4);
269 std::sort(SortedLinesByFile.
begin(), SortedLinesByFile.
end(),
272 return LHS->
getKey() < RHS->getKey();
275 I = SortedLinesByFile.
begin(), E = SortedLinesByFile.
end();
277 (*I)->getValue()->writeOut();
290 assert(LinesByFile.empty());
291 assert(OutEdges.empty());
313 bool UseCfgChecksum,
bool ExitBlockBeforeBody)
314 : SP(SP), Ident(Ident), UseCfgChecksum(UseCfgChecksum), CfgChecksum(0),
322 for (
auto &BB : *F) {
324 if (i == 1 && ExitBlockBeforeBody)
326 Blocks.insert(std::make_pair(&BB,
GCOVBlock(i++, os)));
328 if (!ExitBlockBeforeBody)
329 ReturnBlock.Number = i;
331 std::string FunctionNameAndLine;
335 FuncChecksum =
hash_value(FunctionNameAndLine);
339 return Blocks.find(BB)->second;
346 std::string getEdgeDestinations() {
347 std::string EdgeDestinations;
349 Function *F = Blocks.begin()->first->getParent();
352 for (
int i = 0, e = Block.OutEdges.size(); i != e; ++i)
353 EDOS << Block.OutEdges[i]->Number;
355 return EdgeDestinations;
358 uint32_t getFuncChecksum() {
362 void setCfgChecksum(uint32_t Checksum) {
363 CfgChecksum = Checksum;
367 writeBytes(FunctionTag, 4);
368 uint32_t BlockLen = 1 + 1 + 1 + lengthOfGCOVString(
getFunctionName(SP)) +
379 write(SP->getLine());
382 writeBytes(BlockTag, 4);
383 write(Blocks.size() + 1);
384 for (
int i = 0, e = Blocks.size() + 1; i != e; ++i) {
387 DEBUG(
dbgs() << Blocks.size() <<
" blocks.\n");
390 if (Blocks.empty())
return;
391 Function *F = Blocks.begin()->first->getParent();
394 if (Block.OutEdges.empty())
continue;
396 writeBytes(EdgeTag, 4);
397 write(Block.OutEdges.size() * 2 + 1);
399 for (
int i = 0, e = Block.OutEdges.size(); i != e; ++i) {
400 DEBUG(
dbgs() << Block.Number <<
" -> " << Block.OutEdges[i]->Number
402 write(Block.OutEdges[i]->Number);
409 getBlock(
I).writeOut();
416 uint32_t FuncChecksum;
418 uint32_t CfgChecksum;
424 std::string GCOVProfiler::mangleName(
const DICompileUnit *CU,
425 const char *NewStem) {
426 if (
NamedMDNode *GCov = M->getNamedMetadata(
"llvm.gcov")) {
427 for (
int i = 0, e = GCov->getNumOperands(); i != e; ++i) {
428 MDNode *
N = GCov->getOperand(i);
432 if (!GCovFile || !CompileUnit)
continue;
433 if (CompileUnit == CU) {
436 return Filename.
str();
447 return CurPath.
str();
450 bool GCOVProfiler::runOnModule(
Module &M) {
454 if (Options.EmitNotes) emitProfileNotes();
455 if (Options.EmitData)
return emitProfileArcs();
467 if (isa<DbgInfoIntrinsic>(
I))
continue;
474 if (Loc.
getLine() == 0)
continue;
482 void GCOVProfiler::emitProfileNotes() {
484 if (!CU_Nodes)
return;
486 for (
unsigned i = 0, e = CU_Nodes->
getNumOperands(); i != e; ++i) {
491 auto *CU = cast<DICompileUnit>(CU_Nodes->
getOperand(i));
494 std::string EdgeDestinations;
496 unsigned FunctionIdent = 0;
506 while (isa<AllocaInst>(*It) || isa<DbgInfoIntrinsic>(*It))
510 Funcs.push_back(make_unique<GCOVFunction>(SP, &out, FunctionIdent++,
511 Options.UseCfgChecksum,
512 Options.ExitBlockBeforeBody));
522 }
else if (isa<ReturnInst>(TI)) {
523 Block.addEdge(Func.getReturnBlock());
531 if (isa<DbgInfoIntrinsic>(
I))
continue;
538 if (Loc.
getLine() == 0)
continue;
540 if (Line == Loc.
getLine())
continue;
545 GCOVLines &Lines = Block.getFile(SP->
getFilename());
549 EdgeDestinations += Func.getEdgeDestinations();
552 FileChecksums.push_back(
hash_value(EdgeDestinations));
553 out.write(
"oncg", 4);
554 out.write(ReversedVersion, 4);
555 out.write(reinterpret_cast<char*>(&FileChecksums.back()), 4);
557 for (
auto &Func : Funcs) {
558 Func->setCfgChecksum(FileChecksums.back());
562 out.write(
"\0\0\0\0\0\0\0\0", 8);
567 bool GCOVProfiler::emitProfileArcs() {
569 if (!CU_Nodes)
return false;
572 bool InsertIndCounterIncrCode =
false;
573 for (
unsigned i = 0, e = CU_Nodes->
getNumOperands(); i != e; ++i) {
574 auto *CU = cast<DICompileUnit>(CU_Nodes->
getOperand(i));
580 if (!Result) Result =
true;
584 if (isa<ReturnInst>(TI))
597 CountersBySP.push_back(std::make_pair(Counters, SP));
607 if (Successors == 1) {
609 Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0,
611 Value *Count = Builder.CreateLoad(Counter);
612 Count = Builder.CreateAdd(Count, Builder.getInt64(1));
613 Builder.CreateStore(Count, Counter);
614 }
else if (
BranchInst *BI = dyn_cast<BranchInst>(TI)) {
616 Value *Sel = Builder.CreateSelect(BI->getCondition(),
617 Builder.getInt64(Edge),
618 Builder.getInt64(Edge + 1));
624 Value *Count = Builder.CreateLoad(Counter);
625 Count = Builder.CreateAdd(Count, Builder.getInt64(1));
626 Builder.CreateStore(Count, Counter);
628 ComplexEdgePreds.
insert(BB);
629 for (
int i = 0; i != Successors; ++i)
637 if (!ComplexEdgePreds.
empty()) {
639 buildEdgeLookupTable(F, Counters,
640 ComplexEdgePreds, ComplexEdgeSuccs);
643 for (
int i = 0, e = ComplexEdgePreds.
size(); i != e; ++i) {
644 IRBuilder<> Builder(ComplexEdgePreds[i + 1]->getFirstInsertionPt());
645 Builder.CreateStore(Builder.getInt32(i), EdgeState);
648 for (
int i = 0, e = ComplexEdgeSuccs.
size(); i != e; ++i) {
650 IRBuilder<> Builder(ComplexEdgeSuccs[i+1]->getFirstInsertionPt());
651 Value *CounterPtrArray =
652 Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0,
653 i * ComplexEdgePreds.
size());
656 InsertIndCounterIncrCode =
true;
657 Builder.CreateCall(getIncrementIndirectCounterFunc(),
658 {EdgeState, CounterPtrArray});
663 Function *WriteoutF = insertCounterWriteout(CountersBySP);
664 Function *FlushF = insertFlush(CountersBySP);
671 "__llvm_gcov_init", M);
675 if (Options.NoRedZone)
691 Builder.CreateCall(GCOVInit, {WriteoutF, FlushF});
692 Builder.CreateRetVoid();
697 if (InsertIndCounterIncrCode)
698 insertIndirectCounterIncrement();
715 size_t TableSize = Succs.
size() * Preds.
size();
719 std::unique_ptr<Constant * []> EdgeTable(
new Constant *[TableSize]);
721 for (
size_t i = 0; i != TableSize; ++i)
722 EdgeTable[i] = NullValue;
728 if (Successors > 1 && !isa<BranchInst>(TI) && !isa<ReturnInst>(TI)) {
729 for (
int i = 0; i != Successors; ++i) {
732 Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0,
734 EdgeTable[((Succs.
idFor(Succ)-1) * Preds.
size()) +
735 (Preds.
idFor(BB)-1)] = cast<Constant>(Counter);
746 "__llvm_gcda_edge_table");
751 Constant *GCOVProfiler::getStartFileFunc() {
761 Constant *GCOVProfiler::getIncrementIndirectCounterFunc() {
772 Constant *GCOVProfiler::getEmitFunctionFunc() {
784 Constant *GCOVProfiler::getEmitArcsFunc() {
793 Constant *GCOVProfiler::getSummaryInfoFunc() {
798 Constant *GCOVProfiler::getDeleteWriteoutFunctionListFunc() {
803 Constant *GCOVProfiler::getDeleteFlushFunctionListFunc() {
808 Constant *GCOVProfiler::getEndFileFunc() {
820 "__llvm_gcov_global_state_pred");
826 Function *GCOVProfiler::insertCounterWriteout(
827 ArrayRef<std::pair<GlobalVariable *, MDNode *> > CountersBySP) {
832 "__llvm_gcov_writeout", M);
835 if (Options.NoRedZone)
841 Constant *StartFile = getStartFileFunc();
842 Constant *EmitFunction = getEmitFunctionFunc();
843 Constant *EmitArcs = getEmitArcsFunc();
844 Constant *SummaryInfo = getSummaryInfoFunc();
845 Constant *EndFile = getEndFileFunc();
849 for (
unsigned i = 0, e = CU_Nodes->
getNumOperands(); i != e; ++i) {
850 auto *CU = cast<DICompileUnit>(CU_Nodes->
getOperand(i));
851 std::string FilenameGcda = mangleName(CU,
"gcda");
852 uint32_t CfgChecksum = FileChecksums.empty() ? 0 : FileChecksums[i];
853 Builder.CreateCall(StartFile,
854 {Builder.CreateGlobalStringPtr(FilenameGcda),
855 Builder.CreateGlobalStringPtr(ReversedVersion),
856 Builder.getInt32(CfgChecksum)});
857 for (
unsigned j = 0, e = CountersBySP.size(); j != e; ++j) {
858 auto *SP = cast_or_null<DISubprogram>(CountersBySP[j].second);
859 uint32_t FuncChecksum = Funcs.empty() ? 0 : Funcs[j]->getFuncChecksum();
862 {Builder.getInt32(j),
863 Options.FunctionNamesInData
866 Builder.getInt32(FuncChecksum),
867 Builder.getInt8(Options.UseCfgChecksum),
868 Builder.getInt32(CfgChecksum)});
873 Builder.CreateCall(EmitArcs, {Builder.getInt32(Arcs),
874 Builder.CreateConstGEP2_64(GV, 0, 0)});
876 Builder.CreateCall(SummaryInfo, {});
877 Builder.CreateCall(EndFile, {});
881 Builder.CreateRetVoid();
885 void GCOVProfiler::insertIndirectCounterIncrement() {
887 cast<Function>(GCOVProfiler::getIncrementIndirectCounterFunc());
891 if (Options.NoRedZone)
906 Value *Pred = Builder.CreateLoad(Arg,
"pred");
907 Value *Cond = Builder.CreateICmpEQ(Pred, Builder.getInt32(0xffffffff));
910 Builder.SetInsertPoint(PredNotNegOne);
914 Value *ZExtPred = Builder.CreateZExt(Pred, Builder.getInt64Ty());
918 Value *Counter = Builder.CreateLoad(GEP,
"counter");
919 Cond = Builder.CreateICmpEQ(Counter,
921 Builder.getInt64Ty()->getPointerTo()));
922 Builder.CreateCondBr(Cond, Exit, CounterEnd);
925 Builder.SetInsertPoint(CounterEnd);
926 Value *Add = Builder.CreateAdd(Builder.CreateLoad(Counter),
927 Builder.getInt64(1));
928 Builder.CreateStore(Add, Counter);
929 Builder.CreateBr(Exit);
932 Builder.SetInsertPoint(Exit);
933 Builder.CreateRetVoid();
937 insertFlush(
ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) {
942 "__llvm_gcov_flush", M);
947 if (Options.NoRedZone)
954 assert(WriteoutF &&
"Need to create the writeout function first!");
957 Builder.CreateCall(WriteoutF, {});
960 for (
ArrayRef<std::pair<GlobalVariable *, MDNode *> >::iterator
961 I = CountersBySP.begin(), E = CountersBySP.end();
965 Builder.CreateStore(Null, GV);
970 Builder.CreateRetVoid();
void DeleteContainerSeconds(Container &C)
In a container of pairs (usually a map) whose second element is a pointer, deletes the second element...
DISubprogramArray getSubprograms() const
GCOVOptions - A struct for passing gcov options between functions.
void push_back(const T &Elt)
GCOVBlock(GCOVFunction &P, uint32_t N)
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVM Argument representation.
size_t size() const
size - Get the string size.
MDNode * getScope() const
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
static cl::opt< bool > DefaultExitBlockBeforeBody("gcov-exit-block-before-body", cl::init(false), cl::Hidden)
A Module instance is used to store all the information related to an LLVM module. ...
static GCOVOptions getDefault()
ModulePass * createGCOVProfilerPass(const GCOVOptions &Options=GCOVOptions::getDefault())
unsigned getNumOperands() const
Return number of MDNode operands.
void appendToGlobalCtors(Module &M, Function *F, int Priority)
Append F to the list of global ctors of module M with the given Priority.
Type * getValueType() const
static PointerType * get(Type *ElementType, unsigned AddressSpace)
PointerType::get - This constructs a pointer to an object of the specified type in a numbered address...
void replace_extension(SmallVectorImpl< char > &path, const Twine &extension)
Replace the file extension of path with extension.
std::error_code current_path(SmallVectorImpl< char > &result)
Get the current path.
Type * getReturnType() const
static IntegerType * getInt64Ty(LLVMContext &C)
static PointerType * getInt64PtrTy(LLVMContext &C, unsigned AS=0)
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
Reports a serious error, calling any installed error handler.
static Constant * getNullValue(Type *Ty)
iterator begin()
Instruction iterator methods.
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
static bool functionHasLines(Function *F)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
StringRef getFilename() const
void setName(const Twine &Name)
Change the name of the value.
DISubprogram * getDISubprogram(const MDNode *Scope)
Find subprogram that is enclosing this scope.
void addFnAttr(Attribute::AttrKind N)
Add function attributes to this function.
unsigned idFor(const T &Entry) const
idFor - return the ID for an existing entry.
FunctionType - Class to represent function types.
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
ArrayType - Class to represent array types.
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
FunctionType::get - This static method is the primary way of constructing a FunctionType.
GCOVBlock - Collects block information.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
GCOVFunction(GCOVFile &P)
hash_code hash_value(const APFloat &Arg)
See friend declarations above.
Type * getElementType() const
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
unsigned getNumSuccessors() const
Return the number of successors that this terminator has.
StringRef filename(StringRef path)
Get filename.
initializer< Ty > init(const Ty &Val)
Subclasses of this class are all able to terminate a basic block.
StringRef getName() const
bool empty() const
empty - Returns true if the vector is empty.
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeSet AttributeList)
Look up the specified function in the module symbol table.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
INITIALIZE_PASS(GCOVProfiler,"insert-gcov-profiling","Insert instrumentation for GCOV profiling", false, false) ModulePass *llvm
BasicBlock * getSuccessor(unsigned idx) const
Return the specified successor.
This is an important class for using LLVM in a threaded context.
BranchInst - Conditional or Unconditional Branch instruction.
This is an important base class in LLVM.
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static Type * getVoidTy(LLVMContext &C)
MDNode * getOperand(unsigned i) const
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Value * CreateInBoundsGEP(Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
PointerType * getPointerTo(unsigned AddrSpace=0)
getPointerTo - Return a pointer to the current type.
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
StringRef getString() const
const MDOperand & getOperand(unsigned I) const
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
void initializeGCOVProfilerPass(PassRegistry &)
void setUnnamedAddr(bool Val)
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
const BasicBlock & getEntryBlock() const
void setLinkage(LinkageTypes LT)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static StringRef getFunctionName(const DISubprogram *SP)
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
StringRef str() const
Explicit conversion to StringRef.
bool isIntegerTy() const
isIntegerTy - True if this is an instance of IntegerType.
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
void write(void *memory, value_type value)
Write a value to memory with a particular endianness.
static cl::opt< std::string > DefaultGCOVVersion("default-gcov-version", cl::init("402*"), cl::Hidden, cl::ValueRequired)
PointerType * getType() const
Global values are always pointers.
NamedMDNode * getNamedMetadata(const Twine &Name) const
Return the first NamedMDNode in the module with the specified name.
GCOVFunction - Collects function information.
A raw_ostream that writes to a file descriptor.
static IntegerType * getInt32Ty(LLVMContext &C)
unsigned insert(const T &Entry)
insert - Append entry to the vector if it doesn't already exist.
size_t size() const
size - Returns the number of entries in the vector.
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
static ArrayType * get(Type *ElementType, uint64_t NumElements)
ArrayType::get - This static method is the primary way to construct an ArrayType. ...
Rename collisions when linking (static functions).
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
A raw_ostream that writes to an std::string.
LLVM Value Representation.
~GCOVBlock()
~GCOVBlock - Delete GCOVBlock and its content.
succ_range successors(BasicBlock *BB)
unsigned getNumOperands() const
This class implements an extremely fast bulk output stream that can only output to a stream...
StringRef - Represent a constant reference to a string, i.e.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N="", Module *M=nullptr)
iterator getFirstInsertionPt()
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
static IntegerType * getInt8Ty(LLVMContext &C)
UniqueVector - This class produces a sequential ID number (base 1) for each unique entry that is adde...
GlobalVariable * getGlobalVariable(StringRef Name) const
Look up the specified global variable in the module symbol table.
LLVMContext & getContext() const
Get the global data context.