diff options
Diffstat (limited to 'lib/MC/MCParser/AsmParser.cpp')
-rw-r--r-- | lib/MC/MCParser/AsmParser.cpp | 246 |
1 files changed, 186 insertions, 60 deletions
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 2cf376e013..4e8e15c7d6 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCParser/AsmCond.h" #include "llvm/MC/MCParser/AsmLexer.h" @@ -27,14 +28,12 @@ #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCDwarf.h" +#include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetAsmParser.h" #include <cctype> #include <vector> using namespace llvm; @@ -88,6 +87,8 @@ private: MCStreamer &Out; const MCAsmInfo &MAI; SourceMgr &SrcMgr; + SourceMgr::DiagHandlerTy SavedDiagHandler; + void *SavedDiagContext; MCAsmParserExtension *GenericParser; MCAsmParserExtension *PlatformParser; @@ -116,8 +117,13 @@ 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(const Target &T, SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, + AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, const MCAsmInfo &MAI); ~AsmParser(); @@ -138,8 +144,10 @@ public: virtual MCContext &getContext() { return Ctx; } virtual MCStreamer &getStreamer() { return Out; } - virtual bool Warning(SMLoc L, const Twine &Msg); - virtual bool Error(SMLoc L, const Twine &Msg); + virtual bool Warning(SMLoc L, const Twine &Msg, + ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()); + virtual bool Error(SMLoc L, const Twine &Msg, + ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()); const AsmToken &Lex(); @@ -154,6 +162,8 @@ private: void CheckForValidSection(); bool ParseStatement(); + void EatToEndOfLine(); + bool ParseCppHashLineFilenameComment(const SMLoc &L); bool HandleMacroEntry(StringRef Name, SMLoc NameLoc, const Macro *M); bool expandMacro(SmallString<256> &Buf, StringRef Body, @@ -163,10 +173,11 @@ private: void HandleMacroExit(); void PrintMacroInstantiations(); - void PrintMessage(SMLoc Loc, const Twine &Msg, const char *Type, - bool ShowLine = true) const { - SrcMgr.PrintMessage(Loc, Msg, Type, ShowLine); + void PrintMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg, + ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) const { + SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges); } + static void DiagHandler(const SMDiagnostic &Diag, void *Context); /// EnterIncludeFile - Enter the specified file. This returns true on failure. bool EnterIncludeFile(const std::string &Filename); @@ -339,11 +350,16 @@ extern MCAsmParserExtension *createCOFFAsmParser(); enum { DEFAULT_ADDRSPACE = 0 }; -AsmParser::AsmParser(const Target &T, SourceMgr &_SM, MCContext &_Ctx, +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) { + // Save the old handler. + SavedDiagHandler = SrcMgr.getDiagHandler(); + SavedDiagContext = SrcMgr.getDiagContext(); + // Set our own handler which calls the saved handler. + SrcMgr.setDiagHandler(DiagHandler, this); Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); // Initialize the generic parser. @@ -381,21 +397,21 @@ void AsmParser::PrintMacroInstantiations() { // Print the active macro instantiation stack. for (std::vector<MacroInstantiation*>::const_reverse_iterator it = ActiveMacros.rbegin(), ie = ActiveMacros.rend(); it != ie; ++it) - PrintMessage((*it)->InstantiationLoc, "while in macro instantiation", - "note"); + PrintMessage((*it)->InstantiationLoc, SourceMgr::DK_Note, + "while in macro instantiation"); } -bool AsmParser::Warning(SMLoc L, const Twine &Msg) { +bool AsmParser::Warning(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) { if (FatalAssemblerWarnings) - return Error(L, Msg); - PrintMessage(L, Msg, "warning"); + return Error(L, Msg, Ranges); + PrintMessage(L, SourceMgr::DK_Warning, Msg, Ranges); PrintMacroInstantiations(); return false; } -bool AsmParser::Error(SMLoc L, const Twine &Msg) { +bool AsmParser::Error(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) { HadError = true; - PrintMessage(L, Msg, "error"); + PrintMessage(L, SourceMgr::DK_Error, Msg, Ranges); PrintMacroInstantiations(); return true; } @@ -487,8 +503,9 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // FIXME: We would really like to refer back to where the symbol was // first referenced for a source location. We need to add something // to track that. Currently, we just point to the end of the file. - PrintMessage(getLexer().getLoc(), "assembler local symbol '" + - Sym->getName() + "' not defined", "error", false); + PrintMessage(getLexer().getLoc(), SourceMgr::DK_Error, + "assembler local symbol '" + Sym->getName() + + "' not defined"); } } @@ -741,9 +758,12 @@ AsmParser::ApplyModifierToExpr(const MCExpr *E, /// ParseExpression - Parse an expression and return it. /// -/// expr ::= expr +,- expr -> lowest. -/// expr ::= expr |,^,&,! expr -> middle. -/// expr ::= expr *,/,%,<<,>> expr -> highest. +/// expr ::= expr &&,|| expr -> lowest. +/// expr ::= expr |,^,&,! expr +/// expr ::= expr ==,!=,<>,<,<=,>,>= expr +/// expr ::= expr <<,>> expr +/// expr ::= expr +,- expr +/// expr ::= expr *,/,% expr -> highest. /// expr ::= primaryexpr /// bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) { @@ -810,7 +830,7 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K, default: return 0; // not a binop. - // Lowest Precedence: &&, ||, @ + // Lowest Precedence: &&, || case AsmToken::AmpAmp: Kind = MCBinaryExpr::LAnd; return 1; @@ -853,30 +873,32 @@ static unsigned getBinOpPrecedence(AsmToken::TokenKind K, Kind = MCBinaryExpr::GTE; return 3; + // Intermediate Precedence: <<, >> + case AsmToken::LessLess: + Kind = MCBinaryExpr::Shl; + return 4; + case AsmToken::GreaterGreater: + Kind = MCBinaryExpr::Shr; + return 4; + // High Intermediate Precedence: +, - case AsmToken::Plus: Kind = MCBinaryExpr::Add; - return 4; + return 5; case AsmToken::Minus: Kind = MCBinaryExpr::Sub; - return 4; + return 5; - // Highest Precedence: *, /, %, <<, >> + // Highest Precedence: *, /, % case AsmToken::Star: Kind = MCBinaryExpr::Mul; - return 5; + return 6; case AsmToken::Slash: Kind = MCBinaryExpr::Div; - return 5; + return 6; case AsmToken::Percent: Kind = MCBinaryExpr::Mod; - return 5; - case AsmToken::LessLess: - Kind = MCBinaryExpr::Shl; - return 5; - case AsmToken::GreaterGreater: - Kind = MCBinaryExpr::Shr; - return 5; + return 6; } } @@ -933,10 +955,8 @@ bool AsmParser::ParseStatement() { StringRef IDVal; int64_t LocalLabelVal = -1; // A full line comment is a '#' as the first token. - if (Lexer.is(AsmToken::Hash)) { - EatToEndOfStatement(); - return false; - } + if (Lexer.is(AsmToken::Hash)) + return ParseCppHashLineFilenameComment(IDLoc); // Allow an integer followed by a ':' as a directional local label. if (Lexer.is(AsmToken::Integer)) { @@ -1118,15 +1138,8 @@ bool AsmParser::ParseStatement() { if (IDVal == ".globl" || IDVal == ".global") return ParseDirectiveSymbolAttribute(MCSA_Global); - // ELF only? Should it be here? - if (IDVal == ".local") - return ParseDirectiveSymbolAttribute(MCSA_Local); - if (IDVal == ".hidden") - return ParseDirectiveSymbolAttribute(MCSA_Hidden); if (IDVal == ".indirect_symbol") return ParseDirectiveSymbolAttribute(MCSA_IndirectSymbol); - if (IDVal == ".internal") - return ParseDirectiveSymbolAttribute(MCSA_Internal); if (IDVal == ".lazy_reference") return ParseDirectiveSymbolAttribute(MCSA_LazyReference); if (IDVal == ".no_dead_strip") @@ -1135,12 +1148,8 @@ bool AsmParser::ParseStatement() { return ParseDirectiveSymbolAttribute(MCSA_SymbolResolver); if (IDVal == ".private_extern") return ParseDirectiveSymbolAttribute(MCSA_PrivateExtern); - if (IDVal == ".protected") - return ParseDirectiveSymbolAttribute(MCSA_Protected); if (IDVal == ".reference") return ParseDirectiveSymbolAttribute(MCSA_Reference); - if (IDVal == ".weak") - return ParseDirectiveSymbolAttribute(MCSA_Weak); if (IDVal == ".weak_definition") return ParseDirectiveSymbolAttribute(MCSA_WeakDefinition); if (IDVal == ".weak_reference") @@ -1158,7 +1167,7 @@ bool AsmParser::ParseStatement() { if (IDVal == ".include") return ParseDirectiveInclude(); - if (IDVal == ".code16" || IDVal == ".code32" || IDVal == ".code64") + if (IDVal == ".code16") return TokError(Twine(IDVal) + " not supported yet"); // Look up the handler in the handler table. @@ -1199,7 +1208,7 @@ bool AsmParser::ParseStatement() { } OS << "]"; - PrintMessage(IDLoc, OS.str(), "note"); + PrintMessage(IDLoc, SourceMgr::DK_Note, OS.str()); } // If parsing succeeded, match the instruction. @@ -1216,6 +1225,103 @@ bool AsmParser::ParseStatement() { return false; } +/// EatToEndOfLine uses the Lexer to eat the characters to the end of the line +/// since they may not be able to be tokenized to get to the end of line token. +void AsmParser::EatToEndOfLine() { + Lexer.LexUntilEndOfLine(); + // Eat EOL. + Lex(); +} + +/// ParseCppHashLineFilenameComment as this: +/// ::= # number "filename" +/// or just as a full line comment if it doesn't have a number and a string. +bool AsmParser::ParseCppHashLineFilenameComment(const SMLoc &L) { + Lex(); // Eat the hash token. + + if (getLexer().isNot(AsmToken::Integer)) { + // Consume the line since in cases it is not a well-formed line directive, + // as if were simply a full line comment. + EatToEndOfLine(); + return false; + } + + int64_t LineNumber = getTok().getIntVal(); + Lex(); + + if (getLexer().isNot(AsmToken::String)) { + EatToEndOfLine(); + return false; + } + + StringRef Filename = getTok().getString(); + // Get rid of the enclosing quotes. + Filename = Filename.substr(1, Filename.size()-2); + + // 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<const AsmParser*>(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 (!Parser->SavedDiagHandler && 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) { + if (Parser->SavedDiagHandler) + Parser->SavedDiagHandler(Diag, Parser->SavedDiagContext); + else + 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.getKind(), Diag.getMessage(), + Diag.getLineContents(), Diag.getRanges()); + + if (Parser->SavedDiagHandler) + Parser->SavedDiagHandler(NewDiag, Parser->SavedDiagContext); + else + NewDiag.print(0, OS); +} + bool AsmParser::expandMacro(SmallString<256> &Buf, StringRef Body, const std::vector<StringRef> &Parameters, const std::vector<std::vector<AsmToken> > &A, @@ -1924,12 +2030,17 @@ bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) { if (getLexer().isNot(AsmToken::EndOfStatement)) { for (;;) { StringRef Name; + SMLoc Loc = getTok().getLoc(); if (ParseIdentifier(Name)) - return TokError("expected identifier in directive"); + return Error(Loc, "expected identifier in directive"); MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + // Assembler local symbols don't make any sense here. Complain loudly. + if (Sym->isTemporary()) + return Error(Loc, "non-local symbol required in directive"); + getStreamer().EmitSymbolAttribute(Sym, Attr); if (getLexer().is(AsmToken::EndOfStatement)) @@ -2192,7 +2303,8 @@ bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) { } /// ParseDirectiveFile -/// ::= .file [number] string +/// ::= .file [number] filename +/// ::= .file number directory filename bool GenericAsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) { // FIXME: I'm not sure what this is. int64_t FileNumber = -1; @@ -2208,17 +2320,31 @@ bool GenericAsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) { if (getLexer().isNot(AsmToken::String)) return TokError("unexpected token in '.file' directive"); - StringRef Filename = getTok().getString(); - Filename = Filename.substr(1, Filename.size()-2); + // Usually the directory and filename together, otherwise just the directory. + StringRef Path = getTok().getString(); + Path = Path.substr(1, Path.size()-2); Lex(); + StringRef Directory; + StringRef Filename; + if (getLexer().is(AsmToken::String)) { + if (FileNumber == -1) + return TokError("explicit path specified, but no file number"); + Filename = getTok().getString(); + Filename = Filename.substr(1, Filename.size()-2); + Directory = Path; + Lex(); + } else { + Filename = Path; + } + if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.file' directive"); if (FileNumber == -1) getStreamer().EmitFileDirective(Filename); else { - if (getStreamer().EmitDwarfFileDirective(FileNumber, Filename)) + if (getStreamer().EmitDwarfFileDirective(FileNumber, Directory, Filename)) Error(FileNumberLoc, "file number already allocated"); } @@ -2725,8 +2851,8 @@ bool GenericAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) { /// \brief Create an MCAsmParser instance. -MCAsmParser *llvm::createMCAsmParser(const Target &T, SourceMgr &SM, +MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C, MCStreamer &Out, const MCAsmInfo &MAI) { - return new AsmParser(T, SM, C, Out, MAI); + return new AsmParser(SM, C, Out, MAI); } |