Index: include/llvm/IR/DiagnosticInfo.h =================================================================== --- include/llvm/IR/DiagnosticInfo.h +++ include/llvm/IR/DiagnosticInfo.h @@ -34,7 +34,7 @@ class SMDiagnostic; /// \brief Defines the different supported severity of a diagnostic. -enum DiagnosticSeverity { +enum DiagnosticSeverity : char { DS_Error, DS_Warning, DS_Remark, Index: include/llvm/IR/LLVMContext.h =================================================================== --- include/llvm/IR/LLVMContext.h +++ include/llvm/IR/LLVMContext.h @@ -29,6 +29,7 @@ class DICompositeType; class SMDiagnostic; class DiagnosticInfo; +enum DiagnosticSeverity : char; template class SmallVectorImpl; class Function; class DebugLoc; @@ -172,6 +173,10 @@ /// setDiagnosticContext. void *getDiagnosticContext() const; + /// \brief Get the prefix that should be printed in front of a diagnostic of + /// the given \p Severity + static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity); + /// \brief Report a message to the currently installed diagnostic handler. /// /// This function returns, in particular in the case of error reporting Index: lib/IR/LLVMContext.cpp =================================================================== --- lib/IR/LLVMContext.cpp +++ lib/IR/LLVMContext.cpp @@ -231,7 +231,8 @@ return true; } -static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity) { +const char * +LLVMContext::getDiagnosticMessagePrefix(DiagnosticSeverity Severity) { switch (Severity) { case DS_Error: return "error"; Index: test/CodeGen/AArch64/arm64-inline-asm-error-I.ll =================================================================== --- test/CodeGen/AArch64/arm64-inline-asm-error-I.ll +++ test/CodeGen/AArch64/arm64-inline-asm-error-I.ll @@ -1,4 +1,4 @@ -; RUN: not llc -march=arm64 < %s 2> %t +; RUN: not llc -march=arm64 -exit-on-error < %s 2> %t ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s ; Check for at least one invalid constant. Index: test/CodeGen/AArch64/arm64-inline-asm-error-J.ll =================================================================== --- test/CodeGen/AArch64/arm64-inline-asm-error-J.ll +++ test/CodeGen/AArch64/arm64-inline-asm-error-J.ll @@ -1,4 +1,4 @@ -; RUN: not llc -march=arm64 < %s 2> %t +; RUN: not llc -march=arm64 -exit-on-error < %s 2> %t ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s ; Check for at least one invalid constant. Index: test/CodeGen/AArch64/arm64-inline-asm-error-K.ll =================================================================== --- test/CodeGen/AArch64/arm64-inline-asm-error-K.ll +++ test/CodeGen/AArch64/arm64-inline-asm-error-K.ll @@ -1,4 +1,4 @@ -; RUN: not llc -march=arm64 < %s 2> %t +; RUN: not llc -march=arm64 -exit-on-error < %s 2> %t ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s ; Check for at least one invalid constant. Index: test/CodeGen/AArch64/arm64-inline-asm-error-L.ll =================================================================== --- test/CodeGen/AArch64/arm64-inline-asm-error-L.ll +++ test/CodeGen/AArch64/arm64-inline-asm-error-L.ll @@ -1,4 +1,4 @@ -; RUN: not llc -march=arm64 < %s 2> %t +; RUN: not llc -march=arm64 -exit-on-error < %s 2> %t ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s ; Check for at least one invalid constant. Index: test/CodeGen/AArch64/arm64-inline-asm-error-M.ll =================================================================== --- test/CodeGen/AArch64/arm64-inline-asm-error-M.ll +++ test/CodeGen/AArch64/arm64-inline-asm-error-M.ll @@ -1,4 +1,4 @@ -; RUN: not llc -march=arm64 < %s 2> %t +; RUN: not llc -march=arm64 -exit-on-error < %s 2> %t ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s ; Check for at least one invalid constant. Index: test/CodeGen/AArch64/arm64-inline-asm-error-N.ll =================================================================== --- test/CodeGen/AArch64/arm64-inline-asm-error-N.ll +++ test/CodeGen/AArch64/arm64-inline-asm-error-N.ll @@ -1,4 +1,4 @@ -; RUN: not llc -march=arm64 < %s 2> %t +; RUN: not llc -march=arm64 -exit-on-error < %s 2> %t ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s ; Check for at least one invalid constant. Index: test/CodeGen/AMDGPU/call.ll =================================================================== --- test/CodeGen/AMDGPU/call.ll +++ test/CodeGen/AMDGPU/call.ll @@ -1,6 +1,6 @@ -; RUN: not llc -march=amdgcn -mcpu=SI -verify-machineinstrs< %s 2>&1 | FileCheck %s -; RUN: not llc -march=amdgcn -mcpu=tonga -verify-machineinstrs< %s 2>&1 | FileCheck %s -; RUN: not llc -march=r600 -mcpu=cypress < %s 2>&1 | FileCheck %s +; RUN: not llc -march=amdgcn -mcpu=SI -verify-machineinstrs -exit-on-error < %s 2>&1 | FileCheck %s +; RUN: not llc -march=amdgcn -mcpu=tonga -verify-machineinstrs -exit-on-error < %s 2>&1 | FileCheck %s +; RUN: not llc -march=r600 -mcpu=cypress -exit-on-error < %s 2>&1 | FileCheck %s ; CHECK: in function test_call_external{{.*}}: unsupported call to function external_function Index: test/CodeGen/AMDGPU/dynamic_stackalloc.ll =================================================================== --- test/CodeGen/AMDGPU/dynamic_stackalloc.ll +++ test/CodeGen/AMDGPU/dynamic_stackalloc.ll @@ -1,6 +1,6 @@ -; RUN: not llc -march=amdgcn -mcpu=tahiti -mattr=+promote-alloca -verify-machineinstrs < %s 2>&1 | FileCheck %s -; RUN: not llc -march=amdgcn -mcpu=tahiti -mattr=-promote-alloca -verify-machineinstrs < %s 2>&1 | FileCheck %s -; RUN: not llc -march=r600 -mcpu=cypress < %s 2>&1 | FileCheck %s +; RUN: not llc -march=amdgcn -mcpu=tahiti -mattr=+promote-alloca -verify-machineinstrs -exit-on-error < %s 2>&1 | FileCheck %s +; RUN: not llc -march=amdgcn -mcpu=tahiti -mattr=-promote-alloca -verify-machineinstrs -exit-on-error < %s 2>&1 | FileCheck %s +; RUN: not llc -march=r600 -mcpu=cypress -exit-on-error < %s 2>&1 | FileCheck %s ; CHECK: in function test_dynamic_stackalloc{{.*}}: unsupported dynamic alloca Index: test/CodeGen/AMDGPU/no-hsa-graphics-shaders.ll =================================================================== --- test/CodeGen/AMDGPU/no-hsa-graphics-shaders.ll +++ test/CodeGen/AMDGPU/no-hsa-graphics-shaders.ll @@ -1,4 +1,4 @@ -; RUN: not llc -march=amdgcn -mtriple=amdgcn-unknown-amdhsa < %s 2>&1 | FileCheck %s +; RUN: not llc -march=amdgcn -mtriple=amdgcn-unknown-amdhsa -exit-on-error < %s 2>&1 | FileCheck %s ; CHECK: in function pixel_s{{.*}}: unsupported non-compute shaders with HSA define amdgpu_ps void @pixel_shader() #0 { Index: test/CodeGen/AMDGPU/private-memory-broken.ll =================================================================== --- test/CodeGen/AMDGPU/private-memory-broken.ll +++ test/CodeGen/AMDGPU/private-memory-broken.ll @@ -1,5 +1,5 @@ -; RUN: not llc -verify-machineinstrs -march=amdgcn -mcpu=SI %s -o /dev/null 2>&1 | FileCheck %s -; RUN: not llc -verify-machineinstrs -march=amdgcn -mcpu=tonga %s -o /dev/null 2>&1 | FileCheck %s +; RUN: not llc -verify-machineinstrs -march=amdgcn -mcpu=SI -exit-on-error %s -o /dev/null 2>&1 | FileCheck %s +; RUN: not llc -verify-machineinstrs -march=amdgcn -mcpu=tonga -exit-on-error %s -o /dev/null 2>&1 | FileCheck %s ; Make sure promote alloca pass doesn't crash Index: test/CodeGen/AMDGPU/promote-alloca-bitcast-function.ll =================================================================== --- test/CodeGen/AMDGPU/promote-alloca-bitcast-function.ll +++ test/CodeGen/AMDGPU/promote-alloca-bitcast-function.ll @@ -1,4 +1,4 @@ -; RUN: not llc -march=amdgcn < %s 2>&1 | FileCheck %s +; RUN: not llc -march=amdgcn -exit-on-error < %s 2>&1 | FileCheck %s ; Make sure that AMDGPUPromoteAlloca doesn't crash if the called ; function is a constantexpr cast of a function. Index: test/CodeGen/ARM/2012-09-25-InlineAsmScalarToVectorConv2.ll =================================================================== --- test/CodeGen/ARM/2012-09-25-InlineAsmScalarToVectorConv2.ll +++ test/CodeGen/ARM/2012-09-25-InlineAsmScalarToVectorConv2.ll @@ -1,4 +1,4 @@ -; RUN: not llc -mtriple=arm-eabi -mcpu=cortex-a8 %s -o - 2>&1 | FileCheck %s +; RUN: not llc -mtriple=arm-eabi -mcpu=cortex-a8 -exit-on-error %s -o - 2>&1 | FileCheck %s ; Check for error message: ; CHECK: scalar-to-vector conversion failed, possible invalid constraint for vector type Index: test/CodeGen/BPF/many_args1.ll =================================================================== --- test/CodeGen/BPF/many_args1.ll +++ test/CodeGen/BPF/many_args1.ll @@ -1,4 +1,4 @@ -; RUN: not llc -march=bpf < %s 2> %t1 +; RUN: not llc -march=bpf -exit-on-error < %s 2> %t1 ; RUN: FileCheck %s < %t1 ; CHECK: too many args Index: test/CodeGen/BPF/many_args2.ll =================================================================== --- test/CodeGen/BPF/many_args2.ll +++ test/CodeGen/BPF/many_args2.ll @@ -1,4 +1,4 @@ -; RUN: not llc -march=bpf < %s 2> %t1 +; RUN: not llc -march=bpf -exit-on-error < %s 2> %t1 ; RUN: FileCheck %s < %t1 ; CHECK: too many args Index: test/CodeGen/BPF/struct_ret1.ll =================================================================== --- test/CodeGen/BPF/struct_ret1.ll +++ test/CodeGen/BPF/struct_ret1.ll @@ -1,4 +1,4 @@ -; RUN: not llc -march=bpf < %s 2> %t1 +; RUN: not llc -march=bpf -exit-on-error < %s 2> %t1 ; RUN: FileCheck %s < %t1 ; CHECK: only integer returns Index: test/CodeGen/BPF/struct_ret2.ll =================================================================== --- test/CodeGen/BPF/struct_ret2.ll +++ test/CodeGen/BPF/struct_ret2.ll @@ -1,4 +1,4 @@ -; RUN: not llc -march=bpf < %s 2> %t1 +; RUN: not llc -march=bpf -exit-on-error < %s 2> %t1 ; RUN: FileCheck %s < %t1 ; CHECK: only small returns Index: test/CodeGen/MIR/Generic/invalid-jump-table-kind.mir =================================================================== --- test/CodeGen/MIR/Generic/invalid-jump-table-kind.mir +++ test/CodeGen/MIR/Generic/invalid-jump-table-kind.mir @@ -1,4 +1,4 @@ -# RUN: not llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s +# RUN: not llc -start-after branch-folder -stop-after branch-folder -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s --- | Index: test/CodeGen/MIR/Generic/llvm-ir-error-reported.mir =================================================================== --- test/CodeGen/MIR/Generic/llvm-ir-error-reported.mir +++ test/CodeGen/MIR/Generic/llvm-ir-error-reported.mir @@ -1,4 +1,4 @@ -# RUN: not llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s +# RUN: not llc -start-after branch-folder -stop-after branch-folder -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s # This test ensures an error is reported if the embedded LLVM IR contains an # error. Index: test/CodeGen/MIR/Generic/machine-function-missing-function.mir =================================================================== --- test/CodeGen/MIR/Generic/machine-function-missing-function.mir +++ test/CodeGen/MIR/Generic/machine-function-missing-function.mir @@ -1,4 +1,4 @@ -# RUN: not llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s +# RUN: not llc -start-after branch-folder -stop-after branch-folder -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s # This test ensures that an error is reported when the mir file has LLVM IR and # one of the machine functions has a name that doesn't match any function in # the LLVM IR. Index: test/CodeGen/MIR/Generic/machine-function-missing-name.mir =================================================================== --- test/CodeGen/MIR/Generic/machine-function-missing-name.mir +++ test/CodeGen/MIR/Generic/machine-function-missing-name.mir @@ -1,4 +1,4 @@ -# RUN: not llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s +# RUN: not llc -start-after branch-folder -stop-after branch-folder -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s # This test ensures that an error is reported when a machine function doesn't # have a name attribute. Index: test/CodeGen/MIR/Generic/machine-function-redefinition-error.mir =================================================================== --- test/CodeGen/MIR/Generic/machine-function-redefinition-error.mir +++ test/CodeGen/MIR/Generic/machine-function-redefinition-error.mir @@ -1,4 +1,4 @@ -# RUN: not llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s +# RUN: not llc -start-after branch-folder -stop-after branch-folder -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s # This test ensures that the machine function errors are reported correctly. --- Index: test/CodeGen/MIR/X86/spill-slot-fixed-stack-object-aliased.mir =================================================================== --- test/CodeGen/MIR/X86/spill-slot-fixed-stack-object-aliased.mir +++ test/CodeGen/MIR/X86/spill-slot-fixed-stack-object-aliased.mir @@ -1,4 +1,4 @@ -# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s --- | Index: test/CodeGen/MIR/X86/spill-slot-fixed-stack-object-immutable.mir =================================================================== --- test/CodeGen/MIR/X86/spill-slot-fixed-stack-object-immutable.mir +++ test/CodeGen/MIR/X86/spill-slot-fixed-stack-object-immutable.mir @@ -1,4 +1,4 @@ -# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s --- | Index: test/CodeGen/MIR/X86/variable-sized-stack-object-size-error.mir =================================================================== --- test/CodeGen/MIR/X86/variable-sized-stack-object-size-error.mir +++ test/CodeGen/MIR/X86/variable-sized-stack-object-size-error.mir @@ -1,4 +1,4 @@ -# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s +# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s --- | define i32 @test(i32 %a) { Index: test/CodeGen/PowerPC/crbit-asm-disabled.ll =================================================================== --- test/CodeGen/PowerPC/crbit-asm-disabled.ll +++ test/CodeGen/PowerPC/crbit-asm-disabled.ll @@ -1,4 +1,4 @@ -; RUN: not llc -mcpu=pwr7 -o /dev/null %s 2>&1 | FileCheck %s +; RUN: not llc -mcpu=pwr7 -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" Index: test/CodeGen/PowerPC/vec-asm-disabled.ll =================================================================== --- test/CodeGen/PowerPC/vec-asm-disabled.ll +++ test/CodeGen/PowerPC/vec-asm-disabled.ll @@ -1,4 +1,4 @@ -; RUN: not llc -mcpu=pwr7 -o /dev/null %s 2>&1 | FileCheck %s +; RUN: not llc -mcpu=pwr7 -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" Index: test/CodeGen/X86/asm-reject-reg-type-mismatch.ll =================================================================== --- test/CodeGen/X86/asm-reject-reg-type-mismatch.ll +++ test/CodeGen/X86/asm-reject-reg-type-mismatch.ll @@ -1,4 +1,4 @@ -; RUN: not llc -o /dev/null %s 2>&1 | FileCheck %s +; RUN: not llc -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s target triple = "x86_64--" ; CHECK: error: couldn't allocate output register for constraint '{ax}' Index: tools/llc/llc.cpp =================================================================== --- tools/llc/llc.cpp +++ tools/llc/llc.cpp @@ -25,6 +25,8 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" @@ -111,6 +113,11 @@ cl::desc("Discard names from Value (other than GlobalValue)."), cl::init(false), cl::Hidden); +static cl::opt ExitOnError( + "exit-on-error", + cl::desc("Exit as soon as an error is encountered."), + cl::init(false), cl::Hidden); + static int compileModule(char **, LLVMContext &); static std::unique_ptr @@ -181,6 +188,17 @@ return FDOut; } +static void DiagnosticHandler(const DiagnosticInfo &DI, void *Context) { + bool *HasError = static_cast(Context); + if (DI.getSeverity() == DS_Error) + *HasError = true; + + DiagnosticPrinterRawOStream DP(errs()); + errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; + DI.print(DP); + errs() << "\n"; +} + // main - Entry point for the llc compiler. // int main(int argc, char **argv) { @@ -215,6 +233,12 @@ Context.setDiscardValueNames(DiscardValueNames); + // Set a diagnostic handler that doesn't exit on the first error + if (!ExitOnError) { + bool HasError = false; + Context.setDiagnosticHandler(DiagnosticHandler, &HasError); + } + // Compile the module TimeCompilations times to give better compile time // metrics. for (unsigned I = TimeCompilations; I; --I) @@ -441,6 +465,12 @@ PM.run(*M); + if (!ExitOnError) { + auto HasError = *static_cast(Context.getDiagnosticContext()); + if (HasError) + return 1; + } + // Compare the two outputs and make sure they're the same if (CompileTwice) { if (Buffer.size() != CompileTwiceBuffer.size() ||