17 #define DEBUG_TYPE "insert-gcov-profiling"
69 ReversedVersion[0] = Options.Version[3];
70 ReversedVersion[1] = Options.Version[2];
71 ReversedVersion[2] = Options.Version[1];
72 ReversedVersion[3] = Options.Version[0];
73 ReversedVersion[4] =
'\0';
78 "GCOVProfiler asked to do nothing?");
79 ReversedVersion[0] = Options.
Version[3];
80 ReversedVersion[1] = Options.
Version[2];
81 ReversedVersion[2] = Options.
Version[1];
82 ReversedVersion[3] = Options.
Version[0];
83 ReversedVersion[4] =
'\0';
86 virtual const char *getPassName()
const {
87 return "GCOV Profiler";
91 bool runOnModule(
Module &M);
94 void emitProfileNotes();
98 bool emitProfileArcs();
102 Constant *getIncrementIndirectCounterFunc();
106 Constant *getDeleteWriteoutFunctionListFunc();
107 Constant *getDeleteFlushFunctionListFunc();
126 void insertIndirectCounterIncrement();
128 std::string mangleName(
DICompileUnit CU,
const char *NewStem);
133 char ReversedVersion[5];
142 "Insert instrumentation for GCOV profiling",
false,
false)
145 return new GCOVProfiler(Options);
157 static const char *
const LinesTag;
158 static const char *
const FunctionTag;
159 static const char *
const BlockTag;
160 static const char *
const EdgeTag;
164 void writeBytes(
const char *Bytes,
int Size) {
165 os->write(Bytes, Size);
168 void write(uint32_t i) {
169 writeBytes(reinterpret_cast<char*>(&i), 4);
174 static unsigned lengthOfGCOVString(
StringRef s) {
178 return (s.
size() / 4) + 1;
182 uint32_t Len = lengthOfGCOVString(s);
187 assert((
unsigned)(4 - (s.
size() % 4)) > 0);
188 assert((
unsigned)(4 - (s.
size() % 4)) <= 4);
189 writeBytes(
"\0\0\0\0", 4 - (s.
size() % 4));
194 const char *
const GCOVRecord::LinesTag =
"\0\0\x45\x01";
195 const char *
const GCOVRecord::FunctionTag =
"\0\0\0\1";
196 const char *
const GCOVRecord::BlockTag =
"\0\0\x41\x01";
197 const char *
const GCOVRecord::EdgeTag =
"\0\0\x43\x01";
205 class GCOVLines :
public GCOVRecord {
207 void addLine(uint32_t Line) {
208 Lines.push_back(Line);
211 uint32_t length()
const {
213 return lengthOfGCOVString(Filename) + 2 + Lines.size();
218 writeGCOVString(Filename);
219 for (
int i = 0, e = Lines.size(); i != e; ++i)
235 struct StringKeySort {
248 GCOVLines *&Lines = LinesByFile[Filename];
250 Lines =
new GCOVLines(Filename, os);
256 OutEdges.push_back(&Successor);
263 E = LinesByFile.end();
I != E; ++
I) {
264 Len +=
I->second->length();
268 writeBytes(LinesTag, 4);
272 StringKeySort Sorter;
273 std::sort(SortedLinesByFile.
begin(), SortedLinesByFile.
end(), Sorter);
275 I = SortedLinesByFile.
begin(), E = SortedLinesByFile.
end();
277 (*I)->getValue()->writeOut();
305 bool UseCfgChecksum) {
316 writeBytes(FunctionTag, 4);
317 uint32_t BlockLen = 1 + 1 + 1 + lengthOfGCOVString(
getFunctionName(SP)) +
346 writeBytes(BlockTag, 4);
347 write(Blocks.size() + 1);
348 for (
int i = 0, e = Blocks.size() + 1; i != e; ++i) {
351 DEBUG(
dbgs() << Blocks.size() <<
" blocks.\n");
354 if (Blocks.empty())
return;
355 Function *F = Blocks.begin()->first->getParent();
358 if (Block.OutEdges.empty())
continue;
360 writeBytes(EdgeTag, 4);
361 write(Block.OutEdges.size() * 2 + 1);
363 for (
int i = 0, e = Block.OutEdges.size(); i != e; ++i) {
364 DEBUG(
dbgs() << Block.Number <<
" -> " << Block.OutEdges[i]->Number
366 write(Block.OutEdges[i]->Number);
373 Blocks[
I]->writeOut();
383 std::string GCOVProfiler::mangleName(
DICompileUnit CU,
const char *NewStem) {
384 if (
NamedMDNode *GCov = M->getNamedMetadata(
"llvm.gcov")) {
385 for (
int i = 0, e = GCov->getNumOperands(); i != e; ++i) {
386 MDNode *
N = GCov->getOperand(i);
390 if (!GCovFile || !CompileUnit)
continue;
391 if (CompileUnit == CU) {
394 return Filename.
str();
405 return CurPath.
str();
408 bool GCOVProfiler::runOnModule(
Module &M) {
412 if (Options.EmitNotes) emitProfileNotes();
413 if (Options.EmitData)
return emitProfileArcs();
417 void GCOVProfiler::emitProfileNotes() {
419 if (!CU_Nodes)
return;
421 for (
unsigned i = 0, e = CU_Nodes->
getNumOperands(); i != e; ++i) {
427 std::string ErrorInfo;
430 out.write(
"oncg", 4);
431 out.write(ReversedVersion, 4);
432 out.write(
"MVLL", 4);
438 "A MDNode in subprograms of a CU should be null or a DISubprogram.");
450 for (
int i = 0; i != successors; ++i) {
453 }
else if (isa<ReturnInst>(TI)) {
462 if (Line == Loc.
getLine())
continue;
466 GCOVLines &Lines = Block.getFile(SP.
getFilename());
472 out.write(
"\0\0\0\0\0\0\0\0", 8);
477 bool GCOVProfiler::emitProfileArcs() {
479 if (!CU_Nodes)
return false;
482 bool InsertIndCounterIncrCode =
false;
483 for (
unsigned i = 0, e = CU_Nodes->
getNumOperands(); i != e; ++i) {
487 for (
unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) {
490 "A MDNode in subprograms of a CU should be null or a DISubprogram.");
495 if (!Result) Result =
true;
499 if (isa<ReturnInst>(TI))
522 if (Successors == 1) {
524 Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0,
526 Value *Count = Builder.CreateLoad(Counter);
527 Count = Builder.CreateAdd(Count, Builder.getInt64(1));
528 Builder.CreateStore(Count, Counter);
529 }
else if (
BranchInst *BI = dyn_cast<BranchInst>(TI)) {
531 Value *Sel = Builder.CreateSelect(BI->getCondition(),
532 Builder.getInt64(Edge),
533 Builder.getInt64(Edge + 1));
538 Value *Count = Builder.CreateLoad(Counter);
539 Count = Builder.CreateAdd(Count, Builder.getInt64(1));
540 Builder.CreateStore(Count, Counter);
542 ComplexEdgePreds.
insert(BB);
543 for (
int i = 0; i != Successors; ++i)
551 if (!ComplexEdgePreds.
empty()) {
553 buildEdgeLookupTable(F, Counters,
554 ComplexEdgePreds, ComplexEdgeSuccs);
557 for (
int i = 0, e = ComplexEdgePreds.
size(); i != e; ++i) {
558 IRBuilder<> Builder(ComplexEdgePreds[i + 1]->getFirstInsertionPt());
559 Builder.CreateStore(Builder.getInt32(i), EdgeState);
562 for (
int i = 0, e = ComplexEdgeSuccs.
size(); i != e; ++i) {
564 IRBuilder<> Builder(ComplexEdgeSuccs[i+1]->getFirstInsertionPt());
565 Value *CounterPtrArray =
566 Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0,
567 i * ComplexEdgePreds.
size());
570 InsertIndCounterIncrCode =
true;
571 Builder.CreateCall2(getIncrementIndirectCounterFunc(),
572 EdgeState, CounterPtrArray);
577 Function *WriteoutF = insertCounterWriteout(CountersBySP);
578 Function *FlushF = insertFlush(CountersBySP);
585 "__llvm_gcov_init", M);
589 if (Options.NoRedZone)
605 Builder.CreateCall2(GCOVInit, WriteoutF, FlushF);
606 Builder.CreateRetVoid();
611 if (InsertIndCounterIncrCode)
612 insertIndirectCounterIncrement();
629 size_t TableSize = Succs.
size() * Preds.
size();
635 for (
size_t i = 0; i != TableSize; ++i)
636 EdgeTable[i] = NullValue;
642 if (Successors > 1 && !isa<BranchInst>(TI) && !isa<ReturnInst>(TI)) {
643 for (
int i = 0; i != Successors; ++i) {
646 Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0,
648 EdgeTable[((Succs.
idFor(Succ)-1) * Preds.
size()) +
649 (Preds.
idFor(BB)-1)] = cast<Constant>(Counter);
660 "__llvm_gcda_edge_table");
665 Constant *GCOVProfiler::getStartFileFunc() {
674 Constant *GCOVProfiler::getIncrementIndirectCounterFunc() {
685 Constant *GCOVProfiler::getEmitFunctionFunc() {
695 Constant *GCOVProfiler::getEmitArcsFunc() {
704 Constant *GCOVProfiler::getSummaryInfoFunc() {
709 Constant *GCOVProfiler::getDeleteWriteoutFunctionListFunc() {
714 Constant *GCOVProfiler::getDeleteFlushFunctionListFunc() {
719 Constant *GCOVProfiler::getEndFileFunc() {
731 "__llvm_gcov_global_state_pred");
737 Function *GCOVProfiler::insertCounterWriteout(
738 ArrayRef<std::pair<GlobalVariable *, MDNode *> > CountersBySP) {
743 "__llvm_gcov_writeout", M);
746 if (Options.NoRedZone)
752 Constant *StartFile = getStartFileFunc();
753 Constant *EmitFunction = getEmitFunctionFunc();
754 Constant *EmitArcs = getEmitArcsFunc();
755 Constant *SummaryInfo = getSummaryInfoFunc();
756 Constant *EndFile = getEndFileFunc();
760 for (
unsigned i = 0, e = CU_Nodes->
getNumOperands(); i != e; ++i) {
762 std::string FilenameGcda = mangleName(CU,
"gcda");
763 Builder.CreateCall2(StartFile,
764 Builder.CreateGlobalStringPtr(FilenameGcda),
765 Builder.CreateGlobalStringPtr(ReversedVersion));
766 for (
unsigned j = 0, e = CountersBySP.
size(); j != e; ++j) {
769 EmitFunction, Builder.getInt32(j),
770 Options.FunctionNamesInData ?
773 Builder.getInt8(Options.UseCfgChecksum));
778 Builder.CreateCall2(EmitArcs,
779 Builder.getInt32(Arcs),
780 Builder.CreateConstGEP2_64(GV, 0, 0));
782 Builder.CreateCall(SummaryInfo);
783 Builder.CreateCall(EndFile);
787 Builder.CreateRetVoid();
791 void GCOVProfiler::insertIndirectCounterIncrement() {
793 cast<Function>(GCOVProfiler::getIncrementIndirectCounterFunc());
797 if (Options.NoRedZone)
812 Value *Pred = Builder.CreateLoad(Arg,
"pred");
813 Value *Cond = Builder.CreateICmpEQ(Pred, Builder.getInt32(0xffffffff));
816 Builder.SetInsertPoint(PredNotNegOne);
820 Value *ZExtPred = Builder.CreateZExt(Pred, Builder.getInt64Ty());
823 Value *GEP = Builder.CreateGEP(Arg, ZExtPred);
824 Value *Counter = Builder.CreateLoad(GEP,
"counter");
825 Cond = Builder.CreateICmpEQ(Counter,
827 Builder.getInt64Ty()->getPointerTo()));
828 Builder.CreateCondBr(Cond, Exit, CounterEnd);
831 Builder.SetInsertPoint(CounterEnd);
832 Value *Add = Builder.CreateAdd(Builder.CreateLoad(Counter),
833 Builder.getInt64(1));
834 Builder.CreateStore(Add, Counter);
835 Builder.CreateBr(Exit);
838 Builder.SetInsertPoint(Exit);
839 Builder.CreateRetVoid();
843 insertFlush(
ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) {
848 "__llvm_gcov_flush", M);
853 if (Options.NoRedZone)
860 assert(WriteoutF &&
"Need to create the writeout function first!");
863 Builder.CreateCall(WriteoutF);
866 for (
ArrayRef<std::pair<GlobalVariable *, MDNode *> >::iterator
867 I = CountersBySP.
begin(), E = CountersBySP.
end();
871 Builder.CreateStore(Null, GV);
876 Builder.CreateRetVoid();
void DeleteContainerSeconds(Container &C)
void push_back(const T &Elt)
StringRef getString() const
GCOVBlock(GCOVFunction &P, uint32_t N)
static PassRegistry * getPassRegistry()
LLVM Argument representation.
size_t size() const
size - Get the string size.
bool isSubprogram() const
The main container class for the LLVM Intermediate Representation.
static GCOVOptions getDefault()
ModulePass * createGCOVProfilerPass(const GCOVOptions &Options=GCOVOptions::getDefault())
enable_if_c<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
unsigned getNumOperands() const
getNumOperands - Return number of MDNode operands.
void appendToGlobalCtors(Module &M, Function *F, int Priority)
static PointerType * get(Type *ElementType, unsigned AddressSpace)
void replace_extension(SmallVectorImpl< char > &path, const Twine &extension)
Replace the file extension of path with extension.
error_code current_path(SmallVectorImpl< char > &result)
Get the current path.
std::string str() const
str - Get the contents as an std::string.
Type * getReturnType() const
MDNode - a tuple of other values.
static IntegerType * getInt64Ty(LLVMContext &C)
static PointerType * getInt64PtrTy(LLVMContext &C, unsigned AS=0)
const GlobalVariable * getGlobalVariable(StringRef Name, bool AllowInternal=false) const
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
static Constant * getNullValue(Type *Ty)
StringRef getName() const
static std::string getFunctionName(DISubprogram SP)
Value * getOperand(unsigned i) const LLVM_READONLY
getOperand - Return specified operand.
DIArray - This descriptor holds an array of descriptors.
bool isUnknown() const
isUnknown - Return true if this is an unknown location.
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=0)
void setName(const Twine &Name)
ID
LLVM Calling Convention Representation.
void addFnAttr(Attribute::AttrKind N)
Add function attributes to this function.
unsigned idFor(const T &Entry) const
DISubprogram - This is a wrapper for a subprogram (e.g. a function).
const char * data() const
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
GCOVBlock - Collects block information.
unsigned getLineNumber() const
StringRef getName() const
Type * getElementType() const
Function * getFunction(StringRef Name) const
DISubprogram getDISubprogram(const MDNode *Scope)
getDISubprogram - Find subprogram that is enclosing this scope.
Function * getFunction() const
unsigned getNumSuccessors() const
initializer< Ty > init(const Ty &Val)
StringRef getFilename() const
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeSet AttributeList)
LLVM Basic Block Representation.
INITIALIZE_PASS(GCOVProfiler,"insert-gcov-profiling","Insert instrumentation for GCOV profiling", false, false) ModulePass *llvm
BasicBlock * getSuccessor(unsigned idx) const
DIDescriptor getElement(unsigned Idx) const
LLVM Constant Representation.
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static Type * getVoidTy(LLVMContext &C)
ItTy next(ItTy it, Dist n)
MDNode * getOperand(unsigned i) const
getOperand - Return specified operand.
StringRef getLinkageName() const
unsigned getNumElements() const
Value * CreateInBoundsGEP(Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
PointerType * getPointerTo(unsigned AddrSpace=0)
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
~GCOVFunction()
~GCOVFunction - Delete GCOVFunction and its content.
MDNode * getScope(const LLVMContext &Ctx) const
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
void initializeGCOVProfilerPass(PassRegistry &)
void setUnnamedAddr(bool Val)
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
void setLinkage(LinkageTypes LT)
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
StringRef str() const
Explicit conversion to StringRef.
ssize_t write(int fildes, const void *buf, size_t nbyte);
static cl::opt< std::string > DefaultGCOVVersion("default-gcov-version", cl::init("402*"), cl::Hidden, cl::ValueRequired)
PointerType * getType() const
getType - Global values are always pointers.
NamedMDNode * getNamedMetadata(const Twine &Name) const
GCOVFunction - Collects function information.
static IntegerType * getInt32Ty(LLVMContext &C)
unsigned insert(const T &Entry)
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=0, BasicBlock *InsertBefore=0)
Creates a new BasicBlock.
static ArrayType * get(Type *ElementType, uint64_t NumElements)
Rename collisions when linking (static functions).
LLVM Value Representation.
~GCOVBlock()
~GCOVBlock - Delete GCOVBlock and its content.
unsigned getNumOperands() const
getNumOperands - Return the number of NamedMDNode operands.
DIArray getSubprograms() const
const StringRef filename(StringRef path)
Get filename.
DICompileUnit - A wrapper for a compile unit.
static IntegerType * getInt8Ty(LLVMContext &C)
LLVMContext & getContext() const
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N="", Module *M=0)
bool empty() const
empty - Check if the string is empty.