introduce a new recoverable error handling API to LLVMContext

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 :)

llvm-svn: 100723
This commit is contained in:
Chris Lattner 2010-04-07 23:40:44 +00:00
parent 4e150f8d35
commit 1e45789ee0
3 changed files with 50 additions and 3 deletions

View File

@ -19,6 +19,7 @@ namespace llvm {
class LLVMContextImpl;
class StringRef;
class Instruction;
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;
/// 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

View File

@ -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;

View File

@ -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<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) {