]> granicus.if.org Git - clang/commitdiff
teach clang to install the inline asm diagnostic handler,
authorChris Lattner <sabre@nondot.org>
Tue, 6 Apr 2010 18:38:50 +0000 (18:38 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 6 Apr 2010 18:38:50 +0000 (18:38 +0000)
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

include/clang/Basic/DiagnosticFrontendKinds.td
lib/Frontend/CodeGenAction.cpp

index 2e0b4bad6b5be9620b579bbdd51a102b006660c5..00bf2f0b8439673e87496f6e93d62ee21aa24205 100644 (file)
@@ -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">,
index 66bff3e5ecca0f047fb6f66c253e47c926558c6f..d55688026ab7768d587e18c9108195b087793220 100644 (file)
@@ -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) {}