diff options
author | Quentin Colombet <qcolombet@apple.com> | 2013-12-16 23:22:51 +0000 |
---|---|---|
committer | Quentin Colombet <qcolombet@apple.com> | 2013-12-16 23:22:51 +0000 |
commit | b6c4a845927de16b585639f766a734daf6a861f1 (patch) | |
tree | ce69befe218deb8838cdd2a31c4fef3a321e9662 /lib | |
parent | 4faf2ba0c7ef9f28a5d4a6c096105ff8aca94279 (diff) | |
download | llvm-b6c4a845927de16b585639f766a734daf6a861f1.tar.gz llvm-b6c4a845927de16b585639f766a734daf6a861f1.tar.bz2 llvm-b6c4a845927de16b585639f766a734daf6a861f1.tar.xz |
Add warning capabilities in LLVM.
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 about.
- The severity of the report: How bad this is.
This patch also adds 2 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.
This patch also features dynamic diagnostic identifiers. In other words plugins
can use this infrastructure for their own diagnostics (for more details, see
getNextAvailablePluginDiagnosticKind).
This patch introduces a new DiagnosticHandlerTy and a new DiagnosticContext in
the LLVMContext that should be set by the front-end to be able to map these
diagnostics in its own system.
http://llvm-reviews.chandlerc.com/D2376
<rdar://problem/15515174>
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197438 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/PrologEpilogInserter.cpp | 11 | ||||
-rw-r--r-- | lib/IR/LLVMContext.cpp | 41 | ||||
-rw-r--r-- | lib/IR/LLVMContextImpl.cpp | 2 | ||||
-rw-r--r-- | lib/IR/LLVMContextImpl.h | 9 | ||||
-rw-r--r-- | lib/Support/CMakeLists.txt | 2 | ||||
-rw-r--r-- | lib/Support/DiagnosticInfo.cpp | 54 | ||||
-rw-r--r-- | lib/Support/DiagnosticPrinter.cpp | 103 |
7 files changed, 215 insertions, 7 deletions
diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp index 0107a9cb44..556d92f0dd 100644 --- a/lib/CodeGen/PrologEpilogInserter.cpp +++ b/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 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) { // 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(); diff --git a/lib/IR/LLVMContext.cpp b/lib/IR/LLVMContext.cpp index 883bb9878f..26541d8168 100644 --- a/lib/IR/LLVMContext.cpp +++ b/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 @@ void *LLVMContext::getInlineAsmDiagnosticContext() const { 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 @@ void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) { 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) { diff --git a/lib/IR/LLVMContextImpl.cpp b/lib/IR/LLVMContextImpl.cpp index 6a6a4d6801..ebff9d3a51 100644 --- a/lib/IR/LLVMContextImpl.cpp +++ b/lib/IR/LLVMContextImpl.cpp @@ -37,6 +37,8 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C) Int64Ty(C, 64) { InlineAsmDiagHandler = 0; InlineAsmDiagContext = 0; + DiagnosticHandler = 0; + DiagnosticContext = 0; NamedStructTypesUniqueID = 0; } diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index 407b985689..39e5d778ed 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -238,9 +238,12 @@ public: 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*, diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt index 3aecf3ffa4..50aab382ca 100644 --- a/lib/Support/CMakeLists.txt +++ b/lib/Support/CMakeLists.txt @@ -17,6 +17,8 @@ add_llvm_library(LLVMSupport Debug.cpp DeltaAlgorithm.cpp DAGDeltaAlgorithm.cpp + DiagnosticInfo.cpp + DiagnosticPrinter.cpp Dwarf.cpp ErrorHandling.cpp FileUtilities.cpp diff --git a/lib/Support/DiagnosticInfo.cpp b/lib/Support/DiagnosticInfo.cpp new file mode 100644 index 0000000000..0ce0d90a42 --- /dev/null +++ b/lib/Support/DiagnosticInfo.cpp @@ -0,0 +1,54 @@ +//===- 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/Atomic.h" +#include "llvm/Support/DiagnosticInfo.h" +#include "llvm/Support/DiagnosticPrinter.h" + +#include <string> + +using namespace llvm; + +int getNextAvailablePluginDiagnosticKind() { + static sys::cas_flag PluginKindID = DK_FirstPluginKind; + return (int)sys::AtomicIncrement(&PluginKindID); +} + +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(); +} diff --git a/lib/Support/DiagnosticPrinter.cpp b/lib/Support/DiagnosticPrinter.cpp new file mode 100644 index 0000000000..826bec0d45 --- /dev/null +++ b/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; +} |