From 974c799a5a0288c04e962a1e8575031295f6ed81 Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Wed, 12 Oct 2011 21:38:39 +0000 Subject: [PATCH] Finish supporting cpp #file/line comments in assembler for error messages. So for cpp pre-processed assembly we give correct filename and line numbers when reporting errors in assembly files when using clang and -integrated-as on .s files. rdar://8998895 llvm-svn: 141814 --- include/llvm/Support/SourceMgr.h | 8 +++- lib/MC/MCParser/AsmParser.cpp | 69 +++++++++++++++++++++++++++++--- test/MC/X86/x86_errors.s | 5 +++ 3 files changed, 75 insertions(+), 7 deletions(-) diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index 030db8f4e3f..92ec891699a 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -138,8 +138,12 @@ public: const Twine &Msg, const char *Type, bool ShowLine = true) const; - -private: + /// PrintIncludeStack - Prints the names of included files and the line of the + /// file they were included from. A diagnostic handler can use this before + /// printing its custom formatted message. + /// + /// @param IncludeLoc - The line of the include. + /// @param OS the raw_ostream to print on. void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const; }; diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 9113dd7c310..311c3347a54 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -115,6 +115,11 @@ private: /// Flag tracking whether any errors have been encountered. unsigned HadError : 1; + /// The values from the last parsed cpp hash file line comment if any. + StringRef CppHashFilename; + int64_t CppHashLineNumber; + SMLoc CppHashLoc; + public: AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, const MCAsmInfo &MAI); @@ -168,6 +173,7 @@ private: bool ShowLine = true) const { SrcMgr.PrintMessage(Loc, Msg, Type, ShowLine); } + static void DiagHandler(const SMDiagnostic &Diag, void *Context); /// EnterIncludeFile - Enter the specified file. This returns true on failure. bool EnterIncludeFile(const std::string &Filename); @@ -344,7 +350,8 @@ AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, const MCAsmInfo &_MAI) : Lexer(_MAI), Ctx(_Ctx), Out(_Out), MAI(_MAI), SrcMgr(_SM), GenericParser(new GenericAsmParser), PlatformParser(0), - CurBuffer(0), MacrosEnabled(true) { + CurBuffer(0), MacrosEnabled(true), CppHashLineNumber(0) { + SrcMgr.setDiagHandler(DiagHandler, this); Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); // Initialize the generic parser. @@ -1231,8 +1238,6 @@ bool AsmParser::ParseCppHashLineFilenameComment(const SMLoc &L) { } int64_t LineNumber = getTok().getIntVal(); - // FIXME: remember to remove this line that is silencing a warning for now. - (void) LineNumber; Lex(); if (getLexer().isNot(AsmToken::String)) { @@ -1244,14 +1249,68 @@ bool AsmParser::ParseCppHashLineFilenameComment(const SMLoc &L) { // Get rid of the enclosing quotes. Filename = Filename.substr(1, Filename.size()-2); - // TODO: Now with the Filename, LineNumber set up a mapping to the SMLoc for - // later use by diagnostics. + // Save the SMLoc, Filename and LineNumber for later use by diagnostics. + CppHashLoc = L; + CppHashFilename = Filename; + CppHashLineNumber = LineNumber; // Ignore any trailing characters, they're just comment. EatToEndOfLine(); return false; } +/// DiagHandler - will use the the last parsed cpp hash line filename comment +/// for the Filename and LineNo if any in the diagnostic. +void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) { + const AsmParser *Parser = static_cast(Context); + raw_ostream &OS = errs(); + + const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr(); + const SMLoc &DiagLoc = Diag.getLoc(); + int DiagBuf = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); + int CppHashBuf = Parser->SrcMgr.FindBufferContainingLoc(Parser->CppHashLoc); + + // Like SourceMgr::PrintMessage() we need to print the include stack if any + // before printing the message. + int DiagCurBuffer = DiagSrcMgr.FindBufferContainingLoc(DiagLoc); + if (DiagCurBuffer > 0) { + SMLoc ParentIncludeLoc = DiagSrcMgr.getParentIncludeLoc(DiagCurBuffer); + DiagSrcMgr.PrintIncludeStack(ParentIncludeLoc, OS); + } + + // If we have not parsed a cpp hash line filename comment or the source + // manager changed or buffer changed (like in a nested include) then just + // print the normal diagnostic using its Filename and LineNo. + if (!Parser->CppHashLineNumber || + &DiagSrcMgr != &Parser->SrcMgr || + DiagBuf != CppHashBuf) { + Diag.Print(0, OS); + return; + } + + // Use the CppHashFilename and calculate a line number based on the + // CppHashLoc and CppHashLineNumber relative to this Diag's SMLoc for + // the diagnostic. + const std::string Filename = Parser->CppHashFilename; + + int DiagLocLineNo = DiagSrcMgr.FindLineNumber(DiagLoc, DiagBuf); + int CppHashLocLineNo = + Parser->SrcMgr.FindLineNumber(Parser->CppHashLoc, CppHashBuf); + int LineNo = Parser->CppHashLineNumber - 1 + + (DiagLocLineNo - CppHashLocLineNo); + + SMDiagnostic NewDiag(*Diag.getSourceMgr(), + Diag.getLoc(), + Filename, + LineNo, + Diag.getColumnNo(), + Diag.getMessage(), + Diag.getLineContents(), + Diag.getShowLine()); + + NewDiag.Print(0, OS); +} + bool AsmParser::expandMacro(SmallString<256> &Buf, StringRef Body, const std::vector &Parameters, const std::vector > &A, diff --git a/test/MC/X86/x86_errors.s b/test/MC/X86/x86_errors.s index 318e4788d6d..e0a2c676d3d 100644 --- a/test/MC/X86/x86_errors.s +++ b/test/MC/X86/x86_errors.s @@ -10,3 +10,8 @@ cmp $0, 0(%eax) // 32: error: register %rax is only available in 64-bit mode addl $0, 0(%rax) + +// 32: test.s:8:2: error: invalid instruction mnemonic 'movi' + +# 8 "test.s" + movi $8,%eax