GCOVProfiling.cpp revision 234353
1//===- GCOVProfiling.cpp - Insert edge counters for gcov profiling --------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 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" 13// file on exit. 14// 15//===----------------------------------------------------------------------===// 16 17#define DEBUG_TYPE "insert-gcov-profiling" 18 19#include "ProfilingUtils.h" 20#include "llvm/Transforms/Instrumentation.h" 21#include "llvm/Analysis/DebugInfo.h" 22#include "llvm/Module.h" 23#include "llvm/Pass.h" 24#include "llvm/Instructions.h" 25#include "llvm/Support/raw_ostream.h" 26#include "llvm/Support/Debug.h" 27#include "llvm/Support/DebugLoc.h" 28#include "llvm/Support/InstIterator.h" 29#include "llvm/Support/IRBuilder.h" 30#include "llvm/Support/PathV2.h" 31#include "llvm/ADT/DenseMap.h" 32#include "llvm/ADT/Statistic.h" 33#include "llvm/ADT/STLExtras.h" 34#include "llvm/ADT/StringExtras.h" 35#include "llvm/ADT/StringMap.h" 36#include "llvm/ADT/UniqueVector.h" 37#include <string> 38#include <utility> 39using namespace llvm; 40 41namespace { 42 class GCOVProfiler : public ModulePass { 43 public: 44 static char ID; 45 GCOVProfiler() 46 : ModulePass(ID), EmitNotes(true), EmitData(true), Use402Format(false), 47 UseExtraChecksum(false) { 48 initializeGCOVProfilerPass(*PassRegistry::getPassRegistry()); 49 } 50 GCOVProfiler(bool EmitNotes, bool EmitData, bool use402Format = false, 51 bool useExtraChecksum = false) 52 : ModulePass(ID), EmitNotes(EmitNotes), EmitData(EmitData), 53 Use402Format(use402Format), UseExtraChecksum(useExtraChecksum) { 54 assert((EmitNotes || EmitData) && "GCOVProfiler asked to do nothing?"); 55 initializeGCOVProfilerPass(*PassRegistry::getPassRegistry()); 56 } 57 virtual const char *getPassName() const { 58 return "GCOV Profiler"; 59 } 60 61 private: 62 bool runOnModule(Module &M); 63 64 // Create the GCNO files for the Module based on DebugInfo. 65 void emitGCNO(); 66 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(); 70 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(); 77 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(); 81 82 // Produce a table of pointers to counters, by predecessor and successor 83 // block number. 84 GlobalVariable *buildEdgeLookupTable(Function *F, 85 GlobalVariable *Counter, 86 const UniqueVector<BasicBlock *> &Preds, 87 const UniqueVector<BasicBlock *> &Succs); 88 89 // Add the function to write out all our counters to the global destructor 90 // list. 91 void insertCounterWriteout(SmallVector<std::pair<GlobalVariable *, 92 MDNode *>, 8> &); 93 94 std::string mangleName(DICompileUnit CU, std::string NewStem); 95 96 bool EmitNotes; 97 bool EmitData; 98 bool Use402Format; 99 bool UseExtraChecksum; 100 101 Module *M; 102 LLVMContext *Ctx; 103 }; 104} 105 106char GCOVProfiler::ID = 0; 107INITIALIZE_PASS(GCOVProfiler, "insert-gcov-profiling", 108 "Insert instrumentation for GCOV profiling", false, false) 109 110ModulePass *llvm::createGCOVProfilerPass(bool EmitNotes, bool EmitData, 111 bool Use402Format, 112 bool UseExtraChecksum) { 113 return new GCOVProfiler(EmitNotes, EmitData, Use402Format, UseExtraChecksum); 114} 115 116namespace { 117 class GCOVRecord { 118 protected: 119 static const char *LinesTag; 120 static const char *FunctionTag; 121 static const char *BlockTag; 122 static const char *EdgeTag; 123 124 GCOVRecord() {} 125 126 void writeBytes(const char *Bytes, int Size) { 127 os->write(Bytes, Size); 128 } 129 130 void write(uint32_t i) { 131 writeBytes(reinterpret_cast<char*>(&i), 4); 132 } 133 134 // Returns the length measured in 4-byte blocks that will be used to 135 // represent this string in a GCOV file 136 unsigned lengthOfGCOVString(StringRef s) { 137 // A GCOV string is a length, followed by a NUL, then between 0 and 3 NULs 138 // padding out to the next 4-byte word. The length is measured in 4-byte 139 // words including padding, not bytes of actual string. 140 return (s.size() / 4) + 1; 141 } 142 143 void writeGCOVString(StringRef s) { 144 uint32_t Len = lengthOfGCOVString(s); 145 write(Len); 146 writeBytes(s.data(), s.size()); 147 148 // Write 1 to 4 bytes of NUL padding. 149 assert((unsigned)(4 - (s.size() % 4)) > 0); 150 assert((unsigned)(4 - (s.size() % 4)) <= 4); 151 writeBytes("\0\0\0\0", 4 - (s.size() % 4)); 152 } 153 154 raw_ostream *os; 155 }; 156 const char *GCOVRecord::LinesTag = "\0\0\x45\x01"; 157 const char *GCOVRecord::FunctionTag = "\0\0\0\1"; 158 const char *GCOVRecord::BlockTag = "\0\0\x41\x01"; 159 const char *GCOVRecord::EdgeTag = "\0\0\x43\x01"; 160 161 class GCOVFunction; 162 class GCOVBlock; 163 164 // Constructed only by requesting it from a GCOVBlock, this object stores a 165 // list of line numbers and a single filename, representing lines that belong 166 // to the block. 167 class GCOVLines : public GCOVRecord { 168 public: 169 void addLine(uint32_t Line) { 170 Lines.push_back(Line); 171 } 172 173 uint32_t length() { 174 // Here 2 = 1 for string length + 1 for '0' id#. 175 return lengthOfGCOVString(Filename) + 2 + Lines.size(); 176 } 177 178 void writeOut() { 179 write(0); 180 writeGCOVString(Filename); 181 for (int i = 0, e = Lines.size(); i != e; ++i) 182 write(Lines[i]); 183 } 184 185 GCOVLines(StringRef F, raw_ostream *os) 186 : Filename(F) { 187 this->os = os; 188 } 189 190 private: 191 StringRef Filename; 192 SmallVector<uint32_t, 32> Lines; 193 }; 194 195 // Represent a basic block in GCOV. Each block has a unique number in the 196 // function, number of lines belonging to each block, and a set of edges to 197 // other blocks. 198 class GCOVBlock : public GCOVRecord { 199 public: 200 GCOVLines &getFile(StringRef Filename) { 201 GCOVLines *&Lines = LinesByFile[Filename]; 202 if (!Lines) { 203 Lines = new GCOVLines(Filename, os); 204 } 205 return *Lines; 206 } 207 208 void addEdge(GCOVBlock &Successor) { 209 OutEdges.push_back(&Successor); 210 } 211 212 void writeOut() { 213 uint32_t Len = 3; 214 for (StringMap<GCOVLines *>::iterator I = LinesByFile.begin(), 215 E = LinesByFile.end(); I != E; ++I) { 216 Len += I->second->length(); 217 } 218 219 writeBytes(LinesTag, 4); 220 write(Len); 221 write(Number); 222 for (StringMap<GCOVLines *>::iterator I = LinesByFile.begin(), 223 E = LinesByFile.end(); I != E; ++I) 224 I->second->writeOut(); 225 write(0); 226 write(0); 227 } 228 229 ~GCOVBlock() { 230 DeleteContainerSeconds(LinesByFile); 231 } 232 233 private: 234 friend class GCOVFunction; 235 236 GCOVBlock(uint32_t Number, raw_ostream *os) 237 : Number(Number) { 238 this->os = os; 239 } 240 241 uint32_t Number; 242 StringMap<GCOVLines *> LinesByFile; 243 SmallVector<GCOVBlock *, 4> OutEdges; 244 }; 245 246 // A function has a unique identifier, a checksum (we leave as zero) and a 247 // set of blocks and a map of edges between blocks. This is the only GCOV 248 // object users can construct, the blocks and lines will be rooted here. 249 class GCOVFunction : public GCOVRecord { 250 public: 251 GCOVFunction(DISubprogram SP, raw_ostream *os, 252 bool Use402Format, bool UseExtraChecksum) { 253 this->os = os; 254 255 Function *F = SP.getFunction(); 256 DEBUG(dbgs() << "Function: " << F->getName() << "\n"); 257 uint32_t i = 0; 258 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 259 Blocks[BB] = new GCOVBlock(i++, os); 260 } 261 ReturnBlock = new GCOVBlock(i++, os); 262 263 writeBytes(FunctionTag, 4); 264 uint32_t BlockLen = 1 + 1 + 1 + lengthOfGCOVString(SP.getName()) + 265 1 + lengthOfGCOVString(SP.getFilename()) + 1; 266 if (UseExtraChecksum) 267 ++BlockLen; 268 write(BlockLen); 269 uint32_t Ident = reinterpret_cast<intptr_t>((MDNode*)SP); 270 write(Ident); 271 write(0); // lineno checksum 272 if (UseExtraChecksum) 273 write(0); // cfg checksum 274 writeGCOVString(SP.getName()); 275 writeGCOVString(SP.getFilename()); 276 write(SP.getLineNumber()); 277 } 278 279 ~GCOVFunction() { 280 DeleteContainerSeconds(Blocks); 281 delete ReturnBlock; 282 } 283 284 GCOVBlock &getBlock(BasicBlock *BB) { 285 return *Blocks[BB]; 286 } 287 288 GCOVBlock &getReturnBlock() { 289 return *ReturnBlock; 290 } 291 292 void writeOut() { 293 // Emit count of blocks. 294 writeBytes(BlockTag, 4); 295 write(Blocks.size() + 1); 296 for (int i = 0, e = Blocks.size() + 1; i != e; ++i) { 297 write(0); // No flags on our blocks. 298 } 299 DEBUG(dbgs() << Blocks.size() << " blocks.\n"); 300 301 // Emit edges between blocks. 302 for (DenseMap<BasicBlock *, GCOVBlock *>::iterator I = Blocks.begin(), 303 E = Blocks.end(); I != E; ++I) { 304 GCOVBlock &Block = *I->second; 305 if (Block.OutEdges.empty()) continue; 306 307 writeBytes(EdgeTag, 4); 308 write(Block.OutEdges.size() * 2 + 1); 309 write(Block.Number); 310 for (int i = 0, e = Block.OutEdges.size(); i != e; ++i) { 311 DEBUG(dbgs() << Block.Number << " -> " << Block.OutEdges[i]->Number 312 << "\n"); 313 write(Block.OutEdges[i]->Number); 314 write(0); // no flags 315 } 316 } 317 318 // Emit lines for each block. 319 for (DenseMap<BasicBlock *, GCOVBlock *>::iterator I = Blocks.begin(), 320 E = Blocks.end(); I != E; ++I) { 321 I->second->writeOut(); 322 } 323 } 324 325 private: 326 DenseMap<BasicBlock *, GCOVBlock *> Blocks; 327 GCOVBlock *ReturnBlock; 328 }; 329} 330 331std::string GCOVProfiler::mangleName(DICompileUnit CU, std::string NewStem) { 332 if (NamedMDNode *GCov = M->getNamedMetadata("llvm.gcov")) { 333 for (int i = 0, e = GCov->getNumOperands(); i != e; ++i) { 334 MDNode *N = GCov->getOperand(i); 335 if (N->getNumOperands() != 2) continue; 336 MDString *GCovFile = dyn_cast<MDString>(N->getOperand(0)); 337 MDNode *CompileUnit = dyn_cast<MDNode>(N->getOperand(1)); 338 if (!GCovFile || !CompileUnit) continue; 339 if (CompileUnit == CU) { 340 SmallString<128> Filename = GCovFile->getString(); 341 sys::path::replace_extension(Filename, NewStem); 342 return Filename.str(); 343 } 344 } 345 } 346 347 SmallString<128> Filename = CU.getFilename(); 348 sys::path::replace_extension(Filename, NewStem); 349 return sys::path::filename(Filename.str()); 350} 351 352bool GCOVProfiler::runOnModule(Module &M) { 353 this->M = &M; 354 Ctx = &M.getContext(); 355 356 if (EmitNotes) emitGCNO(); 357 if (EmitData) return emitProfileArcs(); 358 return false; 359} 360 361void GCOVProfiler::emitGCNO() { 362 NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); 363 if (!CU_Nodes) return; 364 365 for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { 366 // Each compile unit gets its own .gcno file. This means that whether we run 367 // this pass over the original .o's as they're produced, or run it after 368 // LTO, we'll generate the same .gcno files. 369 370 DICompileUnit CU(CU_Nodes->getOperand(i)); 371 std::string ErrorInfo; 372 raw_fd_ostream out(mangleName(CU, "gcno").c_str(), ErrorInfo, 373 raw_fd_ostream::F_Binary); 374 if (!Use402Format) 375 out.write("oncg*404MVLL", 12); 376 else 377 out.write("oncg*204MVLL", 12); 378 379 DIArray SPs = CU.getSubprograms(); 380 for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { 381 DISubprogram SP(SPs.getElement(i)); 382 if (!SP.Verify()) continue; 383 384 Function *F = SP.getFunction(); 385 if (!F) continue; 386 GCOVFunction Func(SP, &out, Use402Format, UseExtraChecksum); 387 388 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 389 GCOVBlock &Block = Func.getBlock(BB); 390 TerminatorInst *TI = BB->getTerminator(); 391 if (int successors = TI->getNumSuccessors()) { 392 for (int i = 0; i != successors; ++i) { 393 Block.addEdge(Func.getBlock(TI->getSuccessor(i))); 394 } 395 } else if (isa<ReturnInst>(TI)) { 396 Block.addEdge(Func.getReturnBlock()); 397 } 398 399 uint32_t Line = 0; 400 for (BasicBlock::iterator I = BB->begin(), IE = BB->end(); 401 I != IE; ++I) { 402 const DebugLoc &Loc = I->getDebugLoc(); 403 if (Loc.isUnknown()) continue; 404 if (Line == Loc.getLine()) continue; 405 Line = Loc.getLine(); 406 if (SP != getDISubprogram(Loc.getScope(*Ctx))) continue; 407 408 GCOVLines &Lines = Block.getFile(SP.getFilename()); 409 Lines.addLine(Loc.getLine()); 410 } 411 } 412 Func.writeOut(); 413 } 414 out.write("\0\0\0\0\0\0\0\0", 8); // EOF 415 out.close(); 416 } 417} 418 419bool GCOVProfiler::emitProfileArcs() { 420 NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); 421 if (!CU_Nodes) return false; 422 423 bool Result = false; 424 for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { 425 DICompileUnit CU(CU_Nodes->getOperand(i)); 426 DIArray SPs = CU.getSubprograms(); 427 SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> CountersBySP; 428 for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { 429 DISubprogram SP(SPs.getElement(i)); 430 if (!SP.Verify()) continue; 431 Function *F = SP.getFunction(); 432 if (!F) continue; 433 if (!Result) Result = true; 434 unsigned Edges = 0; 435 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 436 TerminatorInst *TI = BB->getTerminator(); 437 if (isa<ReturnInst>(TI)) 438 ++Edges; 439 else 440 Edges += TI->getNumSuccessors(); 441 } 442 443 ArrayType *CounterTy = 444 ArrayType::get(Type::getInt64Ty(*Ctx), Edges); 445 GlobalVariable *Counters = 446 new GlobalVariable(*M, CounterTy, false, 447 GlobalValue::InternalLinkage, 448 Constant::getNullValue(CounterTy), 449 "__llvm_gcov_ctr", 0, false, 0); 450 CountersBySP.push_back(std::make_pair(Counters, (MDNode*)SP)); 451 452 UniqueVector<BasicBlock *> ComplexEdgePreds; 453 UniqueVector<BasicBlock *> ComplexEdgeSuccs; 454 455 unsigned Edge = 0; 456 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 457 TerminatorInst *TI = BB->getTerminator(); 458 int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors(); 459 if (Successors) { 460 IRBuilder<> Builder(TI); 461 462 if (Successors == 1) { 463 Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0, 464 Edge); 465 Value *Count = Builder.CreateLoad(Counter); 466 Count = Builder.CreateAdd(Count, 467 ConstantInt::get(Type::getInt64Ty(*Ctx),1)); 468 Builder.CreateStore(Count, Counter); 469 } else if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { 470 Value *Sel = Builder.CreateSelect( 471 BI->getCondition(), 472 ConstantInt::get(Type::getInt64Ty(*Ctx), Edge), 473 ConstantInt::get(Type::getInt64Ty(*Ctx), Edge + 1)); 474 SmallVector<Value *, 2> Idx; 475 Idx.push_back(Constant::getNullValue(Type::getInt64Ty(*Ctx))); 476 Idx.push_back(Sel); 477 Value *Counter = Builder.CreateInBoundsGEP(Counters, Idx); 478 Value *Count = Builder.CreateLoad(Counter); 479 Count = Builder.CreateAdd(Count, 480 ConstantInt::get(Type::getInt64Ty(*Ctx),1)); 481 Builder.CreateStore(Count, Counter); 482 } else { 483 ComplexEdgePreds.insert(BB); 484 for (int i = 0; i != Successors; ++i) 485 ComplexEdgeSuccs.insert(TI->getSuccessor(i)); 486 } 487 Edge += Successors; 488 } 489 } 490 491 if (!ComplexEdgePreds.empty()) { 492 GlobalVariable *EdgeTable = 493 buildEdgeLookupTable(F, Counters, 494 ComplexEdgePreds, ComplexEdgeSuccs); 495 GlobalVariable *EdgeState = getEdgeStateValue(); 496 497 Type *Int32Ty = Type::getInt32Ty(*Ctx); 498 for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) { 499 IRBuilder<> Builder(ComplexEdgePreds[i+1]->getTerminator()); 500 Builder.CreateStore(ConstantInt::get(Int32Ty, i), EdgeState); 501 } 502 for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) { 503 // call runtime to perform increment 504 BasicBlock::iterator InsertPt = 505 ComplexEdgeSuccs[i+1]->getFirstInsertionPt(); 506 IRBuilder<> Builder(InsertPt); 507 Value *CounterPtrArray = 508 Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0, 509 i * ComplexEdgePreds.size()); 510 Builder.CreateCall2(getIncrementIndirectCounterFunc(), 511 EdgeState, CounterPtrArray); 512 // clear the predecessor number 513 Builder.CreateStore(ConstantInt::get(Int32Ty, 0xffffffff), EdgeState); 514 } 515 } 516 } 517 insertCounterWriteout(CountersBySP); 518 } 519 return Result; 520} 521 522// All edges with successors that aren't branches are "complex", because it 523// requires complex logic to pick which counter to update. 524GlobalVariable *GCOVProfiler::buildEdgeLookupTable( 525 Function *F, 526 GlobalVariable *Counters, 527 const UniqueVector<BasicBlock *> &Preds, 528 const UniqueVector<BasicBlock *> &Succs) { 529 // TODO: support invoke, threads. We rely on the fact that nothing can modify 530 // the whole-Module pred edge# between the time we set it and the time we next 531 // read it. Threads and invoke make this untrue. 532 533 // emit [(succs * preds) x i64*], logically [succ x [pred x i64*]]. 534 Type *Int64PtrTy = Type::getInt64PtrTy(*Ctx); 535 ArrayType *EdgeTableTy = ArrayType::get( 536 Int64PtrTy, Succs.size() * Preds.size()); 537 538 Constant **EdgeTable = new Constant*[Succs.size() * Preds.size()]; 539 Constant *NullValue = Constant::getNullValue(Int64PtrTy); 540 for (int i = 0, ie = Succs.size() * Preds.size(); i != ie; ++i) 541 EdgeTable[i] = NullValue; 542 543 unsigned Edge = 0; 544 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 545 TerminatorInst *TI = BB->getTerminator(); 546 int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors(); 547 if (Successors > 1 && !isa<BranchInst>(TI) && !isa<ReturnInst>(TI)) { 548 for (int i = 0; i != Successors; ++i) { 549 BasicBlock *Succ = TI->getSuccessor(i); 550 IRBuilder<> builder(Succ); 551 Value *Counter = builder.CreateConstInBoundsGEP2_64(Counters, 0, 552 Edge + i); 553 EdgeTable[((Succs.idFor(Succ)-1) * Preds.size()) + 554 (Preds.idFor(BB)-1)] = cast<Constant>(Counter); 555 } 556 } 557 Edge += Successors; 558 } 559 560 ArrayRef<Constant*> V(&EdgeTable[0], Succs.size() * Preds.size()); 561 GlobalVariable *EdgeTableGV = 562 new GlobalVariable( 563 *M, EdgeTableTy, true, GlobalValue::InternalLinkage, 564 ConstantArray::get(EdgeTableTy, V), 565 "__llvm_gcda_edge_table"); 566 EdgeTableGV->setUnnamedAddr(true); 567 return EdgeTableGV; 568} 569 570Constant *GCOVProfiler::getStartFileFunc() { 571 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), 572 Type::getInt8PtrTy(*Ctx), false); 573 return M->getOrInsertFunction("llvm_gcda_start_file", FTy); 574} 575 576Constant *GCOVProfiler::getIncrementIndirectCounterFunc() { 577 Type *Args[] = { 578 Type::getInt32PtrTy(*Ctx), // uint32_t *predecessor 579 Type::getInt64PtrTy(*Ctx)->getPointerTo(), // uint64_t **state_table_row 580 }; 581 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), 582 Args, false); 583 return M->getOrInsertFunction("llvm_gcda_increment_indirect_counter", FTy); 584} 585 586Constant *GCOVProfiler::getEmitFunctionFunc() { 587 Type *Args[2] = { 588 Type::getInt32Ty(*Ctx), // uint32_t ident 589 Type::getInt8PtrTy(*Ctx), // const char *function_name 590 }; 591 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), 592 Args, false); 593 return M->getOrInsertFunction("llvm_gcda_emit_function", FTy); 594} 595 596Constant *GCOVProfiler::getEmitArcsFunc() { 597 Type *Args[] = { 598 Type::getInt32Ty(*Ctx), // uint32_t num_counters 599 Type::getInt64PtrTy(*Ctx), // uint64_t *counters 600 }; 601 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), 602 Args, false); 603 return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy); 604} 605 606Constant *GCOVProfiler::getEndFileFunc() { 607 FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 608 return M->getOrInsertFunction("llvm_gcda_end_file", FTy); 609} 610 611GlobalVariable *GCOVProfiler::getEdgeStateValue() { 612 GlobalVariable *GV = M->getGlobalVariable("__llvm_gcov_global_state_pred"); 613 if (!GV) { 614 GV = new GlobalVariable(*M, Type::getInt32Ty(*Ctx), false, 615 GlobalValue::InternalLinkage, 616 ConstantInt::get(Type::getInt32Ty(*Ctx), 617 0xffffffff), 618 "__llvm_gcov_global_state_pred"); 619 GV->setUnnamedAddr(true); 620 } 621 return GV; 622} 623 624void GCOVProfiler::insertCounterWriteout( 625 SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> &CountersBySP) { 626 FunctionType *WriteoutFTy = 627 FunctionType::get(Type::getVoidTy(*Ctx), false); 628 Function *WriteoutF = Function::Create(WriteoutFTy, 629 GlobalValue::InternalLinkage, 630 "__llvm_gcov_writeout", M); 631 WriteoutF->setUnnamedAddr(true); 632 BasicBlock *BB = BasicBlock::Create(*Ctx, "", WriteoutF); 633 IRBuilder<> Builder(BB); 634 635 Constant *StartFile = getStartFileFunc(); 636 Constant *EmitFunction = getEmitFunctionFunc(); 637 Constant *EmitArcs = getEmitArcsFunc(); 638 Constant *EndFile = getEndFileFunc(); 639 640 NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); 641 if (CU_Nodes) { 642 for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { 643 DICompileUnit compile_unit(CU_Nodes->getOperand(i)); 644 std::string FilenameGcda = mangleName(compile_unit, "gcda"); 645 Builder.CreateCall(StartFile, 646 Builder.CreateGlobalStringPtr(FilenameGcda)); 647 for (SmallVector<std::pair<GlobalVariable *, MDNode *>, 8>::iterator 648 I = CountersBySP.begin(), E = CountersBySP.end(); 649 I != E; ++I) { 650 DISubprogram SP(I->second); 651 intptr_t ident = reinterpret_cast<intptr_t>(I->second); 652 Builder.CreateCall2(EmitFunction, 653 ConstantInt::get(Type::getInt32Ty(*Ctx), ident), 654 Builder.CreateGlobalStringPtr(SP.getName())); 655 656 GlobalVariable *GV = I->first; 657 unsigned Arcs = 658 cast<ArrayType>(GV->getType()->getElementType())->getNumElements(); 659 Builder.CreateCall2(EmitArcs, 660 ConstantInt::get(Type::getInt32Ty(*Ctx), Arcs), 661 Builder.CreateConstGEP2_64(GV, 0, 0)); 662 } 663 Builder.CreateCall(EndFile); 664 } 665 } 666 Builder.CreateRetVoid(); 667 668 InsertProfilingShutdownCall(WriteoutF, M); 669} 670