[llvm] [LLVM] Parametrize hardcoded behaviors in diagnostics error handling. (PR #156439)
Manuel Carrasco via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 4 03:24:22 PDT 2025
https://github.com/mgcarrasco updated https://github.com/llvm/llvm-project/pull/156439
>From fa0ed237b4ca9c32c2478baae519d6aac0db9eef Mon Sep 17 00:00:00 2001
From: Manuel Carrasco <Manuel.Carrasco at amd.com>
Date: Tue, 2 Sep 2025 03:16:15 -0700
Subject: [PATCH 1/2] [LLVM] Introduce configurable halt actions on first
unhandled diagnostic error
---
llvm/lib/IR/LLVMContext.cpp | 43 +++++++++++++++++++++++++++++++++++--
1 file changed, 41 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp
index 57532cd491dd6..94257a101db51 100644
--- a/llvm/lib/IR/LLVMContext.cpp
+++ b/llvm/lib/IR/LLVMContext.cpp
@@ -31,6 +31,30 @@
using namespace llvm;
+namespace opts {
+
+enum class HaltOnFirstDiagErrorAction {
+ Exit,
+ Abort,
+ None,
+};
+
+static cl::opt<HaltOnFirstDiagErrorAction> HaltOnFirstDiagErrorOpt(
+ "halt-on-first-diag-error",
+ cl::desc(
+ "Halt action to take on the first unhandled diagnostic error reported"),
+ cl::values(
+ clEnumValN(
+ HaltOnFirstDiagErrorAction::Exit, "exit",
+ "Exit with error code 1 on first diagnostic with error severity"),
+ clEnumValN(HaltOnFirstDiagErrorAction::Abort, "abort",
+ "Abort with a stacktrace immediately on first diagnostic "
+ "with error severity"),
+ clEnumValN(HaltOnFirstDiagErrorAction::None, "none",
+ "Do not halt on first diagnostic with error severity")),
+ cl::init(HaltOnFirstDiagErrorAction::Exit), cl::Hidden);
+} // namespace opts
+
static StringRef knownBundleName(unsigned BundleTagID) {
switch (BundleTagID) {
case LLVMContext::OB_deopt:
@@ -242,6 +266,19 @@ LLVMContext::getDiagnosticMessagePrefix(DiagnosticSeverity Severity) {
llvm_unreachable("Unknown DiagnosticSeverity");
}
+static void handleHaltOnFirstDiagError() {
+ switch (opts::HaltOnFirstDiagErrorOpt) {
+ case opts::HaltOnFirstDiagErrorAction::Exit:
+ std::exit(1);
+ break;
+ case opts::HaltOnFirstDiagErrorAction::Abort:
+ std::abort();
+ break;
+ default:
+ break;
+ }
+}
+
void LLVMContext::diagnose(const DiagnosticInfo &DI) {
if (auto *OptDiagBase = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
if (LLVMRemarkStreamer *RS = getLLVMRemarkStreamer())
@@ -264,8 +301,10 @@ void LLVMContext::diagnose(const DiagnosticInfo &DI) {
errs() << getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
DI.print(DP);
errs() << "\n";
- if (DI.getSeverity() == DS_Error)
- exit(1);
+
+ if (DI.getSeverity() == DS_Error) {
+ handleHaltOnFirstDiagError();
+ }
}
//===----------------------------------------------------------------------===//
>From 5a1cc08efbe5f85a77606dd023fcde894f85f1ef Mon Sep 17 00:00:00 2001
From: Manuel Carrasco <Manuel.Carrasco at amd.com>
Date: Tue, 2 Sep 2025 03:18:04 -0700
Subject: [PATCH 2/2] [llc] Add option to disable llc-specific diagnostic
handler
---
llvm/test/tools/llc/no-diagnostic-handler.ll | 25 ++++++++++++++++++++
llvm/tools/llc/llc.cpp | 11 +++++++--
2 files changed, 34 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/tools/llc/no-diagnostic-handler.ll
diff --git a/llvm/test/tools/llc/no-diagnostic-handler.ll b/llvm/test/tools/llc/no-diagnostic-handler.ll
new file mode 100644
index 0000000000000..72f4b3cd2b4a2
--- /dev/null
+++ b/llvm/test/tools/llc/no-diagnostic-handler.ll
@@ -0,0 +1,25 @@
+; COM: Test that the default behavior persists (the llc-specific handler prints all errors).
+; RUN: not llc -mtriple=amdgcn -verify-machineinstrs=0 -global-isel=false < %s 2>&1 | FileCheck -check-prefix=ALL-ERRORS %s
+; COM: Do not halt on the first error when the llc-specific handler is not loaded.
+; RUN: not llc -mtriple=amdgcn -verify-machineinstrs=0 -global-isel=false -no-diag-handler -halt-on-first-diag-error=none < %s 2>&1 | FileCheck -check-prefix=ALL-ERRORS %s
+
+; COM: Now halt on the first error by disabling the llc-specific handler and test the different halt actions
+; RUN: not llc -mtriple=amdgcn -verify-machineinstrs=0 -global-isel=false -no-diag-handler -halt-on-first-diag-error=exit < %s 2>&1 | FileCheck -check-prefix=FIRST-ERROR %s
+; COM: Same error message as in -halt-on-first-diag-error=exit but with a crash.
+; RUN: not --crash llc -mtriple=amdgcn -verify-machineinstrs=0 -global-isel=false -no-diag-handler -halt-on-first-diag-error=abort < %s 2>&1 | FileCheck -check-prefix=FIRST-ERROR %s
+
+; ALL-ERRORS: error: <unknown>:0:0: in function illegal_vgpr_to_sgpr_copy_i32 void (): illegal VGPR to SGPR copy
+; FIRST-ERROR: error: <unknown>:0:0: in function illegal_vgpr_to_sgpr_copy_i32 void (): illegal VGPR to SGPR copy
+define amdgpu_kernel void @illegal_vgpr_to_sgpr_copy_i32() #0 {
+ %vgpr = call i32 asm sideeffect "; def $0", "=${v1}"()
+ call void asm sideeffect "; use $0", "${s9}"(i32 %vgpr)
+ ret void
+}
+
+; ALL-ERRORS: error: <unknown>:0:0: in function illegal_vgpr_to_sgpr_copy_v2i32 void (): illegal VGPR to SGPR copy
+; FIRST-ERROR-NOT: error: <unknown>:0:0: in function illegal_vgpr_to_sgpr_copy_v2i32 void (): illegal VGPR to SGPR copy
+define amdgpu_kernel void @illegal_vgpr_to_sgpr_copy_v2i32() #0 {
+ %vgpr = call <2 x i32> asm sideeffect "; def $0", "=${v[0:1]}"()
+ call void asm sideeffect "; use $0", "${s[10:11]}"(<2 x i32> %vgpr)
+ ret void
+}
diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp
index b3d7185e7f144..06be15500028a 100644
--- a/llvm/tools/llc/llc.cpp
+++ b/llvm/tools/llc/llc.cpp
@@ -213,6 +213,11 @@ static cl::opt<std::string> PassPipeline(
static cl::alias PassPipeline2("p", cl::aliasopt(PassPipeline),
cl::desc("Alias for -passes"));
+static cl::opt<bool>
+ NoDiagHandler("no-diag-handler",
+ cl::desc("Do not load the llc-specific diagnostic handler."),
+ cl::init(false), cl::Hidden);
+
namespace {
std::vector<std::string> &getRunPassNames() {
@@ -384,8 +389,10 @@ int main(int argc, char **argv) {
LLVMContext Context;
Context.setDiscardValueNames(DiscardValueNames);
- // Set a diagnostic handler that doesn't exit on the first error
- Context.setDiagnosticHandler(std::make_unique<LLCDiagnosticHandler>());
+ if (!NoDiagHandler) {
+ // Set a diagnostic handler that doesn't exit on the first error
+ Context.setDiagnosticHandler(std::make_unique<LLCDiagnosticHandler>());
+ }
Expected<std::unique_ptr<ToolOutputFile>> RemarksFileOrErr =
setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses,
More information about the llvm-commits
mailing list