]>
git.proxmox.com Git - rustc.git/blob - src/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
1 //===- GCOVProfiling.cpp - Insert edge counters for gcov profiling --------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This pass implements GCOV-style profiling. When this pass is run it emits
11 // "gcno" files next to the existing source, and instruments the code that runs
12 // to records the edges between blocks that run and emit a complementary "gcda"
15 //===----------------------------------------------------------------------===//
17 #define DEBUG_TYPE "insert-gcov-profiling"
19 #include "ProfilingUtils.h"
20 #include "llvm/Transforms/Instrumentation.h"
21 #include "llvm/DebugInfo.h"
22 #include "llvm/IRBuilder.h"
23 #include "llvm/Instructions.h"
24 #include "llvm/Module.h"
25 #include "llvm/Pass.h"
26 #include "llvm/ADT/DenseMap.h"
27 #include "llvm/ADT/STLExtras.h"
28 #include "llvm/ADT/Statistic.h"
29 #include "llvm/ADT/StringExtras.h"
30 #include "llvm/ADT/StringMap.h"
31 #include "llvm/ADT/UniqueVector.h"
32 #include "llvm/Support/Debug.h"
33 #include "llvm/Support/DebugLoc.h"
34 #include "llvm/Support/InstIterator.h"
35 #include "llvm/Support/PathV2.h"
36 #include "llvm/Support/raw_ostream.h"
37 #include "llvm/Transforms/Utils/ModuleUtils.h"
43 class GCOVProfiler
: public ModulePass
{
47 : ModulePass(ID
), EmitNotes(true), EmitData(true), Use402Format(false),
48 UseExtraChecksum(false) {
49 initializeGCOVProfilerPass(*PassRegistry::getPassRegistry());
51 GCOVProfiler(bool EmitNotes
, bool EmitData
, bool use402Format
= false,
52 bool useExtraChecksum
= false)
53 : ModulePass(ID
), EmitNotes(EmitNotes
), EmitData(EmitData
),
54 Use402Format(use402Format
), UseExtraChecksum(useExtraChecksum
) {
55 assert((EmitNotes
|| EmitData
) && "GCOVProfiler asked to do nothing?");
56 initializeGCOVProfilerPass(*PassRegistry::getPassRegistry());
58 virtual const char *getPassName() const {
59 return "GCOV Profiler";
62 bool runOnModule(Module
&M
);
64 // Create the GCNO files for the Module based on DebugInfo.
67 // Modify the program to track transitions along edges and call into the
68 // profiling runtime to emit .gcda files when run.
69 bool emitProfileArcs();
71 // Get pointers to the functions in the runtime library.
72 Constant
*getStartFileFunc();
73 Constant
*getIncrementIndirectCounterFunc();
74 Constant
*getEmitFunctionFunc();
75 Constant
*getEmitArcsFunc();
76 Constant
*getEndFileFunc();
78 // Create or retrieve an i32 state value that is used to represent the
79 // pred block number for certain non-trivial edges.
80 GlobalVariable
*getEdgeStateValue();
82 // Produce a table of pointers to counters, by predecessor and successor
84 GlobalVariable
*buildEdgeLookupTable(Function
*F
,
85 GlobalVariable
*Counter
,
86 const UniqueVector
<BasicBlock
*> &Preds
,
87 const UniqueVector
<BasicBlock
*> &Succs
);
89 // Add the function to write out all our counters to the global destructor
91 void insertCounterWriteout(ArrayRef
<std::pair
<GlobalVariable
*, MDNode
*> >);
92 void insertIndirectCounterIncrement();
93 void insertFlush(ArrayRef
<std::pair
<GlobalVariable
*, MDNode
*> >);
95 std::string
mangleName(DICompileUnit CU
, const char *NewStem
);
100 bool UseExtraChecksum
;
107 char GCOVProfiler::ID
= 0;
108 INITIALIZE_PASS(GCOVProfiler
, "insert-gcov-profiling",
109 "Insert instrumentation for GCOV profiling", false, false)
111 ModulePass
*llvm::createGCOVProfilerPass(bool EmitNotes
, bool EmitData
,
113 bool UseExtraChecksum
) {
114 return new GCOVProfiler(EmitNotes
, EmitData
, Use402Format
, UseExtraChecksum
);
120 static const char *LinesTag
;
121 static const char *FunctionTag
;
122 static const char *BlockTag
;
123 static const char *EdgeTag
;
127 void writeBytes(const char *Bytes
, int Size
) {
128 os
->write(Bytes
, Size
);
131 void write(uint32_t i
) {
132 writeBytes(reinterpret_cast<char*>(&i
), 4);
135 // Returns the length measured in 4-byte blocks that will be used to
136 // represent this string in a GCOV file
137 unsigned lengthOfGCOVString(StringRef s
) {
138 // A GCOV string is a length, followed by a NUL, then between 0 and 3 NULs
139 // padding out to the next 4-byte word. The length is measured in 4-byte
140 // words including padding, not bytes of actual string.
141 return (s
.size() / 4) + 1;
144 void writeGCOVString(StringRef s
) {
145 uint32_t Len
= lengthOfGCOVString(s
);
147 writeBytes(s
.data(), s
.size());
149 // Write 1 to 4 bytes of NUL padding.
150 assert((unsigned)(4 - (s
.size() % 4)) > 0);
151 assert((unsigned)(4 - (s
.size() % 4)) <= 4);
152 writeBytes("\0\0\0\0", 4 - (s
.size() % 4));
157 const char *GCOVRecord::LinesTag
= "\0\0\x45\x01";
158 const char *GCOVRecord::FunctionTag
= "\0\0\0\1";
159 const char *GCOVRecord::BlockTag
= "\0\0\x41\x01";
160 const char *GCOVRecord::EdgeTag
= "\0\0\x43\x01";
165 // Constructed only by requesting it from a GCOVBlock, this object stores a
166 // list of line numbers and a single filename, representing lines that belong
168 class GCOVLines
: public GCOVRecord
{
170 void addLine(uint32_t Line
) {
171 Lines
.push_back(Line
);
175 // Here 2 = 1 for string length + 1 for '0' id#.
176 return lengthOfGCOVString(Filename
) + 2 + Lines
.size();
181 writeGCOVString(Filename
);
182 for (int i
= 0, e
= Lines
.size(); i
!= e
; ++i
)
186 GCOVLines(StringRef F
, raw_ostream
*os
)
193 SmallVector
<uint32_t, 32> Lines
;
196 // Represent a basic block in GCOV. Each block has a unique number in the
197 // function, number of lines belonging to each block, and a set of edges to
199 class GCOVBlock
: public GCOVRecord
{
201 GCOVLines
&getFile(StringRef Filename
) {
202 GCOVLines
*&Lines
= LinesByFile
[Filename
];
204 Lines
= new GCOVLines(Filename
, os
);
209 void addEdge(GCOVBlock
&Successor
) {
210 OutEdges
.push_back(&Successor
);
215 for (StringMap
<GCOVLines
*>::iterator I
= LinesByFile
.begin(),
216 E
= LinesByFile
.end(); I
!= E
; ++I
) {
217 Len
+= I
->second
->length();
220 writeBytes(LinesTag
, 4);
223 for (StringMap
<GCOVLines
*>::iterator I
= LinesByFile
.begin(),
224 E
= LinesByFile
.end(); I
!= E
; ++I
)
225 I
->second
->writeOut();
231 DeleteContainerSeconds(LinesByFile
);
235 friend class GCOVFunction
;
237 GCOVBlock(uint32_t Number
, raw_ostream
*os
)
243 StringMap
<GCOVLines
*> LinesByFile
;
244 SmallVector
<GCOVBlock
*, 4> OutEdges
;
247 // A function has a unique identifier, a checksum (we leave as zero) and a
248 // set of blocks and a map of edges between blocks. This is the only GCOV
249 // object users can construct, the blocks and lines will be rooted here.
250 class GCOVFunction
: public GCOVRecord
{
252 GCOVFunction(DISubprogram SP
, raw_ostream
*os
,
253 bool Use402Format
, bool UseExtraChecksum
) {
256 Function
*F
= SP
.getFunction();
257 DEBUG(dbgs() << "Function: " << F
->getName() << "\n");
259 for (Function::iterator BB
= F
->begin(), E
= F
->end(); BB
!= E
; ++BB
) {
260 Blocks
[BB
] = new GCOVBlock(i
++, os
);
262 ReturnBlock
= new GCOVBlock(i
++, os
);
264 writeBytes(FunctionTag
, 4);
265 uint32_t BlockLen
= 1 + 1 + 1 + lengthOfGCOVString(SP
.getName()) +
266 1 + lengthOfGCOVString(SP
.getFilename()) + 1;
267 if (UseExtraChecksum
)
270 uint32_t Ident
= reinterpret_cast<intptr_t>((MDNode
*)SP
);
272 write(0); // lineno checksum
273 if (UseExtraChecksum
)
274 write(0); // cfg checksum
275 writeGCOVString(SP
.getName());
276 writeGCOVString(SP
.getFilename());
277 write(SP
.getLineNumber());
281 DeleteContainerSeconds(Blocks
);
285 GCOVBlock
&getBlock(BasicBlock
*BB
) {
289 GCOVBlock
&getReturnBlock() {
294 // Emit count of blocks.
295 writeBytes(BlockTag
, 4);
296 write(Blocks
.size() + 1);
297 for (int i
= 0, e
= Blocks
.size() + 1; i
!= e
; ++i
) {
298 write(0); // No flags on our blocks.
300 DEBUG(dbgs() << Blocks
.size() << " blocks.\n");
302 // Emit edges between blocks.
303 for (DenseMap
<BasicBlock
*, GCOVBlock
*>::iterator I
= Blocks
.begin(),
304 E
= Blocks
.end(); I
!= E
; ++I
) {
305 GCOVBlock
&Block
= *I
->second
;
306 if (Block
.OutEdges
.empty()) continue;
308 writeBytes(EdgeTag
, 4);
309 write(Block
.OutEdges
.size() * 2 + 1);
311 for (int i
= 0, e
= Block
.OutEdges
.size(); i
!= e
; ++i
) {
312 DEBUG(dbgs() << Block
.Number
<< " -> " << Block
.OutEdges
[i
]->Number
314 write(Block
.OutEdges
[i
]->Number
);
315 write(0); // no flags
319 // Emit lines for each block.
320 for (DenseMap
<BasicBlock
*, GCOVBlock
*>::iterator I
= Blocks
.begin(),
321 E
= Blocks
.end(); I
!= E
; ++I
) {
322 I
->second
->writeOut();
327 DenseMap
<BasicBlock
*, GCOVBlock
*> Blocks
;
328 GCOVBlock
*ReturnBlock
;
332 std::string
GCOVProfiler::mangleName(DICompileUnit CU
, const char *NewStem
) {
333 if (NamedMDNode
*GCov
= M
->getNamedMetadata("llvm.gcov")) {
334 for (int i
= 0, e
= GCov
->getNumOperands(); i
!= e
; ++i
) {
335 MDNode
*N
= GCov
->getOperand(i
);
336 if (N
->getNumOperands() != 2) continue;
337 MDString
*GCovFile
= dyn_cast
<MDString
>(N
->getOperand(0));
338 MDNode
*CompileUnit
= dyn_cast
<MDNode
>(N
->getOperand(1));
339 if (!GCovFile
|| !CompileUnit
) continue;
340 if (CompileUnit
== CU
) {
341 SmallString
<128> Filename
= GCovFile
->getString();
342 sys::path::replace_extension(Filename
, NewStem
);
343 return Filename
.str();
348 SmallString
<128> Filename
= CU
.getFilename();
349 sys::path::replace_extension(Filename
, NewStem
);
350 return sys::path::filename(Filename
.str());
353 bool GCOVProfiler::runOnModule(Module
&M
) {
355 Ctx
= &M
.getContext();
357 if (EmitNotes
) emitGCNO();
358 if (EmitData
) return emitProfileArcs();
362 void GCOVProfiler::emitGCNO() {
363 NamedMDNode
*CU_Nodes
= M
->getNamedMetadata("llvm.dbg.cu");
364 if (!CU_Nodes
) return;
366 for (unsigned i
= 0, e
= CU_Nodes
->getNumOperands(); i
!= e
; ++i
) {
367 // Each compile unit gets its own .gcno file. This means that whether we run
368 // this pass over the original .o's as they're produced, or run it after
369 // LTO, we'll generate the same .gcno files.
371 DICompileUnit
CU(CU_Nodes
->getOperand(i
));
372 std::string ErrorInfo
;
373 raw_fd_ostream
out(mangleName(CU
, "gcno").c_str(), ErrorInfo
,
374 raw_fd_ostream::F_Binary
);
376 out
.write("oncg*404MVLL", 12);
378 out
.write("oncg*204MVLL", 12);
380 DIArray SPs
= CU
.getSubprograms();
381 for (unsigned i
= 0, e
= SPs
.getNumElements(); i
!= e
; ++i
) {
382 DISubprogram
SP(SPs
.getElement(i
));
383 if (!SP
.Verify()) continue;
385 Function
*F
= SP
.getFunction();
387 GCOVFunction
Func(SP
, &out
, Use402Format
, UseExtraChecksum
);
389 for (Function::iterator BB
= F
->begin(), E
= F
->end(); BB
!= E
; ++BB
) {
390 GCOVBlock
&Block
= Func
.getBlock(BB
);
391 TerminatorInst
*TI
= BB
->getTerminator();
392 if (int successors
= TI
->getNumSuccessors()) {
393 for (int i
= 0; i
!= successors
; ++i
) {
394 Block
.addEdge(Func
.getBlock(TI
->getSuccessor(i
)));
396 } else if (isa
<ReturnInst
>(TI
)) {
397 Block
.addEdge(Func
.getReturnBlock());
401 for (BasicBlock::iterator I
= BB
->begin(), IE
= BB
->end();
403 const DebugLoc
&Loc
= I
->getDebugLoc();
404 if (Loc
.isUnknown()) continue;
405 if (Line
== Loc
.getLine()) continue;
406 Line
= Loc
.getLine();
407 if (SP
!= getDISubprogram(Loc
.getScope(*Ctx
))) continue;
409 GCOVLines
&Lines
= Block
.getFile(SP
.getFilename());
410 Lines
.addLine(Loc
.getLine());
415 out
.write("\0\0\0\0\0\0\0\0", 8); // EOF
420 bool GCOVProfiler::emitProfileArcs() {
421 NamedMDNode
*CU_Nodes
= M
->getNamedMetadata("llvm.dbg.cu");
422 if (!CU_Nodes
) return false;
425 bool InsertIndCounterIncrCode
= false;
426 for (unsigned i
= 0, e
= CU_Nodes
->getNumOperands(); i
!= e
; ++i
) {
427 DICompileUnit
CU(CU_Nodes
->getOperand(i
));
428 DIArray SPs
= CU
.getSubprograms();
429 SmallVector
<std::pair
<GlobalVariable
*, MDNode
*>, 8> CountersBySP
;
430 for (unsigned i
= 0, e
= SPs
.getNumElements(); i
!= e
; ++i
) {
431 DISubprogram
SP(SPs
.getElement(i
));
432 if (!SP
.Verify()) continue;
433 Function
*F
= SP
.getFunction();
435 if (!Result
) Result
= true;
437 for (Function::iterator BB
= F
->begin(), E
= F
->end(); BB
!= E
; ++BB
) {
438 TerminatorInst
*TI
= BB
->getTerminator();
439 if (isa
<ReturnInst
>(TI
))
442 Edges
+= TI
->getNumSuccessors();
445 ArrayType
*CounterTy
=
446 ArrayType::get(Type::getInt64Ty(*Ctx
), Edges
);
447 GlobalVariable
*Counters
=
448 new GlobalVariable(*M
, CounterTy
, false,
449 GlobalValue::InternalLinkage
,
450 Constant::getNullValue(CounterTy
),
452 CountersBySP
.push_back(std::make_pair(Counters
, (MDNode
*)SP
));
454 UniqueVector
<BasicBlock
*> ComplexEdgePreds
;
455 UniqueVector
<BasicBlock
*> ComplexEdgeSuccs
;
458 for (Function::iterator BB
= F
->begin(), E
= F
->end(); BB
!= E
; ++BB
) {
459 TerminatorInst
*TI
= BB
->getTerminator();
460 int Successors
= isa
<ReturnInst
>(TI
) ? 1 : TI
->getNumSuccessors();
462 IRBuilder
<> Builder(TI
);
464 if (Successors
== 1) {
465 Value
*Counter
= Builder
.CreateConstInBoundsGEP2_64(Counters
, 0,
467 Value
*Count
= Builder
.CreateLoad(Counter
);
468 Count
= Builder
.CreateAdd(Count
,
469 ConstantInt::get(Type::getInt64Ty(*Ctx
),1));
470 Builder
.CreateStore(Count
, Counter
);
471 } else if (BranchInst
*BI
= dyn_cast
<BranchInst
>(TI
)) {
472 Value
*Sel
= Builder
.CreateSelect(
474 ConstantInt::get(Type::getInt64Ty(*Ctx
), Edge
),
475 ConstantInt::get(Type::getInt64Ty(*Ctx
), Edge
+ 1));
476 SmallVector
<Value
*, 2> Idx
;
477 Idx
.push_back(Constant::getNullValue(Type::getInt64Ty(*Ctx
)));
479 Value
*Counter
= Builder
.CreateInBoundsGEP(Counters
, Idx
);
480 Value
*Count
= Builder
.CreateLoad(Counter
);
481 Count
= Builder
.CreateAdd(Count
,
482 ConstantInt::get(Type::getInt64Ty(*Ctx
),1));
483 Builder
.CreateStore(Count
, Counter
);
485 ComplexEdgePreds
.insert(BB
);
486 for (int i
= 0; i
!= Successors
; ++i
)
487 ComplexEdgeSuccs
.insert(TI
->getSuccessor(i
));
493 if (!ComplexEdgePreds
.empty()) {
494 GlobalVariable
*EdgeTable
=
495 buildEdgeLookupTable(F
, Counters
,
496 ComplexEdgePreds
, ComplexEdgeSuccs
);
497 GlobalVariable
*EdgeState
= getEdgeStateValue();
499 Type
*Int32Ty
= Type::getInt32Ty(*Ctx
);
500 for (int i
= 0, e
= ComplexEdgePreds
.size(); i
!= e
; ++i
) {
501 IRBuilder
<> Builder(ComplexEdgePreds
[i
+1]->getTerminator());
502 Builder
.CreateStore(ConstantInt::get(Int32Ty
, i
), EdgeState
);
504 for (int i
= 0, e
= ComplexEdgeSuccs
.size(); i
!= e
; ++i
) {
505 // call runtime to perform increment
506 BasicBlock::iterator InsertPt
=
507 ComplexEdgeSuccs
[i
+1]->getFirstInsertionPt();
508 IRBuilder
<> Builder(InsertPt
);
509 Value
*CounterPtrArray
=
510 Builder
.CreateConstInBoundsGEP2_64(EdgeTable
, 0,
511 i
* ComplexEdgePreds
.size());
513 // Build code to increment the counter.
514 InsertIndCounterIncrCode
= true;
515 Builder
.CreateCall2(getIncrementIndirectCounterFunc(),
516 EdgeState
, CounterPtrArray
);
521 insertCounterWriteout(CountersBySP
);
522 insertFlush(CountersBySP
);
525 if (InsertIndCounterIncrCode
)
526 insertIndirectCounterIncrement();
531 // All edges with successors that aren't branches are "complex", because it
532 // requires complex logic to pick which counter to update.
533 GlobalVariable
*GCOVProfiler::buildEdgeLookupTable(
535 GlobalVariable
*Counters
,
536 const UniqueVector
<BasicBlock
*> &Preds
,
537 const UniqueVector
<BasicBlock
*> &Succs
) {
538 // TODO: support invoke, threads. We rely on the fact that nothing can modify
539 // the whole-Module pred edge# between the time we set it and the time we next
540 // read it. Threads and invoke make this untrue.
542 // emit [(succs * preds) x i64*], logically [succ x [pred x i64*]].
543 Type
*Int64PtrTy
= Type::getInt64PtrTy(*Ctx
);
544 ArrayType
*EdgeTableTy
= ArrayType::get(
545 Int64PtrTy
, Succs
.size() * Preds
.size());
547 Constant
**EdgeTable
= new Constant
*[Succs
.size() * Preds
.size()];
548 Constant
*NullValue
= Constant::getNullValue(Int64PtrTy
);
549 for (int i
= 0, ie
= Succs
.size() * Preds
.size(); i
!= ie
; ++i
)
550 EdgeTable
[i
] = NullValue
;
553 for (Function::iterator BB
= F
->begin(), E
= F
->end(); BB
!= E
; ++BB
) {
554 TerminatorInst
*TI
= BB
->getTerminator();
555 int Successors
= isa
<ReturnInst
>(TI
) ? 1 : TI
->getNumSuccessors();
556 if (Successors
> 1 && !isa
<BranchInst
>(TI
) && !isa
<ReturnInst
>(TI
)) {
557 for (int i
= 0; i
!= Successors
; ++i
) {
558 BasicBlock
*Succ
= TI
->getSuccessor(i
);
559 IRBuilder
<> builder(Succ
);
560 Value
*Counter
= builder
.CreateConstInBoundsGEP2_64(Counters
, 0,
562 EdgeTable
[((Succs
.idFor(Succ
)-1) * Preds
.size()) +
563 (Preds
.idFor(BB
)-1)] = cast
<Constant
>(Counter
);
569 ArrayRef
<Constant
*> V(&EdgeTable
[0], Succs
.size() * Preds
.size());
570 GlobalVariable
*EdgeTableGV
=
572 *M
, EdgeTableTy
, true, GlobalValue::InternalLinkage
,
573 ConstantArray::get(EdgeTableTy
, V
),
574 "__llvm_gcda_edge_table");
575 EdgeTableGV
->setUnnamedAddr(true);
579 Constant
*GCOVProfiler::getStartFileFunc() {
580 FunctionType
*FTy
= FunctionType::get(Type::getVoidTy(*Ctx
),
581 Type::getInt8PtrTy(*Ctx
), false);
582 return M
->getOrInsertFunction("llvm_gcda_start_file", FTy
);
585 Constant
*GCOVProfiler::getIncrementIndirectCounterFunc() {
586 Type
*Int32Ty
= Type::getInt32Ty(*Ctx
);
587 Type
*Int64Ty
= Type::getInt64Ty(*Ctx
);
589 Int32Ty
->getPointerTo(), // uint32_t *predecessor
590 Int64Ty
->getPointerTo()->getPointerTo() // uint64_t **counters
592 FunctionType
*FTy
= FunctionType::get(Type::getVoidTy(*Ctx
), Args
, false);
593 return M
->getOrInsertFunction("__llvm_gcov_indirect_counter_increment", FTy
);
596 Constant
*GCOVProfiler::getEmitFunctionFunc() {
598 Type::getInt32Ty(*Ctx
), // uint32_t ident
599 Type::getInt8PtrTy(*Ctx
), // const char *function_name
601 FunctionType
*FTy
= FunctionType::get(Type::getVoidTy(*Ctx
), Args
, false);
602 return M
->getOrInsertFunction("llvm_gcda_emit_function", FTy
);
605 Constant
*GCOVProfiler::getEmitArcsFunc() {
607 Type::getInt32Ty(*Ctx
), // uint32_t num_counters
608 Type::getInt64PtrTy(*Ctx
), // uint64_t *counters
610 FunctionType
*FTy
= FunctionType::get(Type::getVoidTy(*Ctx
),
612 return M
->getOrInsertFunction("llvm_gcda_emit_arcs", FTy
);
615 Constant
*GCOVProfiler::getEndFileFunc() {
616 FunctionType
*FTy
= FunctionType::get(Type::getVoidTy(*Ctx
), false);
617 return M
->getOrInsertFunction("llvm_gcda_end_file", FTy
);
620 GlobalVariable
*GCOVProfiler::getEdgeStateValue() {
621 GlobalVariable
*GV
= M
->getGlobalVariable("__llvm_gcov_global_state_pred");
623 GV
= new GlobalVariable(*M
, Type::getInt32Ty(*Ctx
), false,
624 GlobalValue::InternalLinkage
,
625 ConstantInt::get(Type::getInt32Ty(*Ctx
),
627 "__llvm_gcov_global_state_pred");
628 GV
->setUnnamedAddr(true);
633 void GCOVProfiler::insertCounterWriteout(
634 ArrayRef
<std::pair
<GlobalVariable
*, MDNode
*> > CountersBySP
) {
635 FunctionType
*WriteoutFTy
= FunctionType::get(Type::getVoidTy(*Ctx
), false);
636 Function
*WriteoutF
= M
->getFunction("__llvm_gcov_writeout");
638 WriteoutF
= Function::Create(WriteoutFTy
, GlobalValue::InternalLinkage
,
639 "__llvm_gcov_writeout", M
);
640 WriteoutF
->setUnnamedAddr(true);
642 BasicBlock
*BB
= BasicBlock::Create(*Ctx
, "entry", WriteoutF
);
643 IRBuilder
<> Builder(BB
);
645 Constant
*StartFile
= getStartFileFunc();
646 Constant
*EmitFunction
= getEmitFunctionFunc();
647 Constant
*EmitArcs
= getEmitArcsFunc();
648 Constant
*EndFile
= getEndFileFunc();
650 NamedMDNode
*CU_Nodes
= M
->getNamedMetadata("llvm.dbg.cu");
652 for (unsigned i
= 0, e
= CU_Nodes
->getNumOperands(); i
!= e
; ++i
) {
653 DICompileUnit
CU(CU_Nodes
->getOperand(i
));
654 std::string FilenameGcda
= mangleName(CU
, "gcda");
655 Builder
.CreateCall(StartFile
,
656 Builder
.CreateGlobalStringPtr(FilenameGcda
));
657 for (ArrayRef
<std::pair
<GlobalVariable
*, MDNode
*> >::iterator
658 I
= CountersBySP
.begin(), E
= CountersBySP
.end();
660 DISubprogram
SP(I
->second
);
661 intptr_t ident
= reinterpret_cast<intptr_t>(I
->second
);
662 Builder
.CreateCall2(EmitFunction
,
663 ConstantInt::get(Type::getInt32Ty(*Ctx
), ident
),
664 Builder
.CreateGlobalStringPtr(SP
.getName()));
666 GlobalVariable
*GV
= I
->first
;
668 cast
<ArrayType
>(GV
->getType()->getElementType())->getNumElements();
669 Builder
.CreateCall2(EmitArcs
,
670 ConstantInt::get(Type::getInt32Ty(*Ctx
), Arcs
),
671 Builder
.CreateConstGEP2_64(GV
, 0, 0));
673 Builder
.CreateCall(EndFile
);
676 Builder
.CreateRetVoid();
678 // Create a small bit of code that registers the "__llvm_gcov_writeout"
679 // function to be executed at exit.
680 FunctionType
*FTy
= FunctionType::get(Type::getVoidTy(*Ctx
), false);
681 Function
*F
= Function::Create(FTy
, GlobalValue::InternalLinkage
,
682 "__llvm_gcov_init", M
);
683 F
->setUnnamedAddr(true);
684 F
->setLinkage(GlobalValue::InternalLinkage
);
685 F
->addFnAttr(Attribute::NoInline
);
687 BB
= BasicBlock::Create(*Ctx
, "entry", F
);
688 Builder
.SetInsertPoint(BB
);
690 FTy
= FunctionType::get(Type::getInt32Ty(*Ctx
),
691 PointerType::get(FTy
, 0), false);
692 Constant
*AtExitFn
= M
->getOrInsertFunction("atexit", FTy
);
693 Builder
.CreateCall(AtExitFn
, WriteoutF
);
694 Builder
.CreateRetVoid();
696 appendToGlobalCtors(*M
, F
, 0);
699 void GCOVProfiler::insertIndirectCounterIncrement() {
701 cast
<Function
>(GCOVProfiler::getIncrementIndirectCounterFunc());
702 Fn
->setUnnamedAddr(true);
703 Fn
->setLinkage(GlobalValue::InternalLinkage
);
704 Fn
->addFnAttr(Attribute::NoInline
);
706 Type
*Int32Ty
= Type::getInt32Ty(*Ctx
);
707 Type
*Int64Ty
= Type::getInt64Ty(*Ctx
);
708 Constant
*NegOne
= ConstantInt::get(Int32Ty
, 0xffffffff);
710 // Create basic blocks for function.
711 BasicBlock
*BB
= BasicBlock::Create(*Ctx
, "entry", Fn
);
712 IRBuilder
<> Builder(BB
);
714 BasicBlock
*PredNotNegOne
= BasicBlock::Create(*Ctx
, "", Fn
);
715 BasicBlock
*CounterEnd
= BasicBlock::Create(*Ctx
, "", Fn
);
716 BasicBlock
*Exit
= BasicBlock::Create(*Ctx
, "exit", Fn
);
718 // uint32_t pred = *predecessor;
719 // if (pred == 0xffffffff) return;
720 Argument
*Arg
= Fn
->arg_begin();
721 Arg
->setName("predecessor");
722 Value
*Pred
= Builder
.CreateLoad(Arg
, "pred");
723 Value
*Cond
= Builder
.CreateICmpEQ(Pred
, NegOne
);
724 BranchInst::Create(Exit
, PredNotNegOne
, Cond
, BB
);
726 Builder
.SetInsertPoint(PredNotNegOne
);
728 // uint64_t *counter = counters[pred];
729 // if (!counter) return;
730 Value
*ZExtPred
= Builder
.CreateZExt(Pred
, Int64Ty
);
731 Arg
= llvm::next(Fn
->arg_begin());
732 Arg
->setName("counters");
733 Value
*GEP
= Builder
.CreateGEP(Arg
, ZExtPred
);
734 Value
*Counter
= Builder
.CreateLoad(GEP
, "counter");
735 Cond
= Builder
.CreateICmpEQ(Counter
,
736 Constant::getNullValue(Int64Ty
->getPointerTo()));
737 Builder
.CreateCondBr(Cond
, Exit
, CounterEnd
);
740 Builder
.SetInsertPoint(CounterEnd
);
741 Value
*Add
= Builder
.CreateAdd(Builder
.CreateLoad(Counter
),
742 ConstantInt::get(Int64Ty
, 1));
743 Builder
.CreateStore(Add
, Counter
);
744 Builder
.CreateBr(Exit
);
746 // Fill in the exit block.
747 Builder
.SetInsertPoint(Exit
);
748 Builder
.CreateRetVoid();
752 insertFlush(ArrayRef
<std::pair
<GlobalVariable
*, MDNode
*> > CountersBySP
) {
753 FunctionType
*FTy
= FunctionType::get(Type::getVoidTy(*Ctx
), false);
754 Function
*FlushF
= M
->getFunction("__gcov_flush");
756 FlushF
= Function::Create(FTy
, GlobalValue::InternalLinkage
,
759 FlushF
->setLinkage(GlobalValue::InternalLinkage
);
760 FlushF
->setUnnamedAddr(true);
762 BasicBlock
*Entry
= BasicBlock::Create(*Ctx
, "entry", FlushF
);
764 // Write out the current counters.
765 Constant
*WriteoutF
= M
->getFunction("__llvm_gcov_writeout");
766 assert(WriteoutF
&& "Need to create the writeout function first!");
768 IRBuilder
<> Builder(Entry
);
769 Builder
.CreateCall(WriteoutF
);
771 // Zero out the counters.
772 for (ArrayRef
<std::pair
<GlobalVariable
*, MDNode
*> >::iterator
773 I
= CountersBySP
.begin(), E
= CountersBySP
.end();
775 GlobalVariable
*GV
= I
->first
;
776 Constant
*Null
= Constant::getNullValue(GV
->getType()->getElementType());
777 Builder
.CreateStore(Null
, GV
);
780 Type
*RetTy
= FlushF
->getReturnType();
781 if (RetTy
== Type::getVoidTy(*Ctx
))
782 Builder
.CreateRetVoid();
783 else if (RetTy
->isIntegerTy())
784 // Used if __gcov_flush was implicitly declared.
785 Builder
.CreateRet(ConstantInt::get(RetTy
, 0));
787 report_fatal_error("invalid return type for __gcov_flush");