From 38fff8682bb519d129f4130865781fe897570c63 Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Wed, 19 Mar 2014 02:20:42 +0000 Subject: [PATCH] llvm-profdata: Update to use the naive text format with function hash This also uses line_iterator to simplify the parsing logic. llvm-svn: 204210 --- llvm/include/llvm/Support/LineIterator.h | 1 + .../Inputs/bad-function-count.profdata | 2 - .../llvm-profdata/Inputs/bad-hash.profdata | 4 + .../llvm-profdata/Inputs/bar3-1.profdata | 4 +- .../llvm-profdata/Inputs/foo3-1.profdata | 4 +- .../llvm-profdata/Inputs/foo3-2.profdata | 4 +- .../llvm-profdata/Inputs/foo3bar3-1.profdata | 8 +- .../llvm-profdata/Inputs/foo3bar3-2.profdata | 8 +- .../llvm-profdata/Inputs/foo4-1.profdata | 4 +- .../llvm-profdata/Inputs/foo4-2.profdata | 4 +- .../Inputs/invalid-count-later.profdata | 4 +- .../llvm-profdata/Inputs/overflow.profdata | 4 +- .../Inputs/three-words-long.profdata | 1 - llvm/test/tools/llvm-profdata/errors.test | 11 +- llvm/test/tools/llvm-profdata/simple.test | 16 +- llvm/tools/llvm-profdata/llvm-profdata.cpp | 154 ++++++------------ 16 files changed, 107 insertions(+), 126 deletions(-) delete mode 100644 llvm/test/tools/llvm-profdata/Inputs/bad-function-count.profdata create mode 100644 llvm/test/tools/llvm-profdata/Inputs/bad-hash.profdata delete mode 100644 llvm/test/tools/llvm-profdata/Inputs/three-words-long.profdata diff --git a/llvm/include/llvm/Support/LineIterator.h b/llvm/include/llvm/Support/LineIterator.h index 861c19881fe3..92a9cc5c574a 100644 --- a/llvm/include/llvm/Support/LineIterator.h +++ b/llvm/include/llvm/Support/LineIterator.h @@ -56,6 +56,7 @@ public: /// \brief Get the current line as a \c StringRef. StringRef operator*() const { return CurrentLine; } + const StringRef *operator->() const { return &CurrentLine; } friend bool operator==(const line_iterator &LHS, const line_iterator &RHS) { return LHS.Buffer == RHS.Buffer && diff --git a/llvm/test/tools/llvm-profdata/Inputs/bad-function-count.profdata b/llvm/test/tools/llvm-profdata/Inputs/bad-function-count.profdata deleted file mode 100644 index 7d247626e5ab..000000000000 --- a/llvm/test/tools/llvm-profdata/Inputs/bad-function-count.profdata +++ /dev/null @@ -1,2 +0,0 @@ -function_count_not 1count -1 diff --git a/llvm/test/tools/llvm-profdata/Inputs/bad-hash.profdata b/llvm/test/tools/llvm-profdata/Inputs/bad-hash.profdata new file mode 100644 index 000000000000..faa6f4015253 --- /dev/null +++ b/llvm/test/tools/llvm-profdata/Inputs/bad-hash.profdata @@ -0,0 +1,4 @@ +function_count_not +badhash +1 +1 diff --git a/llvm/test/tools/llvm-profdata/Inputs/bar3-1.profdata b/llvm/test/tools/llvm-profdata/Inputs/bar3-1.profdata index cb8b409891a5..5486e9d84d72 100644 --- a/llvm/test/tools/llvm-profdata/Inputs/bar3-1.profdata +++ b/llvm/test/tools/llvm-profdata/Inputs/bar3-1.profdata @@ -1,4 +1,6 @@ -bar 3 +bar +3 +3 1 2 3 diff --git a/llvm/test/tools/llvm-profdata/Inputs/foo3-1.profdata b/llvm/test/tools/llvm-profdata/Inputs/foo3-1.profdata index d6f9f648b7bf..14a620043576 100644 --- a/llvm/test/tools/llvm-profdata/Inputs/foo3-1.profdata +++ b/llvm/test/tools/llvm-profdata/Inputs/foo3-1.profdata @@ -1,4 +1,6 @@ -foo 3 +foo +3 +3 1 2 3 diff --git a/llvm/test/tools/llvm-profdata/Inputs/foo3-2.profdata b/llvm/test/tools/llvm-profdata/Inputs/foo3-2.profdata index 94fd0343915a..801846e44045 100644 --- a/llvm/test/tools/llvm-profdata/Inputs/foo3-2.profdata +++ b/llvm/test/tools/llvm-profdata/Inputs/foo3-2.profdata @@ -1,4 +1,6 @@ -foo 3 +foo +3 +3 7 5 3 diff --git a/llvm/test/tools/llvm-profdata/Inputs/foo3bar3-1.profdata b/llvm/test/tools/llvm-profdata/Inputs/foo3bar3-1.profdata index 85b702d49778..12157b9f9ada 100644 --- a/llvm/test/tools/llvm-profdata/Inputs/foo3bar3-1.profdata +++ b/llvm/test/tools/llvm-profdata/Inputs/foo3bar3-1.profdata @@ -1,9 +1,13 @@ -foo 3 +foo +3 +3 2 3 5 -bar 3 +bar +3 +3 7 11 13 diff --git a/llvm/test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata b/llvm/test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata index d652781a35c3..f1f10bd6f3df 100644 --- a/llvm/test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata +++ b/llvm/test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata @@ -1,9 +1,13 @@ -foo 3 +foo +3 +3 17 19 23 -bar 3 +bar +3 +3 29 31 37 diff --git a/llvm/test/tools/llvm-profdata/Inputs/foo4-1.profdata b/llvm/test/tools/llvm-profdata/Inputs/foo4-1.profdata index 4d694080bffa..31d2a2ce7569 100644 --- a/llvm/test/tools/llvm-profdata/Inputs/foo4-1.profdata +++ b/llvm/test/tools/llvm-profdata/Inputs/foo4-1.profdata @@ -1,4 +1,6 @@ -foo 4 +foo +4 +4 11 22 33 diff --git a/llvm/test/tools/llvm-profdata/Inputs/foo4-2.profdata b/llvm/test/tools/llvm-profdata/Inputs/foo4-2.profdata index 8d91d8bbef0f..01d8309b5ce2 100644 --- a/llvm/test/tools/llvm-profdata/Inputs/foo4-2.profdata +++ b/llvm/test/tools/llvm-profdata/Inputs/foo4-2.profdata @@ -1,4 +1,6 @@ -foo 4 +foo +4 +4 7 6 5 diff --git a/llvm/test/tools/llvm-profdata/Inputs/invalid-count-later.profdata b/llvm/test/tools/llvm-profdata/Inputs/invalid-count-later.profdata index 5575df3fda66..2b61c55a6766 100644 --- a/llvm/test/tools/llvm-profdata/Inputs/invalid-count-later.profdata +++ b/llvm/test/tools/llvm-profdata/Inputs/invalid-count-later.profdata @@ -1,2 +1,4 @@ -invalid_count 1 +invalid_count +1 +1 1later diff --git a/llvm/test/tools/llvm-profdata/Inputs/overflow.profdata b/llvm/test/tools/llvm-profdata/Inputs/overflow.profdata index bfb9a52d2ec5..c9a9d697ecfb 100644 --- a/llvm/test/tools/llvm-profdata/Inputs/overflow.profdata +++ b/llvm/test/tools/llvm-profdata/Inputs/overflow.profdata @@ -1,2 +1,4 @@ -overflow 1 +overflow +1 +1 9223372036854775808 diff --git a/llvm/test/tools/llvm-profdata/Inputs/three-words-long.profdata b/llvm/test/tools/llvm-profdata/Inputs/three-words-long.profdata deleted file mode 100644 index a4d45fb3bfab..000000000000 --- a/llvm/test/tools/llvm-profdata/Inputs/three-words-long.profdata +++ /dev/null @@ -1 +0,0 @@ -three words long diff --git a/llvm/test/tools/llvm-profdata/errors.test b/llvm/test/tools/llvm-profdata/errors.test index 6335ea95f9ea..6570d172ee82 100644 --- a/llvm/test/tools/llvm-profdata/errors.test +++ b/llvm/test/tools/llvm-profdata/errors.test @@ -6,8 +6,8 @@ LENGTH: error: {{.*}}: truncated file RUN: not llvm-profdata %p/Inputs/foo3-1.profdata %p/Inputs/bar3-1.profdata 2>&1 | FileCheck %s --check-prefix=NAME NAME: error: {{.*}}: function name mismatch -RUN: not llvm-profdata %p/Inputs/foo3-1.profdata %p/Inputs/foo4-1.profdata 2>&1 | FileCheck %s --check-prefix=COUNT -COUNT: error: {{.*}}: function count mismatch +RUN: not llvm-profdata %p/Inputs/foo3-1.profdata %p/Inputs/foo4-1.profdata 2>&1 | FileCheck %s --check-prefix=HASH +HASH: error: {{.*}}: function hash mismatch RUN: not llvm-profdata %p/Inputs/overflow.profdata %p/Inputs/overflow.profdata 2>&1 | FileCheck %s --check-prefix=OVERFLOW OVERFLOW: error: {{.*}}: counter overflow @@ -15,8 +15,5 @@ OVERFLOW: error: {{.*}}: counter overflow RUN: not llvm-profdata %p/Inputs/invalid-count-later.profdata %p/Inputs/invalid-count-later.profdata 2>&1 | FileCheck %s --check-prefix=INVALID-COUNT-LATER INVALID-COUNT-LATER: error: {{.*}}: invalid counter -RUN: not llvm-profdata %p/Inputs/bad-function-count.profdata %p/Inputs/bad-function-count.profdata 2>&1 | FileCheck %s --check-prefix=BAD-FUNCTION-COUNT -BAD-FUNCTION-COUNT: error: {{.*}}: bad function count - -RUN: not llvm-profdata %p/Inputs/three-words-long.profdata %p/Inputs/three-words-long.profdata 2>&1 | FileCheck %s --check-prefix=INVALID-DATA -INVALID-DATA: error: {{.*}}: invalid data +RUN: not llvm-profdata %p/Inputs/bad-hash.profdata %p/Inputs/bad-hash.profdata 2>&1 | FileCheck %s --check-prefix=BAD-HASH +BAD-HASH: error: {{.*}}: bad function hash diff --git a/llvm/test/tools/llvm-profdata/simple.test b/llvm/test/tools/llvm-profdata/simple.test index 87073fad9cfa..7e375bf4b47a 100644 --- a/llvm/test/tools/llvm-profdata/simple.test +++ b/llvm/test/tools/llvm-profdata/simple.test @@ -1,13 +1,17 @@ RUN: llvm-profdata %p/Inputs/foo3-1.profdata %p/Inputs/foo3-2.profdata 2>&1 | FileCheck %s --check-prefix=FOO3 RUN: llvm-profdata %p/Inputs/foo3-2.profdata %p/Inputs/foo3-1.profdata 2>&1 | FileCheck %s --check-prefix=FOO3 -FOO3: {{^foo 3$}} +FOO3: {{^foo$}} +FOO3-NEXT: {{^3$}} +FOO3-NEXT: {{^3$}} FOO3-NEXT: {{^8$}} FOO3-NEXT: {{^7$}} FOO3-NEXT: {{^6$}} RUN: llvm-profdata %p/Inputs/foo4-1.profdata %p/Inputs/foo4-2.profdata 2>&1 | FileCheck %s --check-prefix=FOO4 RUN: llvm-profdata %p/Inputs/foo4-2.profdata %p/Inputs/foo4-1.profdata 2>&1 | FileCheck %s --check-prefix=FOO4 -FOO4: {{^foo 4$}} +FOO4: {{^foo$}} +FOO4-NEXT: {{^4$}} +FOO4-NEXT: {{^4$}} FOO4-NEXT: {{^18$}} FOO4-NEXT: {{^28$}} FOO4-NEXT: {{^38$}} @@ -15,11 +19,15 @@ FOO4-NEXT: {{^48$}} RUN: llvm-profdata %p/Inputs/foo3bar3-1.profdata %p/Inputs/foo3bar3-2.profdata 2>&1 | FileCheck %s --check-prefix=FOO3BAR3 RUN: llvm-profdata %p/Inputs/foo3bar3-2.profdata %p/Inputs/foo3bar3-1.profdata 2>&1 | FileCheck %s --check-prefix=FOO3BAR3 -FOO3BAR3: {{^foo 3$}} +FOO3BAR3: {{^foo$}} +FOO3BAR3-NEXT: {{^3$}} +FOO3BAR3-NEXT: {{^3$}} FOO3BAR3-NEXT: {{^19$}} FOO3BAR3-NEXT: {{^22$}} FOO3BAR3-NEXT: {{^28$}} -FOO3BAR3: {{^bar 3$}} +FOO3BAR3: {{^bar$}} +FOO3BAR3-NEXT: {{^3$}} +FOO3BAR3-NEXT: {{^3$}} FOO3BAR3-NEXT: {{^36$}} FOO3BAR3-NEXT: {{^42$}} FOO3BAR3-NEXT: {{^50$}} diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp index b338efd27e35..b4dd55c83375 100644 --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/LineIterator.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" @@ -32,56 +33,6 @@ static cl::opt OutputFilename("output", cl::value_desc("output"), static cl::alias OutputFilenameA("o", cl::desc("Alias for --output"), cl::aliasopt(OutputFilename)); -static bool readLine(const char *&Start, const char *End, StringRef &S) { - if (Start == End) - return false; - - for (const char *I = Start; I != End; ++I) { - assert(*I && "unexpected binary data"); - if (*I == '\n') { - S = StringRef(Start, I - Start); - Start = I + 1; - return true; - } - } - - S = StringRef(Start, End - Start); - Start = End; - return true; -} - -static StringRef getWord(const char *&Start, const char *End) { - for (const char *I = Start; I != End; ++I) - if (*I == ' ') { - StringRef S(Start, I - Start); - Start = I + 1; - return S; - } - StringRef S(Start, End - Start); - Start = End; - return S; -} - -static size_t splitWords(const StringRef &Line, std::vector &Words) { - const char *Start = Line.data(); - const char *End = Line.data() + Line.size(); - Words.clear(); - while (Start != End) - Words.push_back(getWord(Start, End)); - return Words.size(); -} - -static bool getNumber(const StringRef &S, uint64_t &N) { - N = 0; - for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) - if (*I >= '0' && *I <= '9') - N = N * 10 + (*I - '0'); - else - return false; - - return true; -} - static void exitWithError(const std::string &Message, const std::string &Filename, int64_t Line = -1) { errs() << "error: " << Filename; @@ -115,63 +66,64 @@ int main(int argc, char **argv) { if (!ErrorInfo.empty()) exitWithError(ErrorInfo, OutputFilename); - const char *Start1 = File1->getBufferStart(); - const char *Start2 = File2->getBufferStart(); - const char *End1 = File1->getBufferEnd(); - const char *End2 = File2->getBufferEnd(); - const char *P1 = Start1; - const char *P2 = Start2; - - StringRef Line1, Line2; - int64_t Num = 0; - while (readLine(P1, End1, Line1)) { - ++Num; - if (!readLine(P2, End2, Line2)) - exitWithError("truncated file", Filename2, Num); - - std::vector Words1, Words2; - if (splitWords(Line1, Words1) != splitWords(Line2, Words2)) - exitWithError("data mismatch", Filename2, Num); - - if (Words1.size() > 2) - exitWithError("invalid data", Filename1, Num); - - if (Words1.empty()) { + enum {ReadName, ReadHash, ReadCount, ReadCounters} State = ReadName; + uint64_t N1, N2, NumCounters; + line_iterator I1(*File1, '#'), I2(*File2, '#'); + for (; !I1.is_at_end() && !I2.is_at_end(); ++I1, ++I2) { + if (I1->empty()) { + if (!I2->empty()) + exitWithError("data mismatch", Filename2, I2.line_number()); Output << "\n"; continue; } - - if (Words1.size() == 2) { - if (Words1[0] != Words2[0]) - exitWithError("function name mismatch", Filename2, Num); - - uint64_t N1, N2; - if (!getNumber(Words1[1], N1)) - exitWithError("bad function count", Filename1, Num); - if (!getNumber(Words2[1], N2)) - exitWithError("bad function count", Filename2, Num); - + switch (State) { + case ReadName: + if (*I1 != *I2) + exitWithError("function name mismatch", Filename2, I2.line_number()); + Output << *I1 << "\n"; + State = ReadHash; + break; + case ReadHash: + if (I1->getAsInteger(10, N1)) + exitWithError("bad function hash", Filename1, I1.line_number()); + if (I2->getAsInteger(10, N2)) + exitWithError("bad function hash", Filename2, I2.line_number()); if (N1 != N2) - exitWithError("function count mismatch", Filename2, Num); - - Output << Line1 << "\n"; - continue; + exitWithError("function hash mismatch", Filename2, I2.line_number()); + Output << N1 << "\n"; + State = ReadCount; + break; + case ReadCount: + if (I1->getAsInteger(10, N1)) + exitWithError("bad function count", Filename1, I1.line_number()); + if (I2->getAsInteger(10, N2)) + exitWithError("bad function count", Filename2, I2.line_number()); + if (N1 != N2) + exitWithError("function count mismatch", Filename2, I2.line_number()); + Output << N1 << "\n"; + NumCounters = N1; + State = ReadCounters; + break; + case ReadCounters: + if (I1->getAsInteger(10, N1)) + exitWithError("invalid counter", Filename1, I1.line_number()); + if (I2->getAsInteger(10, N2)) + exitWithError("invalid counter", Filename2, I2.line_number()); + uint64_t Sum = N1 + N2; + if (Sum < N1) + exitWithError("counter overflow", Filename2, I2.line_number()); + Output << N1 + N2 << "\n"; + if (--NumCounters == 0) + State = ReadName; + break; } - - uint64_t N1, N2; - if (!getNumber(Words1[0], N1)) - exitWithError("invalid counter", Filename1, Num); - if (!getNumber(Words2[0], N2)) - exitWithError("invalid counter", Filename2, Num); - - uint64_t Sum = N1 + N2; - if (Sum < N1) - exitWithError("counter overflow", Filename2, Num); - - Output << N1 + N2 << "\n"; } - if (readLine(P2, End2, Line2)) - exitWithError("truncated file", Filename1, Num + 1); + if (!I1.is_at_end()) + exitWithError("truncated file", Filename1, I1.line_number()); + if (!I2.is_at_end()) + exitWithError("truncated file", Filename2, I2.line_number()); + if (State != ReadName) + exitWithError("truncated file", Filename1, I1.line_number()); return 0; }