diff options
author | Chris Lattner <sabre@nondot.org> | 2010-04-06 18:38:50 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-04-06 18:38:50 +0000 |
commit | 6da9eb661616ffd702deeb37e6872dd2294c8fef (patch) | |
tree | c8d2edb3fb983bdcdb43adaeeeac19acf554dfde /lib/Frontend | |
parent | cabae68037bd3740ac4fb73382e04cd365457c17 (diff) |
teach clang to install the inline asm diagnostic handler,
allowing backend errors to be mapped through clang's
diagnostics subsystem, including the backend location info.
We now get:
$ clang asm.c -c -o t.o -integrated-as
<inline asm>:1:2: error: unrecognized instruction
abc incl %eax
^
1 diagnostic generated.
With colors, and correct "# diagnostics generated".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100543 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/CodeGenAction.cpp | 76 |
1 files changed, 74 insertions, 2 deletions
diff --git a/lib/Frontend/CodeGenAction.cpp b/lib/Frontend/CodeGenAction.cpp index 66bff3e5ec..d55688026a 100644 --- a/lib/Frontend/CodeGenAction.cpp +++ b/lib/Frontend/CodeGenAction.cpp @@ -8,11 +8,12 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/CodeGenAction.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TargetOptions.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclGroup.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/TargetOptions.h" #include "clang/CodeGen/CodeGenOptions.h" #include "clang/CodeGen/ModuleBuilder.h" #include "clang/Frontend/ASTConsumers.h" @@ -29,6 +30,8 @@ #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" #include "llvm/Support/StandardPasses.h" #include "llvm/Support/Timer.h" #include "llvm/Target/SubtargetFeature.h" @@ -176,6 +179,15 @@ namespace { virtual void CompleteTentativeDefinition(VarDecl *D) { Gen->CompleteTentativeDefinition(D); } + + static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context, + unsigned LocCookie) { + SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie); + ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc); + } + + void InlineAsmDiagHandler2(const llvm::SMDiagnostic &, + SourceLocation LocCookie); }; } @@ -438,15 +450,75 @@ void BackendConsumer::EmitAssembly() { if (CodeGenPasses) { PrettyStackTraceString CrashInfo("Code generation"); + // Install an inline asm handler so that diagnostics get printed through our + // diagnostics hooks. + LLVMContext &Ctx = TheModule->getContext(); + void *OldHandler = Ctx.getInlineAsmDiagnosticHandler(); + void *OldContext = Ctx.getInlineAsmDiagnosticContext(); + Ctx.setInlineAsmDiagnosticHandler((void*)(intptr_t)InlineAsmDiagHandler, + this); + CodeGenPasses->doInitialization(); for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) if (!I->isDeclaration()) CodeGenPasses->run(*I); CodeGenPasses->doFinalization(); + + Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext); } } +/// InlineAsmDiagHandler2 - This function is invoked when the backend hits an +/// error parsing inline asm. The SMDiagnostic indicates the error relative to +/// the temporary memory buffer that the inline asm parser has set up. +void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D, + SourceLocation LocCookie) { + // There are a couple of different kinds of errors we could get here. First, + // we re-format the SMDiagnostic in terms of a clang diagnostic. + + // Strip "error: " off the start of the message string. + llvm::StringRef Message = D.getMessage(); + if (Message.startswith("error: ")) + Message = Message.substr(7); + + // There are two cases: the SMDiagnostic could have a inline asm source + // location or it might not. If it does, translate the location. + FullSourceLoc Loc; + if (D.getLoc() != SMLoc()) { + // Get both the clang and llvm source managers. The location is relative to + // a memory buffer that the LLVM Source Manager is handling, we need to add + // a copy to the Clang source manager. + SourceManager &CSM = Context->getSourceManager(); + const llvm::SourceMgr &LSM = *D.getSourceMgr(); + + // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr + // already owns its one and clang::SourceManager wants to own its one. + const MemoryBuffer *LBuf = + LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); + + // Create the copy and transfer ownership to clang::SourceManager. + llvm::MemoryBuffer *CBuf = + llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(), + LBuf->getBufferIdentifier()); + FileID FID = CSM.createFileIDForMemBuffer(CBuf); + + // Translate the offset into the file. + unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); + SourceLocation NewLoc = + CSM.getLocForStartOfFile(FID).getFileLocWithOffset(Offset); + Loc = FullSourceLoc(NewLoc, CSM); + } + Diags.Report(Loc, diag::err_fe_inline_asm).AddString(Message); + + // This could be a problem with no clang-level source location information. + // In this case, LocCookie is invalid. If there is source level information, + // print an "generated from" note. + if (LocCookie.isValid()) + Diags.Report(FullSourceLoc(LocCookie, Context->getSourceManager()), + diag::note_fe_inline_asm_here); +} + // CodeGenAction::CodeGenAction(unsigned _Act) : Act(_Act) {} |