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> 39 using namespace llvm; 40 41 namespace { 42 class GCOVProfiler : public ModulePass { 43 bool runOnModule(Module &M); 44 public: 45 static char ID; 46 GCOVProfiler() 47 : ModulePass(ID), EmitNotes(true), EmitData(true) { 48 initializeGCOVProfilerPass(*PassRegistry::getPassRegistry()); 49 } 50 GCOVProfiler(bool EmitNotes, bool EmitData) 51 : ModulePass(ID), EmitNotes(EmitNotes), EmitData(EmitData) { 52 assert((EmitNotes || EmitData) && "GCOVProfiler asked to do nothing?"); 53 initializeGCOVProfilerPass(*PassRegistry::getPassRegistry()); 54 } 55 virtual const char *getPassName() const { 56 return "GCOV Profiler"; 57 } 58 59 private: 60 // Create the GCNO files for the Module based on DebugInfo. 61 void emitGCNO(DebugInfoFinder &DIF); 62 63 // Modify the program to track transitions along edges and call into the 64 // profiling runtime to emit .gcda files when run. 65 bool emitProfileArcs(DebugInfoFinder &DIF); 66 67 // Get pointers to the functions in the runtime library. 68 Constant *getStartFileFunc(); 69 Constant *getIncrementIndirectCounterFunc(); 70 Constant *getEmitFunctionFunc(); 71 Constant *getEmitArcsFunc(); 72 Constant *getEndFileFunc(); 73 74 // Create or retrieve an i32 state value that is used to represent the 75 // pred block number for certain non-trivial edges. 76 GlobalVariable *getEdgeStateValue(); 77 78 // Produce a table of pointers to counters, by predecessor and successor 79 // block number. 80 GlobalVariable *buildEdgeLookupTable(Function *F, 81 GlobalVariable *Counter, 82 const UniqueVector<BasicBlock *> &Preds, 83 const UniqueVector<BasicBlock *> &Succs); 84 85 // Add the function to write out all our counters to the global destructor 86 // list. 87 void insertCounterWriteout(DebugInfoFinder &, 88 SmallVector<std::pair<GlobalVariable *, 89 uint32_t>, 8> &); 90 91 bool EmitNotes; 92 bool EmitData; 93 94 Module *M; 95 LLVMContext *Ctx; 96 }; 97 } 98 99 char GCOVProfiler::ID = 0; 100 INITIALIZE_PASS(GCOVProfiler, "insert-gcov-profiling", 101 "Insert instrumentation for GCOV profiling", false, false) 102 103 ModulePass *llvm::createGCOVProfilerPass(bool EmitNotes, bool EmitData) { 104 return new GCOVProfiler(EmitNotes, EmitData); 105 } 106 107 static DISubprogram findSubprogram(DIScope Scope) { 108 while (!Scope.isSubprogram()) { 109 assert(Scope.isLexicalBlock() && 110 "Debug location not lexical block or subprogram"); 111 Scope = DILexicalBlock(Scope).getContext(); 112 } 113 return DISubprogram(Scope); 114 } 115 116 namespace { 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() + 5) / 4; 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 return lengthOfGCOVString(Filename) + 2 + Lines.size(); 175 } 176 177 private: 178 friend class GCOVBlock; 179 180 GCOVLines(std::string Filename, raw_ostream *os) 181 : Filename(Filename) { 182 this->os = os; 183 } 184 185 std::string Filename; 186 SmallVector<uint32_t, 32> Lines; 187 }; 188 189 // Represent a basic block in GCOV. Each block has a unique number in the 190 // function, number of lines belonging to each block, and a set of edges to 191 // other blocks. 192 class GCOVBlock : public GCOVRecord { 193 public: 194 GCOVLines &getFile(std::string Filename) { 195 GCOVLines *&Lines = LinesByFile[Filename]; 196 if (!Lines) { 197 Lines = new GCOVLines(Filename, os); 198 } 199 return *Lines; 200 } 201 202 void addEdge(GCOVBlock &Successor) { 203 OutEdges.push_back(&Successor); 204 } 205 206 void writeOut() { 207 uint32_t Len = 3; 208 for (StringMap<GCOVLines *>::iterator I = LinesByFile.begin(), 209 E = LinesByFile.end(); I != E; ++I) { 210 Len += I->second->length(); 211 } 212 213 writeBytes(LinesTag, 4); 214 write(Len); 215 write(Number); 216 for (StringMap<GCOVLines *>::iterator I = LinesByFile.begin(), 217 E = LinesByFile.end(); I != E; ++I) { 218 write(0); 219 writeGCOVString(I->second->Filename); 220 for (int i = 0, e = I->second->Lines.size(); i != e; ++i) { 221 write(I->second->Lines[i]); 222 } 223 } 224 write(0); 225 write(0); 226 } 227 228 ~GCOVBlock() { 229 DeleteContainerSeconds(LinesByFile); 230 } 231 232 private: 233 friend class GCOVFunction; 234 235 GCOVBlock(uint32_t Number, raw_ostream *os) 236 : Number(Number) { 237 this->os = os; 238 } 239 240 uint32_t Number; 241 StringMap<GCOVLines *> LinesByFile; 242 SmallVector<GCOVBlock *, 4> OutEdges; 243 }; 244 245 // A function has a unique identifier, a checksum (we leave as zero) and a 246 // set of blocks and a map of edges between blocks. This is the only GCOV 247 // object users can construct, the blocks and lines will be rooted here. 248 class GCOVFunction : public GCOVRecord { 249 public: 250 GCOVFunction(DISubprogram SP, raw_ostream *os) { 251 this->os = os; 252 253 Function *F = SP.getFunction(); 254 uint32_t i = 0; 255 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 256 Blocks[BB] = new GCOVBlock(i++, os); 257 } 258 ReturnBlock = new GCOVBlock(i++, os); 259 260 writeBytes(FunctionTag, 4); 261 uint32_t BlockLen = 1 + 1 + 1 + lengthOfGCOVString(SP.getName()) + 262 1 + lengthOfGCOVString(SP.getFilename()) + 1; 263 write(BlockLen); 264 uint32_t Ident = reinterpret_cast<intptr_t>((MDNode*)SP); 265 write(Ident); 266 write(0); // checksum 267 writeGCOVString(SP.getName()); 268 writeGCOVString(SP.getFilename()); 269 write(SP.getLineNumber()); 270 } 271 272 ~GCOVFunction() { 273 DeleteContainerSeconds(Blocks); 274 delete ReturnBlock; 275 } 276 277 GCOVBlock &getBlock(BasicBlock *BB) { 278 return *Blocks[BB]; 279 } 280 281 GCOVBlock &getReturnBlock() { 282 return *ReturnBlock; 283 } 284 285 void writeOut() { 286 // Emit count of blocks. 287 writeBytes(BlockTag, 4); 288 write(Blocks.size() + 1); 289 for (int i = 0, e = Blocks.size() + 1; i != e; ++i) { 290 write(0); // No flags on our blocks. 291 } 292 293 // Emit edges between blocks. 294 for (DenseMap<BasicBlock *, GCOVBlock *>::iterator I = Blocks.begin(), 295 E = Blocks.end(); I != E; ++I) { 296 GCOVBlock &Block = *I->second; 297 if (Block.OutEdges.empty()) continue; 298 299 writeBytes(EdgeTag, 4); 300 write(Block.OutEdges.size() * 2 + 1); 301 write(Block.Number); 302 for (int i = 0, e = Block.OutEdges.size(); i != e; ++i) { 303 write(Block.OutEdges[i]->Number); 304 write(0); // no flags 305 } 306 } 307 308 // Emit lines for each block. 309 for (DenseMap<BasicBlock *, GCOVBlock *>::iterator I = Blocks.begin(), 310 E = Blocks.end(); I != E; ++I) { 311 I->second->writeOut(); 312 } 313 } 314 315 private: 316 DenseMap<BasicBlock *, GCOVBlock *> Blocks; 317 GCOVBlock *ReturnBlock; 318 }; 319 } 320 321 // Replace the stem of a file, or add one if missing. 322 static std::string replaceStem(std::string OrigFilename, std::string NewStem) { 323 return (sys::path::stem(OrigFilename) + "." + NewStem).str(); 324 } 325 326 bool GCOVProfiler::runOnModule(Module &M) { 327 this->M = &M; 328 Ctx = &M.getContext(); 329 330 DebugInfoFinder DIF; 331 DIF.processModule(M); 332 333 if (EmitNotes) emitGCNO(DIF); 334 if (EmitData) return emitProfileArcs(DIF); 335 return false; 336 } 337 338 void GCOVProfiler::emitGCNO(DebugInfoFinder &DIF) { 339 DenseMap<const MDNode *, raw_fd_ostream *> GcnoFiles; 340 for (DebugInfoFinder::iterator I = DIF.compile_unit_begin(), 341 E = DIF.compile_unit_end(); I != E; ++I) { 342 // Each compile unit gets its own .gcno file. This means that whether we run 343 // this pass over the original .o's as they're produced, or run it after 344 // LTO, we'll generate the same .gcno files. 345 346 DICompileUnit CU(*I); 347 raw_fd_ostream *&out = GcnoFiles[CU]; 348 std::string ErrorInfo; 349 out = new raw_fd_ostream(replaceStem(CU.getFilename(), "gcno").c_str(), 350 ErrorInfo, raw_fd_ostream::F_Binary); 351 out->write("oncg*404MVLL", 12); 352 } 353 354 for (DebugInfoFinder::iterator SPI = DIF.subprogram_begin(), 355 SPE = DIF.subprogram_end(); SPI != SPE; ++SPI) { 356 DISubprogram SP(*SPI); 357 raw_fd_ostream *&os = GcnoFiles[SP.getCompileUnit()]; 358 359 Function *F = SP.getFunction(); 360 if (!F) continue; 361 GCOVFunction Func(SP, os); 362 363 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 364 GCOVBlock &Block = Func.getBlock(BB); 365 TerminatorInst *TI = BB->getTerminator(); 366 if (int successors = TI->getNumSuccessors()) { 367 for (int i = 0; i != successors; ++i) { 368 Block.addEdge(Func.getBlock(TI->getSuccessor(i))); 369 } 370 } else if (isa<ReturnInst>(TI)) { 371 Block.addEdge(Func.getReturnBlock()); 372 } 373 374 uint32_t Line = 0; 375 for (BasicBlock::iterator I = BB->begin(), IE = BB->end(); I != IE; ++I) { 376 const DebugLoc &Loc = I->getDebugLoc(); 377 if (Loc.isUnknown()) continue; 378 if (Line == Loc.getLine()) continue; 379 Line = Loc.getLine(); 380 if (SP != findSubprogram(DIScope(Loc.getScope(*Ctx)))) continue; 381 382 GCOVLines &Lines = Block.getFile(SP.getFilename()); 383 Lines.addLine(Loc.getLine()); 384 } 385 } 386 Func.writeOut(); 387 } 388 389 for (DenseMap<const MDNode *, raw_fd_ostream *>::iterator 390 I = GcnoFiles.begin(), E = GcnoFiles.end(); I != E; ++I) { 391 raw_fd_ostream *&out = I->second; 392 out->write("\0\0\0\0\0\0\0\0", 8); // EOF 393 out->close(); 394 delete out; 395 } 396 } 397 398 bool GCOVProfiler::emitProfileArcs(DebugInfoFinder &DIF) { 399 if (DIF.subprogram_begin() == DIF.subprogram_end()) 400 return false; 401 402 SmallVector<std::pair<GlobalVariable *, uint32_t>, 8> CountersByIdent; 403 for (DebugInfoFinder::iterator SPI = DIF.subprogram_begin(), 404 SPE = DIF.subprogram_end(); SPI != SPE; ++SPI) { 405 DISubprogram SP(*SPI); 406 Function *F = SP.getFunction(); 407 if (!F) continue; 408 409 unsigned Edges = 0; 410 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 411 TerminatorInst *TI = BB->getTerminator(); 412 if (isa<ReturnInst>(TI)) 413 ++Edges; 414 else 415 Edges += TI->getNumSuccessors(); 416 } 417 418 const ArrayType *CounterTy = 419 ArrayType::get(Type::getInt64Ty(*Ctx), Edges); 420 GlobalVariable *Counters = 421 new GlobalVariable(*M, CounterTy, false, 422 GlobalValue::InternalLinkage, 423 Constant::getNullValue(CounterTy), 424 "__llvm_gcov_ctr", 0, false, 0); 425 CountersByIdent.push_back( 426 std::make_pair(Counters, reinterpret_cast<intptr_t>((MDNode*)SP))); 427 428 UniqueVector<BasicBlock *> ComplexEdgePreds; 429 UniqueVector<BasicBlock *> ComplexEdgeSuccs; 430 431 unsigned Edge = 0; 432 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 433 TerminatorInst *TI = BB->getTerminator(); 434 int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors(); 435 if (Successors) { 436 IRBuilder<> Builder(TI); 437 438 if (Successors == 1) { 439 Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0, 440 Edge); 441 Value *Count = Builder.CreateLoad(Counter); 442 Count = Builder.CreateAdd(Count, 443 ConstantInt::get(Type::getInt64Ty(*Ctx),1)); 444 Builder.CreateStore(Count, Counter); 445 } else if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { 446 Value *Sel = Builder.CreateSelect( 447 BI->getCondition(), 448 ConstantInt::get(Type::getInt64Ty(*Ctx), Edge), 449 ConstantInt::get(Type::getInt64Ty(*Ctx), Edge + 1)); 450 SmallVector<Value *, 2> Idx; 451 Idx.push_back(Constant::getNullValue(Type::getInt64Ty(*Ctx))); 452 Idx.push_back(Sel); 453 Value *Counter = Builder.CreateInBoundsGEP(Counters, 454 Idx.begin(), Idx.end()); 455 Value *Count = Builder.CreateLoad(Counter); 456 Count = Builder.CreateAdd(Count, 457 ConstantInt::get(Type::getInt64Ty(*Ctx),1)); 458 Builder.CreateStore(Count, Counter); 459 } else { 460 ComplexEdgePreds.insert(BB); 461 for (int i = 0; i != Successors; ++i) 462 ComplexEdgeSuccs.insert(TI->getSuccessor(i)); 463 } 464 Edge += Successors; 465 } 466 } 467 468 if (!ComplexEdgePreds.empty()) { 469 GlobalVariable *EdgeTable = 470 buildEdgeLookupTable(F, Counters, 471 ComplexEdgePreds, ComplexEdgeSuccs); 472 GlobalVariable *EdgeState = getEdgeStateValue(); 473 474 const Type *Int32Ty = Type::getInt32Ty(*Ctx); 475 for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) { 476 IRBuilder<> Builder(ComplexEdgePreds[i+1]->getTerminator()); 477 Builder.CreateStore(ConstantInt::get(Int32Ty, i), EdgeState); 478 } 479 for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) { 480 // call runtime to perform increment 481 IRBuilder<> Builder(ComplexEdgeSuccs[i+1]->getFirstNonPHI()); 482 Value *CounterPtrArray = 483 Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0, 484 i * ComplexEdgePreds.size()); 485 Builder.CreateCall2(getIncrementIndirectCounterFunc(), 486 EdgeState, CounterPtrArray); 487 // clear the predecessor number 488 Builder.CreateStore(ConstantInt::get(Int32Ty, 0xffffffff), EdgeState); 489 } 490 } 491 } 492 493 insertCounterWriteout(DIF, CountersByIdent); 494 495 return true; 496 } 497 498 // All edges with successors that aren't branches are "complex", because it 499 // requires complex logic to pick which counter to update. 500 GlobalVariable *GCOVProfiler::buildEdgeLookupTable( 501 Function *F, 502 GlobalVariable *Counters, 503 const UniqueVector<BasicBlock *> &Preds, 504 const UniqueVector<BasicBlock *> &Succs) { 505 // TODO: support invoke, threads. We rely on the fact that nothing can modify 506 // the whole-Module pred edge# between the time we set it and the time we next 507 // read it. Threads and invoke make this untrue. 508 509 // emit [(succs * preds) x i64*], logically [succ x [pred x i64*]]. 510 const Type *Int64PtrTy = Type::getInt64PtrTy(*Ctx); 511 const ArrayType *EdgeTableTy = ArrayType::get( 512 Int64PtrTy, Succs.size() * Preds.size()); 513 514 Constant **EdgeTable = new Constant*[Succs.size() * Preds.size()]; 515 Constant *NullValue = Constant::getNullValue(Int64PtrTy); 516 for (int i = 0, ie = Succs.size() * Preds.size(); i != ie; ++i) 517 EdgeTable[i] = NullValue; 518 519 unsigned Edge = 0; 520 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { 521 TerminatorInst *TI = BB->getTerminator(); 522 int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors(); 523 if (Successors > 1 && !isa<BranchInst>(TI) && !isa<ReturnInst>(TI)) { 524 for (int i = 0; i != Successors; ++i) { 525 BasicBlock *Succ = TI->getSuccessor(i); 526 IRBuilder<> builder(Succ); 527 Value *Counter = builder.CreateConstInBoundsGEP2_64(Counters, 0, 528 Edge + i); 529 EdgeTable[((Succs.idFor(Succ)-1) * Preds.size()) + 530 (Preds.idFor(BB)-1)] = cast<Constant>(Counter); 531 } 532 } 533 Edge += Successors; 534 } 535 536 GlobalVariable *EdgeTableGV = 537 new GlobalVariable( 538 *M, EdgeTableTy, true, GlobalValue::InternalLinkage, 539 ConstantArray::get(EdgeTableTy, 540 &EdgeTable[0], Succs.size() * Preds.size()), 541 "__llvm_gcda_edge_table"); 542 EdgeTableGV->setUnnamedAddr(true); 543 return EdgeTableGV; 544 } 545 546 Constant *GCOVProfiler::getStartFileFunc() { 547 const Type *Args[] = { Type::getInt8PtrTy(*Ctx) }; 548 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), 549 Args, false); 550 return M->getOrInsertFunction("llvm_gcda_start_file", FTy); 551 } 552 553 Constant *GCOVProfiler::getIncrementIndirectCounterFunc() { 554 const Type *Args[] = { 555 Type::getInt32PtrTy(*Ctx), // uint32_t *predecessor 556 Type::getInt64PtrTy(*Ctx)->getPointerTo(), // uint64_t **state_table_row 557 }; 558 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), 559 Args, false); 560 return M->getOrInsertFunction("llvm_gcda_increment_indirect_counter", FTy); 561 } 562 563 Constant *GCOVProfiler::getEmitFunctionFunc() { 564 const Type *Args[] = { Type::getInt32Ty(*Ctx) }; 565 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), 566 Args, false); 567 return M->getOrInsertFunction("llvm_gcda_emit_function", FTy); 568 } 569 570 Constant *GCOVProfiler::getEmitArcsFunc() { 571 const Type *Args[] = { 572 Type::getInt32Ty(*Ctx), // uint32_t num_counters 573 Type::getInt64PtrTy(*Ctx), // uint64_t *counters 574 }; 575 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), 576 Args, false); 577 return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy); 578 } 579 580 Constant *GCOVProfiler::getEndFileFunc() { 581 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); 582 return M->getOrInsertFunction("llvm_gcda_end_file", FTy); 583 } 584 585 GlobalVariable *GCOVProfiler::getEdgeStateValue() { 586 GlobalVariable *GV = M->getGlobalVariable("__llvm_gcov_global_state_pred"); 587 if (!GV) { 588 GV = new GlobalVariable(*M, Type::getInt32Ty(*Ctx), false, 589 GlobalValue::InternalLinkage, 590 ConstantInt::get(Type::getInt32Ty(*Ctx), 591 0xffffffff), 592 "__llvm_gcov_global_state_pred"); 593 GV->setUnnamedAddr(true); 594 } 595 return GV; 596 } 597 598 void GCOVProfiler::insertCounterWriteout( 599 DebugInfoFinder &DIF, 600 SmallVector<std::pair<GlobalVariable *, uint32_t>, 8> &CountersByIdent) { 601 const FunctionType *WriteoutFTy = 602 FunctionType::get(Type::getVoidTy(*Ctx), false); 603 Function *WriteoutF = Function::Create(WriteoutFTy, 604 GlobalValue::InternalLinkage, 605 "__llvm_gcov_writeout", M); 606 WriteoutF->setUnnamedAddr(true); 607 BasicBlock *BB = BasicBlock::Create(*Ctx, "", WriteoutF); 608 IRBuilder<> Builder(BB); 609 610 Constant *StartFile = getStartFileFunc(); 611 Constant *EmitFunction = getEmitFunctionFunc(); 612 Constant *EmitArcs = getEmitArcsFunc(); 613 Constant *EndFile = getEndFileFunc(); 614 615 for (DebugInfoFinder::iterator CUI = DIF.compile_unit_begin(), 616 CUE = DIF.compile_unit_end(); CUI != CUE; ++CUI) { 617 DICompileUnit compile_unit(*CUI); 618 std::string FilenameGcda = replaceStem(compile_unit.getFilename(), "gcda"); 619 Builder.CreateCall(StartFile, 620 Builder.CreateGlobalStringPtr(FilenameGcda)); 621 for (SmallVector<std::pair<GlobalVariable *, uint32_t>, 8>::iterator 622 I = CountersByIdent.begin(), E = CountersByIdent.end(); 623 I != E; ++I) { 624 Builder.CreateCall(EmitFunction, ConstantInt::get(Type::getInt32Ty(*Ctx), 625 I->second)); 626 GlobalVariable *GV = I->first; 627 unsigned Arcs = 628 cast<ArrayType>(GV->getType()->getElementType())->getNumElements(); 629 Builder.CreateCall2(EmitArcs, 630 ConstantInt::get(Type::getInt32Ty(*Ctx), Arcs), 631 Builder.CreateConstGEP2_64(GV, 0, 0)); 632 } 633 Builder.CreateCall(EndFile); 634 } 635 Builder.CreateRetVoid(); 636 637 InsertProfilingShutdownCall(WriteoutF, M); 638 } 639