introduce a new recoverable error handling API to LLVMContext
authorChris Lattner <sabre@nondot.org>
Wed, 7 Apr 2010 23:40:44 +0000 (23:40 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 7 Apr 2010 23:40:44 +0000 (23:40 +0000)
and use it in one place in inline asm handling stuff.  Before
we'd generate this for an invalid modifier letter:

$ clang asm.c -c -o t.o
fatal error: error in backend: Invalid operand found in inline asm: 'abc incl    ${0:Z}'
INLINEASM <es:abc incl    ${0:Z}>, 10, %EAX<def>, 2147483657, %EAX, 14, %EFLAGS<earlyclobber,def,dead>, <!-1>

Now we generate this:

$ clang asm.c -c -o t.o
error: invalid operand in inline asm: 'incl    ${0:Z}'
asm.c:3:12: note: generated from here
  __asm__ ("incl    %Z0" : "+r" (X));
           ^
1 error generated.

This is much better but still admittedly not great ("why" is the operand
invalid??), codegen should try harder with its diagnostics :)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@100723 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/LLVMContext.h
lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
lib/VMCore/LLVMContext.cpp

index 43548407f681cb55970bee424ed206476f1b0aae..afae08b07dafd44262037500c993f24570b35c99 100644 (file)
@@ -19,6 +19,7 @@ namespace llvm {
 
 class LLVMContextImpl;
 class StringRef;
 
 class LLVMContextImpl;
 class StringRef;
+class Instruction;
 template <typename T> class SmallVectorImpl;
 
 /// This is an important class for using LLVM in a threaded context.  It
 template <typename T> class SmallVectorImpl;
 
 /// This is an important class for using LLVM in a threaded context.  It
@@ -68,6 +69,15 @@ public:
   /// setInlineAsmDiagnosticHandler.
   void *getInlineAsmDiagnosticContext() const;
   
   /// setInlineAsmDiagnosticHandler.
   void *getInlineAsmDiagnosticContext() const;
   
+  
+  /// emitError - Emit an error message to the currently installed error handler
+  /// with optional location information.  This function returns, so code should
+  /// be prepared to drop the erroneous construct on the floor and "not crash".
+  /// The generated code need not be correct.  The error message will be
+  /// implicitly prefixed with "error: " and should not end with a ".".
+  void emitError(unsigned LocCookie, StringRef ErrorStr);
+  void emitError(const Instruction *I, StringRef ErrorStr);
+  void emitError(StringRef ErrorStr);
 };
 
 /// getGlobalContext - Returns a global context.  This is for LLVM clients that
 };
 
 /// getGlobalContext - Returns a global context.  This is for LLVM clients that
index 679473ccb157da38026009b7bf8e6902fcb01ce4..1d03f58b0a837539b02a75bc14b78a1434879bfd 100644 (file)
@@ -295,9 +295,8 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
         if (Error) {
           std::string msg;
           raw_string_ostream Msg(msg);
         if (Error) {
           std::string msg;
           raw_string_ostream Msg(msg);
-          Msg << "Invalid operand found in inline asm: '" << AsmStr << "'\n";
-          MI->print(Msg);
-          report_fatal_error(Msg.str());
+          Msg << "invalid operand in inline asm: '" << AsmStr << "'";
+          MMI->getModule()->getContext().emitError(LocCookie, Msg.str());
         }
       }
       break;
         }
       }
       break;
index 3244f2842c4fdf0b2662b54185b7bdcfb61d72fd..4d61363b9394d0cbafca018028ad1c353c517557 100644 (file)
@@ -17,6 +17,7 @@
 #include "llvm/Constants.h"
 #include "llvm/Instruction.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Constants.h"
 #include "llvm/Instruction.h"
 #include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/SourceMgr.h"
 #include "LLVMContextImpl.h"
 using namespace llvm;
 
 #include "LLVMContextImpl.h"
 using namespace llvm;
 
@@ -33,6 +34,10 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
 }
 LLVMContext::~LLVMContext() { delete pImpl; }
 
 }
 LLVMContext::~LLVMContext() { delete pImpl; }
 
+//===----------------------------------------------------------------------===//
+// Recoverable Backend Errors
+//===----------------------------------------------------------------------===//
+
 void LLVMContext::setInlineAsmDiagnosticHandler(void *DiagHandler, 
                                                 void *DiagContext) {
   pImpl->InlineAsmDiagHandler = DiagHandler;
 void LLVMContext::setInlineAsmDiagnosticHandler(void *DiagHandler, 
                                                 void *DiagContext) {
   pImpl->InlineAsmDiagHandler = DiagHandler;
@@ -51,6 +56,39 @@ void *LLVMContext::getInlineAsmDiagnosticContext() const {
   return pImpl->InlineAsmDiagContext;
 }
 
   return pImpl->InlineAsmDiagContext;
 }
 
+void LLVMContext::emitError(StringRef ErrorStr) {
+  emitError(0U, ErrorStr);
+}
+
+void LLVMContext::emitError(const Instruction *I, StringRef ErrorStr) {
+  unsigned LocCookie = 0;
+  if (const MDNode *SrcLoc = I->getMetadata("srcloc")) {
+    if (SrcLoc->getNumOperands() != 0)
+      if (const ConstantInt *CI = dyn_cast<ConstantInt>(SrcLoc->getOperand(0)))
+        LocCookie = CI->getZExtValue();
+  }
+  return emitError(LocCookie, ErrorStr);
+}
+
+void LLVMContext::emitError(unsigned LocCookie, StringRef ErrorStr) {
+  // If there is no error handler installed, just print the error and exit.
+  if (pImpl->InlineAsmDiagHandler == 0) {
+    errs() << "error: " << ErrorStr << "\n";
+    exit(1);
+  }
+  
+  // If we do have an error handler, we can report the error and keep going.
+  SMDiagnostic Diag("", "error: " + ErrorStr.str());
+  
+  ((SourceMgr::DiagHandlerTy)(intptr_t)pImpl->InlineAsmDiagHandler)
+      (Diag, pImpl->InlineAsmDiagContext, LocCookie);
+  
+}
+
+//===----------------------------------------------------------------------===//
+// Metadata Kind Uniquing
+//===----------------------------------------------------------------------===//
+
 #ifndef NDEBUG
 /// isValidName - Return true if Name is a valid custom metadata handler name.
 static bool isValidName(StringRef MDName) {
 #ifndef NDEBUG
 /// isValidName - Return true if Name is a valid custom metadata handler name.
 static bool isValidName(StringRef MDName) {