Use DiagnosticInfo facility.
authorDiego Novillo <dnovillo@google.com>
Fri, 14 Mar 2014 21:58:59 +0000 (21:58 +0000)
committerDiego Novillo <dnovillo@google.com>
Fri, 14 Mar 2014 21:58:59 +0000 (21:58 +0000)
Summary:
The sample profiler pass emits several error messages. Instead of
just aborting the compiler with report_fatal_error, we can emit
better messages using DiagnosticInfo.

This adds a new sub-class of DiagnosticInfo to handle the sample
profiler.

Reviewers: chandlerc, qcolombet

CC: llvm-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D3086

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203976 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/DiagnosticInfo.h
lib/IR/DiagnosticInfo.cpp
lib/Transforms/Scalar/SampleProfile.cpp
test/Transforms/SampleProfile/syntax.ll

index de2a9d8b1a0cbc087a42aa40545729148dfe0253..49eb1b0c1448eb52afe20877da66eadb07da4b14 100644 (file)
@@ -43,6 +43,7 @@ enum DiagnosticKind {
   DK_InlineAsm,
   DK_StackSize,
   DK_DebugMetadataVersion,
+  DK_SampleProfile,
   DK_FirstPluginKind
 };
 
@@ -193,6 +194,47 @@ public:
   }
 };
 
+/// Diagnostic information for the sample profiler.
+class DiagnosticInfoSampleProfile : public DiagnosticInfo {
+public:
+  DiagnosticInfoSampleProfile(const char *FileName, unsigned LineNum,
+                              const Twine &Msg,
+                              DiagnosticSeverity Severity = DS_Error)
+      : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName),
+        LineNum(LineNum), Msg(Msg) {}
+  DiagnosticInfoSampleProfile(const char *FileName, const Twine &Msg,
+                              DiagnosticSeverity Severity = DS_Error)
+      : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName),
+        LineNum(0), Msg(Msg) {}
+  DiagnosticInfoSampleProfile(const Twine &Msg,
+                              DiagnosticSeverity Severity = DS_Error)
+      : DiagnosticInfo(DK_SampleProfile, Severity), FileName(NULL),
+        LineNum(0), Msg(Msg) {}
+
+  /// \see DiagnosticInfo::print.
+  void print(DiagnosticPrinter &DP) const override;
+
+  /// Hand rolled RTTI.
+  static bool classof(const DiagnosticInfo *DI) {
+    return DI->getKind() == DK_SampleProfile;
+  }
+
+  const char *getFileName() const { return FileName; }
+  unsigned getLineNum() const { return LineNum; }
+  const Twine &getMsg() const { return Msg; }
+
+private:
+  /// Name of the input file associated with this diagnostic.
+  const char *FileName;
+
+  /// Line number where the diagnostic occured. If 0, no line number will
+  /// be emitted in the message.
+  unsigned LineNum;
+
+  /// Message to report.
+  const Twine &Msg;
+};
+
 } // End namespace llvm
 
 #endif
index 86e8788eb091df8926d485c525e971d9339863c3..d59d4cf0b5077bf17d2991155672187c5279d9fc 100644 (file)
@@ -56,3 +56,11 @@ void DiagnosticInfoDebugMetadataVersion::print(DiagnosticPrinter &DP) const {
   DP << "ignoring debug info with an invalid version (" << getMetadataVersion()
      << ") in " << getModule();
 }
+
+void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const {
+  if (getFileName() && getLineNum() > 0)
+    DP << getFileName() << ":" << getLineNum() << ": ";
+  else if (getFileName())
+    DP << getFileName() << ": ";
+  DP << getMsg();
+}
index ab26fa5b23e058377ceba307ceea72f7646e91c9..e8adc64eeeedf26b92993217d99a39ec2327d588 100644 (file)
@@ -34,6 +34,7 @@
 #include "llvm/Analysis/PostDominators.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/InstIterator.h"
@@ -238,10 +239,11 @@ protected:
 ///      be relative to the start of the function.
 class SampleModuleProfile {
 public:
-  SampleModuleProfile(StringRef F) : Profiles(0), Filename(F) {}
+  SampleModuleProfile(const Module &M, StringRef F)
+      : Profiles(0), Filename(F), M(M) {}
 
   void dump();
-  void loadText();
+  bool loadText();
   void loadNative() { llvm_unreachable("not implemented"); }
   void printFunctionProfile(raw_ostream &OS, StringRef FName);
   void dumpFunctionProfile(StringRef FName);
@@ -251,7 +253,8 @@ public:
 
   /// \brief Report a parse error message and stop compilation.
   void reportParseError(int64_t LineNumber, Twine Msg) const {
-    report_fatal_error(Filename + ":" + Twine(LineNumber) + ": " + Msg + "\n");
+    DiagnosticInfoSampleProfile Diag(Filename.data(), LineNumber, Msg);
+    M.getContext().diagnose(Diag);
   }
 
 protected:
@@ -269,6 +272,10 @@ protected:
   /// version of the profile format to be used in constructing test
   /// cases and debugging.
   StringRef Filename;
+
+  /// \brief Module being compiled. Used mainly to access the current
+  /// LLVM context for diagnostics.
+  const Module &M;
 };
 
 /// \brief Sample profile pass.
@@ -282,7 +289,7 @@ public:
   static char ID;
 
   SampleProfileLoader(StringRef Name = SampleProfileFile)
-      : FunctionPass(ID), Profiler(), Filename(Name) {
+      : FunctionPass(ID), Profiler(), Filename(Name), ProfileIsValid(false) {
     initializeSampleProfileLoaderPass(*PassRegistry::getPassRegistry());
   }
 
@@ -307,6 +314,9 @@ protected:
 
   /// \brief Name of the profile file to load.
   StringRef Filename;
+
+  /// \brief Flag indicating whether the profile input loaded succesfully.
+  bool ProfileIsValid;
 };
 }
 
@@ -437,11 +447,17 @@ void SampleModuleProfile::dump() {
 /// for debugging purposes, but it should not be used to generate
 /// profiles for large programs, as the representation is extremely
 /// inefficient.
-void SampleModuleProfile::loadText() {
+///
+/// \returns true if the file was loaded successfully, false otherwise.
+bool SampleModuleProfile::loadText() {
   std::unique_ptr<MemoryBuffer> Buffer;
   error_code EC = MemoryBuffer::getFile(Filename, Buffer);
-  if (EC)
-    report_fatal_error("Could not open file " + Filename + ": " + EC.message());
+  if (EC) {
+    std::string Msg(EC.message());
+    DiagnosticInfoSampleProfile Diag(Filename.data(), Msg);
+    M.getContext().diagnose(Diag);
+    return false;
+  }
   line_iterator LineIt(*Buffer, '#');
 
   // Read the profile of each function. Since each function may be
@@ -457,9 +473,11 @@ void SampleModuleProfile::loadText() {
     //
     // See above for an explanation of each field.
     SmallVector<StringRef, 3> Matches;
-    if (!HeadRE.match(*LineIt, &Matches))
+    if (!HeadRE.match(*LineIt, &Matches)) {
       reportParseError(LineIt.line_number(),
                        "Expected 'mangled_name:NUM:NUM', found " + *LineIt);
+      return false;
+    }
     assert(Matches.size() == 4);
     StringRef FName = Matches[1];
     unsigned NumSamples, NumHeadSamples;
@@ -474,10 +492,12 @@ void SampleModuleProfile::loadText() {
     // Now read the body. The body of the function ends when we reach
     // EOF or when we see the start of the next function.
     while (!LineIt.is_at_eof() && isdigit((*LineIt)[0])) {
-      if (!LineSample.match(*LineIt, &Matches))
+      if (!LineSample.match(*LineIt, &Matches)) {
         reportParseError(
             LineIt.line_number(),
             "Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found " + *LineIt);
+        return false;
+      }
       assert(Matches.size() == 5);
       unsigned LineOffset, NumSamples, Discriminator = 0;
       Matches[1].getAsInteger(10, LineOffset);
@@ -497,6 +517,8 @@ void SampleModuleProfile::loadText() {
       ++LineIt;
     }
   }
+
+  return true;
 }
 
 /// \brief Get the weight for an instruction.
@@ -935,7 +957,8 @@ void SampleFunctionProfile::propagateWeights(Function &F) {
 ///
 /// \param F  Function object to query.
 ///
-/// \returns the line number where \p F is defined.
+/// \returns the line number where \p F is defined. If it returns 0,
+///          it means that there is no debug information available for \p F.
 unsigned SampleFunctionProfile::getFunctionLoc(Function &F) {
   NamedMDNode *CUNodes = F.getParent()->getNamedMetadata("llvm.dbg.cu");
   if (CUNodes) {
@@ -950,8 +973,10 @@ unsigned SampleFunctionProfile::getFunctionLoc(Function &F) {
     }
   }
 
-  report_fatal_error("No debug information found in function " + F.getName() +
-                     "\n");
+  DiagnosticInfoSampleProfile Diag("No debug information found in function " +
+                                   F.getName());
+  F.getContext().diagnose(Diag);
+  return 0;
 }
 
 /// \brief Generate branch weight metadata for all branches in \p F.
@@ -1001,6 +1026,8 @@ unsigned SampleFunctionProfile::getFunctionLoc(Function &F) {
 /// metadata on B using the computed values for each of its branches.
 ///
 /// \param F The function to query.
+///
+/// \returns true if \p F was modified. Returns false, otherwise.
 bool SampleFunctionProfile::emitAnnotations(Function &F, DominatorTree *DomTree,
                                             PostDominatorTree *PostDomTree,
                                             LoopInfo *Loops) {
@@ -1008,6 +1035,9 @@ bool SampleFunctionProfile::emitAnnotations(Function &F, DominatorTree *DomTree,
 
   // Initialize invariants used during computation and propagation.
   HeaderLineno = getFunctionLoc(F);
+  if (HeaderLineno == 0)
+    return false;
+
   DEBUG(dbgs() << "Line number for the first instruction in " << F.getName()
                << ": " << HeaderLineno << "\n");
   DT = DomTree;
@@ -1040,8 +1070,8 @@ INITIALIZE_PASS_END(SampleProfileLoader, "sample-profile",
                     "Sample Profile loader", false, false)
 
 bool SampleProfileLoader::doInitialization(Module &M) {
-  Profiler.reset(new SampleModuleProfile(Filename));
-  Profiler->loadText();
+  Profiler.reset(new SampleModuleProfile(M, Filename));
+  ProfileIsValid = Profiler->loadText();
   return true;
 }
 
@@ -1054,6 +1084,8 @@ FunctionPass *llvm::createSampleProfileLoaderPass(StringRef Name) {
 }
 
 bool SampleProfileLoader::runOnFunction(Function &F) {
+  if (!ProfileIsValid)
+    return false;
   DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
   PostDominatorTree *PDT = &getAnalysis<PostDominatorTree>();
   LoopInfo *LI = &getAnalysis<LoopInfo>();
index 60b9dac88cdd99624bd78abb518de5a04a836f4a..3aee6b219a8adcca95bce749f680b232ff20aa7b 100644 (file)
@@ -10,10 +10,10 @@ define void @empty() {
 entry:
   ret void
 }
-; NO-DEBUG: LLVM ERROR: No debug information found in function empty
-; MISSING-FILE: LLVM ERROR: Could not open file missing.prof:
-; BAD-FN-HEADER: LLVM ERROR: {{.*}}bad_fn_header.prof:1: Expected 'mangled_name:NUM:NUM', found empty:100:BAD
-; BAD-SAMPLE-LINE: LLVM ERROR: {{.*}}bad_sample_line.prof:3: Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found 1: BAD
-; BAD-LINE-VALUES: LLVM ERROR: {{.*}}bad_line_values.prof:2: Expected 'mangled_name:NUM:NUM', found -1: 10
-; BAD-DISCRIMINATOR-VALUE: LLVM ERROR: {{.*}}bad_discriminator_value.prof:2: Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found 1.-3: 10
-; BAD-SAMPLES: LLVM ERROR: {{.*}}bad_samples.prof:2: Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found 1.3: -10
+; NO-DEBUG: error: No debug information found in function empty
+; MISSING-FILE: error: missing.prof: No such file or directory
+; BAD-FN-HEADER: error: {{.*}}bad_fn_header.prof:1: Expected 'mangled_name:NUM:NUM', found empty:100:BAD
+; BAD-SAMPLE-LINE: error: {{.*}}bad_sample_line.prof:3: Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found 1: BAD
+; BAD-LINE-VALUES: error: {{.*}}bad_line_values.prof:2: Expected 'mangled_name:NUM:NUM', found -1: 10
+; BAD-DISCRIMINATOR-VALUE: error: {{.*}}bad_discriminator_value.prof:2: Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found 1.-3: 10
+; BAD-SAMPLES: error: {{.*}}bad_samples.prof:2: Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found 1.3: -10