From 7a2ba2fbe4b0ccaacc2cedbc1bfd2a3764170efe Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Thu, 28 Apr 2011 21:35:49 +0000 Subject: [PATCH] Only read *predecessor once so as to fix a theoretical issue where it changes between two reads (threading). Fix an off-by-one in the indirect counter table that I meant to revert after an earlier experiment. Whoops! Implement GCOV_PREFIX. Doesn't handle GCOV_PREFIX_STRIP yet. Fix an off-by-one in string emission. Extra whoops! Tolerate DISubprograms that have null Function*'s attached to them. I don't yet understand what this means, but it happens when you have a global static with a non-trivial constructor/destructor. Fix a crash on switch statements with a single successor (default-only). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@130443 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Instrumentation/GCOVProfiling.cpp | 17 +++++---- runtime/libprofile/GCDAProfiling.c | 36 ++++++++++++++++--- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/lib/Transforms/Instrumentation/GCOVProfiling.cpp index 7a40fe6bbd6..2425342f7e6 100644 --- a/lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ b/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -146,9 +146,9 @@ namespace { writeBytes(s.data(), s.size()); // Write 1 to 4 bytes of NUL padding. - assert((unsigned)(5 - ((s.size() + 1) % 4)) > 0); - assert((unsigned)(5 - ((s.size() + 1) % 4)) <= 4); - writeBytes("\0\0\0\0", 5 - ((s.size() + 1) % 4)); + assert((unsigned)(4 - (s.size() % 4)) > 0); + assert((unsigned)(4 - (s.size() % 4)) <= 4); + writeBytes("\0\0\0\0", 4 - (s.size() % 4)); } raw_ostream *os; @@ -263,7 +263,7 @@ namespace { write(BlockLen); uint32_t Ident = reinterpret_cast((MDNode*)SP); write(Ident); - write(0); // checksum + write(0); // checksum writeGCOVString(SP.getName()); writeGCOVString(SP.getFilename()); write(SP.getLineNumber()); @@ -356,8 +356,10 @@ void GCOVProfiler::emitGCNO(DebugInfoFinder &DIF) { DISubprogram SP(*SPI); raw_fd_ostream *&os = GcnoFiles[SP.getCompileUnit()]; - GCOVFunction Func(SP, os); Function *F = SP.getFunction(); + if (!F) continue; + GCOVFunction Func(SP, os); + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { GCOVBlock &Block = Func.getBlock(BB); TerminatorInst *TI = BB->getTerminator(); @@ -402,6 +404,7 @@ bool GCOVProfiler::emitProfileArcs(DebugInfoFinder &DIF) { SPE = DIF.subprogram_end(); SPI != SPE; ++SPI) { DISubprogram SP(*SPI); Function *F = SP.getFunction(); + if (!F) continue; unsigned Edges = 0; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { @@ -471,7 +474,7 @@ bool GCOVProfiler::emitProfileArcs(DebugInfoFinder &DIF) { const Type *Int32Ty = Type::getInt32Ty(*Ctx); for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) { IRBuilder<> Builder(ComplexEdgePreds[i+1]->getTerminator()); - Builder.CreateStore(ConstantInt::get(Int32Ty, i+1), EdgeState); + Builder.CreateStore(ConstantInt::get(Int32Ty, i), EdgeState); } for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) { // call runtime to perform increment @@ -517,7 +520,7 @@ GlobalVariable *GCOVProfiler::buildEdgeLookupTable( for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { TerminatorInst *TI = BB->getTerminator(); int Successors = isa(TI) ? 1 : TI->getNumSuccessors(); - if (Successors && !isa(TI) && !isa(TI)) { + if (Successors > 1 && !isa(TI) && !isa(TI)) { for (int i = 0; i != Successors; ++i) { BasicBlock *Succ = TI->getSuccessor(i); IRBuilder<> builder(Succ); diff --git a/runtime/libprofile/GCDAProfiling.c b/runtime/libprofile/GCDAProfiling.c index c8161d44b07..2dcf22d9647 100644 --- a/runtime/libprofile/GCDAProfiling.c +++ b/runtime/libprofile/GCDAProfiling.c @@ -46,6 +46,24 @@ static void write_int64(uint64_t i) { write_int32(hi); } +static char *mangle_filename(const char *orig_filename) { + /* TODO: handle GCOV_PREFIX_STRIP */ + const char *prefix; + char *filename = 0; + + prefix = getenv("GCOV_PREFIX"); + + if (!prefix) + return strdup(filename); + + filename = malloc(strlen(prefix) + 1 + strlen(orig_filename) + 1); + strcpy(filename, prefix); + strcat(filename, "/"); + strcat(filename, orig_filename); + + return filename; +} + /* * --- LLVM line counter API --- */ @@ -54,15 +72,19 @@ static void write_int64(uint64_t i) { * profiling enabled will emit to a different file. Only one file may be * started at a time. */ -void llvm_gcda_start_file(const char *filename) { - output_file = fopen(filename, "w+"); +void llvm_gcda_start_file(const char *orig_filename) { + char *filename; + filename = mangle_filename(orig_filename); + output_file = fopen(filename, "wb"); /* gcda file, version 404*, stamp LLVM. */ fwrite("adcg*404MVLL", 12, 1, output_file); #ifdef DEBUG_GCDAPROFILING - printf("llvmgcda: [%s]\n", filename); + printf("llvmgcda: [%s]\n", orig_filename); #endif + + free(filename); } /* Given an array of pointers to counters (counters), increment the n-th one, @@ -71,12 +93,16 @@ void llvm_gcda_start_file(const char *filename) { void llvm_gcda_increment_indirect_counter(uint32_t *predecessor, uint64_t **counters) { uint64_t *counter; - if (*predecessor == 0xffffffff) + uint32_t pred; + + pred = *predecessor; + if (pred == 0xffffffff) return; + counter = counters[pred]; /* Don't crash if the pred# is out of sync. This can happen due to threads, or because of a TODO in GCOVProfiling.cpp buildEdgeLookupTable(). */ - if ((counter = counters[*predecessor])) + if (counter) ++*counter; #ifdef DEBUG_GCDAPROFILING else