diff --git a/include/llvm/LLVMContext.h b/include/llvm/LLVMContext.h index 43548407f68..afae08b07da 100644 --- a/include/llvm/LLVMContext.h +++ b/include/llvm/LLVMContext.h @@ -19,6 +19,7 @@ namespace llvm { class LLVMContextImpl; class StringRef; +class Instruction; template class SmallVectorImpl; /// This is an important class for using LLVM in a threaded context. It @@ -68,6 +69,15 @@ public: /// 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 diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index 679473ccb15..1d03f58b0a8 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -295,9 +295,8 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { 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; diff --git a/lib/VMCore/LLVMContext.cpp b/lib/VMCore/LLVMContext.cpp index 3244f2842c4..4d61363b939 100644 --- a/lib/VMCore/LLVMContext.cpp +++ b/lib/VMCore/LLVMContext.cpp @@ -17,6 +17,7 @@ #include "llvm/Constants.h" #include "llvm/Instruction.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/SourceMgr.h" #include "LLVMContextImpl.h" using namespace llvm; @@ -33,6 +34,10 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) { } LLVMContext::~LLVMContext() { delete pImpl; } +//===----------------------------------------------------------------------===// +// Recoverable Backend Errors +//===----------------------------------------------------------------------===// + void LLVMContext::setInlineAsmDiagnosticHandler(void *DiagHandler, void *DiagContext) { pImpl->InlineAsmDiagHandler = DiagHandler; @@ -51,6 +56,39 @@ void *LLVMContext::getInlineAsmDiagnosticContext() const { 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(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) {