diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticCategories.td | 1 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticFrontendKinds.td | 9 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticGroups.td | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenAction.cpp | 114 | ||||
-rw-r--r-- | clang/test/Frontend/backend-diagnostic.c | 34 |
5 files changed, 162 insertions, 1 deletions
diff --git a/clang/include/clang/Basic/DiagnosticCategories.td b/clang/include/clang/Basic/DiagnosticCategories.td index a02fbdf93fc..37b856976d5 100644 --- a/clang/include/clang/Basic/DiagnosticCategories.td +++ b/clang/include/clang/Basic/DiagnosticCategories.td @@ -8,3 +8,4 @@ //===----------------------------------------------------------------------===// class CatInlineAsm : DiagCategory<"Inline Assembly Issue">; +class CatBackend : DiagCategory<"Backend Issue">; diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index b0b140d6192..21809ad63ff 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -16,11 +16,20 @@ def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal; // Error generated by the backend. def err_fe_inline_asm : Error<"%0">, CatInlineAsm; +def warn_fe_inline_asm : Warning<"%0">, CatInlineAsm, InGroup<BackendInlineAsm>; +def note_fe_inline_asm : Note<"%0">, CatInlineAsm; def note_fe_inline_asm_here : Note<"instantiated into assembly here">; def err_fe_cannot_link_module : Error<"cannot link module '%0': %1">, DefaultFatal; +def warn_fe_backend_frame_larger_than: Warning<"stack size exceeded (%0) in %1">, + CatBackend, InGroup<BackendFrameLargerThan>; +def err_fe_backend_frame_larger_than: Error<"%0">, CatBackend; +def note_fe_backend_frame_larger_than: Note<"%0">, CatBackend; +def warn_fe_backend_plugin: Warning<"%0">, CatBackend, InGroup<BackendPlugin>; +def err_fe_backend_plugin: Error<"%0">, CatBackend; +def note_fe_backend_plugin: Note<"%0">, CatBackend; def err_fe_invalid_code_complete_file : Error< "cannot locate code-completion file %0">, DefaultFatal; diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 8e9ef688c6f..441b5af4cda 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -625,3 +625,8 @@ def ASM : DiagGroup<"asm", [ // OpenMP warnings. def SourceUsesOpenMP : DiagGroup<"source-uses-openmp">; + +// Backend warnings. +def BackendInlineAsm : DiagGroup<"inline-asm">; +def BackendFrameLargerThan : DiagGroup<"frame-larger-than">; +def BackendPlugin : DiagGroup<"backend-plugin">; diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index ef44c96bb6b..5f66ba1735e 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -21,6 +21,8 @@ #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IRReader/IRReader.h" @@ -149,11 +151,18 @@ namespace clang { void *OldContext = Ctx.getInlineAsmDiagnosticContext(); Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this); + LLVMContext::DiagnosticHandlerTy OldDiagnosticHandler = + Ctx.getDiagnosticHandler(); + void *OldDiagnosticContext = Ctx.getDiagnosticContext(); + Ctx.setDiagnosticHandler(DiagnosticHandler, this); + EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts, C.getTargetInfo().getTargetDescription(), TheModule.get(), Action, AsmOutStream); Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext); + + Ctx.setDiagnosticHandler(OldDiagnosticHandler, OldDiagnosticContext); } virtual void HandleTagDeclDefinition(TagDecl *D) { @@ -194,8 +203,23 @@ namespace clang { ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc); } + static void DiagnosticHandler(const llvm::DiagnosticInfo &DI, + void *Context) { + ((BackendConsumer *)Context)->DiagnosticHandlerImpl(DI); + } + void InlineAsmDiagHandler2(const llvm::SMDiagnostic &, SourceLocation LocCookie); + + void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI); + /// \brief Specialized handler for InlineAsm diagnostic. + /// \return True if the diagnostic has been successfully reported, false + /// otherwise. + bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D); + /// \brief Specialized handler for StackSize diagnostic. + /// \return True if the diagnostic has been successfully reported, false + /// otherwise. + bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D); }; void BackendConsumer::anchor() {} @@ -274,7 +298,95 @@ void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D, Diags.Report(Loc, diag::err_fe_inline_asm).AddString(Message); } -// +#define ComputeDiagID(Severity, GroupName, DiagID) \ + do { \ + switch (Severity) { \ + case llvm::DS_Error: \ + DiagID = diag::err_fe_##GroupName; \ + break; \ + case llvm::DS_Warning: \ + DiagID = diag::warn_fe_##GroupName; \ + break; \ + case llvm::DS_Note: \ + DiagID = diag::note_fe_##GroupName; \ + break; \ + } \ + } while (false) + +bool +BackendConsumer::InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D) { + unsigned DiagID; + ComputeDiagID(D.getSeverity(), inline_asm, DiagID); + std::string Message = D.getMsgStr().str(); + + // If this problem has clang-level source location information, report the + // issue as being a prbolem in the source with a note showing the instantiated + // code. + SourceLocation LocCookie = + SourceLocation::getFromRawEncoding(D.getLocCookie()); + if (LocCookie.isValid()) + Diags.Report(LocCookie, DiagID).AddString(Message); + else { + // Otherwise, report the backend diagnostic as occurring in the generated + // .s file. + // If Loc is invalid, we still need to report the diagnostic, it just gets + // no location info. + FullSourceLoc Loc; + Diags.Report(Loc, DiagID).AddString(Message); + } + // We handled all the possible severities. + return true; +} + +bool +BackendConsumer::StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D) { + if (D.getSeverity() != llvm::DS_Warning) + // For now, the only support we have for StackSize diagnostic is warning. + // We do not know how to format other severities. + return false; + + // FIXME: We should demangle the function name. + // FIXME: Is there a way to get a location for that function? + FullSourceLoc Loc; + Diags.Report(Loc, diag::warn_fe_backend_frame_larger_than) + << D.getStackSize() << D.getFunction().getName(); + return true; +} + +/// \brief This function is invoked when the backend needs +/// to report something to the user. +void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) { + unsigned DiagID = diag::err_fe_inline_asm; + llvm::DiagnosticSeverity Severity = DI.getSeverity(); + // Get the diagnostic ID based. + switch (DI.getKind()) { + case llvm::DK_InlineAsm: + if (InlineAsmDiagHandler(cast<DiagnosticInfoInlineAsm>(DI))) + return; + ComputeDiagID(Severity, inline_asm, DiagID); + break; + case llvm::DK_StackSize: + if (StackSizeDiagHandler(cast<DiagnosticInfoStackSize>(DI))) + return; + ComputeDiagID(Severity, backend_frame_larger_than, DiagID); + break; + default: + // Plugin IDs are not bound to any value as they are set dynamically. + ComputeDiagID(Severity, backend_plugin, DiagID); + break; + } + std::string MsgStorage; + { + raw_string_ostream Stream(MsgStorage); + DiagnosticPrinterRawOStream DP(Stream); + DI.print(DP); + } + + // Report the backend message using the usual diagnostic mechanism. + FullSourceLoc Loc; + Diags.Report(Loc, DiagID).AddString(MsgStorage); +} +#undef ComputeDiagID CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext) : Act(_Act), LinkModule(0), diff --git a/clang/test/Frontend/backend-diagnostic.c b/clang/test/Frontend/backend-diagnostic.c new file mode 100644 index 00000000000..acb15f27d1a --- /dev/null +++ b/clang/test/Frontend/backend-diagnostic.c @@ -0,0 +1,34 @@ +// REQUIRES: x86-registered-target +// Play around with backend reporting: +// _REGULAR_: Regular behavior, no warning switch enabled. +// _PROMOTE_: Promote warning to error. +// _IGNORE_: Drop backend warning. +// +// RUN: not %clang_cc1 %s -mllvm -warn-stack-size=0 -S -o - -triple=i386-apple-darwin 2> %t.err +// RUN: FileCheck < %t.err %s --check-prefix=REGULAR --check-prefix=ASM +// RUN: not %clang_cc1 %s -mllvm -warn-stack-size=0 -S -o - -triple=i386-apple-darwin -Werror=frame-larger-than 2> %t.err +// RUN: FileCheck < %t.err %s --check-prefix=PROMOTE --check-prefix=ASM +// RUN: not %clang_cc1 %s -mllvm -warn-stack-size=0 -S -o - -triple=i386-apple-darwin -Wno-frame-larger-than 2> %t.err +// RUN: FileCheck < %t.err %s --check-prefix=IGNORE --check-prefix=ASM +// +// Currently the stack size reporting cannot be checked with -verify because +// no source location is attached to the diagnostic. Therefore do not emit +// them for the -verify test for now. +// RUN: %clang_cc1 %s -S -o - -triple=i386-apple-darwin -verify + +extern void doIt(char *); + +// REGULAR: warning: stack size exceeded ({{[0-9]+}}) in stackSizeWarning +// PROMOTE: error: stack size exceeded ({{[0-9]+}}) in stackSizeWarning +// IGNORE-NOT: stack size exceeded ({{[0-9]+}}) in stackSizeWarning +void stackSizeWarning() { + char buffer[80]; + doIt(buffer); +} + +// ASM: inline assembly requires more registers than available +void inlineAsmError(int x0, int x1, int x2, int x3, int x4, + int x5, int x6, int x7, int x8, int x9) { + __asm__("hello world": : "r" (x0),"r" (x1),"r" (x2),"r" (x3), // expected-error + {{inline assembly requires more registers than available}} + "r" (x4),"r" (x5),"r" (x6),"r" (x7),"r" (x8),"r" (x9)); +} |