summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorQuentin Colombet <qcolombet@apple.com>2013-12-17 17:47:22 +0000
committerQuentin Colombet <qcolombet@apple.com>2013-12-17 17:47:22 +0000
commitde262fecd2f4eeb266b67eaaed783cfc52f88b5f (patch)
tree638224b52042159d949e23ccfb42b27d405323b3 /lib
parent24c63679d7e82da13157d538cee27fbca66d645e (diff)
Add warning capabilities in LLVM.
This reapplies r197438 and fixes the link-time circular dependency between IR and Support. The fix consists in moving the diagnostic support into IR. 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@197508 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/PrologEpilogInserter.cpp11
-rw-r--r--lib/IR/CMakeLists.txt2
-rw-r--r--lib/IR/DiagnosticInfo.cpp54
-rw-r--r--lib/IR/DiagnosticPrinter.cpp101
-rw-r--r--lib/IR/LLVMContext.cpp41
-rw-r--r--lib/IR/LLVMContextImpl.cpp2
-rw-r--r--lib/IR/LLVMContextImpl.h9
7 files changed, 213 insertions, 7 deletions
diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp
index 0107a9cb442..9e699799912 100644
--- a/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/lib/CodeGen/PrologEpilogInserter.cpp
@@ -29,7 +29,9 @@
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/IR/DiagnosticInfo.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 +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/CMakeLists.txt b/lib/IR/CMakeLists.txt
index 581946c5486..b825583bf37 100644
--- a/lib/IR/CMakeLists.txt
+++ b/lib/IR/CMakeLists.txt
@@ -6,6 +6,8 @@ add_llvm_library(LLVMCore
ConstantFold.cpp
Constants.cpp
Core.cpp
+ DiagnosticInfo.cpp
+ DiagnosticPrinter.cpp
DIBuilder.cpp
DataLayout.cpp
DebugInfo.cpp
diff --git a/lib/IR/DiagnosticInfo.cpp b/lib/IR/DiagnosticInfo.cpp
new file mode 100644
index 00000000000..0db962691f5
--- /dev/null
+++ b/lib/IR/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/DiagnosticInfo.h"
+#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/Support/Atomic.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/IR/DiagnosticPrinter.cpp b/lib/IR/DiagnosticPrinter.cpp
new file mode 100644
index 00000000000..04cd6c7e6f7
--- /dev/null
+++ b/lib/IR/DiagnosticPrinter.cpp
@@ -0,0 +1,101 @@
+//===- 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/IR/DiagnosticPrinter.h"
+#include "llvm/IR/Value.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;
+}
diff --git a/lib/IR/LLVMContext.cpp b/lib/IR/LLVMContext.cpp
index 883bb9878fa..bae83dd3015 100644
--- a/lib/IR/LLVMContext.cpp
+++ b/lib/IR/LLVMContext.cpp
@@ -15,6 +15,8 @@
#include "llvm/IR/LLVMContext.h"
#include "LLVMContextImpl.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/ManagedStatic.h"
@@ -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 6a6a4d6801f..ebff9d3a51f 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 407b9856892..39e5d778ed6 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*,