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
diff --git a/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
index 7a40fe6..2425342 100644
--- a/lib/Transforms/Instrumentation/GCOVProfiling.cpp
+++ b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
@@ -146,9 +146,9 @@
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 @@
write(BlockLen);
uint32_t Ident = reinterpret_cast<intptr_t>((MDNode*)SP);
write(Ident);
- write(0); // checksum
+ write(0); // checksum
writeGCOVString(SP.getName());
writeGCOVString(SP.getFilename());
write(SP.getLineNumber());
@@ -356,8 +356,10 @@
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 @@
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 @@
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 @@
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
TerminatorInst *TI = BB->getTerminator();
int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors();
- if (Successors && !isa<BranchInst>(TI) && !isa<ReturnInst>(TI)) {
+ if (Successors > 1 && !isa<BranchInst>(TI) && !isa<ReturnInst>(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 c8161d4..2dcf22d 100644
--- a/runtime/libprofile/GCDAProfiling.c
+++ b/runtime/libprofile/GCDAProfiling.c
@@ -46,6 +46,24 @@
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 @@
* 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_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