Skip to content

Commit 313e7d3

Browse files
[llvm-exegesis] Use explicit error classes for different snippet crashes
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.
1 parent bb6497f commit 313e7d3

File tree

5 files changed

+65
-27
lines changed

5 files changed

+65
-27
lines changed

llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# REQUIRES: exegesis-can-measure-latency, x86_64-linux
22

3-
# RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess | FileCheck %s
3+
# RUN: not llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess 2>&1 | FileCheck %s
44

5-
# CHECK: error: 'Child benchmarking process exited with non-zero exit code: Child process returned with unknown exit code'
5+
# CHECK: llvm-exegesis error: Child benchmarking process exited with non-zero exit code: Child process returned with unknown exit code
66

77
movl $60, %eax
88
movl $127, %edi

llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess | FileCheck %s
44

5-
# CHECK: error: 'The benchmarking subprocess sent unexpected signal: Segmentation fault'
5+
# CHECK: error: The snippet encountered a segmentation fault at address 10
66

7-
# LLVM-EXEGESIS-DEFREG RBX 0
7+
# LLVM-EXEGESIS-DEFREG RBX 10
88
movq (%rbx), %rax

llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -141,17 +141,10 @@ class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
141141
CrashRecoveryContext::Disable();
142142
PS.reset();
143143
if (Crashed) {
144-
std::string Msg = "snippet crashed while running";
145-
#ifdef LLVM_ON_UNIX
146144
// See "Exit Status for Commands":
147145
// https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html
148146
constexpr const int kSigOffset = 128;
149-
if (const char *const SigName = strsignal(CRC.RetCode - kSigOffset)) {
150-
Msg += ": ";
151-
Msg += SigName;
152-
}
153-
#endif
154-
return make_error<SnippetCrash>(std::move(Msg));
147+
return make_error<SnippetSignal>(CRC.RetCode - kSigOffset);
155148
}
156149
}
157150

@@ -360,7 +353,7 @@ class SubProcessFunctionExecutorImpl
360353
return Error::success();
361354
}
362355
// The child exited, but not successfully
363-
return make_error<SnippetCrash>(
356+
return make_error<Failure>(
364357
"Child benchmarking process exited with non-zero exit code: " +
365358
childProcessExitCodeToString(ChildExitCode));
366359
}
@@ -373,9 +366,11 @@ class SubProcessFunctionExecutorImpl
373366
Twine(strerror(errno)));
374367
}
375368

376-
return make_error<SnippetCrash>(
377-
"The benchmarking subprocess sent unexpected signal: " +
378-
Twine(strsignal(ChildSignalInfo.si_signo)));
369+
if (ChildSignalInfo.si_signo == SIGSEGV)
370+
return make_error<SnippetSegmentationFault>(
371+
reinterpret_cast<intptr_t>(ChildSignalInfo.si_addr));
372+
373+
return make_error<SnippetSignal>(ChildSignalInfo.si_signo);
379374
}
380375

381376
[[noreturn]] void prepareAndRunBenchmark(int Pipe,
@@ -575,7 +570,7 @@ Expected<Benchmark> BenchmarkRunner::runConfiguration(
575570
auto NewMeasurements = runMeasurements(**Executor);
576571

577572
if (Error E = NewMeasurements.takeError()) {
578-
if (!E.isA<SnippetCrash>())
573+
if (!E.isA<SnippetExecutionFailure>())
579574
return std::move(E);
580575
InstrBenchmark.Error = toString(std::move(E));
581576
return std::move(InstrBenchmark);

llvm/tools/llvm-exegesis/lib/Error.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99
#include "Error.h"
1010

11+
#ifdef LLVM_ON_UNIX
12+
#include <string.h>
13+
#endif // LLVM_ON_UNIX
14+
1115
namespace llvm {
1216
namespace exegesis {
1317

@@ -19,13 +23,27 @@ std::error_code ClusteringError::convertToErrorCode() const {
1923
return inconvertibleErrorCode();
2024
}
2125

22-
char SnippetCrash::ID;
23-
24-
void SnippetCrash::log(raw_ostream &OS) const { OS << Msg; }
26+
char SnippetExecutionFailure::ID;
2527

26-
std::error_code SnippetCrash::convertToErrorCode() const {
28+
std::error_code SnippetExecutionFailure::convertToErrorCode() const {
2729
return inconvertibleErrorCode();
2830
}
2931

32+
char SnippetSegmentationFault::ID;
33+
34+
void SnippetSegmentationFault::log(raw_ostream &OS) const {
35+
OS << "The snippet encountered a segmentation fault at address "
36+
<< Twine::utohexstr(Address);
37+
}
38+
39+
char SnippetSignal::ID;
40+
41+
void SnippetSignal::log(raw_ostream &OS) const {
42+
OS << "snippet crashed while running";
43+
#ifdef LLVM_ON_UNIX
44+
OS << ": " << strsignal(SignalNumber);
45+
#endif // LLVM_ON_UNIX
46+
}
47+
3048
} // namespace exegesis
3149
} // namespace llvm

llvm/tools/llvm-exegesis/lib/Error.h

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,44 @@ class ClusteringError : public ErrorInfo<ClusteringError> {
3636
std::string Msg;
3737
};
3838

39-
// A class representing failures that happened during snippet execution.
40-
// Instead of terminating the program crashes are logged into the output.
41-
class SnippetCrash : public ErrorInfo<SnippetCrash> {
39+
// A class representing a non-descript snippet execution failure. This class
40+
// is designed to sub-classed into more specific failures that contain
41+
// additional data about the specific error that they represent. Instead of
42+
// halting the program, the errors are reported in the output.
43+
class SnippetExecutionFailure : public ErrorInfo<SnippetExecutionFailure> {
4244
public:
4345
static char ID;
44-
SnippetCrash(const Twine &S) : Msg(S.str()) {}
46+
47+
std::error_code convertToErrorCode() const override;
48+
};
49+
50+
// A class representing specifically segmentation faults that happen during
51+
// snippet execution.
52+
class SnippetSegmentationFault : public SnippetExecutionFailure {
53+
public:
54+
static char ID;
55+
SnippetSegmentationFault(intptr_t SegFaultAddress)
56+
: Address(SegFaultAddress){};
57+
58+
intptr_t getAddress() { return Address; }
4559

4660
void log(raw_ostream &OS) const override;
4761

48-
std::error_code convertToErrorCode() const override;
62+
private:
63+
intptr_t Address;
64+
};
65+
66+
// A class representing all other non-specific failures that happen during
67+
// snippet execution.
68+
class SnippetSignal : public SnippetExecutionFailure {
69+
public:
70+
static char ID;
71+
SnippetSignal(int Signal) : SignalNumber(Signal){};
72+
73+
void log(raw_ostream &OS) const override;
4974

5075
private:
51-
std::string Msg;
76+
int SignalNumber;
5277
};
5378

5479
} // namespace exegesis

0 commit comments

Comments
 (0)