llvm.org GIT mirror llvm / 2c05d88
[llc] New diagnostic handler Without a diagnostic handler installed, llc's behaviour is to exit on the first error that it encounters. This is very different from the behaviour of clang and other front ends, which try to gather as many errors as possible before exiting. This commit adds a diagnostic handler to llc, allowing it to find and report more than one error. The old behaviour is preserved under a flag (-exit-on-error). Some of the tests fail with the new diagnostic handler, so they have to use the new flag in order to run under the previous behaviour. Some of these are known bugs, others need further investigation. Ideally, we should fix the tests and remove the flag at some point in the future. Reapplied after fixing the LLDB build that was broken due to the new DiagnosticSeverity in LLVMContext.h. Patch by Diana Picus. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@269563 91177308-0d34-0410-b5e6-96231b3b80d8 Renato Golin 4 years ago
31 changed file(s) with 70 addition(s) and 34 deletion(s). Raw diff Collapse all Expand all
3333 class SMDiagnostic;
3434
3535 /// \brief Defines the different supported severity of a diagnostic.
36 enum DiagnosticSeverity {
36 enum DiagnosticSeverity : char {
3737 DS_Error,
3838 DS_Warning,
3939 DS_Remark,
2828 class DICompositeType;
2929 class SMDiagnostic;
3030 class DiagnosticInfo;
31 enum DiagnosticSeverity : char;
3132 template class SmallVectorImpl;
3233 class Function;
3334 class DebugLoc;
171172 /// setDiagnosticContext.
172173 void *getDiagnosticContext() const;
173174
175 /// \brief Get the prefix that should be printed in front of a diagnostic of
176 /// the given \p Severity
177 static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity);
178
174179 /// \brief Report a message to the currently installed diagnostic handler.
175180 ///
176181 /// This function returns, in particular in the case of error reporting
230230 return true;
231231 }
232232
233 static const char *getDiagnosticMessagePrefix(DiagnosticSeverity Severity) {
233 const char *
234 LLVMContext::getDiagnosticMessagePrefix(DiagnosticSeverity Severity) {
234235 switch (Severity) {
235236 case DS_Error:
236237 return "error";
None ; RUN: not llc -march=arm64 < %s 2> %t
0 ; RUN: not llc -march=arm64 -exit-on-error < %s 2> %t
11 ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
22
33 ; Check for at least one invalid constant.
None ; RUN: not llc -march=arm64 < %s 2> %t
0 ; RUN: not llc -march=arm64 -exit-on-error < %s 2> %t
11 ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
22
33 ; Check for at least one invalid constant.
None ; RUN: not llc -march=arm64 < %s 2> %t
0 ; RUN: not llc -march=arm64 -exit-on-error < %s 2> %t
11 ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
22
33 ; Check for at least one invalid constant.
None ; RUN: not llc -march=arm64 < %s 2> %t
0 ; RUN: not llc -march=arm64 -exit-on-error < %s 2> %t
11 ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
22
33 ; Check for at least one invalid constant.
None ; RUN: not llc -march=arm64 < %s 2> %t
0 ; RUN: not llc -march=arm64 -exit-on-error < %s 2> %t
11 ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
22
33 ; Check for at least one invalid constant.
None ; RUN: not llc -march=arm64 < %s 2> %t
0 ; RUN: not llc -march=arm64 -exit-on-error < %s 2> %t
11 ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
22
33 ; Check for at least one invalid constant.
None ; RUN: not llc -march=amdgcn -mcpu=SI -verify-machineinstrs< %s 2>&1 | FileCheck %s
1 ; RUN: not llc -march=amdgcn -mcpu=tonga -verify-machineinstrs< %s 2>&1 | FileCheck %s
2 ; RUN: not llc -march=r600 -mcpu=cypress < %s 2>&1 | FileCheck %s
0 ; RUN: not llc -march=amdgcn -mcpu=SI -verify-machineinstrs -exit-on-error < %s 2>&1 | FileCheck %s
1 ; RUN: not llc -march=amdgcn -mcpu=tonga -verify-machineinstrs -exit-on-error < %s 2>&1 | FileCheck %s
2 ; RUN: not llc -march=r600 -mcpu=cypress -exit-on-error < %s 2>&1 | FileCheck %s
33
44 ; CHECK: in function test_call_external{{.*}}: unsupported call to function external_function
55
None ; RUN: not llc -march=amdgcn -mcpu=tahiti -mattr=+promote-alloca -verify-machineinstrs < %s 2>&1 | FileCheck %s
1 ; RUN: not llc -march=amdgcn -mcpu=tahiti -mattr=-promote-alloca -verify-machineinstrs < %s 2>&1 | FileCheck %s
2 ; RUN: not llc -march=r600 -mcpu=cypress < %s 2>&1 | FileCheck %s
0 ; RUN: not llc -march=amdgcn -mcpu=tahiti -mattr=+promote-alloca -verify-machineinstrs -exit-on-error < %s 2>&1 | FileCheck %s
1 ; RUN: not llc -march=amdgcn -mcpu=tahiti -mattr=-promote-alloca -verify-machineinstrs -exit-on-error < %s 2>&1 | FileCheck %s
2 ; RUN: not llc -march=r600 -mcpu=cypress -exit-on-error < %s 2>&1 | FileCheck %s
33
44 ; CHECK: in function test_dynamic_stackalloc{{.*}}: unsupported dynamic alloca
55
None ; RUN: not llc -march=amdgcn -mtriple=amdgcn-unknown-amdhsa < %s 2>&1 | FileCheck %s
0 ; RUN: not llc -march=amdgcn -mtriple=amdgcn-unknown-amdhsa -exit-on-error < %s 2>&1 | FileCheck %s
11
22 ; CHECK: in function pixel_s{{.*}}: unsupported non-compute shaders with HSA
33 define amdgpu_ps void @pixel_shader() #0 {
None ; RUN: not llc -verify-machineinstrs -march=amdgcn -mcpu=SI %s -o /dev/null 2>&1 | FileCheck %s
1 ; RUN: not llc -verify-machineinstrs -march=amdgcn -mcpu=tonga %s -o /dev/null 2>&1 | FileCheck %s
0 ; RUN: not llc -verify-machineinstrs -march=amdgcn -mcpu=SI -exit-on-error %s -o /dev/null 2>&1 | FileCheck %s
1 ; RUN: not llc -verify-machineinstrs -march=amdgcn -mcpu=tonga -exit-on-error %s -o /dev/null 2>&1 | FileCheck %s
22
33 ; Make sure promote alloca pass doesn't crash
44
None ; RUN: not llc -march=amdgcn < %s 2>&1 | FileCheck %s
0 ; RUN: not llc -march=amdgcn -exit-on-error < %s 2>&1 | FileCheck %s
11
22 ; Make sure that AMDGPUPromoteAlloca doesn't crash if the called
33 ; function is a constantexpr cast of a function.
None ; RUN: not llc -mtriple=arm-eabi -mcpu=cortex-a8 %s -o - 2>&1 | FileCheck %s
0 ; RUN: not llc -mtriple=arm-eabi -mcpu=cortex-a8 -exit-on-error %s -o - 2>&1 | FileCheck %s
11
22 ; Check for error message:
33 ; CHECK: scalar-to-vector conversion failed, possible invalid constraint for vector type
None ; RUN: not llc -march=bpf < %s 2> %t1
0 ; RUN: not llc -march=bpf -exit-on-error < %s 2> %t1
11 ; RUN: FileCheck %s < %t1
22 ; CHECK: too many args
33
None ; RUN: not llc -march=bpf < %s 2> %t1
0 ; RUN: not llc -march=bpf -exit-on-error < %s 2> %t1
11 ; RUN: FileCheck %s < %t1
22 ; CHECK: too many args
33
None ; RUN: not llc -march=bpf < %s 2> %t1
0 ; RUN: not llc -march=bpf -exit-on-error < %s 2> %t1
11 ; RUN: FileCheck %s < %t1
22 ; CHECK: only integer returns
33
None ; RUN: not llc -march=bpf < %s 2> %t1
0 ; RUN: not llc -march=bpf -exit-on-error < %s 2> %t1
11 ; RUN: FileCheck %s < %t1
22 ; CHECK: only small returns
33
None # RUN: not llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
0 # RUN: not llc -start-after branch-folder -stop-after branch-folder -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s
11
22 --- |
33
None # RUN: not llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
0 # RUN: not llc -start-after branch-folder -stop-after branch-folder -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s
11 # This test ensures an error is reported if the embedded LLVM IR contains an
22 # error.
33
None # RUN: not llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
0 # RUN: not llc -start-after branch-folder -stop-after branch-folder -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s
11 # This test ensures that an error is reported when the mir file has LLVM IR and
22 # one of the machine functions has a name that doesn't match any function in
33 # the LLVM IR.
None # RUN: not llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
0 # RUN: not llc -start-after branch-folder -stop-after branch-folder -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s
11 # This test ensures that an error is reported when a machine function doesn't
22 # have a name attribute.
33
None # RUN: not llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
0 # RUN: not llc -start-after branch-folder -stop-after branch-folder -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s
11 # This test ensures that the machine function errors are reported correctly.
22
33 ---
None # RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
0 # 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
11
22 --- |
33
None # RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
0 # 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
11
22 --- |
33
None # RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
0 # 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
11 --- |
22
33 define i32 @test(i32 %a) {
None ; RUN: not llc -mcpu=pwr7 -o /dev/null %s 2>&1 | FileCheck %s
0 ; RUN: not llc -mcpu=pwr7 -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s
11 target datalayout = "E-m:e-i64:64-n32:64"
22 target triple = "powerpc64-unknown-linux-gnu"
33
None ; RUN: not llc -mcpu=pwr7 -o /dev/null %s 2>&1 | FileCheck %s
0 ; RUN: not llc -mcpu=pwr7 -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s
11 target datalayout = "E-m:e-i64:64-n32:64"
22 target triple = "powerpc64-unknown-linux-gnu"
33
None ; RUN: not llc -o /dev/null %s 2>&1 | FileCheck %s
0 ; RUN: not llc -exit-on-error -o /dev/null %s 2>&1 | FileCheck %s
11 target triple = "x86_64--"
22
33 ; CHECK: error: couldn't allocate output register for constraint '{ax}'
2424 #include "llvm/CodeGen/MachineModuleInfo.h"
2525 #include "llvm/CodeGen/TargetPassConfig.h"
2626 #include "llvm/IR/DataLayout.h"
27 #include "llvm/IR/DiagnosticInfo.h"
28 #include "llvm/IR/DiagnosticPrinter.h"
2729 #include "llvm/IR/IRPrintingPasses.h"
2830 #include "llvm/IR/LLVMContext.h"
2931 #include "llvm/IR/LegacyPassManager.h"
110112 cl::desc("Discard names from Value (other than GlobalValue)."),
111113 cl::init(false), cl::Hidden);
112114
115 static cl::opt ExitOnError(
116 "exit-on-error",
117 cl::desc("Exit as soon as an error is encountered."),
118 cl::init(false), cl::Hidden);
119
113120 static int compileModule(char **, LLVMContext &);
114121
115122 static std::unique_ptr
180187 return FDOut;
181188 }
182189
190 static void DiagnosticHandler(const DiagnosticInfo &DI, void *Context) {
191 bool *HasError = static_cast(Context);
192 if (DI.getSeverity() == DS_Error)
193 *HasError = true;
194
195 DiagnosticPrinterRawOStream DP(errs());
196 errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
197 DI.print(DP);
198 errs() << "\n";
199 }
200
183201 // main - Entry point for the llc compiler.
184202 //
185203 int main(int argc, char **argv) {
213231 cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");
214232
215233 Context.setDiscardValueNames(DiscardValueNames);
234
235 // Set a diagnostic handler that doesn't exit on the first error
236 if (!ExitOnError) {
237 bool HasError = false;
238 Context.setDiagnosticHandler(DiagnosticHandler, &HasError);
239 }
216240
217241 // Compile the module TimeCompilations times to give better compile time
218242 // metrics.
439463 }
440464
441465 PM.run(*M);
466
467 if (!ExitOnError) {
468 auto HasError = *static_cast(Context.getDiagnosticContext());
469 if (HasError)
470 return 1;
471 }
442472
443473 // Compare the two outputs and make sure they're the same
444474 if (CompileTwice) {