mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-19 04:32:19 +00:00
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
This commit is contained in:
parent
f86500bc4f
commit
7a2ba2fbe4
@ -146,9 +146,9 @@ namespace {
|
|||||||
writeBytes(s.data(), s.size());
|
writeBytes(s.data(), s.size());
|
||||||
|
|
||||||
// Write 1 to 4 bytes of NUL padding.
|
// Write 1 to 4 bytes of NUL padding.
|
||||||
assert((unsigned)(5 - ((s.size() + 1) % 4)) > 0);
|
assert((unsigned)(4 - (s.size() % 4)) > 0);
|
||||||
assert((unsigned)(5 - ((s.size() + 1) % 4)) <= 4);
|
assert((unsigned)(4 - (s.size() % 4)) <= 4);
|
||||||
writeBytes("\0\0\0\0", 5 - ((s.size() + 1) % 4));
|
writeBytes("\0\0\0\0", 4 - (s.size() % 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_ostream *os;
|
raw_ostream *os;
|
||||||
@ -263,7 +263,7 @@ namespace {
|
|||||||
write(BlockLen);
|
write(BlockLen);
|
||||||
uint32_t Ident = reinterpret_cast<intptr_t>((MDNode*)SP);
|
uint32_t Ident = reinterpret_cast<intptr_t>((MDNode*)SP);
|
||||||
write(Ident);
|
write(Ident);
|
||||||
write(0); // checksum
|
write(0); // checksum
|
||||||
writeGCOVString(SP.getName());
|
writeGCOVString(SP.getName());
|
||||||
writeGCOVString(SP.getFilename());
|
writeGCOVString(SP.getFilename());
|
||||||
write(SP.getLineNumber());
|
write(SP.getLineNumber());
|
||||||
@ -356,8 +356,10 @@ void GCOVProfiler::emitGCNO(DebugInfoFinder &DIF) {
|
|||||||
DISubprogram SP(*SPI);
|
DISubprogram SP(*SPI);
|
||||||
raw_fd_ostream *&os = GcnoFiles[SP.getCompileUnit()];
|
raw_fd_ostream *&os = GcnoFiles[SP.getCompileUnit()];
|
||||||
|
|
||||||
GCOVFunction Func(SP, os);
|
|
||||||
Function *F = SP.getFunction();
|
Function *F = SP.getFunction();
|
||||||
|
if (!F) continue;
|
||||||
|
GCOVFunction Func(SP, os);
|
||||||
|
|
||||||
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
|
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
|
||||||
GCOVBlock &Block = Func.getBlock(BB);
|
GCOVBlock &Block = Func.getBlock(BB);
|
||||||
TerminatorInst *TI = BB->getTerminator();
|
TerminatorInst *TI = BB->getTerminator();
|
||||||
@ -402,6 +404,7 @@ bool GCOVProfiler::emitProfileArcs(DebugInfoFinder &DIF) {
|
|||||||
SPE = DIF.subprogram_end(); SPI != SPE; ++SPI) {
|
SPE = DIF.subprogram_end(); SPI != SPE; ++SPI) {
|
||||||
DISubprogram SP(*SPI);
|
DISubprogram SP(*SPI);
|
||||||
Function *F = SP.getFunction();
|
Function *F = SP.getFunction();
|
||||||
|
if (!F) continue;
|
||||||
|
|
||||||
unsigned Edges = 0;
|
unsigned Edges = 0;
|
||||||
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
|
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);
|
const Type *Int32Ty = Type::getInt32Ty(*Ctx);
|
||||||
for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) {
|
for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) {
|
||||||
IRBuilder<> Builder(ComplexEdgePreds[i+1]->getTerminator());
|
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) {
|
for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) {
|
||||||
// call runtime to perform increment
|
// call runtime to perform increment
|
||||||
@ -517,7 +520,7 @@ GlobalVariable *GCOVProfiler::buildEdgeLookupTable(
|
|||||||
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
|
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
|
||||||
TerminatorInst *TI = BB->getTerminator();
|
TerminatorInst *TI = BB->getTerminator();
|
||||||
int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors();
|
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) {
|
for (int i = 0; i != Successors; ++i) {
|
||||||
BasicBlock *Succ = TI->getSuccessor(i);
|
BasicBlock *Succ = TI->getSuccessor(i);
|
||||||
IRBuilder<> builder(Succ);
|
IRBuilder<> builder(Succ);
|
||||||
|
@ -46,6 +46,24 @@ static void write_int64(uint64_t i) {
|
|||||||
write_int32(hi);
|
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 ---
|
* --- 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
|
* profiling enabled will emit to a different file. Only one file may be
|
||||||
* started at a time.
|
* started at a time.
|
||||||
*/
|
*/
|
||||||
void llvm_gcda_start_file(const char *filename) {
|
void llvm_gcda_start_file(const char *orig_filename) {
|
||||||
output_file = fopen(filename, "w+");
|
char *filename;
|
||||||
|
filename = mangle_filename(orig_filename);
|
||||||
|
output_file = fopen(filename, "wb");
|
||||||
|
|
||||||
/* gcda file, version 404*, stamp LLVM. */
|
/* gcda file, version 404*, stamp LLVM. */
|
||||||
fwrite("adcg*404MVLL", 12, 1, output_file);
|
fwrite("adcg*404MVLL", 12, 1, output_file);
|
||||||
|
|
||||||
#ifdef DEBUG_GCDAPROFILING
|
#ifdef DEBUG_GCDAPROFILING
|
||||||
printf("llvmgcda: [%s]\n", filename);
|
printf("llvmgcda: [%s]\n", orig_filename);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
free(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given an array of pointers to counters (counters), increment the n-th one,
|
/* 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,
|
void llvm_gcda_increment_indirect_counter(uint32_t *predecessor,
|
||||||
uint64_t **counters) {
|
uint64_t **counters) {
|
||||||
uint64_t *counter;
|
uint64_t *counter;
|
||||||
if (*predecessor == 0xffffffff)
|
uint32_t pred;
|
||||||
|
|
||||||
|
pred = *predecessor;
|
||||||
|
if (pred == 0xffffffff)
|
||||||
return;
|
return;
|
||||||
|
counter = counters[pred];
|
||||||
|
|
||||||
/* Don't crash if the pred# is out of sync. This can happen due to threads,
|
/* 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(). */
|
or because of a TODO in GCOVProfiling.cpp buildEdgeLookupTable(). */
|
||||||
if ((counter = counters[*predecessor]))
|
if (counter)
|
||||||
++*counter;
|
++*counter;
|
||||||
#ifdef DEBUG_GCDAPROFILING
|
#ifdef DEBUG_GCDAPROFILING
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user