aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms/Instrumentation/GCOVProfiling.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/Instrumentation/GCOVProfiling.cpp')
-rw-r--r--lib/Transforms/Instrumentation/GCOVProfiling.cpp66
1 files changed, 44 insertions, 22 deletions
diff --git a/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
index 3ce9cf6..4c2681f 100644
--- a/lib/Transforms/Instrumentation/GCOVProfiling.cpp
+++ b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
@@ -37,6 +37,7 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
+#include <algorithm>
#include <string>
#include <utility>
using namespace llvm;
@@ -153,10 +154,10 @@ static std::string getFunctionName(DISubprogram SP) {
namespace {
class GCOVRecord {
protected:
- static const char *LinesTag;
- static const char *FunctionTag;
- static const char *BlockTag;
- static const char *EdgeTag;
+ static const char *const LinesTag;
+ static const char *const FunctionTag;
+ static const char *const BlockTag;
+ static const char *const EdgeTag;
GCOVRecord() {}
@@ -170,7 +171,7 @@ namespace {
// Returns the length measured in 4-byte blocks that will be used to
// represent this string in a GCOV file
- unsigned lengthOfGCOVString(StringRef s) {
+ static unsigned lengthOfGCOVString(StringRef s) {
// A GCOV string is a length, followed by a NUL, then between 0 and 3 NULs
// padding out to the next 4-byte word. The length is measured in 4-byte
// words including padding, not bytes of actual string.
@@ -190,10 +191,10 @@ namespace {
raw_ostream *os;
};
- const char *GCOVRecord::LinesTag = "\0\0\x45\x01";
- const char *GCOVRecord::FunctionTag = "\0\0\0\1";
- const char *GCOVRecord::BlockTag = "\0\0\x41\x01";
- const char *GCOVRecord::EdgeTag = "\0\0\x43\x01";
+ const char *const GCOVRecord::LinesTag = "\0\0\x45\x01";
+ const char *const GCOVRecord::FunctionTag = "\0\0\0\1";
+ const char *const GCOVRecord::BlockTag = "\0\0\x41\x01";
+ const char *const GCOVRecord::EdgeTag = "\0\0\x43\x01";
class GCOVFunction;
class GCOVBlock;
@@ -207,7 +208,7 @@ namespace {
Lines.push_back(Line);
}
- uint32_t length() {
+ uint32_t length() const {
// Here 2 = 1 for string length + 1 for '0' id#.
return lengthOfGCOVString(Filename) + 2 + Lines.size();
}
@@ -229,6 +230,15 @@ namespace {
SmallVector<uint32_t, 32> Lines;
};
+
+ // Sorting function for deterministic behaviour in GCOVBlock::writeOut.
+ struct StringKeySort {
+ bool operator()(StringMapEntry<GCOVLines *> *LHS,
+ StringMapEntry<GCOVLines *> *RHS) const {
+ return LHS->getKey() < RHS->getKey();
+ }
+ };
+
// Represent a basic block in GCOV. Each block has a unique number in the
// function, number of lines belonging to each block, and a set of edges to
// other blocks.
@@ -248,17 +258,23 @@ namespace {
void writeOut() {
uint32_t Len = 3;
+ SmallVector<StringMapEntry<GCOVLines *> *, 32> SortedLinesByFile;
for (StringMap<GCOVLines *>::iterator I = LinesByFile.begin(),
E = LinesByFile.end(); I != E; ++I) {
Len += I->second->length();
+ SortedLinesByFile.push_back(&*I);
}
writeBytes(LinesTag, 4);
write(Len);
write(Number);
- for (StringMap<GCOVLines *>::iterator I = LinesByFile.begin(),
- E = LinesByFile.end(); I != E; ++I)
- I->second->writeOut();
+
+ StringKeySort Sorter;
+ std::sort(SortedLinesByFile.begin(), SortedLinesByFile.end(), Sorter);
+ for (SmallVectorImpl<StringMapEntry<GCOVLines *> *>::iterator
+ I = SortedLinesByFile.begin(), E = SortedLinesByFile.end();
+ I != E; ++I)
+ (*I)->getValue()->writeOut();
write(0);
write(0);
}
@@ -335,9 +351,10 @@ namespace {
DEBUG(dbgs() << Blocks.size() << " blocks.\n");
// Emit edges between blocks.
- for (DenseMap<BasicBlock *, GCOVBlock *>::iterator I = Blocks.begin(),
- E = Blocks.end(); I != E; ++I) {
- GCOVBlock &Block = *I->second;
+ if (Blocks.empty()) return;
+ Function *F = Blocks.begin()->first->getParent();
+ for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
+ GCOVBlock &Block = *Blocks[I];
if (Block.OutEdges.empty()) continue;
writeBytes(EdgeTag, 4);
@@ -352,9 +369,8 @@ namespace {
}
// Emit lines for each block.
- for (DenseMap<BasicBlock *, GCOVBlock *>::iterator I = Blocks.begin(),
- E = Blocks.end(); I != E; ++I) {
- I->second->writeOut();
+ for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
+ Blocks[I]->writeOut();
}
}
@@ -410,7 +426,7 @@ void GCOVProfiler::emitProfileNotes() {
DICompileUnit CU(CU_Nodes->getOperand(i));
std::string ErrorInfo;
raw_fd_ostream out(mangleName(CU, "gcno").c_str(), ErrorInfo,
- raw_fd_ostream::F_Binary);
+ sys::fs::F_Binary);
out.write("oncg", 4);
out.write(ReversedVersion, 4);
out.write("MVLL", 4);
@@ -418,7 +434,10 @@ void GCOVProfiler::emitProfileNotes() {
DIArray SPs = CU.getSubprograms();
for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) {
DISubprogram SP(SPs.getElement(i));
- if (!SP.Verify()) continue;
+ assert((!SP || SP.isSubprogram()) &&
+ "A MDNode in subprograms of a CU should be null or a DISubprogram.");
+ if (!SP)
+ continue;
Function *F = SP.getFunction();
if (!F) continue;
@@ -467,7 +486,10 @@ bool GCOVProfiler::emitProfileArcs() {
SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> CountersBySP;
for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) {
DISubprogram SP(SPs.getElement(i));
- if (!SP.Verify()) continue;
+ assert((!SP || SP.isSubprogram()) &&
+ "A MDNode in subprograms of a CU should be null or a DISubprogram.");
+ if (!SP)
+ continue;
Function *F = SP.getFunction();
if (!F) continue;
if (!Result) Result = true;