[PATCH] Add warning capabilities in LLVM (backend part), Take 2

Quentin Colombet qcolombet at apple.com
Wed Dec 11 10:26:50 PST 2013


Hi Tom,

On Dec 10, 2013, at 5:02 PM, Tom Stellard <tom at stellard.net> wrote:

> On Tue, Dec 10, 2013 at 04:31:36PM -0800, Quentin Colombet wrote:
>> Hi dblaikie, rengolin, chandlerc, echristo,
>> 
>> Hi,
>> 
> 
> Hi Quentin,
> 
> Thanks for continuing to work on this, I think this will be a very
> useful feature.
> 
>> This patch implements the latest  proposal discussed a few weeks ago regarding adding warning capabilities in LLVM.
>> The original RFC:
>> http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-July/063845.html
>> 
>> The latest discussion with the new design:
>> http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20131111/195244.html
>> http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20131118/195627.html 
>> 
>> //// Overview ////
>> 
>> The patch adds a new LLVMContext::diagnose that can be used to communicate to the front-end, if any, that something of interest happened.
>> The diagnostics are supported by a new abstraction, the DiagnosticInfo class.
>> The base class contains the following information:
>> - The kind of the report: What this is this about.
>> - The severity of the report: How bad this is.
>> 
>> This patch also adds 3 classes:
>> - DiagnosticInfoInlineAsm: For inline asm reporting. Basically, this diagnostic will be used to switch to the new diagnostic API for LLVMContext::emitError.
>> - DiagnosticStackSize: For stack size reporting. Comes as a replacement of the hard coded warning in PEI.
>> - 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.
>> 
>> 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.
>> 
>> //// Next Steps ////
>> 
>> - Send the patch for clang (I have it on hold).
>> - Switch to this reporting for all warnings printing happening in the backend (i.e., get rid of the hard coded warnings).
>> - Switch LLVMContext::emitError to the new diagnostic API.
>> - Add an entry in LLVM documentation about this diagnostic reporting feature.
>> 
>> //// Open Questions ////
>> 
>> - Should we make SMDiagnostic a sub class of DiagnosticInfo?
>> The idea would be to get rid of the InlineAsmDiagHandler.
>> 
>> - Do we want to provide a C API for this?
> 
> I would like to see this in the C API.  If there is no C API when I
> start integrating this into Mesa (which may not be for several months),
> I can add it myself.
Based on your comment, I guess we can move forward with that proposal and look into the C API as a second step.
Is this right?

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?

> 
>> 
>> - Do we want to extend that to fatal error as well?
>> That would be a nice homogenization of the framework (replace (some of) the calls to report_fatal_error).
>> 
> 
> I'm not sure what 'that' refers to here, but I am in favor of replacing as
> many calls to report_fatal_error() as possible (preferably all of them).
> This is especially important for API implementations, like OpenCL that
> use LLVM as a library, because those APIs need to be able to report errors
> to the user.  Handling errors by calling exit() is not really acceptable.
Agree.

Thanks for your feedbacks.

-Quentin

> 
> -Tom
> 
>> Thanks for your reviews.
>> 
>> Cheers,
>> Quentin
>> 
>> PS: Hal, DiagnosticPrinter class does not include SCEV or MachineInstr because these are not part of the IR library.
>> 
>> http://llvm-reviews.chandlerc.com/D2376
>> 
>> Files:
>>  include/llvm/IR/LLVMContext.h
>>  include/llvm/Support/DiagnosticInfo.h
>>  include/llvm/Support/DiagnosticPrinter.h
>>  lib/CodeGen/PrologEpilogInserter.cpp
>>  lib/IR/LLVMContext.cpp
>>  lib/IR/LLVMContextImpl.cpp
>>  lib/IR/LLVMContextImpl.h
>>  lib/Support/CMakeLists.txt
>>  lib/Support/DiagnosticInfo.cpp
>>  lib/Support/DiagnosticPrinter.cpp
>>  test/CodeGen/ARM/warn-stack.ll
>>  test/CodeGen/X86/warn-stack.ll
> 
>> Index: include/llvm/IR/LLVMContext.h
>> ===================================================================
>> --- include/llvm/IR/LLVMContext.h
>> +++ include/llvm/IR/LLVMContext.h
>> @@ -27,6 +27,7 @@
>> class Instruction;
>> class Module;
>> class SMDiagnostic;
>> +class DiagnosticInfo;
>> template <typename T> class SmallVectorImpl;
>> 
>> /// This is an important class for using LLVM in a threaded context.  It
>> @@ -64,6 +65,11 @@
>>   typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context,
>>                                          unsigned LocCookie);
>> 
>> +  /// Defines the type of a diagnostic handler.
>> +  /// \see LLVMContext::setDiagnosticHandler.
>> +  /// \see LLVMContext::diagnose.
>> +  typedef void (*DiagnosticHandlerTy)(const DiagnosticInfo &DI, void *Context);
>> +
>>   /// 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 +88,33 @@
>>   /// setInlineAsmDiagnosticHandler.
>>   void *getInlineAsmDiagnosticContext() const;
>> 
>> +  /// setDiagnosticHandler - 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 DiagHandler.
>> +  ///
>> +  /// LLVMContext doesn't take ownership or interpret either of these
>> +  /// pointers.
>> +  void setDiagnosticHandler(DiagnosticHandlerTy DiagHandler,
>> +                            void *DiagContext = 0);
>> +
>> +  /// getDiagnosticHandler - Return the diagnostic handler set by
>> +  /// setDiagnosticHandler.
>> +  DiagnosticHandlerTy getDiagnosticHandler() const;
>> +
>> +  /// getDiagnosticContext - Return the diagnostic context set by
>> +  /// setDiagnosticContext.
>> +  void *getDiagnosticContext() const;
>> +
>> +  /// diagnose - Report a message to the currently installed diagnostic handler.
>> +  /// This function returns, in particular in the case of error reporting
>> +  /// (DI.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.
>> +  /// The diagnostic message will be implicitly prefixed with a severity
>> +  /// keyword according to \p DI.getSeverity(), i.e., "error: "
>> +  /// for RS_Error, "warning: " for RS_Warning, and "note: " for RS_Note.
>> +  void diagnose(const DiagnosticInfo &DI);
>> 
>>   /// emitError - Emit an error message to the currently installed error handler
>>   /// with optional location information.  This function returns, so code should
>> Index: include/llvm/Support/DiagnosticInfo.h
>> ===================================================================
>> --- include/llvm/Support/DiagnosticInfo.h
>> +++ include/llvm/Support/DiagnosticInfo.h
>> @@ -0,0 +1,192 @@
>> +//===- llvm/Support/DiagnosticInfo.h - Diagnostic Declaration ---*- C++ -*-===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// This file declares the different classes involved in low level diagnostics.
>> +//
>> +// Diagnostics reporting is still done as part of the LLVMContext.
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_SUPPORT_DIAGNOSTICINFO_H
>> +#define LLVM_SUPPORT_DIAGNOSTICINFO_H
>> +
>> +#include "llvm/ADT/ArrayRef.h"
>> +#include "llvm/Support/Casting.h"
>> +
>> +namespace llvm {
>> +
>> +// Forward declarations.
>> +class DiagnosticPrinter;
>> +class Function;
>> +class Instruction;
>> +class Twine;
>> +class Value;
>> +
>> +/// Defines the different supported severity of a diagnostic.
>> +enum DiagnosticSeverity {
>> +  DS_Error,
>> +  DS_Warning,
>> +  DS_Note
>> +};
>> +
>> +/// Defines the different supported kind of a diagnostic.
>> +/// This enum should be extended with a new ID for each added concrete subclass.
>> +enum DiagnosticKind {
>> +  DK_InlineAsm,
>> +  DK_StackSize,
>> +  DK_Other
>> +};
>> +
>> +/// This is the base abstract class for diagnostic reporting in the backend.
>> +/// The print method must be overloaded by the subclasses to print a
>> +/// user-friendly message in the client of the backend (let us call it a
>> +/// frontend).
>> +class DiagnosticInfo {
>> +private:
>> +  /// Kind defines the kind of report this is about.
>> +  const DiagnosticKind Kind;
>> +  /// Severity gives the severity of the diagnostic.
>> +  const DiagnosticSeverity Severity;
>> +
>> +public:
>> +  DiagnosticInfo(DiagnosticKind Kind, DiagnosticSeverity Severity)
>> +      : Kind(Kind), Severity(Severity) {}
>> +
>> +  virtual ~DiagnosticInfo() {}
>> +
>> +  DiagnosticKind getKind() const { return Kind; }
>> +  DiagnosticSeverity getSeverity() const { return Severity; }
>> +
>> +  /// Print using the given \p DP a user-friendly message.
>> +  /// This is the default message that will be printed to the user.
>> +  /// It is used when the frontend does not directly take advantage
>> +  /// of the information contained in fields of the subclasses.
>> +  /// The printed message must not end with '.' nor start with a severity
>> +  /// keyword.
>> +  virtual void print(DiagnosticPrinter &DP) const = 0;
>> +};
>> +
>> +/// Diagnostic information for inline asm reporting.
>> +/// This is basically a message and an optional location.
>> +class DiagnosticInfoInlineAsm : public DiagnosticInfo {
>> +private:
>> +  /// Optional line information. 0 if not set.
>> +  unsigned LocCookie;
>> +  /// Message to be reported.
>> +  const Twine &MsgStr;
>> +  /// Optional origin of the problem.
>> +  const Instruction *Instr;
>> +
>> +public:
>> +  /// \p MsgStr is the message to be reported to the frontend.
>> +  /// This class does not copy \p MsgStr, therefore the reference must be valid
>> +  /// for the whole life time of the Diagnostic.
>> +  DiagnosticInfoInlineAsm(const Twine &MsgStr,
>> +                          DiagnosticSeverity Severity = DS_Error)
>> +      : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(0), MsgStr(MsgStr),
>> +        Instr(NULL) {}
>> +
>> +  /// \p LocCookie if non-zero gives the line number for this report.
>> +  /// \p MsgStr gives the message.
>> +  /// This class does not copy \p MsgStr, therefore the reference must be valid
>> +  /// for the whole life time of the Diagnostic.
>> +  DiagnosticInfoInlineAsm(unsigned LocCookie, const Twine &MsgStr,
>> +                          DiagnosticSeverity Severity = DS_Error)
>> +      : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie),
>> +        MsgStr(MsgStr), Instr(NULL) {}
>> +
>> +  /// \p Instr gives the original instruction that triggered the diagnostic.
>> +  /// \p MsgStr gives the message.
>> +  /// This class does not copy \p MsgStr, therefore the reference must be valid
>> +  /// for the whole life time of the Diagnostic.
>> +  /// Same for \p I.
>> +  DiagnosticInfoInlineAsm(const Instruction &I, const Twine &MsgStr,
>> +                          DiagnosticSeverity Severity = DS_Error);
>> +
>> +  unsigned getLocCookie() const { return LocCookie; }
>> +  const Twine &getMsgStr() const { return MsgStr; }
>> +  const Instruction *getInstruction() const { return Instr; }
>> +
>> +  /// \see DiagnosticInfo::print.
>> +  virtual void print(DiagnosticPrinter &DP) const;
>> +
>> +  /// Hand rolled RTTI.
>> +  static bool classof(const DiagnosticInfo *DI) {
>> +    return DI->getKind() == DK_InlineAsm;
>> +  }
>> +};
>> +
>> +/// Diagnostic information for stack size reporting.
>> +/// This is basically a function and a size.
>> +class DiagnosticInfoStackSize : public DiagnosticInfo {
>> +private:
>> +  /// The function that is concerned by this stack size diagnostic.
>> +  const Function &Fn;
>> +  /// The computed stack size.
>> +  unsigned StackSize;
>> +
>> +public:
>> +  /// \p The function that is concerned by this stack size diagnostic.
>> +  /// \p The computed stack size.
>> +  DiagnosticInfoStackSize(const Function &Fn, unsigned StackSize,
>> +                          DiagnosticSeverity Severity = DS_Warning)
>> +      : DiagnosticInfo(DK_StackSize, Severity), Fn(Fn), StackSize(StackSize) {}
>> +
>> +  const Function &getFunction() const { return Fn; }
>> +  unsigned getStackSize() const { return StackSize; }
>> +
>> +  /// \see DiagnosticInfo::print.
>> +  virtual void print(DiagnosticPrinter &DP) const;
>> +
>> +  /// Hand rolled RTTI.
>> +  static bool classof(const DiagnosticInfo *DI) {
>> +    return DI->getKind() == DK_StackSize;
>> +  }
>> +};
>> +
>> +/// Diagnostic information for all other diagnostics.
>> +/// This consists in a message string that uses a %[0-9]+ and
>> +/// an array of arguments.
>> +/// For printing, each %i specifier is replaced by the printing of Vals[i].
>> +/// E.g., the message string: "Something weird happens in %0, with analysis
>> +/// %1, and %0 seems broken", use Vals[0], Vals[1], and Vals[0] again.
>> +class DiagnosticInfoOther : public DiagnosticInfo {
>> +public:
>> +  // Shortcut for arguments type.
>> +  typedef ArrayRef<Value *> Values;
>> +
>> +private:
>> +  /// Message string using %[0-9]+ for argument specifier.
>> +  const Twine &MsgStr;
>> +  /// Array of arguments.
>> +  Values Vals;
>> +
>> +public:
>> +  /// \p MsgStr gives the message to be reported using %[0-9]+ specifier to
>> +  /// indicate where to print the related argument given by \p Vals.
>> +  /// To issue a '%' character, one has to escape it with another '%'
>> +  /// character. Thus, to issue '%' character, use "%%".
>> +  DiagnosticInfoOther(const Twine &MsgStr, Values Vals,
>> +                      DiagnosticSeverity Severity)
>> +      : DiagnosticInfo(DK_Other, Severity), MsgStr(MsgStr), Vals(Vals) {}
>> +
>> +  const Twine &getMsgStr() const { return MsgStr; }
>> +  Values getVals() const { return Vals; }
>> +
>> +  /// \see DiagnosticInfo::print.
>> +  virtual void print(DiagnosticPrinter &DP) const;
>> +
>> +  /// Hand rolled RTTI.
>> +  static bool classof(const DiagnosticInfo *DI) {
>> +    return DI->getKind() == DK_Other;
>> +  }
>> +};
>> +
>> +} // End namespace llvm
>> +
>> +#endif
>> Index: include/llvm/Support/DiagnosticPrinter.h
>> ===================================================================
>> --- include/llvm/Support/DiagnosticPrinter.h
>> +++ include/llvm/Support/DiagnosticPrinter.h
>> @@ -0,0 +1,84 @@
>> +//===- llvm/Support/DiagnosticPrinter.h - Diagnostic Printer ----*- C++ -*-===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// This file declares the main interface for printer backend diagnostic.
>> +//
>> +// Clients of the backend diagnostics should overload this interface based
>> +// on their needs.
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLVM_SUPPORT_DIAGNOSTICPRINTER_H
>> +#define LLVM_SUPPORT_DIAGNOSTICPRINTER_H
>> +
>> +#include <string>
>> +
>> +namespace llvm {
>> +// Forward declarations.
>> +class raw_ostream;
>> +class StringRef;
>> +class Twine;
>> +class Value;
>> +
>> +/// Interface for custom diagnostic printing.
>> +class DiagnosticPrinter {
>> +public:
>> +  virtual ~DiagnosticPrinter() {}
>> +
>> +  // Simple types.
>> +  virtual DiagnosticPrinter &operator<<(char C) = 0;
>> +  virtual DiagnosticPrinter &operator<<(unsigned char C) = 0;
>> +  virtual DiagnosticPrinter &operator<<(signed char C) = 0;
>> +  virtual DiagnosticPrinter &operator<<(StringRef Str) = 0;
>> +  virtual DiagnosticPrinter &operator<<(const char *Str) = 0;
>> +  virtual DiagnosticPrinter &operator<<(const std::string &Str) = 0;
>> +  virtual DiagnosticPrinter &operator<<(unsigned long N) = 0;
>> +  virtual DiagnosticPrinter &operator<<(long N) = 0;
>> +  virtual DiagnosticPrinter &operator<<(unsigned long long N) = 0;
>> +  virtual DiagnosticPrinter &operator<<(long long N) = 0;
>> +  virtual DiagnosticPrinter &operator<<(const void *P) = 0;
>> +  virtual DiagnosticPrinter &operator<<(unsigned int N) = 0;
>> +  virtual DiagnosticPrinter &operator<<(int N) = 0;
>> +  virtual DiagnosticPrinter &operator<<(double N) = 0;
>> +  virtual DiagnosticPrinter &operator<<(const Twine &Str) = 0;
>> +
>> +  // IR related types.
>> +  virtual DiagnosticPrinter &operator<<(const Value &V) = 0;
>> +};
>> +
>> +/// Basic diagnostic printer that uses an underlying raw_ostream.
>> +class DiagnosticPrinterRawOStream : public DiagnosticPrinter {
>> +protected:
>> +  raw_ostream &Stream;
>> +
>> +public:
>> +  DiagnosticPrinterRawOStream(raw_ostream &Stream) : Stream(Stream) {};
>> +
>> +  // Simple types.
>> +  virtual DiagnosticPrinter &operator<<(char C);
>> +  virtual DiagnosticPrinter &operator<<(unsigned char C);
>> +  virtual DiagnosticPrinter &operator<<(signed char C);
>> +  virtual DiagnosticPrinter &operator<<(StringRef Str);
>> +  virtual DiagnosticPrinter &operator<<(const char *Str);
>> +  virtual DiagnosticPrinter &operator<<(const std::string &Str);
>> +  virtual DiagnosticPrinter &operator<<(unsigned long N);
>> +  virtual DiagnosticPrinter &operator<<(long N);
>> +  virtual DiagnosticPrinter &operator<<(unsigned long long N);
>> +  virtual DiagnosticPrinter &operator<<(long long N);
>> +  virtual DiagnosticPrinter &operator<<(const void *P);
>> +  virtual DiagnosticPrinter &operator<<(unsigned int N);
>> +  virtual DiagnosticPrinter &operator<<(int N);
>> +  virtual DiagnosticPrinter &operator<<(double N);
>> +  virtual DiagnosticPrinter &operator<<(const Twine &Str);
>> +
>> +  // IR related types.
>> +  virtual DiagnosticPrinter &operator<<(const Value &V);
>> +};
>> +} // End namespace llvm
>> +
>> +#endif
>> Index: lib/CodeGen/PrologEpilogInserter.cpp
>> ===================================================================
>> --- lib/CodeGen/PrologEpilogInserter.cpp
>> +++ lib/CodeGen/PrologEpilogInserter.cpp
>> @@ -30,9 +30,11 @@
>> #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"
>> +#include "llvm/Support/DiagnosticInfo.h"
>> #include "llvm/Support/raw_ostream.h"
>> #include "llvm/Target/TargetFrameLowering.h"
>> #include "llvm/Target/TargetInstrInfo.h"
>> @@ -160,10 +162,11 @@
>> 
>>   // Warn on stack size when we exceeds the given limit.
>>   MachineFrameInfo *MFI = Fn.getFrameInfo();
>> -  if (WarnStackSize.getNumOccurrences() > 0 &&
>> -      WarnStackSize < MFI->getStackSize())
>> -    errs() << "warning: Stack size limit exceeded (" << MFI->getStackSize()
>> -           << ") in " << Fn.getName()  << ".\n";
>> +  uint64_t StackSize = MFI->getStackSize();
>> +  if (WarnStackSize.getNumOccurrences() > 0 && WarnStackSize < StackSize) {
>> +    DiagnosticInfoStackSize DiagStackSize(*F, StackSize);
>> +    F->getContext().diagnose(DiagStackSize);
>> +  }
>> 
>>   delete RS;
>>   ReturnBlocks.clear();
>> Index: lib/IR/LLVMContext.cpp
>> ===================================================================
>> --- lib/IR/LLVMContext.cpp
>> +++ lib/IR/LLVMContext.cpp
>> @@ -17,6 +17,8 @@
>> #include "llvm/IR/Constants.h"
>> #include "llvm/IR/Instruction.h"
>> #include "llvm/IR/Metadata.h"
>> +#include "llvm/Support/DiagnosticInfo.h"
>> +#include "llvm/Support/DiagnosticPrinter.h"
>> #include "llvm/Support/ManagedStatic.h"
>> #include "llvm/Support/SourceMgr.h"
>> #include <cctype>
>> @@ -98,6 +100,20 @@
>>   return pImpl->InlineAsmDiagContext;
>> }
>> 
>> +void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler,
>> +                                       void *DiagnosticContext) {
>> +  pImpl->DiagnosticHandler = DiagnosticHandler;
>> +  pImpl->DiagnosticContext = DiagnosticContext;
>> +}
>> +
>> +LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const {
>> +  return pImpl->DiagnosticHandler;
>> +}
>> +
>> +void *LLVMContext::getDiagnosticContext() const {
>> +  return pImpl->DiagnosticContext;
>> +}
>> +
>> void LLVMContext::emitError(const Twine &ErrorStr) {
>>   emitError(0U, ErrorStr);
>> }
>> @@ -112,6 +128,31 @@
>>   return emitError(LocCookie, ErrorStr);
>> }
>> 
>> +void LLVMContext::diagnose(const DiagnosticInfo &DI) {
>> +  // If there is a report handler, use it.
>> +  if (pImpl->DiagnosticHandler != 0) {
>> +    pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext);
>> +    return;
>> +  }
>> +  // Otherwise, print the message with a prefix based on the severity.
>> +  std::string MsgStorage;
>> +  raw_string_ostream Stream(MsgStorage);
>> +  DiagnosticPrinterRawOStream DP(Stream);
>> +  DI.print(DP);
>> +  Stream.flush();
>> +  switch (DI.getSeverity()) {
>> +  case DS_Error:
>> +    errs() << "error: " << MsgStorage << "\n";
>> +    exit(1);
>> +  case DS_Warning:
>> +    errs() << "warning: " << MsgStorage << "\n";
>> +    break;
>> +  case DS_Note:
>> +    errs() << "note: " << MsgStorage << "\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;
>> +  DiagnosticHandler = 0;
>> +  DiagnosticContext = 0;
>>   NamedStructTypesUniqueID = 0;
>> }
>> 
>> Index: lib/IR/LLVMContextImpl.h
>> ===================================================================
>> --- lib/IR/LLVMContextImpl.h
>> +++ lib/IR/LLVMContextImpl.h
>> @@ -238,9 +238,12 @@
>> 
>>   LLVMContext::InlineAsmDiagHandlerTy InlineAsmDiagHandler;
>>   void *InlineAsmDiagContext;
>> -  
>> -  typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt*, 
>> -                         DenseMapAPIntKeyInfo> IntMapTy;
>> +
>> +  LLVMContext::DiagnosticHandlerTy DiagnosticHandler;
>> +  void *DiagnosticContext;
>> +
>> +  typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt *,
>> +                   DenseMapAPIntKeyInfo> IntMapTy;
>>   IntMapTy IntConstants;
>> 
>>   typedef DenseMap<DenseMapAPFloatKeyInfo::KeyTy, ConstantFP*, 
>> Index: lib/Support/CMakeLists.txt
>> ===================================================================
>> --- lib/Support/CMakeLists.txt
>> +++ lib/Support/CMakeLists.txt
>> @@ -17,6 +17,8 @@
>>   Debug.cpp
>>   DeltaAlgorithm.cpp
>>   DAGDeltaAlgorithm.cpp
>> +  DiagnosticInfo.cpp
>> +  DiagnosticPrinter.cpp
>>   Dwarf.cpp
>>   ErrorHandling.cpp
>>   FileUtilities.cpp
>> Index: lib/Support/DiagnosticInfo.cpp
>> ===================================================================
>> --- lib/Support/DiagnosticInfo.cpp
>> +++ lib/Support/DiagnosticInfo.cpp
>> @@ -0,0 +1,98 @@
>> +//===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// This file defines the different classes involved in low level diagnostics.
>> +//
>> +// Diagnostics reporting is still done as part of the LLVMContext.
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "llvm/ADT/Twine.h"
>> +#include "llvm/IR/Constants.h"
>> +#include "llvm/IR/Function.h"
>> +#include "llvm/IR/Instruction.h"
>> +#include "llvm/IR/Metadata.h"
>> +#include "llvm/Support/DiagnosticInfo.h"
>> +#include "llvm/Support/DiagnosticPrinter.h"
>> +
>> +#include <string>
>> +
>> +using namespace llvm;
>> +
>> +DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I,
>> +                                                 const Twine &MsgStr,
>> +                                                 DiagnosticSeverity Severity)
>> +    : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(0), MsgStr(MsgStr),
>> +      Instr(&I) {
>> +  if (const MDNode *SrcLoc = I.getMetadata("srcloc")) {
>> +    if (SrcLoc->getNumOperands() != 0)
>> +      if (const ConstantInt *CI = dyn_cast<ConstantInt>(SrcLoc->getOperand(0)))
>> +        LocCookie = CI->getZExtValue();
>> +  }
>> +}
>> +
>> +void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const {
>> +  DP << getMsgStr();
>> +  if (getLocCookie())
>> +    DP << " at line " << getLocCookie();
>> +}
>> +
>> +void DiagnosticInfoStackSize::print(DiagnosticPrinter &DP) const {
>> +  DP << "stack size limit exceeded (" << getStackSize() << ") in "
>> +     << getFunction();
>> +}
>> +
>> +void DiagnosticInfoOther::print(DiagnosticPrinter &DP) const {
>> +  // Look for %[0-9]+ and insert the related argument.
>> +  std::string Msg = MsgStr.str();
>> +  // True if the scan of the string is currently in a %[0-9]+ mode.
>> +  bool ArgIdxBuildMode = false;
>> +  // Keep track of the ArgIdx when building it through the %[0-9]+ syntax.
>> +  int ArgIdx = -1;
>> +  for (std::string::const_iterator ItMsg = Msg.begin(), ItMsgEnd = Msg.end();
>> +       ItMsg != ItMsgEnd; ++ItMsg) {
>> +    const char Cur = *ItMsg;
>> +    // Check if we are inside of a %[0-9]+
>> +    if (ArgIdxBuildMode) {
>> +      // if we are keeping seeing [0-9], update the ArgIdx accordingly.
>> +      if (Cur >= '0' && Cur <= '9') {
>> +        if (ArgIdx == -1)
>> +          ArgIdx = 0;
>> +        ArgIdx *= 10;
>> +        ArgIdx += Cur - '0';
>> +        continue;
>> +      }
>> +      // No more argument index building, emit the related argument and
>> +      // keep going. In particular fallthrough the default path to emit the
>> +      // current character.
>> +
>> +      // If the argument index is invalid, this means we are excaping
>> +      // '%', thus the substring must be "%%".
>> +      assert((ArgIdx > -1 || Cur == '%') &&
>> +             "Invalid string format (did not found \"%%\" or \"%[0-9]+\").");
>> +      if (ArgIdx > -1) {
>> +        assert(((size_t)ArgIdx) < Vals.size() && "Invalid argument index.");
>> +        DP << Vals[ArgIdx];
>> +      }
>> +      ArgIdxBuildMode = false;
>> +      ArgIdx = -1;
>> +    } else if (Cur == '%') {
>> +      ArgIdxBuildMode = true;
>> +      continue;
>> +    }
>> +    DP << Cur;
>> +  }
>> +  // Print any remaining argument.
>> +  // If ArgIdx == -1, this means MsgStr ends with a single '%',
>> +  // which is invalid.
>> +  if (ArgIdxBuildMode) {
>> +    assert(ArgIdx > -1 && "Invalid string format (trailing '%').");
>> +    assert(((size_t)ArgIdx) < Vals.size() && "Invalid argument index.");
>> +    DP << Vals[ArgIdx];
>> +  }
>> +}
>> Index: lib/Support/DiagnosticPrinter.cpp
>> ===================================================================
>> --- lib/Support/DiagnosticPrinter.cpp
>> +++ lib/Support/DiagnosticPrinter.cpp
>> @@ -0,0 +1,103 @@
>> +//===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===//
>> +//
>> +//                     The LLVM Compiler Infrastructure
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +//
>> +// This file defines the a diagnostic printer relying on raw_ostream.
>> +//
>> +//===----------------------------------------------------------------------===//
>> +
>> +#include "llvm/ADT/Twine.h"
>> +#include "llvm/Analysis/ScalarEvolution.h"
>> +#include "llvm/CodeGen/MachineInstr.h"
>> +#include "llvm/IR/Value.h"
>> +#include "llvm/Support/DiagnosticPrinter.h"
>> +#include "llvm/Support/raw_ostream.h"
>> +
>> +using namespace llvm;
>> +
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(char C) {
>> +  Stream << C;
>> +  return *this;
>> +}
>> +
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(unsigned char C) {
>> +  Stream << C;
>> +  return *this;
>> +}
>> +
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(signed char C) {
>> +  Stream << C;
>> +  return *this;
>> +}
>> +
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(StringRef Str) {
>> +  Stream << Str;
>> +  return *this;
>> +}
>> +
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const char *Str) {
>> +  Stream << Str;
>> +  return *this;
>> +}
>> +
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(
>> +    const std::string &Str) {
>> +  Stream << Str;
>> +  return *this;
>> +}
>> +
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(unsigned long N) {
>> +  Stream << N;
>> +  return *this;
>> +}
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(long N) {
>> +  Stream << N;
>> +  return *this;
>> +}
>> +
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(
>> +    unsigned long long N) {
>> +  Stream << N;
>> +  return *this;
>> +}
>> +
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(long long N) {
>> +  Stream << N;
>> +  return *this;
>> +}
>> +
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const void *P) {
>> +  Stream << P;
>> +  return *this;
>> +}
>> +
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(unsigned int N) {
>> +  Stream << N;
>> +  return *this;
>> +}
>> +
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(int N) {
>> +  Stream << N;
>> +  return *this;
>> +}
>> +
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(double N) {
>> +  Stream << N;
>> +  return *this;
>> +}
>> +
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const Twine &Str) {
>> +  Stream << Str.getSingleStringRef();
>> +  return *this;
>> +}
>> +
>> +// IR related types.
>> +DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const Value &V) {
>> +  Stream << V.getName();
>> +  return *this;
>> +}
>> Index: test/CodeGen/ARM/warn-stack.ll
>> ===================================================================
>> --- test/CodeGen/ARM/warn-stack.ll
>> +++ test/CodeGen/ARM/warn-stack.ll
>> @@ -12,7 +12,7 @@
>>   ret void
>> }
>> 
>> -; CHECK: warning: Stack size limit exceeded (96) in warn.
>> +; CHECK: warning: stack size limit exceeded (96) in warn
>> define void @warn() nounwind ssp {
>> entry:
>>   %buffer = alloca [80 x i8], align 1
>> Index: test/CodeGen/X86/warn-stack.ll
>> ===================================================================
>> --- test/CodeGen/X86/warn-stack.ll
>> +++ test/CodeGen/X86/warn-stack.ll
>> @@ -12,7 +12,7 @@
>>   ret void
>> }
>> 
>> -; CHECK: warning: Stack size limit exceeded (104) in warn.
>> +; CHECK: warning: stack size limit exceeded (104) in warn
>> define void @warn() nounwind ssp {
>> entry:
>>   %buffer = alloca [80 x i8], align 1
> 
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20131211/17a18b01/attachment.html>


More information about the llvm-commits mailing list