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 | 5ec32e7fd845e0b7db33689f33cc2ef7c83710fa (patch) | |
| tree | 316d2d28f5b5e83ec4aeb3da2606bac02e987f3a /clang | |
| parent | 6c61f4434ce4178b0139282e64f17927e12260aa (diff) | |
| download | bcm5719-llvm-5ec32e7fd845e0b7db33689f33cc2ef7c83710fa.tar.gz bcm5719-llvm-5ec32e7fd845e0b7db33689f33cc2ef7c83710fa.zip  | |
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".
llvm-svn: 100543
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticFrontendKinds.td | 5 | ||||
| -rw-r--r-- | clang/lib/Frontend/CodeGenAction.cpp | 76 | 
2 files changed, 78 insertions, 3 deletions
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 2e0b4bad6b5..00bf2f0b843 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -14,7 +14,10 @@ def err_fe_error_reading : Error<"error reading '%0'">;  def err_fe_error_reading_stdin : Error<"error reading stdin">;  def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal;  def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal; -def err_fe_invalid_ast_action : Error<"invalid action for AST input">, DefaultFatal; +def err_fe_invalid_ast_action : Error<"invalid action for AST input">, +                                      DefaultFatal; +def err_fe_inline_asm : Error<"%0">;  // Error generated by the backend. +def note_fe_inline_asm_here : Note<"generated from here">;  def err_fe_invalid_code_complete_file : Error<      "cannot locate code-completion file %0">, DefaultFatal;  def err_fe_stdout_binary : Error<"unable to change standard output to binary">, diff --git a/clang/lib/Frontend/CodeGenAction.cpp b/clang/lib/Frontend/CodeGenAction.cpp index 66bff3e5ecc..d55688026ab 100644 --- a/clang/lib/Frontend/CodeGenAction.cpp +++ b/clang/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) {}  | 

