<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Hi Tom,<div><br></div><div><div><div>On Dec 10, 2013, at 5:02 PM, Tom Stellard <<a href="mailto:tom@stellard.net">tom@stellard.net</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">On Tue, Dec 10, 2013 at 04:31:36PM -0800, Quentin Colombet wrote:<br><blockquote type="cite">Hi dblaikie, rengolin, chandlerc, echristo,<br><br>Hi,<br><br></blockquote><br>Hi Quentin,<br><br>Thanks for continuing to work on this, I think this will be a very<br>useful feature.<br><br><blockquote type="cite">This patch implements the latest proposal discussed a few weeks ago regarding adding warning capabilities in LLVM.<br>The original RFC:<br><a href="http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-July/063845.html">http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-July/063845.html</a><br><br>The latest discussion with the new design:<br>http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20131111/195244.html<br>http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20131118/195627.html<span class="Apple-converted-space"> </span><br><br>//// Overview ////<br><br>The patch adds a new LLVMContext::diagnose that can be used to communicate to the front-end, if any, that something of interest happened.<br>The diagnostics are supported by a new abstraction, the DiagnosticInfo class.<br>The base class contains the following information:<br>- The kind of the report: What this is this about.<br>- The severity of the report: How bad this is.<br><br>This patch also adds 3 classes:<br>- DiagnosticInfoInlineAsm: For inline asm reporting. Basically, this diagnostic will be used to switch to the new diagnostic API for LLVMContext::emitError.<br>- DiagnosticStackSize: For stack size reporting. Comes as a replacement of the hard coded warning in PEI.<br>- DiagnosticOther: For all other reporting. Features a message with %[0-9]+ specifiers and an array of values. Each specifier will be replaced by the printing of the related index from the array of values.<br><br>This patch introduces a new DiagnosticHandlerTy and a new DiagnosticContext that should be set by the front-end to be able to map these diagnostics in its own system.<br><br>//// Next Steps ////<br><br>- Send the patch for clang (I have it on hold).<br>- Switch to this reporting for all warnings printing happening in the backend (i.e., get rid of the hard coded warnings).<br>- Switch LLVMContext::emitError to the new diagnostic API.<br>- Add an entry in LLVM documentation about this diagnostic reporting feature.<br><br>//// Open Questions ////<br><br>- Should we make SMDiagnostic a sub class of DiagnosticInfo?<br>The idea would be to get rid of the InlineAsmDiagHandler.<br><br>- Do we want to provide a C API for this?<br></blockquote><br>I would like to see this in the C API. If there is no C API when I<br>start integrating this into Mesa (which may not be for several months),<br>I can add it myself.<br></div></blockquote>Based on your comment, I guess we can move forward with that proposal and look into the C API as a second step.</div><div>Is this right?</div><div><br></div><div>Just to be sure we are on the right track, looking into the current proposal are you seeing anything missing or anything that will obviously not work with a C API?<br><br><blockquote type="cite"><div style="font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br><blockquote type="cite"><br>- Do we want to extend that to fatal error as well?<br>That would be a nice homogenization of the framework (replace (some of) the calls to report_fatal_error).<br><br></blockquote><br>I'm not sure what 'that' refers to here, but I am in favor of replacing as<br>many calls to report_fatal_error() as possible (preferably all of them).<br>This is especially important for API implementations, like OpenCL that<br>use LLVM as a library, because those APIs need to be able to report errors<br>to the user. Handling errors by calling exit() is not really acceptable.<br></div></blockquote><div>Agree.</div><div><br></div><div>Thanks for your feedbacks.</div><div><br></div><div>-Quentin</div><br><blockquote type="cite"><div style="font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br>-Tom<br><br><blockquote type="cite">Thanks for your reviews.<br><br>Cheers,<br>Quentin<br><br>PS: Hal, DiagnosticPrinter class does not include SCEV or MachineInstr because these are not part of the IR library.<br><br><a href="http://llvm-reviews.chandlerc.com/D2376">http://llvm-reviews.chandlerc.com/D2376</a><br><br>Files:<br> include/llvm/IR/LLVMContext.h<br> include/llvm/Support/DiagnosticInfo.h<br> include/llvm/Support/DiagnosticPrinter.h<br> lib/CodeGen/PrologEpilogInserter.cpp<br> lib/IR/LLVMContext.cpp<br> lib/IR/LLVMContextImpl.cpp<br> lib/IR/LLVMContextImpl.h<br> lib/Support/CMakeLists.txt<br> lib/Support/DiagnosticInfo.cpp<br> lib/Support/DiagnosticPrinter.cpp<br> test/CodeGen/ARM/warn-stack.ll<br> test/CodeGen/X86/warn-stack.ll<br></blockquote><br><blockquote type="cite">Index: include/llvm/IR/LLVMContext.h<br>===================================================================<br>--- include/llvm/IR/LLVMContext.h<br>+++ include/llvm/IR/LLVMContext.h<br>@@ -27,6 +27,7 @@<br>class Instruction;<br>class Module;<br>class SMDiagnostic;<br>+class DiagnosticInfo;<br>template <typename T> class SmallVectorImpl;<br><br>/// This is an important class for using LLVM in a threaded context. It<br>@@ -64,6 +65,11 @@<br> typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context,<br> unsigned LocCookie);<br><br>+ /// Defines the type of a diagnostic handler.<br>+ /// \see LLVMContext::setDiagnosticHandler.<br>+ /// \see LLVMContext::diagnose.<br>+ typedef void (*DiagnosticHandlerTy)(const DiagnosticInfo &DI, void *Context);<br>+<br> /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked<br> /// when problems with inline asm are detected by the backend. The first<br> /// argument is a function pointer and the second is a context pointer that<br>@@ -82,6 +88,33 @@<br> /// setInlineAsmDiagnosticHandler.<br> void *getInlineAsmDiagnosticContext() const;<br><br>+ /// setDiagnosticHandler - This method sets a handler that is invoked<br>+ /// when the backend needs to report anything to the user. The first<br>+ /// argument is a function pointer and the second is a context pointer that<br>+ /// gets passed into the DiagHandler.<br>+ ///<br>+ /// LLVMContext doesn't take ownership or interpret either of these<br>+ /// pointers.<br>+ void setDiagnosticHandler(DiagnosticHandlerTy DiagHandler,<br>+ void *DiagContext = 0);<br>+<br>+ /// getDiagnosticHandler - Return the diagnostic handler set by<br>+ /// setDiagnosticHandler.<br>+ DiagnosticHandlerTy getDiagnosticHandler() const;<br>+<br>+ /// getDiagnosticContext - Return the diagnostic context set by<br>+ /// setDiagnosticContext.<br>+ void *getDiagnosticContext() const;<br>+<br>+ /// diagnose - Report a message to the currently installed diagnostic handler.<br>+ /// This function returns, in particular in the case of error reporting<br>+ /// (DI.Severity == RS_Error), so code should be prepared to drop the<br>+ /// erroneous construct on the floor and "not crash".<br>+ /// The generated code need not be correct.<br>+ /// The diagnostic message will be implicitly prefixed with a severity<br>+ /// keyword according to \p DI.getSeverity(), i.e., "error: "<br>+ /// for RS_Error, "warning: " for RS_Warning, and "note: " for RS_Note.<br>+ void diagnose(const DiagnosticInfo &DI);<br><br> /// emitError - Emit an error message to the currently installed error handler<br> /// with optional location information. This function returns, so code should<br>Index: include/llvm/Support/DiagnosticInfo.h<br>===================================================================<br>--- include/llvm/Support/DiagnosticInfo.h<br>+++ include/llvm/Support/DiagnosticInfo.h<br>@@ -0,0 +1,192 @@<br>+//===- llvm/Support/DiagnosticInfo.h - Diagnostic Declaration ---*- C++ -*-===//<br>+//<br>+// The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+//<br>+// This file declares the different classes involved in low level diagnostics.<br>+//<br>+// Diagnostics reporting is still done as part of the LLVMContext.<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef LLVM_SUPPORT_DIAGNOSTICINFO_H<br>+#define LLVM_SUPPORT_DIAGNOSTICINFO_H<br>+<br>+#include "llvm/ADT/ArrayRef.h"<br>+#include "llvm/Support/Casting.h"<br>+<br>+namespace llvm {<br>+<br>+// Forward declarations.<br>+class DiagnosticPrinter;<br>+class Function;<br>+class Instruction;<br>+class Twine;<br>+class Value;<br>+<br>+/// Defines the different supported severity of a diagnostic.<br>+enum DiagnosticSeverity {<br>+ DS_Error,<br>+ DS_Warning,<br>+ DS_Note<br>+};<br>+<br>+/// Defines the different supported kind of a diagnostic.<br>+/// This enum should be extended with a new ID for each added concrete subclass.<br>+enum DiagnosticKind {<br>+ DK_InlineAsm,<br>+ DK_StackSize,<br>+ DK_Other<br>+};<br>+<br>+/// This is the base abstract class for diagnostic reporting in the backend.<br>+/// The print method must be overloaded by the subclasses to print a<br>+/// user-friendly message in the client of the backend (let us call it a<br>+/// frontend).<br>+class DiagnosticInfo {<br>+private:<br>+ /// Kind defines the kind of report this is about.<br>+ const DiagnosticKind Kind;<br>+ /// Severity gives the severity of the diagnostic.<br>+ const DiagnosticSeverity Severity;<br>+<br>+public:<br>+ DiagnosticInfo(DiagnosticKind Kind, DiagnosticSeverity Severity)<br>+ : Kind(Kind), Severity(Severity) {}<br>+<br>+ virtual ~DiagnosticInfo() {}<br>+<br>+ DiagnosticKind getKind() const { return Kind; }<br>+ DiagnosticSeverity getSeverity() const { return Severity; }<br>+<br>+ /// Print using the given \p DP a user-friendly message.<br>+ /// This is the default message that will be printed to the user.<br>+ /// It is used when the frontend does not directly take advantage<br>+ /// of the information contained in fields of the subclasses.<br>+ /// The printed message must not end with '.' nor start with a severity<br>+ /// keyword.<br>+ virtual void print(DiagnosticPrinter &DP) const = 0;<br>+};<br>+<br>+/// Diagnostic information for inline asm reporting.<br>+/// This is basically a message and an optional location.<br>+class DiagnosticInfoInlineAsm : public DiagnosticInfo {<br>+private:<br>+ /// Optional line information. 0 if not set.<br>+ unsigned LocCookie;<br>+ /// Message to be reported.<br>+ const Twine &MsgStr;<br>+ /// Optional origin of the problem.<br>+ const Instruction *Instr;<br>+<br>+public:<br>+ /// \p MsgStr is the message to be reported to the frontend.<br>+ /// This class does not copy \p MsgStr, therefore the reference must be valid<br>+ /// for the whole life time of the Diagnostic.<br>+ DiagnosticInfoInlineAsm(const Twine &MsgStr,<br>+ DiagnosticSeverity Severity = DS_Error)<br>+ : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(0), MsgStr(MsgStr),<br>+ Instr(NULL) {}<br>+<br>+ /// \p LocCookie if non-zero gives the line number for this report.<br>+ /// \p MsgStr gives the message.<br>+ /// This class does not copy \p MsgStr, therefore the reference must be valid<br>+ /// for the whole life time of the Diagnostic.<br>+ DiagnosticInfoInlineAsm(unsigned LocCookie, const Twine &MsgStr,<br>+ DiagnosticSeverity Severity = DS_Error)<br>+ : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie),<br>+ MsgStr(MsgStr), Instr(NULL) {}<br>+<br>+ /// \p Instr gives the original instruction that triggered the diagnostic.<br>+ /// \p MsgStr gives the message.<br>+ /// This class does not copy \p MsgStr, therefore the reference must be valid<br>+ /// for the whole life time of the Diagnostic.<br>+ /// Same for \p I.<br>+ DiagnosticInfoInlineAsm(const Instruction &I, const Twine &MsgStr,<br>+ DiagnosticSeverity Severity = DS_Error);<br>+<br>+ unsigned getLocCookie() const { return LocCookie; }<br>+ const Twine &getMsgStr() const { return MsgStr; }<br>+ const Instruction *getInstruction() const { return Instr; }<br>+<br>+ /// \see DiagnosticInfo::print.<br>+ virtual void print(DiagnosticPrinter &DP) const;<br>+<br>+ /// Hand rolled RTTI.<br>+ static bool classof(const DiagnosticInfo *DI) {<br>+ return DI->getKind() == DK_InlineAsm;<br>+ }<br>+};<br>+<br>+/// Diagnostic information for stack size reporting.<br>+/// This is basically a function and a size.<br>+class DiagnosticInfoStackSize : public DiagnosticInfo {<br>+private:<br>+ /// The function that is concerned by this stack size diagnostic.<br>+ const Function &Fn;<br>+ /// The computed stack size.<br>+ unsigned StackSize;<br>+<br>+public:<br>+ /// \p The function that is concerned by this stack size diagnostic.<br>+ /// \p The computed stack size.<br>+ DiagnosticInfoStackSize(const Function &Fn, unsigned StackSize,<br>+ DiagnosticSeverity Severity = DS_Warning)<br>+ : DiagnosticInfo(DK_StackSize, Severity), Fn(Fn), StackSize(StackSize) {}<br>+<br>+ const Function &getFunction() const { return Fn; }<br>+ unsigned getStackSize() const { return StackSize; }<br>+<br>+ /// \see DiagnosticInfo::print.<br>+ virtual void print(DiagnosticPrinter &DP) const;<br>+<br>+ /// Hand rolled RTTI.<br>+ static bool classof(const DiagnosticInfo *DI) {<br>+ return DI->getKind() == DK_StackSize;<br>+ }<br>+};<br>+<br>+/// Diagnostic information for all other diagnostics.<br>+/// This consists in a message string that uses a %[0-9]+ and<br>+/// an array of arguments.<br>+/// For printing, each %i specifier is replaced by the printing of Vals[i].<br>+/// E.g., the message string: "Something weird happens in %0, with analysis<br>+/// %1, and %0 seems broken", use Vals[0], Vals[1], and Vals[0] again.<br>+class DiagnosticInfoOther : public DiagnosticInfo {<br>+public:<br>+ // Shortcut for arguments type.<br>+ typedef ArrayRef<Value *> Values;<br>+<br>+private:<br>+ /// Message string using %[0-9]+ for argument specifier.<br>+ const Twine &MsgStr;<br>+ /// Array of arguments.<br>+ Values Vals;<br>+<br>+public:<br>+ /// \p MsgStr gives the message to be reported using %[0-9]+ specifier to<br>+ /// indicate where to print the related argument given by \p Vals.<br>+ /// To issue a '%' character, one has to escape it with another '%'<br>+ /// character. Thus, to issue '%' character, use "%%".<br>+ DiagnosticInfoOther(const Twine &MsgStr, Values Vals,<br>+ DiagnosticSeverity Severity)<br>+ : DiagnosticInfo(DK_Other, Severity), MsgStr(MsgStr), Vals(Vals) {}<br>+<br>+ const Twine &getMsgStr() const { return MsgStr; }<br>+ Values getVals() const { return Vals; }<br>+<br>+ /// \see DiagnosticInfo::print.<br>+ virtual void print(DiagnosticPrinter &DP) const;<br>+<br>+ /// Hand rolled RTTI.<br>+ static bool classof(const DiagnosticInfo *DI) {<br>+ return DI->getKind() == DK_Other;<br>+ }<br>+};<br>+<br>+} // End namespace llvm<br>+<br>+#endif<br>Index: include/llvm/Support/DiagnosticPrinter.h<br>===================================================================<br>--- include/llvm/Support/DiagnosticPrinter.h<br>+++ include/llvm/Support/DiagnosticPrinter.h<br>@@ -0,0 +1,84 @@<br>+//===- llvm/Support/DiagnosticPrinter.h - Diagnostic Printer ----*- C++ -*-===//<br>+//<br>+// The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+//<br>+// This file declares the main interface for printer backend diagnostic.<br>+//<br>+// Clients of the backend diagnostics should overload this interface based<br>+// on their needs.<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef LLVM_SUPPORT_DIAGNOSTICPRINTER_H<br>+#define LLVM_SUPPORT_DIAGNOSTICPRINTER_H<br>+<br>+#include <string><br>+<br>+namespace llvm {<br>+// Forward declarations.<br>+class raw_ostream;<br>+class StringRef;<br>+class Twine;<br>+class Value;<br>+<br>+/// Interface for custom diagnostic printing.<br>+class DiagnosticPrinter {<br>+public:<br>+ virtual ~DiagnosticPrinter() {}<br>+<br>+ // Simple types.<br>+ virtual DiagnosticPrinter &operator<<(char C) = 0;<br>+ virtual DiagnosticPrinter &operator<<(unsigned char C) = 0;<br>+ virtual DiagnosticPrinter &operator<<(signed char C) = 0;<br>+ virtual DiagnosticPrinter &operator<<(StringRef Str) = 0;<br>+ virtual DiagnosticPrinter &operator<<(const char *Str) = 0;<br>+ virtual DiagnosticPrinter &operator<<(const std::string &Str) = 0;<br>+ virtual DiagnosticPrinter &operator<<(unsigned long N) = 0;<br>+ virtual DiagnosticPrinter &operator<<(long N) = 0;<br>+ virtual DiagnosticPrinter &operator<<(unsigned long long N) = 0;<br>+ virtual DiagnosticPrinter &operator<<(long long N) = 0;<br>+ virtual DiagnosticPrinter &operator<<(const void *P) = 0;<br>+ virtual DiagnosticPrinter &operator<<(unsigned int N) = 0;<br>+ virtual DiagnosticPrinter &operator<<(int N) = 0;<br>+ virtual DiagnosticPrinter &operator<<(double N) = 0;<br>+ virtual DiagnosticPrinter &operator<<(const Twine &Str) = 0;<br>+<br>+ // IR related types.<br>+ virtual DiagnosticPrinter &operator<<(const Value &V) = 0;<br>+};<br>+<br>+/// Basic diagnostic printer that uses an underlying raw_ostream.<br>+class DiagnosticPrinterRawOStream : public DiagnosticPrinter {<br>+protected:<br>+ raw_ostream &Stream;<br>+<br>+public:<br>+ DiagnosticPrinterRawOStream(raw_ostream &Stream) : Stream(Stream) {};<br>+<br>+ // Simple types.<br>+ virtual DiagnosticPrinter &operator<<(char C);<br>+ virtual DiagnosticPrinter &operator<<(unsigned char C);<br>+ virtual DiagnosticPrinter &operator<<(signed char C);<br>+ virtual DiagnosticPrinter &operator<<(StringRef Str);<br>+ virtual DiagnosticPrinter &operator<<(const char *Str);<br>+ virtual DiagnosticPrinter &operator<<(const std::string &Str);<br>+ virtual DiagnosticPrinter &operator<<(unsigned long N);<br>+ virtual DiagnosticPrinter &operator<<(long N);<br>+ virtual DiagnosticPrinter &operator<<(unsigned long long N);<br>+ virtual DiagnosticPrinter &operator<<(long long N);<br>+ virtual DiagnosticPrinter &operator<<(const void *P);<br>+ virtual DiagnosticPrinter &operator<<(unsigned int N);<br>+ virtual DiagnosticPrinter &operator<<(int N);<br>+ virtual DiagnosticPrinter &operator<<(double N);<br>+ virtual DiagnosticPrinter &operator<<(const Twine &Str);<br>+<br>+ // IR related types.<br>+ virtual DiagnosticPrinter &operator<<(const Value &V);<br>+};<br>+} // End namespace llvm<br>+<br>+#endif<br>Index: lib/CodeGen/PrologEpilogInserter.cpp<br>===================================================================<br>--- lib/CodeGen/PrologEpilogInserter.cpp<br>+++ lib/CodeGen/PrologEpilogInserter.cpp<br>@@ -30,9 +30,11 @@<br>#include "llvm/CodeGen/MachineRegisterInfo.h"<br>#include "llvm/CodeGen/RegisterScavenging.h"<br>#include "llvm/IR/InlineAsm.h"<br>+#include "llvm/IR/LLVMContext.h"<br>#include "llvm/Support/CommandLine.h"<br>#include "llvm/Support/Compiler.h"<br>#include "llvm/Support/Debug.h"<br>+#include "llvm/Support/DiagnosticInfo.h"<br>#include "llvm/Support/raw_ostream.h"<br>#include "llvm/Target/TargetFrameLowering.h"<br>#include "llvm/Target/TargetInstrInfo.h"<br>@@ -160,10 +162,11 @@<br><br> // Warn on stack size when we exceeds the given limit.<br> MachineFrameInfo *MFI = Fn.getFrameInfo();<br>- if (WarnStackSize.getNumOccurrences() > 0 &&<br>- WarnStackSize < MFI->getStackSize())<br>- errs() << "warning: Stack size limit exceeded (" << MFI->getStackSize()<br>- << ") in " << Fn.getName() << ".\n";<br>+ uint64_t StackSize = MFI->getStackSize();<br>+ if (WarnStackSize.getNumOccurrences() > 0 && WarnStackSize < StackSize) {<br>+ DiagnosticInfoStackSize DiagStackSize(*F, StackSize);<br>+ F->getContext().diagnose(DiagStackSize);<br>+ }<br><br> delete RS;<br> ReturnBlocks.clear();<br>Index: lib/IR/LLVMContext.cpp<br>===================================================================<br>--- lib/IR/LLVMContext.cpp<br>+++ lib/IR/LLVMContext.cpp<br>@@ -17,6 +17,8 @@<br>#include "llvm/IR/Constants.h"<br>#include "llvm/IR/Instruction.h"<br>#include "llvm/IR/Metadata.h"<br>+#include "llvm/Support/DiagnosticInfo.h"<br>+#include "llvm/Support/DiagnosticPrinter.h"<br>#include "llvm/Support/ManagedStatic.h"<br>#include "llvm/Support/SourceMgr.h"<br>#include <cctype><br>@@ -98,6 +100,20 @@<br> return pImpl->InlineAsmDiagContext;<br>}<br><br>+void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler,<br>+ void *DiagnosticContext) {<br>+ pImpl->DiagnosticHandler = DiagnosticHandler;<br>+ pImpl->DiagnosticContext = DiagnosticContext;<br>+}<br>+<br>+LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const {<br>+ return pImpl->DiagnosticHandler;<br>+}<br>+<br>+void *LLVMContext::getDiagnosticContext() const {<br>+ return pImpl->DiagnosticContext;<br>+}<br>+<br>void LLVMContext::emitError(const Twine &ErrorStr) {<br> emitError(0U, ErrorStr);<br>}<br>@@ -112,6 +128,31 @@<br> return emitError(LocCookie, ErrorStr);<br>}<br><br>+void LLVMContext::diagnose(const DiagnosticInfo &DI) {<br>+ // If there is a report handler, use it.<br>+ if (pImpl->DiagnosticHandler != 0) {<br>+ pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext);<br>+ return;<br>+ }<br>+ // Otherwise, print the message with a prefix based on the severity.<br>+ std::string MsgStorage;<br>+ raw_string_ostream Stream(MsgStorage);<br>+ DiagnosticPrinterRawOStream DP(Stream);<br>+ DI.print(DP);<br>+ Stream.flush();<br>+ switch (DI.getSeverity()) {<br>+ case DS_Error:<br>+ errs() << "error: " << MsgStorage << "\n";<br>+ exit(1);<br>+ case DS_Warning:<br>+ errs() << "warning: " << MsgStorage << "\n";<br>+ break;<br>+ case DS_Note:<br>+ errs() << "note: " << MsgStorage << "\n";<br>+ break;<br>+ }<br>+}<br>+<br>void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) {<br> // If there is no error handler installed, just print the error and exit.<br> if (pImpl->InlineAsmDiagHandler == 0) {<br>Index: lib/IR/LLVMContextImpl.cpp<br>===================================================================<br>--- lib/IR/LLVMContextImpl.cpp<br>+++ lib/IR/LLVMContextImpl.cpp<br>@@ -37,6 +37,8 @@<br> Int64Ty(C, 64) {<br> InlineAsmDiagHandler = 0;<br> InlineAsmDiagContext = 0;<br>+ DiagnosticHandler = 0;<br>+ DiagnosticContext = 0;<br> NamedStructTypesUniqueID = 0;<br>}<br><br>Index: lib/IR/LLVMContextImpl.h<br>===================================================================<br>--- lib/IR/LLVMContextImpl.h<br>+++ lib/IR/LLVMContextImpl.h<br>@@ -238,9 +238,12 @@<br><br> LLVMContext::InlineAsmDiagHandlerTy InlineAsmDiagHandler;<br> void *InlineAsmDiagContext;<br>- <br>- typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt*,<span class="Apple-converted-space"> </span><br>- DenseMapAPIntKeyInfo> IntMapTy;<br>+<br>+ LLVMContext::DiagnosticHandlerTy DiagnosticHandler;<br>+ void *DiagnosticContext;<br>+<br>+ typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt *,<br>+ DenseMapAPIntKeyInfo> IntMapTy;<br> IntMapTy IntConstants;<br><br> typedef DenseMap<DenseMapAPFloatKeyInfo::KeyTy, ConstantFP*,<span class="Apple-converted-space"> </span><br>Index: lib/Support/CMakeLists.txt<br>===================================================================<br>--- lib/Support/CMakeLists.txt<br>+++ lib/Support/CMakeLists.txt<br>@@ -17,6 +17,8 @@<br> Debug.cpp<br> DeltaAlgorithm.cpp<br> DAGDeltaAlgorithm.cpp<br>+ DiagnosticInfo.cpp<br>+ DiagnosticPrinter.cpp<br> Dwarf.cpp<br> ErrorHandling.cpp<br> FileUtilities.cpp<br>Index: lib/Support/DiagnosticInfo.cpp<br>===================================================================<br>--- lib/Support/DiagnosticInfo.cpp<br>+++ lib/Support/DiagnosticInfo.cpp<br>@@ -0,0 +1,98 @@<br>+//===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===//<br>+//<br>+// The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+//<br>+// This file defines the different classes involved in low level diagnostics.<br>+//<br>+// Diagnostics reporting is still done as part of the LLVMContext.<br>+//===----------------------------------------------------------------------===//<br>+<br>+#include "llvm/ADT/Twine.h"<br>+#include "llvm/IR/Constants.h"<br>+#include "llvm/IR/Function.h"<br>+#include "llvm/IR/Instruction.h"<br>+#include "llvm/IR/Metadata.h"<br>+#include "llvm/Support/DiagnosticInfo.h"<br>+#include "llvm/Support/DiagnosticPrinter.h"<br>+<br>+#include <string><br>+<br>+using namespace llvm;<br>+<br>+DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I,<br>+ const Twine &MsgStr,<br>+ DiagnosticSeverity Severity)<br>+ : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(0), MsgStr(MsgStr),<br>+ Instr(&I) {<br>+ if (const MDNode *SrcLoc = I.getMetadata("srcloc")) {<br>+ if (SrcLoc->getNumOperands() != 0)<br>+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(SrcLoc->getOperand(0)))<br>+ LocCookie = CI->getZExtValue();<br>+ }<br>+}<br>+<br>+void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const {<br>+ DP << getMsgStr();<br>+ if (getLocCookie())<br>+ DP << " at line " << getLocCookie();<br>+}<br>+<br>+void DiagnosticInfoStackSize::print(DiagnosticPrinter &DP) const {<br>+ DP << "stack size limit exceeded (" << getStackSize() << ") in "<br>+ << getFunction();<br>+}<br>+<br>+void DiagnosticInfoOther::print(DiagnosticPrinter &DP) const {<br>+ // Look for %[0-9]+ and insert the related argument.<br>+ std::string Msg = MsgStr.str();<br>+ // True if the scan of the string is currently in a %[0-9]+ mode.<br>+ bool ArgIdxBuildMode = false;<br>+ // Keep track of the ArgIdx when building it through the %[0-9]+ syntax.<br>+ int ArgIdx = -1;<br>+ for (std::string::const_iterator ItMsg = Msg.begin(), ItMsgEnd = Msg.end();<br>+ ItMsg != ItMsgEnd; ++ItMsg) {<br>+ const char Cur = *ItMsg;<br>+ // Check if we are inside of a %[0-9]+<br>+ if (ArgIdxBuildMode) {<br>+ // if we are keeping seeing [0-9], update the ArgIdx accordingly.<br>+ if (Cur >= '0' && Cur <= '9') {<br>+ if (ArgIdx == -1)<br>+ ArgIdx = 0;<br>+ ArgIdx *= 10;<br>+ ArgIdx += Cur - '0';<br>+ continue;<br>+ }<br>+ // No more argument index building, emit the related argument and<br>+ // keep going. In particular fallthrough the default path to emit the<br>+ // current character.<br>+<br>+ // If the argument index is invalid, this means we are excaping<br>+ // '%', thus the substring must be "%%".<br>+ assert((ArgIdx > -1 || Cur == '%') &&<br>+ "Invalid string format (did not found \"%%\" or \"%[0-9]+\").");<br>+ if (ArgIdx > -1) {<br>+ assert(((size_t)ArgIdx) < Vals.size() && "Invalid argument index.");<br>+ DP << Vals[ArgIdx];<br>+ }<br>+ ArgIdxBuildMode = false;<br>+ ArgIdx = -1;<br>+ } else if (Cur == '%') {<br>+ ArgIdxBuildMode = true;<br>+ continue;<br>+ }<br>+ DP << Cur;<br>+ }<br>+ // Print any remaining argument.<br>+ // If ArgIdx == -1, this means MsgStr ends with a single '%',<br>+ // which is invalid.<br>+ if (ArgIdxBuildMode) {<br>+ assert(ArgIdx > -1 && "Invalid string format (trailing '%').");<br>+ assert(((size_t)ArgIdx) < Vals.size() && "Invalid argument index.");<br>+ DP << Vals[ArgIdx];<br>+ }<br>+}<br>Index: lib/Support/DiagnosticPrinter.cpp<br>===================================================================<br>--- lib/Support/DiagnosticPrinter.cpp<br>+++ lib/Support/DiagnosticPrinter.cpp<br>@@ -0,0 +1,103 @@<br>+//===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===//<br>+//<br>+// The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+//<br>+// This file defines the a diagnostic printer relying on raw_ostream.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#include "llvm/ADT/Twine.h"<br>+#include "llvm/Analysis/ScalarEvolution.h"<br>+#include "llvm/CodeGen/MachineInstr.h"<br>+#include "llvm/IR/Value.h"<br>+#include "llvm/Support/DiagnosticPrinter.h"<br>+#include "llvm/Support/raw_ostream.h"<br>+<br>+using namespace llvm;<br>+<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(char C) {<br>+ Stream << C;<br>+ return *this;<br>+}<br>+<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(unsigned char C) {<br>+ Stream << C;<br>+ return *this;<br>+}<br>+<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(signed char C) {<br>+ Stream << C;<br>+ return *this;<br>+}<br>+<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(StringRef Str) {<br>+ Stream << Str;<br>+ return *this;<br>+}<br>+<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const char *Str) {<br>+ Stream << Str;<br>+ return *this;<br>+}<br>+<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(<br>+ const std::string &Str) {<br>+ Stream << Str;<br>+ return *this;<br>+}<br>+<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(unsigned long N) {<br>+ Stream << N;<br>+ return *this;<br>+}<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(long N) {<br>+ Stream << N;<br>+ return *this;<br>+}<br>+<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(<br>+ unsigned long long N) {<br>+ Stream << N;<br>+ return *this;<br>+}<br>+<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(long long N) {<br>+ Stream << N;<br>+ return *this;<br>+}<br>+<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const void *P) {<br>+ Stream << P;<br>+ return *this;<br>+}<br>+<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(unsigned int N) {<br>+ Stream << N;<br>+ return *this;<br>+}<br>+<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(int N) {<br>+ Stream << N;<br>+ return *this;<br>+}<br>+<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(double N) {<br>+ Stream << N;<br>+ return *this;<br>+}<br>+<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const Twine &Str) {<br>+ Stream << Str.getSingleStringRef();<br>+ return *this;<br>+}<br>+<br>+// IR related types.<br>+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const Value &V) {<br>+ Stream << V.getName();<br>+ return *this;<br>+}<br>Index: test/CodeGen/ARM/warn-stack.ll<br>===================================================================<br>--- test/CodeGen/ARM/warn-stack.ll<br>+++ test/CodeGen/ARM/warn-stack.ll<br>@@ -12,7 +12,7 @@<br> ret void<br>}<br><br>-; CHECK: warning: Stack size limit exceeded (96) in warn.<br>+; CHECK: warning: stack size limit exceeded (96) in warn<br>define void @warn() nounwind ssp {<br>entry:<br> %buffer = alloca [80 x i8], align 1<br>Index: test/CodeGen/X86/warn-stack.ll<br>===================================================================<br>--- test/CodeGen/X86/warn-stack.ll<br>+++ test/CodeGen/X86/warn-stack.ll<br>@@ -12,7 +12,7 @@<br> ret void<br>}<br><br>-; CHECK: warning: Stack size limit exceeded (104) in warn.<br>+; CHECK: warning: stack size limit exceeded (104) in warn<br>define void @warn() nounwind ssp {<br>entry:<br> %buffer = alloca [80 x i8], align 1<br></blockquote><br><blockquote type="cite">_______________________________________________<br>llvm-commits mailing list<br><a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a></blockquote></div></blockquote></div><br></div></body></html>