[llvm] 5830e8e - [llvm-exegesis] Use explicit error classes for different snippet crashes (#74210)

via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 11 23:16:01 PST 2023


Author: Aiden Grossman
Date: 2023-12-11T23:15:56-08:00
New Revision: 5830e8e7458f3605f67a33439592432cc599ea40

URL: https://github.com/llvm/llvm-project/commit/5830e8e7458f3605f67a33439592432cc599ea40
DIFF: https://github.com/llvm/llvm-project/commit/5830e8e7458f3605f67a33439592432cc599ea40.diff

LOG: [llvm-exegesis] Use explicit error classes for different snippet crashes (#74210)

This patch switches to using explicit snippet crashes that contain more
information about the specific type of error (like the address for a
segmentation fault) that occurred. All these new error classes inherit
from SnippetExecutionFailure to allow for easily grabbing all of them in
addition to filtering for specific types using the standard LLVM error
primitives.

Added: 
    

Modified: 
    llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s
    llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s
    llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
    llvm/tools/llvm-exegesis/lib/Error.cpp
    llvm/tools/llvm-exegesis/lib/Error.h
    llvm/tools/llvm-exegesis/llvm-exegesis.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s b/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s
index 849f1a2e552f1..1edb263455f95 100644
--- a/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s
+++ b/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s
@@ -1,8 +1,8 @@
 # REQUIRES: exegesis-can-measure-latency, x86_64-linux
 
-# RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess | FileCheck %s
+# RUN: not llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess 2>&1 | FileCheck %s
 
-# CHECK: error: 'Child benchmarking process exited with non-zero exit code: Child process returned with unknown exit code'
+# CHECK: llvm-exegesis error: Child benchmarking process exited with non-zero exit code: Child process returned with unknown exit code
 
 movl $60, %eax
 movl $127, %edi

diff  --git a/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s b/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s
index 92b08e1c18c62..c72ac287d7170 100644
--- a/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s
+++ b/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s
@@ -2,7 +2,7 @@
 
 # RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess | FileCheck %s
 
-# CHECK: error:           'The benchmarking subprocess sent unexpected signal: Segmentation fault'
+# CHECK: error: The snippet encountered a segmentation fault at address 10
 
-# LLVM-EXEGESIS-DEFREG RBX 0
+# LLVM-EXEGESIS-DEFREG RBX 10
 movq (%rbx), %rax

diff  --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 6c34446e8d663..2d396df7337f8 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -147,17 +147,16 @@ class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
       CrashRecoveryContext::Disable();
       PS.reset();
       if (Crashed) {
-        std::string Msg = "snippet crashed while running";
 #ifdef LLVM_ON_UNIX
         // See "Exit Status for Commands":
         // https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html
         constexpr const int kSigOffset = 128;
-        if (const char *const SigName = strsignal(CRC.RetCode - kSigOffset)) {
-          Msg += ": ";
-          Msg += SigName;
-        }
-#endif
-        return make_error<SnippetCrash>(std::move(Msg));
+        return make_error<SnippetSignal>(CRC.RetCode - kSigOffset);
+#else
+        // The exit code of the process on windows is not meaningful as a
+        // signal, so simply pass in -1 as the signal into the error.
+        return make_error<SnippetSignal>(-1);
+#endif // LLVM_ON_UNIX
       }
     }
 
@@ -366,7 +365,7 @@ class SubProcessFunctionExecutorImpl
         return Error::success();
       }
       // The child exited, but not successfully
-      return make_error<SnippetCrash>(
+      return make_error<Failure>(
           "Child benchmarking process exited with non-zero exit code: " +
           childProcessExitCodeToString(ChildExitCode));
     }
@@ -379,9 +378,11 @@ class SubProcessFunctionExecutorImpl
                                  Twine(strerror(errno)));
     }
 
-    return make_error<SnippetCrash>(
-        "The benchmarking subprocess sent unexpected signal: " +
-        Twine(strsignal(ChildSignalInfo.si_signo)));
+    if (ChildSignalInfo.si_signo == SIGSEGV)
+      return make_error<SnippetSegmentationFault>(
+          reinterpret_cast<intptr_t>(ChildSignalInfo.si_addr));
+
+    return make_error<SnippetSignal>(ChildSignalInfo.si_signo);
   }
 
   void disableCoreDumps() const {

diff  --git a/llvm/tools/llvm-exegesis/lib/Error.cpp b/llvm/tools/llvm-exegesis/lib/Error.cpp
index 51ce41bf00bf5..d29c413856704 100644
--- a/llvm/tools/llvm-exegesis/lib/Error.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Error.cpp
@@ -8,6 +8,10 @@
 
 #include "Error.h"
 
+#ifdef LLVM_ON_UNIX
+#include <string.h>
+#endif // LLVM_ON_UNIX
+
 namespace llvm {
 namespace exegesis {
 
@@ -19,13 +23,27 @@ std::error_code ClusteringError::convertToErrorCode() const {
   return inconvertibleErrorCode();
 }
 
-char SnippetCrash::ID;
-
-void SnippetCrash::log(raw_ostream &OS) const { OS << Msg; }
+char SnippetExecutionFailure::ID;
 
-std::error_code SnippetCrash::convertToErrorCode() const {
+std::error_code SnippetExecutionFailure::convertToErrorCode() const {
   return inconvertibleErrorCode();
 }
 
+char SnippetSegmentationFault::ID;
+
+void SnippetSegmentationFault::log(raw_ostream &OS) const {
+  OS << "The snippet encountered a segmentation fault at address "
+     << Twine::utohexstr(Address);
+}
+
+char SnippetSignal::ID;
+
+void SnippetSignal::log(raw_ostream &OS) const {
+  OS << "snippet crashed while running";
+#ifdef LLVM_ON_UNIX
+  OS << ": " << strsignal(SignalNumber);
+#endif // LLVM_ON_UNIX
+}
+
 } // namespace exegesis
 } // namespace llvm

diff  --git a/llvm/tools/llvm-exegesis/lib/Error.h b/llvm/tools/llvm-exegesis/lib/Error.h
index e5fa093e6e125..2587c45f55743 100644
--- a/llvm/tools/llvm-exegesis/lib/Error.h
+++ b/llvm/tools/llvm-exegesis/lib/Error.h
@@ -36,19 +36,44 @@ class ClusteringError : public ErrorInfo<ClusteringError> {
   std::string Msg;
 };
 
-// A class representing failures that happened during snippet execution.
-// Instead of terminating the program crashes are logged into the output.
-class SnippetCrash : public ErrorInfo<SnippetCrash> {
+// A class representing a non-descript snippet execution failure. This class
+// is designed to sub-classed into more specific failures that contain
+// additional data about the specific error that they represent. Instead of
+// halting the program, the errors are reported in the output.
+class SnippetExecutionFailure : public ErrorInfo<SnippetExecutionFailure> {
 public:
   static char ID;
-  SnippetCrash(const Twine &S) : Msg(S.str()) {}
+
+  std::error_code convertToErrorCode() const override;
+};
+
+// A class representing specifically segmentation faults that happen during
+// snippet execution.
+class SnippetSegmentationFault : public SnippetExecutionFailure {
+public:
+  static char ID;
+  SnippetSegmentationFault(intptr_t SegFaultAddress)
+      : Address(SegFaultAddress){};
+
+  intptr_t getAddress() { return Address; }
 
   void log(raw_ostream &OS) const override;
 
-  std::error_code convertToErrorCode() const override;
+private:
+  intptr_t Address;
+};
+
+// A class representing all other non-specific failures that happen during
+// snippet execution.
+class SnippetSignal : public SnippetExecutionFailure {
+public:
+  static char ID;
+  SnippetSignal(int Signal) : SignalNumber(Signal){};
+
+  void log(raw_ostream &OS) const override;
 
 private:
-  std::string Msg;
+  int SignalNumber;
 };
 
 } // namespace exegesis

diff  --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index 148891a18246f..a5f8a09dcb241 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -415,7 +415,7 @@ static void runBenchmarkConfigurations(
       if (Err) {
         // Errors from executing the snippets are fine.
         // All other errors are a framework issue and should fail.
-        if (!Err.isA<SnippetCrash>()) {
+        if (!Err.isA<SnippetExecutionFailure>()) {
           llvm::errs() << "llvm-exegesis error: " << toString(std::move(Err));
           exit(1);
         }


        


More information about the llvm-commits mailing list