[PATCH] Add warning capabilities in LLVM (backend part)
Tom Stellard
tom at stellard.net
Fri Nov 15 10:28:03 PST 2013
On Fri, Nov 15, 2013 at 10:17:11AM -0800, Quentin Colombet wrote:
> Hi dblaikie, echristo, rengolin, chandlerc,
>
> Hi,
>
> This patch implements the proposal discussed a few months ago (http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-July/063845.html) regarding adding warning capabilities in LLVM.
>
> //// Overview ////
>
> The patch adds a new LLVMContext::report that can be used to communicate to the front-end, if any, that something of interest happened.
> The report contains the following information:
> - The kind of the report: What this is this about.
> - The severity of the report: How bad this is.
> - The default message to print: What should be reported.
> - A data field: Some meta information.
>
> The data field should be used to communicate all sort of data to the front-end. Ultimately, this field should provide enough information to the front-end so that it could build its own diagnostic if it does not want to print the default message.
> This means that both the back-end and the front-end should agree on the structure of this field based on the pair kind/severity.
> This feature is not stressed by this patch.
>
> This patch introduces a new ReportHandlerTy and a new ReportContext that should be set by the front-end to be able to map these reports in its own diagnostics system.
I like this feature, thanks for working on it. Could it be used as
a replacement for report_fatal_error() ?
-Tom
>
> //// Next Steps ////
>
> - Send the patch for clang (I have it on hold).
> - Switch to this reporting for all warnings printing happening in the backend.
> - Switch the InlineAsmDiagHandler to the new reporting mechanism. This involves a bit of work, especially regarding the meta data.
>
> Thanks for your reviews.
>
> Cheers,
> Quentin
>
> PS: Sorry for the delay, it took my ages to get to this point in my todolist.
>
> http://llvm-reviews.chandlerc.com/D2190
>
> Files:
> include/llvm/IR/LLVMContext.h
> lib/CodeGen/PrologEpilogInserter.cpp
> lib/IR/LLVMContext.cpp
> lib/IR/LLVMContextImpl.cpp
> lib/IR/LLVMContextImpl.h
> Index: include/llvm/IR/LLVMContext.h
> ===================================================================
> --- include/llvm/IR/LLVMContext.h
> +++ include/llvm/IR/LLVMContext.h
> @@ -52,6 +52,22 @@
> MD_invariant_load = 6 // "invariant.load"
> };
>
> + /// Defines the different supported kind of report.
> + /// \see LLVMContext::report.
> + enum ReportKind {
> + RK_InlineAsm,
> + RK_StackSize,
> + RK_Other
> + };
> +
> + /// Defines the different supported severity of a report.
> + /// \see LLVMContext::report.
> + enum ReportSeverity {
> + RS_Error,
> + RS_Warning,
> + RS_Note
> + };
> +
> /// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
> /// This ID is uniqued across modules in the current LLVMContext.
> unsigned getMDKindID(StringRef Name) const;
> @@ -64,6 +80,14 @@
> typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context,
> unsigned LocCookie);
>
> + /// Defines the type of a report handler.
> + /// \see LLVMContext::setReportHandler.
> + /// \see LLVMContext::report.
> + typedef void (*ReportHandlerTy)(void *Context, ReportKind Kind,
> + StringRef StringData,
> + ReportSeverity Severity,
> + StringRef Message);
> +
> /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked
> /// when problems with inline asm are detected by the backend. The first
> /// argument is a function pointer and the second is a context pointer that
> @@ -82,6 +106,40 @@
> /// setInlineAsmDiagnosticHandler.
> void *getInlineAsmDiagnosticContext() const;
>
> + /// setReportHandler - This method sets a handler that is invoked
> + /// when the backend needs to report anything to the user. The first
> + /// argument is a function pointer and the second is a context pointer that
> + /// gets passed into the ReportHandler.
> + ///
> + /// LLVMContext doesn't take ownership or interpret either of these
> + /// pointers.
> + void setReportHandler(ReportHandlerTy ReportHandler, void *ReportContext = 0);
> +
> + /// getReportHandler - Return the diagnostic handler set by
> + /// setReportHandler.
> + ReportHandlerTy getReportHandler() const;
> +
> + /// getReportContext - Return the diagnostic context set by
> + /// setReportContext.
> + void *getReportContext() const;
> +
> + /// report - Report a message to the currently installed report handler.
> + /// This function returns, in particular in the case of error reporting
> + /// (Severity == RS_Error), so code should be prepared to drop the
> + /// erroneous construct on the floor and "not crash".
> + /// The generated code need not be correct.
> + /// \p Kind is used to precise the kind of report this is about.
> + /// \p StringData can be used to pass specific information to the report
> + /// handler, so that it can create its own specific message.
> + /// \p Severity gives the severity of the report.
> + /// \p Message is the default message to be printed. It is used when the
> + /// report handler is not capable to take advantages of \p StringData.
> + /// The reported message will be implicitly prefixed with the severity
> + /// keyword, i.e., "error: " for RS_Error, "warning: " for RS_Warning,
> + /// and "note: " for RS_Note.
> + /// The message should not end with a ".".
> + void report(ReportKind Kind, StringRef StringData,
> + ReportSeverity Severity, StringRef Message);
>
> /// emitError - Emit an error message to the currently installed error handler
> /// with optional location information. This function returns, so code should
> Index: lib/CodeGen/PrologEpilogInserter.cpp
> ===================================================================
> --- lib/CodeGen/PrologEpilogInserter.cpp
> +++ lib/CodeGen/PrologEpilogInserter.cpp
> @@ -30,6 +30,7 @@
> #include "llvm/CodeGen/MachineRegisterInfo.h"
> #include "llvm/CodeGen/RegisterScavenging.h"
> #include "llvm/IR/InlineAsm.h"
> +#include "llvm/IR/LLVMContext.h"
> #include "llvm/Support/CommandLine.h"
> #include "llvm/Support/Compiler.h"
> #include "llvm/Support/Debug.h"
> @@ -160,10 +161,19 @@
>
> // Warn on stack size when we exceeds the given limit.
> MachineFrameInfo *MFI = Fn.getFrameInfo();
> + uint64_t StackSize = MFI->getStackSize();
> if (WarnStackSize.getNumOccurrences() > 0 &&
> - WarnStackSize < MFI->getStackSize())
> - errs() << "warning: Stack size limit exceeded (" << MFI->getStackSize()
> - << ") in " << Fn.getName() << ".\n";
> + WarnStackSize < StackSize) {
> + std::string DataStorage;
> + raw_string_ostream Data(DataStorage);
> + Data << StackSize;
> +
> + std::string MsgStorage("Stack size limit exceeded (");
> + raw_string_ostream Msg(MsgStorage);
> + Msg << StackSize << ") in " << Fn.getName();
> + F->getContext().report(LLVMContext::RK_StackSize, Data.str(),
> + LLVMContext::RS_Warning, Msg.str());
> + }
>
> delete RS;
> ReturnBlocks.clear();
> Index: lib/IR/LLVMContext.cpp
> ===================================================================
> --- lib/IR/LLVMContext.cpp
> +++ lib/IR/LLVMContext.cpp
> @@ -98,6 +98,22 @@
> return pImpl->InlineAsmDiagContext;
> }
>
> +void LLVMContext::setReportHandler(ReportHandlerTy ReportHandler,
> + void *ReportContext) {
> + pImpl->ReportHandler = ReportHandler;
> + pImpl->ReportContext = ReportContext;
> +}
> +
> +/// getReportHandler - Return the diagnostic handler set by
> +/// setReportHandler.
> +LLVMContext::ReportHandlerTy LLVMContext::getReportHandler() const {
> + return pImpl->ReportHandler;
> +}
> +
> +/// getReportContext - Return the diagnostic context set by
> +/// setReportContext.
> +void *LLVMContext::getReportContext() const { return pImpl->ReportContext; }
> +
> void LLVMContext::emitError(const Twine &ErrorStr) {
> emitError(0U, ErrorStr);
> }
> @@ -112,6 +128,29 @@
> return emitError(LocCookie, ErrorStr);
> }
>
> +void LLVMContext::report(ReportKind Kind, StringRef StringData,
> + ReportSeverity Severity,
> + StringRef Message) {
> + // If there is a report handler, use it.
> + if (pImpl->ReportHandler != 0) {
> + pImpl->ReportHandler(pImpl->ReportContext, Kind, StringData, Severity,
> + Message);
> + return;
> + }
> + // Otherwise, print the message with a prefix based on the severity.
> + switch (Severity) {
> + case RS_Error:
> + errs() << "error: " << Message << "\n";
> + exit(1);
> + case RS_Warning:
> + errs() << "warning: " << Message << "\n";
> + break;
> + case RS_Note:
> + errs() << "note: " << Message << "\n";
> + break;
> + }
> +}
> +
> void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) {
> // If there is no error handler installed, just print the error and exit.
> if (pImpl->InlineAsmDiagHandler == 0) {
> Index: lib/IR/LLVMContextImpl.cpp
> ===================================================================
> --- lib/IR/LLVMContextImpl.cpp
> +++ lib/IR/LLVMContextImpl.cpp
> @@ -37,6 +37,8 @@
> Int64Ty(C, 64) {
> InlineAsmDiagHandler = 0;
> InlineAsmDiagContext = 0;
> + ReportHandler = 0;
> + ReportContext = 0;
> NamedStructTypesUniqueID = 0;
> }
>
> Index: lib/IR/LLVMContextImpl.h
> ===================================================================
> --- lib/IR/LLVMContextImpl.h
> +++ lib/IR/LLVMContextImpl.h
> @@ -238,8 +238,11 @@
>
> LLVMContext::InlineAsmDiagHandlerTy InlineAsmDiagHandler;
> void *InlineAsmDiagContext;
> -
> - typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt*,
> +
> + LLVMContext::ReportHandlerTy ReportHandler;
> + void *ReportContext;
> +
> + typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt *,
> DenseMapAPIntKeyInfo> IntMapTy;
> IntMapTy IntConstants;
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list