llvm.org GIT mirror llvm / 1790c9c
Rename everything to follow LLVM style ... I think. Add support for switch and indirectbr edges. This works by densely numbering all blocks which have such terminators, and then separately numbering the possible successors. The predecessors write down a number, the successor knows its own number (as a ConstantInt) and sends that and the pointer to the number the predecessor wrote down to the runtime, who looks up the counter in a per-function table. Coverage data should now be functional, but I haven't tested it on anything other than my 2-file synthetic test program for coverage. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@130186 91177308-0d34-0410-b5e6-96231b3b80d8 Nick Lewycky 8 years ago
3 changed file(s) with 378 addition(s) and 261 deletion(s). Raw diff Collapse all Expand all
5757
5858 private:
5959 // Create the GCNO files for the Module based on DebugInfo.
60 void EmitGCNO(DebugInfoFinder &DIF);
60 void emitGCNO(DebugInfoFinder &DIF);
6161
6262 // Modify the program to track transitions along edges and call into the
6363 // profiling runtime to emit .gcda files when run.
64 bool EmitProfileArcs(DebugInfoFinder &DIF);
64 bool emitProfileArcs(DebugInfoFinder &DIF);
6565
6666 // Get pointers to the functions in the runtime library.
6767 Constant *getStartFileFunc();
68 Constant *getIncrementIndirectCounterFunc();
6869 Constant *getEmitFunctionFunc();
6970 Constant *getEmitArcsFunc();
7071 Constant *getEndFileFunc();
7172
73 // Create or retrieve an i32 state value that is used to represent the
74 // pred block number for certain non-trivial edges.
75 GlobalVariable *getEdgeStateValue();
76
77 // Produce a table of pointers to counters, by predecessor and successor
78 // block number.
79 GlobalVariable *buildEdgeLookupTable(Function *F,
80 GlobalVariable *Counter,
81 const UniqueVector &Preds,
82 const UniqueVector &Succs);
83
7284 // Add the function to write out all our counters to the global destructor
7385 // list.
74 void InsertCounterWriteout(DebugInfoFinder &,
86 void insertCounterWriteout(DebugInfoFinder &,
7587 SmallVector
7688 uint32_t>, 8> &);
7789
7890 bool EmitNotes;
7991 bool EmitData;
8092
81 Module *Mod;
93 Module *M;
8294 LLVMContext *Ctx;
8395 };
8496 }
91103 return new GCOVProfiler(EmitNotes, EmitData);
92104 }
93105
94 static DISubprogram FindSubprogram(DIScope scope) {
95 while (!scope.isSubprogram()) {
96 assert(scope.isLexicalBlock() &&
106 static DISubprogram findSubprogram(DIScope Scope) {
107 while (!Scope.isSubprogram()) {
108 assert(Scope.isLexicalBlock() &&
97109 "Debug location not lexical block or subprogram");
98 scope = DILexicalBlock(scope).getContext();
99 }
100 return DISubprogram(scope);
110 Scope = DILexicalBlock(Scope).getContext();
111 }
112 return DISubprogram(Scope);
101113 }
102114
103115 namespace {
104116 class GCOVRecord {
105117 protected:
106 static const char *lines_tag;
107 static const char *function_tag;
108 static const char *block_tag;
109 static const char *edge_tag;
118 static const char *LinesTag;
119 static const char *FunctionTag;
120 static const char *BlockTag;
121 static const char *EdgeTag;
110122
111123 GCOVRecord() {}
112124
113 void WriteBytes(const char *b, int size) {
114 os->write(b, size);
115 }
116
117 void Write(uint32_t i) {
118 WriteBytes(reinterpret_cast(&i), 4);
125 void writeBytes(const char *Bytes, int Size) {
126 os->write(Bytes, Size);
127 }
128
129 void write(uint32_t i) {
130 writeBytes(reinterpret_cast(&i), 4);
119131 }
120132
121133 // Returns the length measured in 4-byte blocks that will be used to
122134 // represent this string in a GCOV file
123 unsigned LengthOfGCOVString(StringRef s) {
135 unsigned lengthOfGCOVString(StringRef s) {
124136 // A GCOV string is a length, followed by a NUL, then between 0 and 3 NULs
125137 // padding out to the next 4-byte word. The length is measured in 4-byte
126138 // words including padding, not bytes of actual string.
127139 return (s.size() + 5) / 4;
128140 }
129141
130 void WriteGCOVString(StringRef s) {
131 uint32_t len = LengthOfGCOVString(s);
132 Write(len);
133 WriteBytes(s.data(), s.size());
142 void writeGCOVString(StringRef s) {
143 uint32_t Len = lengthOfGCOVString(s);
144 write(Len);
145 writeBytes(s.data(), s.size());
134146
135147 // Write 1 to 4 bytes of NUL padding.
136148 assert((unsigned)(5 - ((s.size() + 1) % 4)) > 0);
137149 assert((unsigned)(5 - ((s.size() + 1) % 4)) <= 4);
138 WriteBytes("\0\0\0\0", 5 - ((s.size() + 1) % 4));
150 writeBytes("\0\0\0\0", 5 - ((s.size() + 1) % 4));
139151 }
140152
141153 raw_ostream *os;
142154 };
143 const char *GCOVRecord::lines_tag = "\0\0\x45\x01";
144 const char *GCOVRecord::function_tag = "\0\0\0\1";
145 const char *GCOVRecord::block_tag = "\0\0\x41\x01";
146 const char *GCOVRecord::edge_tag = "\0\0\x43\x01";
155 const char *GCOVRecord::LinesTag = "\0\0\x45\x01";
156 const char *GCOVRecord::FunctionTag = "\0\0\0\1";
157 const char *GCOVRecord::BlockTag = "\0\0\x41\x01";
158 const char *GCOVRecord::EdgeTag = "\0\0\x43\x01";
147159
148160 class GCOVFunction;
149161 class GCOVBlock;
153165 // to the block.
154166 class GCOVLines : public GCOVRecord {
155167 public:
156 void AddLine(uint32_t line) {
157 lines.push_back(line);
158 }
159
160 uint32_t Length() {
161 return LengthOfGCOVString(filename) + 2 + lines.size();
168 void addLine(uint32_t Line) {
169 Lines.push_back(Line);
170 }
171
172 uint32_t length() {
173 return lengthOfGCOVString(Filename) + 2 + Lines.size();
162174 }
163175
164176 private:
165177 friend class GCOVBlock;
166178
167 GCOVLines(std::string filename, raw_ostream *os)
168 : filename(filename) {
179 GCOVLines(std::string Filename, raw_ostream *os)
180 : Filename(Filename) {
169181 this->os = os;
170182 }
171183
172 std::string filename;
173 SmallVector lines;
184 std::string Filename;
185 SmallVector Lines;
174186 };
175187
176188 // Represent a basic block in GCOV. Each block has a unique number in the
178190 // other blocks.
179191 class GCOVBlock : public GCOVRecord {
180192 public:
181 GCOVLines &GetFile(std::string filename) {
182 GCOVLines *&lines = lines_by_file[filename];
183 if (!lines) {
184 lines = new GCOVLines(filename, os);
185 }
186 return *lines;
187 }
188
189 void AddEdge(GCOVBlock &successor) {
190 out_edges.push_back(&successor);
191 }
192
193 void WriteOut() {
194 uint32_t len = 3;
195 for (StringMap::iterator I = lines_by_file.begin(),
196 E = lines_by_file.end(); I != E; ++I) {
197 len += I->second->Length();
198 }
199
200 WriteBytes(lines_tag, 4);
201 Write(len);
202 Write(number);
203 for (StringMap::iterator I = lines_by_file.begin(),
204 E = lines_by_file.end(); I != E; ++I) {
205 Write(0);
206 WriteGCOVString(I->second->filename);
207 for (int i = 0, e = I->second->lines.size(); i != e; ++i) {
208 Write(I->second->lines[i]);
193 GCOVLines &getFile(std::string Filename) {
194 GCOVLines *&Lines = LinesByFile[Filename];
195 if (!Lines) {
196 Lines = new GCOVLines(Filename, os);
197 }
198 return *Lines;
199 }
200
201 void addEdge(GCOVBlock &Successor) {
202 OutEdges.push_back(&Successor);
203 }
204
205 void writeOut() {
206 uint32_t Len = 3;
207 for (StringMap::iterator I = LinesByFile.begin(),
208 E = LinesByFile.end(); I != E; ++I) {
209 Len += I->second->length();
210 }
211
212 writeBytes(LinesTag, 4);
213 write(Len);
214 write(Number);
215 for (StringMap::iterator I = LinesByFile.begin(),
216 E = LinesByFile.end(); I != E; ++I) {
217 write(0);
218 writeGCOVString(I->second->Filename);
219 for (int i = 0, e = I->second->Lines.size(); i != e; ++i) {
220 write(I->second->Lines[i]);
209221 }
210222 }
211 Write(0);
212 Write(0);
223 write(0);
224 write(0);
213225 }
214226
215227 ~GCOVBlock() {
216 DeleteContainerSeconds(lines_by_file);
228 DeleteContainerSeconds(LinesByFile);
217229 }
218230
219231 private:
220232 friend class GCOVFunction;
221233
222 GCOVBlock(uint32_t number, raw_ostream *os)
223 : number(number) {
234 GCOVBlock(uint32_t Number, raw_ostream *os)
235 : Number(Number) {
224236 this->os = os;
225237 }
226238
227 uint32_t number;
228 BasicBlock *block;
229 StringMap lines_by_file;
230 SmallVector out_edges;
239 uint32_t Number;
240 StringMap LinesByFile;
241 SmallVector OutEdges;
231242 };
232243
233244 // A function has a unique identifier, a checksum (we leave as zero) and a
241252 Function *F = SP.getFunction();
242253 uint32_t i = 0;
243254 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
244 blocks[BB] = new GCOVBlock(i++, os);
245 }
246 return_block = new GCOVBlock(i++, os);
247
248 WriteBytes(function_tag, 4);
249 uint32_t block_len = 1 + 1 + 1 + LengthOfGCOVString(SP.getName()) +
250 1 + LengthOfGCOVString(SP.getFilename()) + 1;
251 Write(block_len);
252 uint32_t ident = reinterpret_cast((MDNode*)SP);
253 Write(ident);
254 Write(0); // checksum
255 WriteGCOVString(SP.getName());
256 WriteGCOVString(SP.getFilename());
257 Write(SP.getLineNumber());
255 Blocks[BB] = new GCOVBlock(i++, os);
256 }
257 ReturnBlock = new GCOVBlock(i++, os);
258
259 writeBytes(FunctionTag, 4);
260 uint32_t BlockLen = 1 + 1 + 1 + lengthOfGCOVString(SP.getName()) +
261 1 + lengthOfGCOVString(SP.getFilename()) + 1;
262 write(BlockLen);
263 uint32_t Ident = reinterpret_cast((MDNode*)SP);
264 write(Ident);
265 write(0); // checksum
266 writeGCOVString(SP.getName());
267 writeGCOVString(SP.getFilename());
268 write(SP.getLineNumber());
258269 }
259270
260271 ~GCOVFunction() {
261 DeleteContainerSeconds(blocks);
262 delete return_block;
263 }
264
265 GCOVBlock &GetBlock(BasicBlock *BB) {
266 return *blocks[BB];
267 }
268
269 GCOVBlock &GetReturnBlock() {
270 return *return_block;
271 }
272
273 void WriteOut() {
272 DeleteContainerSeconds(Blocks);
273 delete ReturnBlock;
274 }
275
276 GCOVBlock &getBlock(BasicBlock *BB) {
277 return *Blocks[BB];
278 }
279
280 GCOVBlock &getReturnBlock() {
281 return *ReturnBlock;
282 }
283
284 void writeOut() {
274285 // Emit count of blocks.
275 WriteBytes(block_tag, 4);
276 Write(blocks.size() + 1);
277 for (int i = 0, e = blocks.size() + 1; i != e; ++i) {
278 Write(0); // No flags on our blocks.
286 writeBytes(BlockTag, 4);
287 write(Blocks.size() + 1);
288 for (int i = 0, e = Blocks.size() + 1; i != e; ++i) {
289 write(0); // No flags on our blocks.
279290 }
280291
281292 // Emit edges between blocks.
282 for (DenseMap::iterator I = blocks.begin(),
283 E = blocks.end(); I != E; ++I) {
284 GCOVBlock &block = *I->second;
285 if (block.out_edges.empty()) continue;
286
287 WriteBytes(edge_tag, 4);
288 Write(block.out_edges.size() * 2 + 1);
289 Write(block.number);
290 for (int i = 0, e = block.out_edges.size(); i != e; ++i) {
291 Write(block.out_edges[i]->number);
292 Write(0); // no flags
293 for (DenseMap::iterator I = Blocks.begin(),
294 E = Blocks.end(); I != E; ++I) {
295 GCOVBlock &Block = *I->second;
296 if (Block.OutEdges.empty()) continue;
297
298 writeBytes(EdgeTag, 4);
299 write(Block.OutEdges.size() * 2 + 1);
300 write(Block.Number);
301 for (int i = 0, e = Block.OutEdges.size(); i != e; ++i) {
302 write(Block.OutEdges[i]->Number);
303 write(0); // no flags
293304 }
294305 }
295306
296307 // Emit lines for each block.
297 for (DenseMap::iterator I = blocks.begin(),
298 E = blocks.end(); I != E; ++I) {
299 I->second->WriteOut();
308 for (DenseMap::iterator I = Blocks.begin(),
309 E = Blocks.end(); I != E; ++I) {
310 I->second->writeOut();
300311 }
301312 }
302313
303314 private:
304 DenseMap blocks;
305 GCOVBlock *return_block;
315 DenseMap Blocks;
316 GCOVBlock *ReturnBlock;
306317 };
307318 }
308319
309320 // Replace the stem of a file, or add one if missing.
310 static std::string ReplaceStem(std::string orig_filename, std::string new_stem){
311 return (sys::path::stem(orig_filename) + "." + new_stem).str();
321 static std::string replaceStem(std::string OrigFilename, std::string NewStem) {
322 return (sys::path::stem(OrigFilename) + "." + NewStem).str();
312323 }
313324
314325 bool GCOVProfiler::runOnModule(Module &M) {
315 Mod = &M;
326 this->M = &M;
316327 Ctx = &M.getContext();
317328
318329 DebugInfoFinder DIF;
319 DIF.processModule(*Mod);
320
321 if (EmitNotes) EmitGCNO(DIF);
322 if (EmitData) return EmitProfileArcs(DIF);
330 DIF.processModule(M);
331
332 if (EmitNotes) emitGCNO(DIF);
333 if (EmitData) return emitProfileArcs(DIF);
323334 return false;
324335 }
325336
326 void GCOVProfiler::EmitGCNO(DebugInfoFinder &DIF) {
327 DenseMap gcno_files;
337 void GCOVProfiler::emitGCNO(DebugInfoFinder &DIF) {
338 DenseMap GcnoFiles;
328339 for (DebugInfoFinder::iterator I = DIF.compile_unit_begin(),
329340 E = DIF.compile_unit_end(); I != E; ++I) {
330341 // Each compile unit gets its own .gcno file. This means that whether we run
332343 // LTO, we'll generate the same .gcno files.
333344
334345 DICompileUnit CU(*I);
335 raw_fd_ostream *&Out = gcno_files[CU];
346 raw_fd_ostream *&out = GcnoFiles[CU];
336347 std::string ErrorInfo;
337 Out = new raw_fd_ostream(ReplaceStem(CU.getFilename(), "gcno").c_str(),
348 out = new raw_fd_ostream(replaceStem(CU.getFilename(), "gcno").c_str(),
338349 ErrorInfo, raw_fd_ostream::F_Binary);
339 Out->write("oncg*404MVLL", 12);
350 out->write("oncg*404MVLL", 12);
340351 }
341352
342353 for (DebugInfoFinder::iterator SPI = DIF.subprogram_begin(),
343354 SPE = DIF.subprogram_end(); SPI != SPE; ++SPI) {
344355 DISubprogram SP(*SPI);
345 raw_fd_ostream *&os = gcno_files[SP.getCompileUnit()];
346
347 GCOVFunction function(SP, os);
356 raw_fd_ostream *&os = GcnoFiles[SP.getCompileUnit()];
357
358 GCOVFunction Func(SP, os);
348359 Function *F = SP.getFunction();
349360 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
350 GCOVBlock &block = function.GetBlock(BB);
361 GCOVBlock &Block = Func.getBlock(BB);
351362 TerminatorInst *TI = BB->getTerminator();
352363 if (int successors = TI->getNumSuccessors()) {
353364 for (int i = 0; i != successors; ++i) {
354 block.AddEdge(function.GetBlock(TI->getSuccessor(i)));
365 Block.addEdge(Func.getBlock(TI->getSuccessor(i)));
355366 }
356367 } else if (isa(TI)) {
357 block.AddEdge(function.GetReturnBlock());
358 }
359
360 uint32_t line = 0;
368 Block.addEdge(Func.getReturnBlock());
369 }
370
371 uint32_t Line = 0;
361372 for (BasicBlock::iterator I = BB->begin(), IE = BB->end(); I != IE; ++I) {
362 const DebugLoc &loc = I->getDebugLoc();
363 if (loc.isUnknown()) continue;
364 if (line == loc.getLine()) continue;
365 line = loc.getLine();
366 if (SP != FindSubprogram(DIScope(loc.getScope(*Ctx)))) continue;
367
368 GCOVLines &lines = block.GetFile(SP.getFilename());
369 lines.AddLine(loc.getLine());
370 }
371 }
372 function.WriteOut();
373 const DebugLoc &Loc = I->getDebugLoc();
374 if (Loc.isUnknown()) continue;
375 if (Line == Loc.getLine()) continue;
376 Line = Loc.getLine();
377 if (SP != findSubprogram(DIScope(Loc.getScope(*Ctx)))) continue;
378
379 GCOVLines &Lines = Block.getFile(SP.getFilename());
380 Lines.addLine(Loc.getLine());
381 }
382 }
383 Func.writeOut();
373384 }
374385
375386 for (DenseMap::iterator
376 I = gcno_files.begin(), E = gcno_files.end(); I != E; ++I) {
377 raw_fd_ostream *&Out = I->second;
378 Out->write("\0\0\0\0\0\0\0\0", 8); // EOF
379 Out->close();
380 delete Out;
381 }
382 }
383
384 bool GCOVProfiler::EmitProfileArcs(DebugInfoFinder &DIF) {
387 I = GcnoFiles.begin(), E = GcnoFiles.end(); I != E; ++I) {
388 raw_fd_ostream *&out = I->second;
389 out->write("\0\0\0\0\0\0\0\0", 8); // EOF
390 out->close();
391 delete out;
392 }
393 }
394
395 bool GCOVProfiler::emitProfileArcs(DebugInfoFinder &DIF) {
385396 if (DIF.subprogram_begin() == DIF.subprogram_end())
386397 return false;
387398
388 SmallVector, 8> counters_by_ident;
399 SmallVector, 8> CountersByIdent;
389400 for (DebugInfoFinder::iterator SPI = DIF.subprogram_begin(),
390401 SPE = DIF.subprogram_end(); SPI != SPE; ++SPI) {
391402 DISubprogram SP(*SPI);
392403 Function *F = SP.getFunction();
393404
394 unsigned edges = 0;
405 unsigned Edges = 0;
395406 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
396407 TerminatorInst *TI = BB->getTerminator();
397408 if (isa(TI))
398 ++edges;
409 ++Edges;
399410 else
400 edges += TI->getNumSuccessors();
401 }
402
403 const ArrayType *counter_type =
404 ArrayType::get(Type::getInt64Ty(*Ctx), edges);
405 GlobalVariable *counter =
406 new GlobalVariable(*Mod, counter_type, false,
411 Edges += TI->getNumSuccessors();
412 }
413
414 const ArrayType *CounterTy =
415 ArrayType::get(Type::getInt64Ty(*Ctx), Edges);
416 GlobalVariable *Counters =
417 new GlobalVariable(*M, CounterTy, false,
407418 GlobalValue::InternalLinkage,
408 Constant::getNullValue(counter_type),
419 Constant::getNullValue(CounterTy),
409420 "__llvm_gcov_ctr", 0, false, 0);
410 counters_by_ident.push_back(
411 std::make_pair(counter, reinterpret_cast((MDNode*)SP)));
412
413 UniqueVector complex_edge_preds;
414 UniqueVector complex_edge_succs;
415
416 unsigned edge_num = 0;
421 CountersByIdent.push_back(
422 std::make_pair(Counters, reinterpret_cast((MDNode*)SP)));
423
424 UniqueVector ComplexEdgePreds;
425 UniqueVector ComplexEdgeSuccs;
426
427 unsigned Edge = 0;
417428 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
418429 TerminatorInst *TI = BB->getTerminator();
419 int successors = isa(TI) ? 1 : TI->getNumSuccessors();
420 if (successors) {
421 IRBuilder<> builder(TI);
422
423 if (successors == 1) {
424 Value *ctr = builder.CreateConstInBoundsGEP2_64(counter, 0, edge_num);
425 Value *count = builder.CreateLoad(ctr);
426 count = builder.CreateAdd(count,
430 int Successors = isa(TI) ? 1 : TI->getNumSuccessors();
431 if (Successors) {
432 IRBuilder<> Builder(TI);
433
434 if (Successors == 1) {
435 Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0,
436 Edge);
437 Value *Count = Builder.CreateLoad(Counter);
438 Count = Builder.CreateAdd(Count,
427439 ConstantInt::get(Type::getInt64Ty(*Ctx),1));
428 builder.CreateStore(count, ctr);
440 Builder.CreateStore(Count, Counter);
429441 } else if (BranchInst *BI = dyn_cast(TI)) {
430 Value *sel = builder.CreateSelect(
442 Value *Sel = Builder.CreateSelect(
431443 BI->getCondition(),
432 ConstantInt::get(Type::getInt64Ty(*Ctx), edge_num),
433 ConstantInt::get(Type::getInt64Ty(*Ctx), edge_num + 1));
434 SmallVector idx;
435 idx.push_back(Constant::getNullValue(Type::getInt64Ty(*Ctx)));
436 idx.push_back(sel);
437 Value *ctr = builder.CreateInBoundsGEP(counter,
438 idx.begin(), idx.end());
439 Value *count = builder.CreateLoad(ctr);
440 count = builder.CreateAdd(count,
444 ConstantInt::get(Type::getInt64Ty(*Ctx), Edge),
445 ConstantInt::get(Type::getInt64Ty(*Ctx), Edge + 1));
446 SmallVector Idx;
447 Idx.push_back(Constant::getNullValue(Type::getInt64Ty(*Ctx)));
448 Idx.push_back(Sel);
449 Value *Counter = Builder.CreateInBoundsGEP(Counters,
450 Idx.begin(), Idx.end());
451 Value *Count = Builder.CreateLoad(Counter);
452 Count = Builder.CreateAdd(Count,
441453 ConstantInt::get(Type::getInt64Ty(*Ctx),1));
442 builder.CreateStore(count, ctr);
454 Builder.CreateStore(Count, Counter);
443455 } else {
444 complex_edge_preds.insert(BB);
445 for (int i = 0; i != successors; ++i) {
446 complex_edge_succs.insert(TI->getSuccessor(i));
447 }
456 ComplexEdgePreds.insert(BB);
457 for (int i = 0; i != Successors; ++i)
458 ComplexEdgeSuccs.insert(TI->getSuccessor(i));
448459 }
449 edge_num += successors;
450 }
451 }
452
453 // TODO: support switch, invoke, indirectbr
454 if (!complex_edge_preds.empty()) {
455 // emit a [preds x [succs x i64*]].
456 for (int i = 0, e = complex_edge_preds.size(); i != e; ++i) {
457 // call runtime to state save
458 }
459 for (int i = 0, e = complex_edge_succs.size(); i != e; ++i) {
460 Edge += Successors;
461 }
462 }
463
464 if (!ComplexEdgePreds.empty()) {
465 GlobalVariable *EdgeTable =
466 buildEdgeLookupTable(F, Counters,
467 ComplexEdgePreds, ComplexEdgeSuccs);
468 GlobalVariable *EdgeState = getEdgeStateValue();
469
470 const Type *Int32Ty = Type::getInt32Ty(*Ctx);
471 for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) {
472 IRBuilder<> Builder(ComplexEdgePreds[i+1]->getTerminator());
473 Builder.CreateStore(ConstantInt::get(Int32Ty, i+1), EdgeState);
474 }
475 for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) {
460476 // call runtime to perform increment
461 }
462 }
463 }
464
465 InsertCounterWriteout(DIF, counters_by_ident);
477 IRBuilder<> Builder(ComplexEdgeSuccs[i+1]->getFirstNonPHI());
478 Value *CounterPtrArray =
479 Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0,
480 i * ComplexEdgePreds.size());
481 Builder.CreateCall2(getIncrementIndirectCounterFunc(),
482 EdgeState, CounterPtrArray);
483 // clear the predecessor number
484 Builder.CreateStore(ConstantInt::get(Int32Ty, 0xffffffff), EdgeState);
485 }
486 }
487 }
488
489 insertCounterWriteout(DIF, CountersByIdent);
466490
467491 return true;
468492 }
469493
494 // All edges with successors that aren't branches are "complex", because it
495 // requires complex logic to pick which counter to update.
496 GlobalVariable *GCOVProfiler::buildEdgeLookupTable(
497 Function *F,
498 GlobalVariable *Counters,
499 const UniqueVector &Preds,
500 const UniqueVector &Succs) {
501 // TODO: support invoke, threads. We rely on the fact that nothing can modify
502 // the whole-Module pred edge# between the time we set it and the time we next
503 // read it. Threads and invoke make this untrue.
504
505 // emit [(succs * preds) x i64*], logically [succ x [pred x i64*]].
506 const Type *Int64PtrTy = Type::getInt64PtrTy(*Ctx);
507 const ArrayType *EdgeTableTy = ArrayType::get(
508 Int64PtrTy, Succs.size() * Preds.size());
509
510 Constant **EdgeTable = new Constant*[Succs.size() * Preds.size()];
511 Constant *NullValue = Constant::getNullValue(Int64PtrTy);
512 for (int i = 0, ie = Succs.size() * Preds.size(); i != ie; ++i)
513 EdgeTable[i] = NullValue;
514
515 unsigned Edge = 0;
516 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
517 TerminatorInst *TI = BB->getTerminator();
518 int Successors = isa(TI) ? 1 : TI->getNumSuccessors();
519 if (Successors && !isa(TI) && !isa(TI)) {
520 for (int i = 0; i != Successors; ++i) {
521 BasicBlock *Succ = TI->getSuccessor(i);
522 IRBuilder<> builder(Succ);
523 Value *Counter = builder.CreateConstInBoundsGEP2_64(Counters, 0,
524 Edge + i);
525 EdgeTable[((Succs.idFor(Succ)-1) * Preds.size()) +
526 (Preds.idFor(BB)-1)] = cast(Counter);
527 }
528 }
529 Edge += Successors;
530 }
531
532 GlobalVariable *EdgeTableGV =
533 new GlobalVariable(
534 *M, EdgeTableTy, true, GlobalValue::InternalLinkage,
535 ConstantArray::get(EdgeTableTy,
536 &EdgeTable[0], Succs.size() * Preds.size()),
537 "__llvm_gcda_edge_table");
538 EdgeTableGV->setUnnamedAddr(true);
539 return EdgeTableGV;
540 }
541
470542 Constant *GCOVProfiler::getStartFileFunc() {
471 const Type *Args[1] = { Type::getInt8PtrTy(*Ctx) };
543 const Type *Args[] = { Type::getInt8PtrTy(*Ctx) };
472544 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
473545 Args, false);
474 return Mod->getOrInsertFunction("llvm_gcda_start_file", FTy);
475 }
476
477 Constant *GCOVProfiler::getEmitFunctionFunc() {
478 const Type *Args[1] = { Type::getInt32Ty(*Ctx) };
546 return M->getOrInsertFunction("llvm_gcda_start_file", FTy);
547 }
548
549 Constant *GCOVProfiler::getIncrementIndirectCounterFunc() {
550 const Type *Args[] = {
551 Type::getInt32PtrTy(*Ctx), // uint32_t *predecessor
552 Type::getInt64PtrTy(*Ctx)->getPointerTo(), // uint64_t **state_table_row
553 };
479554 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
480555 Args, false);
481 return Mod->getOrInsertFunction("llvm_gcda_emit_function", FTy);
556 return M->getOrInsertFunction("llvm_gcda_increment_indirect_counter", FTy);
557 }
558
559 Constant *GCOVProfiler::getEmitFunctionFunc() {
560 const Type *Args[] = { Type::getInt32Ty(*Ctx) };
561 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
562 Args, false);
563 return M->getOrInsertFunction("llvm_gcda_emit_function", FTy);
482564 }
483565
484566 Constant *GCOVProfiler::getEmitArcsFunc() {
488570 };
489571 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
490572 Args, false);
491 return Mod->getOrInsertFunction("llvm_gcda_emit_arcs", FTy);
573 return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy);
492574 }
493575
494576 Constant *GCOVProfiler::getEndFileFunc() {
495577 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
496 return Mod->getOrInsertFunction("llvm_gcda_end_file", FTy);
497 }
498
499 void GCOVProfiler::InsertCounterWriteout(
578 return M->getOrInsertFunction("llvm_gcda_end_file", FTy);
579 }
580
581 GlobalVariable *GCOVProfiler::getEdgeStateValue() {
582 GlobalVariable *GV = M->getGlobalVariable("__llvm_gcov_global_state_pred");
583 if (!GV) {
584 GV = new GlobalVariable(*M, Type::getInt32Ty(*Ctx), false,
585 GlobalValue::InternalLinkage,
586 ConstantInt::get(Type::getInt32Ty(*Ctx),
587 0xffffffff),
588 "__llvm_gcov_global_state_pred");
589 GV->setUnnamedAddr(true);
590 }
591 return GV;
592 }
593
594 void GCOVProfiler::insertCounterWriteout(
500595 DebugInfoFinder &DIF,
501 SmallVector, 8> &counters_by_ident) {
502
596 SmallVector, 8> &CountersByIdent) {
503597 const FunctionType *WriteoutFTy =
504598 FunctionType::get(Type::getVoidTy(*Ctx), false);
505599 Function *WriteoutF = Function::Create(WriteoutFTy,
506600 GlobalValue::InternalLinkage,
507 "__llvm_gcda_writeout", Mod);
601 "__llvm_gcov_writeout", M);
508602 WriteoutF->setUnnamedAddr(true);
509603 BasicBlock *BB = BasicBlock::Create(*Ctx, "", WriteoutF);
510 IRBuilder<> builder(BB);
604 IRBuilder<> Builder(BB);
511605
512606 Constant *StartFile = getStartFileFunc();
513607 Constant *EmitFunction = getEmitFunctionFunc();
517611 for (DebugInfoFinder::iterator CUI = DIF.compile_unit_begin(),
518612 CUE = DIF.compile_unit_end(); CUI != CUE; ++CUI) {
519613 DICompileUnit compile_unit(*CUI);
520 std::string filename_gcda = ReplaceStem(compile_unit.getFilename(), "gcda");
521 builder.CreateCall(StartFile,
522 builder.CreateGlobalStringPtr(filename_gcda));
614 std::string FilenameGcda = replaceStem(compile_unit.getFilename(), "gcda");
615 Builder.CreateCall(StartFile,
616 Builder.CreateGlobalStringPtr(FilenameGcda));
523617 for (SmallVector, 8>::iterator
524 I = counters_by_ident.begin(), E = counters_by_ident.end();
618 I = CountersByIdent.begin(), E = CountersByIdent.end();
525619 I != E; ++I) {
526 builder.CreateCall(EmitFunction, ConstantInt::get(Type::getInt32Ty(*Ctx),
620 Builder.CreateCall(EmitFunction, ConstantInt::get(Type::getInt32Ty(*Ctx),
527621 I->second));
528622 GlobalVariable *GV = I->first;
529 unsigned num_arcs =
623 unsigned Arcs =
530624 cast(GV->getType()->getElementType())->getNumElements();
531 builder.CreateCall2(
532 EmitArcs,
533 ConstantInt::get(Type::getInt32Ty(*Ctx), num_arcs),
534 builder.CreateConstGEP2_64(GV, 0, 0));
535 }
536 builder.CreateCall(EndFile);
537 }
538 builder.CreateRetVoid();
539
540 InsertProfilingShutdownCall(WriteoutF, Mod);
541 }
625 Builder.CreateCall2(EmitArcs,
626 ConstantInt::get(Type::getInt32Ty(*Ctx), Arcs),
627 Builder.CreateConstGEP2_64(GV, 0, 0));
628 }
629 Builder.CreateCall(EndFile);
630 }
631 Builder.CreateRetVoid();
632
633 InsertProfilingShutdownCall(WriteoutF, M);
634 }
1313 |* We emit files in a corrupt version of GCOV's "gcda" file format. These files
1414 |* are only close enough that LCOV will happily parse them. Anything that lcov
1515 |* ignores is missing.
16 |*
17 |* TODO: gcov is multi-process safe by having each exit open the existing file
18 |* and append to it. We'd like to achieve that and be thread-safe too.
1619 |*
1720 \*===----------------------------------------------------------------------===*/
1821
5760 fwrite("adcg*404MVLL", 12, 1, output_file);
5861
5962 #ifdef DEBUG_GCDAPROFILING
60 printf("[%s]\n", filename);
63 printf("llvmgcda: [%s]\n", filename);
64 #endif
65 }
66
67 /* Given an array of pointers to counters (counters), increment the n-th one,
68 * where we're also given a pointer to n (predecessor).
69 */
70 void llvm_gcda_increment_indirect_counter(uint32_t *predecessor,
71 uint64_t **counters) {
72 uint64_t *counter;
73 if (*predecessor == 0xffffffff)
74 return;
75
76 /* Don't crash if the pred# is out of sync. This can happen due to threads,
77 or because of a TODO in GCOVProfiling.cpp buildEdgeLookupTable(). */
78 if ((counter = counters[*predecessor]))
79 ++*counter;
80 #ifdef DEBUG_GCDAPROFILING
81 else
82 printf("llvmgcda: increment_indirect_counter counters=%x, pred=%u\n",
83 state_table_row, *predecessor);
6184 #endif
6285 }
6386
6487 void llvm_gcda_emit_function(uint32_t ident) {
6588 #ifdef DEBUG_GCDAPROFILING
66 printf("function id=%x\n", ident);
89 printf("llvmgcda: function id=%x\n", ident);
6790 #endif
6891
6992 /* function tag */
83106 }
84107
85108 #ifdef DEBUG_GCDAPROFILING
86 printf(" %u arcs\n", num_counters);
109 printf("llvmgcda: %u arcs\n", num_counters);
87110 for (i = 0; i < num_counters; ++i) {
88 printf(" %llu\n", (unsigned long long)counters[i]);
111 printf("llvmgcda: %llu\n", (unsigned long long)counters[i]);
89112 }
90113 #endif
91114 }
97120 output_file = NULL;
98121
99122 #ifdef DEBUG_GCDAPROFILING
100 printf("-----\n");
123 printf("llvmgcda: -----\n");
101124 #endif
102125 }
55 llvm_increment_path_count
66 llvm_decrement_path_count
77 llvm_gcda_start_file
8 llvm_gcda_increment_indirect_counter
89 llvm_gcda_emit_function
910 llvm_gcda_emit_arcs
1011 llvm_gcda_end_file