diff options
Diffstat (limited to 'contrib/llvm/lib/MC/MCParser/AsmParser.cpp')
-rw-r--r-- | contrib/llvm/lib/MC/MCParser/AsmParser.cpp | 1556 |
1 files changed, 931 insertions, 625 deletions
diff --git a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp index 1548aee..da54155 100644 --- a/contrib/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/contrib/llvm/lib/MC/MCParser/AsmParser.cpp @@ -12,42 +12,69 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/APFloat.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCCodeView.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCParser/AsmCond.h" #include "llvm/MC/MCParser/AsmLexer.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCParser/MCAsmParserUtils.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCParser/MCTargetAsmParser.h" #include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> #include <cctype> +#include <cstddef> +#include <cstdint> #include <deque> +#include <memory> +#include <sstream> #include <string> +#include <tuple> +#include <utility> #include <vector> + using namespace llvm; MCAsmParserSemaCallback::~MCAsmParserSemaCallback() {} +static cl::opt<unsigned> AsmMacroMaxNestingDepth( + "asm-macro-max-nesting-depth", cl::init(20), cl::Hidden, + cl::desc("The maximum nesting depth allowed for assembly macros.")); + namespace { + /// \brief Helper types for tracking macro definitions. typedef std::vector<AsmToken> MCAsmMacroArgument; typedef std::vector<MCAsmMacroArgument> MCAsmMacroArguments; @@ -113,6 +140,7 @@ struct ParseStatementInfo { class AsmParser : public MCAsmParser { AsmParser(const AsmParser &) = delete; void operator=(const AsmParser &) = delete; + private: AsmLexer Lexer; MCContext &Ctx; @@ -150,9 +178,6 @@ private: /// \brief Keeps track of how many .macro's have been instantiated. unsigned NumOfMacroInstantiations; - /// Flag tracking whether any errors have been encountered. - unsigned HadError : 1; - /// The values from the last parsed cpp hash file line comment if any. struct CppHashInfoTy { StringRef Filename; @@ -206,6 +231,9 @@ public: MCAsmLexer &getLexer() override { return Lexer; } MCContext &getContext() override { return Ctx; } MCStreamer &getStreamer() override { return Out; } + + CodeViewContext &getCVContext() { return Ctx.getCVContext(); } + unsigned getAssemblerDialect() override { if (AssemblerDialect == ~0U) return MAI.getAssemblerDialect(); @@ -216,16 +244,16 @@ public: AssemblerDialect = i; } - void Note(SMLoc L, const Twine &Msg, - ArrayRef<SMRange> Ranges = None) override; - bool Warning(SMLoc L, const Twine &Msg, - ArrayRef<SMRange> Ranges = None) override; - bool Error(SMLoc L, const Twine &Msg, - ArrayRef<SMRange> Ranges = None) override; + void Note(SMLoc L, const Twine &Msg, SMRange Range = None) override; + bool Warning(SMLoc L, const Twine &Msg, SMRange Range = None) override; + bool printError(SMLoc L, const Twine &Msg, SMRange Range = None) override; const AsmToken &Lex() override; - void setParsingInlineAsm(bool V) override { ParsingInlineAsm = V; } + void setParsingInlineAsm(bool V) override { + ParsingInlineAsm = V; + Lexer.setParsingMSInlineAsm(V); + } bool isParsingInlineAsm() override { return ParsingInlineAsm; } bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, @@ -244,39 +272,20 @@ public: SMLoc &EndLoc) override; bool parseAbsoluteExpression(int64_t &Res) override; + /// \brief Parse a floating point expression using the float \p Semantics + /// and set \p Res to the value. + bool parseRealValue(const fltSemantics &Semantics, APInt &Res); + /// \brief Parse an identifier or string (as a quoted identifier) /// and set \p Res to the identifier contents. bool parseIdentifier(StringRef &Res) override; void eatToEndOfStatement() override; - void checkForValidSection() override; - - bool getTokenLoc(SMLoc &Loc) { - Loc = getTok().getLoc(); - return false; - } - - /// parseToken - If current token has the specified kind, eat it and - /// return success. Otherwise, emit the specified error and return failure. - bool parseToken(AsmToken::TokenKind T, const Twine &ErrMsg) { - if (getTok().getKind() != T) - return TokError(ErrMsg); - Lex(); - return false; - } - - bool parseIntToken(int64_t &V, const Twine &ErrMsg) { - if (getTok().getKind() != AsmToken::Integer) - return TokError(ErrMsg); - V = getTok().getIntVal(); - Lex(); - return false; - } + bool checkForValidSection() override; /// } private: - bool parseStatement(ParseStatementInfo &Info, MCAsmParserSemaCallback *SI); bool parseCurlyBlockScope(SmallVectorImpl<AsmRewrite>& AsmStrRewrites); @@ -326,29 +335,19 @@ private: void printMacroInstantiations(); void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind, const Twine &Msg, - ArrayRef<SMRange> Ranges = None) const { + SMRange Range = None) const { + ArrayRef<SMRange> Ranges(Range); SrcMgr.PrintMessage(Loc, Kind, Msg, Ranges); } static void DiagHandler(const SMDiagnostic &Diag, void *Context); - bool check(bool P, SMLoc Loc, const Twine &Msg) { - if (P) - return Error(Loc, Msg); - return false; - } - - bool check(bool P, const Twine &Msg) { - if (P) - return TokError(Msg); - return false; - } - /// \brief Enter the specified file. This returns true on failure. bool enterIncludeFile(const std::string &Filename); /// \brief Process the specified file for the .incbin directive. /// This returns true on failure. - bool processIncbinFile(const std::string &Filename); + bool processIncbinFile(const std::string &Filename, int64_t Skip = 0, + const MCExpr *Count = nullptr, SMLoc Loc = SMLoc()); /// \brief Reset the current lexer position to that given by \p Loc. The /// current token is not set; clients should ensure Lex() is called @@ -379,12 +378,18 @@ private: bool parseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc); + bool parseCVFunctionId(int64_t &FunctionId, StringRef DirectiveName); + bool parseCVFileId(int64_t &FileId, StringRef DirectiveName); + // Generic (target and platform independent) directive parsing. enum DirectiveKind { DK_NO_DIRECTIVE, // Placeholder DK_SET, DK_EQU, DK_EQUIV, DK_ASCII, DK_ASCIZ, DK_STRING, DK_BYTE, DK_SHORT, DK_RELOC, DK_VALUE, DK_2BYTE, DK_LONG, DK_INT, DK_4BYTE, DK_QUAD, DK_8BYTE, DK_OCTA, + DK_DC, DK_DC_A, DK_DC_B, DK_DC_D, DK_DC_L, DK_DC_S, DK_DC_W, DK_DC_X, + DK_DCB, DK_DCB_B, DK_DCB_D, DK_DCB_L, DK_DCB_S, DK_DCB_W, DK_DCB_X, + DK_DS, DK_DS_B, DK_DS_D, DK_DS_L, DK_DS_P, DK_DS_S, DK_DS_W, DK_DS_X, DK_SINGLE, DK_FLOAT, DK_DOUBLE, DK_ALIGN, DK_ALIGN32, DK_BALIGN, DK_BALIGNW, DK_BALIGNL, DK_P2ALIGN, DK_P2ALIGNW, DK_P2ALIGNL, DK_ORG, DK_FILL, DK_ENDR, DK_BUNDLE_ALIGN_MODE, DK_BUNDLE_LOCK, DK_BUNDLE_UNLOCK, @@ -397,8 +402,9 @@ private: DK_IFNB, DK_IFC, DK_IFEQS, DK_IFNC, DK_IFNES, DK_IFDEF, DK_IFNDEF, DK_IFNOTDEF, DK_ELSEIF, DK_ELSE, DK_ENDIF, DK_SPACE, DK_SKIP, DK_FILE, DK_LINE, DK_LOC, DK_STABS, - DK_CV_FILE, DK_CV_LOC, DK_CV_LINETABLE, DK_CV_INLINE_LINETABLE, - DK_CV_DEF_RANGE, DK_CV_STRINGTABLE, DK_CV_FILECHECKSUMS, + DK_CV_FILE, DK_CV_FUNC_ID, DK_CV_INLINE_SITE_ID, DK_CV_LOC, DK_CV_LINETABLE, + DK_CV_INLINE_LINETABLE, DK_CV_DEF_RANGE, DK_CV_STRINGTABLE, + DK_CV_FILECHECKSUMS, DK_CFI_SECTIONS, DK_CFI_STARTPROC, DK_CFI_ENDPROC, DK_CFI_DEF_CFA, DK_CFI_DEF_CFA_OFFSET, DK_CFI_ADJUST_CFA_OFFSET, DK_CFI_DEF_CFA_REGISTER, DK_CFI_OFFSET, DK_CFI_REL_OFFSET, DK_CFI_PERSONALITY, DK_CFI_LSDA, @@ -419,9 +425,11 @@ private: // ".ascii", ".asciz", ".string" bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated); bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc" - bool parseDirectiveValue(unsigned Size); // ".byte", ".long", ... - bool parseDirectiveOctaValue(); // ".octa" - bool parseDirectiveRealValue(const fltSemantics &); // ".single", ... + bool parseDirectiveValue(StringRef IDVal, + unsigned Size); // ".byte", ".long", ... + bool parseDirectiveOctaValue(StringRef IDVal); // ".octa", ... + bool parseDirectiveRealValue(StringRef IDVal, + const fltSemantics &); // ".single", ... bool parseDirectiveFill(); // ".fill" bool parseDirectiveZero(); // ".zero" // ".set", ".equ", ".equiv" @@ -436,9 +444,11 @@ private: bool parseDirectiveLoc(); bool parseDirectiveStabs(); - // ".cv_file", ".cv_loc", ".cv_linetable", "cv_inline_linetable", - // ".cv_def_range" + // ".cv_file", ".cv_func_id", ".cv_inline_site_id", ".cv_loc", ".cv_linetable", + // ".cv_inline_linetable", ".cv_def_range" bool parseDirectiveCVFile(); + bool parseDirectiveCVFuncId(); + bool parseDirectiveCVInlineSiteId(); bool parseDirectiveCVLoc(); bool parseDirectiveCVLinetable(); bool parseDirectiveCVInlineLinetable(); @@ -484,6 +494,12 @@ private: // ".space", ".skip" bool parseDirectiveSpace(StringRef IDVal); + // ".dcb" + bool parseDirectiveDCB(StringRef IDVal, unsigned Size); + bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &); + // ".ds" + bool parseDirectiveDS(StringRef IDVal, unsigned Size); + // .sleb128 (Signed=true) and .uleb128 (Signed=false) bool parseDirectiveLEB128(bool Signed); @@ -542,7 +558,8 @@ private: void initializeDirectiveKindMap(); }; -} + +} // end anonymous namespace namespace llvm { @@ -550,7 +567,7 @@ extern MCAsmParserExtension *createDarwinAsmParser(); extern MCAsmParserExtension *createELFAsmParser(); extern MCAsmParserExtension *createCOFFAsmParser(); -} +} // end namespace llvm enum { DEFAULT_ADDRSPACE = 0 }; @@ -558,8 +575,9 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, const MCAsmInfo &MAI) : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM), PlatformParser(nullptr), CurBuffer(SM.getMainFileID()), - MacrosEnabledFlag(true), HadError(false), CppHashInfo(), - AssemblerDialect(~0U), IsDarwin(false), ParsingInlineAsm(false) { + MacrosEnabledFlag(true), CppHashInfo(), AssemblerDialect(~0U), + IsDarwin(false), ParsingInlineAsm(false) { + HadError = false; // Save the old handler. SavedDiagHandler = SrcMgr.getDiagHandler(); SavedDiagContext = SrcMgr.getDiagContext(); @@ -602,24 +620,25 @@ void AsmParser::printMacroInstantiations() { "while in macro instantiation"); } -void AsmParser::Note(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) { - printMessage(L, SourceMgr::DK_Note, Msg, Ranges); +void AsmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) { + printPendingErrors(); + printMessage(L, SourceMgr::DK_Note, Msg, Range); printMacroInstantiations(); } -bool AsmParser::Warning(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) { +bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) { if(getTargetParser().getTargetOptions().MCNoWarn) return false; if (getTargetParser().getTargetOptions().MCFatalWarnings) - return Error(L, Msg, Ranges); - printMessage(L, SourceMgr::DK_Warning, Msg, Ranges); + return Error(L, Msg, Range); + printMessage(L, SourceMgr::DK_Warning, Msg, Range); printMacroInstantiations(); return false; } -bool AsmParser::Error(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges) { +bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) { HadError = true; - printMessage(L, SourceMgr::DK_Error, Msg, Ranges); + printMessage(L, SourceMgr::DK_Error, Msg, Range); printMacroInstantiations(); return true; } @@ -639,7 +658,8 @@ bool AsmParser::enterIncludeFile(const std::string &Filename) { /// Process the specified .incbin file by searching for it in the include paths /// then just emitting the byte contents of the file to the streamer. This /// returns true on failure. -bool AsmParser::processIncbinFile(const std::string &Filename) { +bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip, + const MCExpr *Count, SMLoc Loc) { std::string IncludedFile; unsigned NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile); @@ -647,7 +667,17 @@ bool AsmParser::processIncbinFile(const std::string &Filename) { return true; // Pick up the bytes from the file and emit them. - getStreamer().EmitBytes(SrcMgr.getMemoryBuffer(NewBuf)->getBuffer()); + StringRef Bytes = SrcMgr.getMemoryBuffer(NewBuf)->getBuffer(); + Bytes = Bytes.drop_front(Skip); + if (Count) { + int64_t Res; + if (!Count->evaluateAsAbsolute(Res)) + return Error(Loc, "expected absolute expression"); + if (Res < 0) + return Warning(Loc, "negative count has no effect"); + Bytes = Bytes.take_front(Res); + } + getStreamer().EmitBytes(Bytes); return false; } @@ -688,7 +718,6 @@ const AsmToken &AsmParser::Lex() { } } - return *tok; } @@ -706,7 +735,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // If we are generating dwarf for assembly source files save the initial text // section and generate a .file directive. if (getContext().getGenDwarfForAssembly()) { - MCSection *Sec = getStreamer().getCurrentSection().first; + MCSection *Sec = getStreamer().getCurrentSectionOnly(); if (!Sec->getBeginSymbol()) { MCSymbol *SectionStartSym = getContext().createTempSymbol(); getStreamer().EmitLabel(SectionStartSym); @@ -725,30 +754,38 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { if (!parseStatement(Info, nullptr)) continue; - // If we've failed, but on a Error Token, but did not consume it in - // favor of a better message, emit it now. - if (Lexer.getTok().is(AsmToken::Error)) { + // If we have a Lexer Error we are on an Error Token. Load in Lexer Error + // for printing ErrMsg via Lex() only if no (presumably better) parser error + // exists. + if (!hasPendingError() && Lexer.getTok().is(AsmToken::Error)) { Lex(); } - // We had an error, validate that one was emitted and recover by skipping to - // the next line. - assert(HadError && "Parse statement returned an error, but none emitted!"); - eatToEndOfStatement(); + // parseStatement returned true so may need to emit an error. + printPendingErrors(); + + // Skipping to the next line if needed. + if (!getLexer().isAtStartOfStatement()) + eatToEndOfStatement(); } + // All errors should have been emitted. + assert(!hasPendingError() && "unexpected error from parseStatement"); + + getTargetParser().flushPendingInstructions(getStreamer()); + if (TheCondState.TheCond != StartingCondState.TheCond || TheCondState.Ignore != StartingCondState.Ignore) - return TokError("unmatched .ifs or .elses"); - + printError(getTok().getLoc(), "unmatched .ifs or .elses"); // Check to see there are no empty DwarfFile slots. const auto &LineTables = getContext().getMCDwarfLineTables(); if (!LineTables.empty()) { unsigned Index = 0; for (const auto &File : LineTables.begin()->second.getMCDwarfFiles()) { if (File.Name.empty() && Index != 0) - TokError("unassigned file number: " + Twine(Index) + - " for .file directives"); + printError(getTok().getLoc(), "unassigned file number: " + + Twine(Index) + + " for .file directives"); ++Index; } } @@ -768,9 +805,8 @@ 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. - HadError |= - Error(getTok().getLoc(), "assembler local symbol '" + - Sym->getName() + "' not defined"); + printError(getTok().getLoc(), "assembler local symbol '" + + Sym->getName() + "' not defined"); } } @@ -781,7 +817,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // Reset the state of any "# line file" directives we've seen to the // context as it was at the diagnostic site. CppHashInfo = std::get<1>(LocSym); - HadError |= Error(std::get<0>(LocSym), "directional label undefined"); + printError(std::get<0>(LocSym), "directional label undefined"); } } } @@ -794,11 +830,13 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { return HadError || getContext().hadError(); } -void AsmParser::checkForValidSection() { - if (!ParsingInlineAsm && !getStreamer().getCurrentSection().first) { - TokError("expected section directive before assembly directive"); +bool AsmParser::checkForValidSection() { + if (!ParsingInlineAsm && !getStreamer().getCurrentSectionOnly()) { Out.InitSections(false); + return Error(getTok().getLoc(), + "expected section directive before assembly directive"); } + return false; } /// \brief Throw away the rest of the line for testing purposes. @@ -888,8 +926,10 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { case AsmToken::Identifier: { StringRef Identifier; if (parseIdentifier(Identifier)) { - if (FirstTokenKind == AsmToken::Dollar) { + // We may have failed but $ may be a valid token. + if (getTok().is(AsmToken::Dollar)) { if (Lexer.getMAI().getDollarIsPC()) { + Lex(); // This is a '$' reference, which references the current PC. Emit a // temporary label to the streamer and refer to it. MCSymbol *Sym = Ctx.createTempSymbol(); @@ -933,6 +973,9 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { // This is a symbol reference. StringRef SymbolName = Identifier; + if (SymbolName.empty()) + return true; + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; // Lookup the symbol variant if used. @@ -999,7 +1042,7 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { return false; } case AsmToken::Real: { - APFloat RealVal(APFloat::IEEEdouble, getTok().getString()); + APFloat RealVal(APFloat::IEEEdouble(), getTok().getString()); uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue(); Res = MCConstantExpr::create(IntVal, getContext()); EndLoc = Lexer.getTok().getEndLoc(); @@ -1042,6 +1085,43 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { return true; Res = MCUnaryExpr::createNot(Res, getContext()); return false; + // MIPS unary expression operators. The lexer won't generate these tokens if + // MCAsmInfo::HasMipsExpressions is false for the target. + case AsmToken::PercentCall16: + case AsmToken::PercentCall_Hi: + case AsmToken::PercentCall_Lo: + case AsmToken::PercentDtprel_Hi: + case AsmToken::PercentDtprel_Lo: + case AsmToken::PercentGot: + case AsmToken::PercentGot_Disp: + case AsmToken::PercentGot_Hi: + case AsmToken::PercentGot_Lo: + case AsmToken::PercentGot_Ofst: + case AsmToken::PercentGot_Page: + case AsmToken::PercentGottprel: + case AsmToken::PercentGp_Rel: + case AsmToken::PercentHi: + case AsmToken::PercentHigher: + case AsmToken::PercentHighest: + case AsmToken::PercentLo: + case AsmToken::PercentNeg: + case AsmToken::PercentPcrel_Hi: + case AsmToken::PercentPcrel_Lo: + case AsmToken::PercentTlsgd: + case AsmToken::PercentTlsldm: + case AsmToken::PercentTprel_Hi: + case AsmToken::PercentTprel_Lo: + Lex(); // Eat the operator. + if (Lexer.isNot(AsmToken::LParen)) + return TokError("expected '(' after operator"); + Lex(); // Eat the operator. + if (parseExpression(Res, EndLoc)) + return true; + if (Lexer.isNot(AsmToken::RParen)) + return TokError("expected ')'"); + Lex(); // Eat the operator. + Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx); + return !Res; } } @@ -1356,7 +1436,7 @@ unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K, /// Res contains the LHS of the expression on input. bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc) { - while (1) { + while (true) { MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add; unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind); @@ -1390,6 +1470,7 @@ bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, /// ::= Label* Identifier OperandList* EndOfStatement bool AsmParser::parseStatement(ParseStatementInfo &Info, MCAsmParserSemaCallback *SI) { + assert(!hasPendingError() && "parseStatement started with pending error"); // Eat initial spaces and comments while (Lexer.is(AsmToken::Space)) Lex(); @@ -1401,6 +1482,16 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, Lex(); return false; } + if (Lexer.is(AsmToken::Hash)) { + // Seeing a hash here means that it was an end-of-line comment in + // an asm syntax where hash's are not comment and the previous + // statement parser did not check the end of statement. Relex as + // EndOfStatement. + StringRef CommentStr = parseStringToEndOfStatement(); + Lexer.Lex(); + Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr)); + return false; + } // Statements always start with an identifier. AsmToken ID = getTok(); SMLoc IDLoc = ID.getLoc(); @@ -1412,15 +1503,19 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, if (Lexer.is(AsmToken::Integer)) { LocalLabelVal = getTok().getIntVal(); if (LocalLabelVal < 0) { - if (!TheCondState.Ignore) - return TokError("unexpected token at start of statement"); + if (!TheCondState.Ignore) { + Lex(); // always eat a token + return Error(IDLoc, "unexpected token at start of statement"); + } IDVal = ""; } else { IDVal = getTok().getString(); Lex(); // Consume the integer token to be used as an identifier token. if (Lexer.getKind() != AsmToken::Colon) { - if (!TheCondState.Ignore) - return TokError("unexpected token at start of statement"); + if (!TheCondState.Ignore) { + Lex(); // always eat a token + return Error(IDLoc, "unexpected token at start of statement"); + } } } } else if (Lexer.is(AsmToken::Dot)) { @@ -1437,8 +1532,10 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, Lex(); IDVal = "}"; } else if (parseIdentifier(IDVal)) { - if (!TheCondState.Ignore) - return TokError("unexpected token at start of statement"); + if (!TheCondState.Ignore) { + Lex(); // always eat a token + return Error(IDLoc, "unexpected token at start of statement"); + } IDVal = ""; } @@ -1500,7 +1597,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, case AsmToken::Colon: { if (!getTargetParser().isLabel(ID)) break; - checkForValidSection(); + if (checkForValidSection()) + return true; // identifier ':' -> Label. Lex(); @@ -1534,6 +1632,16 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, if (!Sym->isUndefined() || Sym->isVariable()) return Error(IDLoc, "invalid symbol redefinition"); + // End of Labels should be treated as end of line for lexing + // purposes but that information is not available to the Lexer who + // does not understand Labels. This may cause us to see a Hash + // here instead of a preprocessor line comment. + if (getTok().is(AsmToken::Hash)) { + StringRef CommentStr = parseStringToEndOfStatement(); + Lexer.Lex(); + Lexer.UnLex(AsmToken(AsmToken::EndOfStatement, CommentStr)); + } + // Consume any end of statement token, if present, to avoid spurious // AddBlankLine calls(). if (getTok().is(AsmToken::EndOfStatement)) { @@ -1552,8 +1660,6 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, getTargetParser().onLabelParsed(Sym); - - return false; } @@ -1590,9 +1696,22 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, // manner, or at least have a default behavior that's shared between // all targets and platforms. - // First query the target-specific parser. It will return 'true' if it - // isn't interested in this directive. - if (!getTargetParser().ParseDirective(ID)) + getTargetParser().flushPendingInstructions(getStreamer()); + + SMLoc StartTokLoc = getTok().getLoc(); + bool TPDirectiveReturn = getTargetParser().ParseDirective(ID); + + if (hasPendingError()) + return true; + // Currently the return value should be true if we are + // uninterested but as this is at odds with the standard parsing + // convention (return true = error) we have instances of a parsed + // directive that fails returning true as an error. Catch these + // cases as best as possible errors here. + if (TPDirectiveReturn && StartTokLoc != getTok().getLoc()) + return true; + // Return if we did some parsing or believe we succeeded. + if (!TPDirectiveReturn || StartTokLoc != getTok().getLoc()) return false; // Next, check the extension directive map to see if any extension has @@ -1618,25 +1737,34 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, case DK_STRING: return parseDirectiveAscii(IDVal, true); case DK_BYTE: - return parseDirectiveValue(1); + case DK_DC_B: + return parseDirectiveValue(IDVal, 1); + case DK_DC: + case DK_DC_W: case DK_SHORT: case DK_VALUE: case DK_2BYTE: - return parseDirectiveValue(2); + return parseDirectiveValue(IDVal, 2); case DK_LONG: case DK_INT: case DK_4BYTE: - return parseDirectiveValue(4); + case DK_DC_L: + return parseDirectiveValue(IDVal, 4); case DK_QUAD: case DK_8BYTE: - return parseDirectiveValue(8); + return parseDirectiveValue(IDVal, 8); + case DK_DC_A: + return parseDirectiveValue(IDVal, + getContext().getAsmInfo()->getPointerSize()); case DK_OCTA: - return parseDirectiveOctaValue(); + return parseDirectiveOctaValue(IDVal); case DK_SINGLE: case DK_FLOAT: - return parseDirectiveRealValue(APFloat::IEEEsingle); + case DK_DC_S: + return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle()); case DK_DOUBLE: - return parseDirectiveRealValue(APFloat::IEEEdouble); + case DK_DC_D: + return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble()); case DK_ALIGN: { bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes(); return parseDirectiveAlign(IsPow2, /*ExprSize=*/1); @@ -1731,6 +1859,10 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, return parseDirectiveStabs(); case DK_CV_FILE: return parseDirectiveCVFile(); + case DK_CV_FUNC_ID: + return parseDirectiveCVFuncId(); + case DK_CV_INLINE_SITE_ID: + return parseDirectiveCVInlineSiteId(); case DK_CV_LOC: return parseDirectiveCVLoc(); case DK_CV_LINETABLE: @@ -1805,6 +1937,34 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, return parseDirectiveWarning(IDLoc); case DK_RELOC: return parseDirectiveReloc(IDLoc); + case DK_DCB: + case DK_DCB_W: + return parseDirectiveDCB(IDVal, 2); + case DK_DCB_B: + return parseDirectiveDCB(IDVal, 1); + case DK_DCB_D: + return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble()); + case DK_DCB_L: + return parseDirectiveDCB(IDVal, 4); + case DK_DCB_S: + return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle()); + case DK_DC_X: + case DK_DCB_X: + return TokError(Twine(IDVal) + + " not currently supported for this target"); + case DK_DS: + case DK_DS_W: + return parseDirectiveDS(IDVal, 2); + case DK_DS_B: + return parseDirectiveDS(IDVal, 1); + case DK_DS_D: + return parseDirectiveDS(IDVal, 8); + case DK_DS_L: + case DK_DS_S: + return parseDirectiveDS(IDVal, 4); + case DK_DS_P: + case DK_DS_X: + return parseDirectiveDS(IDVal, 12); } return Error(IDLoc, "unknown directive"); @@ -1821,14 +1981,15 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, if (ParsingInlineAsm && (IDVal == "even")) Info.AsmRewrites->emplace_back(AOK_EVEN, IDLoc, 4); - checkForValidSection(); + if (checkForValidSection()) + return true; // Canonicalize the opcode to lower case. std::string OpcodeStr = IDVal.lower(); ParseInstructionInfo IInfo(Info.AsmRewrites); - bool HadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID, - Info.ParsedOperands); - Info.ParseError = HadError; + bool ParseHadError = getTargetParser().ParseInstruction(IInfo, OpcodeStr, ID, + Info.ParsedOperands); + Info.ParseError = ParseHadError; // Dump the parsed representation, if requested. if (getShowParsedOperands()) { @@ -1845,11 +2006,15 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, printMessage(IDLoc, SourceMgr::DK_Note, OS.str()); } + // Fail even if ParseInstruction erroneously returns false. + if (hasPendingError() || ParseHadError) + return true; + // If we are generating dwarf for the current section then generate a .loc // directive for the instruction. - if (!HadError && getContext().getGenDwarfForAssembly() && + if (!ParseHadError && getContext().getGenDwarfForAssembly() && getContext().getGenDwarfSectionSyms().count( - getStreamer().getCurrentSection().first)) { + getStreamer().getCurrentSectionOnly())) { unsigned Line; if (ActiveMacros.empty()) Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer); @@ -1889,15 +2054,13 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info, } // If parsing succeeded, match the instruction. - if (!HadError) { + if (!ParseHadError) { uint64_t ErrorInfo; - getTargetParser().MatchAndEmitInstruction(IDLoc, Info.Opcode, - Info.ParsedOperands, Out, - ErrorInfo, ParsingInlineAsm); + if (getTargetParser().MatchAndEmitInstruction(IDLoc, Info.Opcode, + Info.ParsedOperands, Out, + ErrorInfo, ParsingInlineAsm)) + return true; } - - // Don't skip the rest of the line, the instruction parser is responsible for - // that. return false; } @@ -1933,6 +2096,7 @@ bool AsmParser::parseCppHashLineFilenameComment(SMLoc L) { "Lexing Cpp line comment: Expected String"); StringRef Filename = getTok().getString(); Lex(); + // Get rid of the enclosing quotes. Filename = Filename.substr(1, Filename.size() - 2); @@ -2158,6 +2322,7 @@ static bool isOperator(AsmToken::TokenKind kind) { } namespace { + class AsmLexerSkipSpaceRAII { public: AsmLexerSkipSpaceRAII(AsmLexer &Lexer, bool SkipSpace) : Lexer(Lexer) { @@ -2171,7 +2336,8 @@ public: private: AsmLexer &Lexer; }; -} + +} // end anonymous namespace bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) { @@ -2190,7 +2356,7 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) { bool SpaceEaten; - for (;;) { + while (true) { SpaceEaten = false; if (Lexer.is(AsmToken::Eof) || Lexer.is(AsmToken::Equal)) return TokError("unexpected token in macro instantiation"); @@ -2265,27 +2431,19 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M, MCAsmMacroParameter FA; if (Lexer.is(AsmToken::Identifier) && Lexer.peekTok().is(AsmToken::Equal)) { - if (parseIdentifier(FA.Name)) { - Error(IDLoc, "invalid argument identifier for formal argument"); - eatToEndOfStatement(); - return true; - } + if (parseIdentifier(FA.Name)) + return Error(IDLoc, "invalid argument identifier for formal argument"); + + if (Lexer.isNot(AsmToken::Equal)) + return TokError("expected '=' after formal parameter identifier"); - if (Lexer.isNot(AsmToken::Equal)) { - TokError("expected '=' after formal parameter identifier"); - eatToEndOfStatement(); - return true; - } Lex(); NamedParametersFound = true; } - if (NamedParametersFound && FA.Name.empty()) { - Error(IDLoc, "cannot mix positional and keyword arguments"); - eatToEndOfStatement(); - return true; - } + if (NamedParametersFound && FA.Name.empty()) + return Error(IDLoc, "cannot mix positional and keyword arguments"); bool Vararg = HasVararg && Parameter == (NParameters - 1); if (parseMacroArgument(FA.Value, Vararg)) @@ -2300,10 +2458,8 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M, if (FAI >= NParameters) { assert(M && "expected macro to be defined"); - Error(IDLoc, - "parameter named '" + FA.Name + "' does not exist for macro '" + - M->Name + "'"); - return true; + return Error(IDLoc, "parameter named '" + FA.Name + + "' does not exist for macro '" + M->Name + "'"); } PI = FAI; } @@ -2359,10 +2515,17 @@ void AsmParser::defineMacro(StringRef Name, MCAsmMacro Macro) { void AsmParser::undefineMacro(StringRef Name) { MacroMap.erase(Name); } bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) { - // Arbitrarily limit macro nesting depth, to match 'as'. We can eliminate - // this, although we should protect against infinite loops. - if (ActiveMacros.size() == 20) - return TokError("macros cannot be nested more than 20 levels deep"); + // Arbitrarily limit macro nesting depth (default matches 'as'). We can + // eliminate this, although we should protect against infinite loops. + unsigned MaxNestingDepth = AsmMacroMaxNestingDepth; + if (ActiveMacros.size() == MaxNestingDepth) { + std::ostringstream MaxNestingDepthError; + MaxNestingDepthError << "macros cannot be nested more than " + << MaxNestingDepth << " levels deep." + << " Use -asm-macro-max-nesting-depth to increase " + "this limit."; + return TokError(MaxNestingDepthError.str()); + } MCAsmMacroArguments A; if (parseMacroArguments(M, A)) @@ -2446,14 +2609,19 @@ bool AsmParser::parseIdentifier(StringRef &Res) { SMLoc PrefixLoc = getLexer().getLoc(); // Consume the prefix character, and check for a following identifier. - Lexer.Lex(); // Lexer's Lex guarantees consecutive token. - if (Lexer.isNot(AsmToken::Identifier)) + + AsmToken Buf[1]; + Lexer.peekTokens(Buf, false); + + if (Buf[0].isNot(AsmToken::Identifier)) return true; // We have a '$' or '@' followed by an identifier, make sure they are adjacent. - if (PrefixLoc.getPointer() + 1 != getTok().getLoc().getPointer()) + if (PrefixLoc.getPointer() + 1 != Buf[0].getLoc().getPointer()) return true; + // eat $ or @ + Lexer.Lex(); // Lexer's Lex guarantees consecutive token. // Construct the joined identifier and consume the token. Res = StringRef(PrefixLoc.getPointer(), getTok().getIdentifier().size() + 1); @@ -2477,17 +2645,15 @@ bool AsmParser::parseIdentifier(StringRef &Res) { /// ::= .set identifier ',' expression bool AsmParser::parseDirectiveSet(StringRef IDVal, bool allow_redef) { StringRef Name; - - if (check(parseIdentifier(Name), - "expected identifier after '" + Twine(IDVal) + "'") || - parseToken(AsmToken::Comma, "unexpected token in '" + Twine(IDVal) + "'")) - return true; - - return parseAssignment(Name, allow_redef, true); + if (check(parseIdentifier(Name), "expected identifier") || + parseToken(AsmToken::Comma) || parseAssignment(Name, allow_redef, true)) + return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); + return false; } bool AsmParser::parseEscapedString(std::string &Data) { - assert(getLexer().is(AsmToken::String) && "Unexpected current token!"); + if (check(getTok().isNot(AsmToken::String), "expected string")) + return true; Data = ""; StringRef Str = getTok().getStringContents(); @@ -2548,30 +2714,18 @@ bool AsmParser::parseEscapedString(std::string &Data) { /// parseDirectiveAscii: /// ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ] bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) { - if (getLexer().isNot(AsmToken::EndOfStatement)) { - checkForValidSection(); - - for (;;) { - std::string Data; - if (check(getTok().isNot(AsmToken::String), - "expected string in '" + Twine(IDVal) + "' directive") || - parseEscapedString(Data)) - return true; - - getStreamer().EmitBytes(Data); - if (ZeroTerminated) - getStreamer().EmitBytes(StringRef("\0", 1)); - - if (getLexer().is(AsmToken::EndOfStatement)) - break; - - if (parseToken(AsmToken::Comma, - "unexpected token in '" + Twine(IDVal) + "' directive")) - return true; - } - } + auto parseOp = [&]() -> bool { + std::string Data; + if (checkForValidSection() || parseEscapedString(Data)) + return true; + getStreamer().EmitBytes(Data); + if (ZeroTerminated) + getStreamer().EmitBytes(StringRef("\0", 1)); + return false; + }; - Lex(); + if (parseMany(parseOp)) + return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); return false; } @@ -2582,11 +2736,12 @@ bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) { const MCExpr *Expr = nullptr; SMLoc OffsetLoc = Lexer.getTok().getLoc(); + int64_t OffsetValue; + // We can only deal with constant expressions at the moment. + if (parseExpression(Offset)) return true; - // We can only deal with constant expressions at the moment. - int64_t OffsetValue; if (check(!Offset->evaluateAsAbsolute(OffsetValue), OffsetLoc, "expression is not a constant value") || check(OffsetValue < 0, OffsetLoc, "expression is negative") || @@ -2610,162 +2765,141 @@ bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) { } if (parseToken(AsmToken::EndOfStatement, - "unexpected token in .reloc directive") || - check(getStreamer().EmitRelocDirective(*Offset, Name, Expr, DirectiveLoc), - NameLoc, "unknown relocation name")) - return true; + "unexpected token in .reloc directive")) + return true; + + if (getStreamer().EmitRelocDirective(*Offset, Name, Expr, DirectiveLoc)) + return Error(NameLoc, "unknown relocation name"); + return false; } /// parseDirectiveValue /// ::= (.byte | .short | ... ) [ expression (, expression)* ] -bool AsmParser::parseDirectiveValue(unsigned Size) { - if (getLexer().isNot(AsmToken::EndOfStatement)) { - checkForValidSection(); - - for (;;) { - const MCExpr *Value; - SMLoc ExprLoc = getLexer().getLoc(); - if (parseExpression(Value)) - return true; - - // Special case constant expressions to match code generator. - if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { - assert(Size <= 8 && "Invalid size"); - uint64_t IntValue = MCE->getValue(); - if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue)) - return Error(ExprLoc, "literal value out of range for directive"); - getStreamer().EmitIntValue(IntValue, Size); - } else - getStreamer().EmitValue(Value, Size, ExprLoc); - - if (getLexer().is(AsmToken::EndOfStatement)) - break; - - // FIXME: Improve diagnostic. - if (parseToken(AsmToken::Comma, "unexpected token in directive")) - return true; - } - } +bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) { + auto parseOp = [&]() -> bool { + const MCExpr *Value; + SMLoc ExprLoc = getLexer().getLoc(); + if (checkForValidSection() || parseExpression(Value)) + return true; + // Special case constant expressions to match code generator. + if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { + assert(Size <= 8 && "Invalid size"); + uint64_t IntValue = MCE->getValue(); + if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue)) + return Error(ExprLoc, "out of range literal value"); + getStreamer().EmitIntValue(IntValue, Size); + } else + getStreamer().EmitValue(Value, Size, ExprLoc); + return false; + }; - Lex(); + if (parseMany(parseOp)) + return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); return false; } /// ParseDirectiveOctaValue /// ::= .octa [ hexconstant (, hexconstant)* ] -bool AsmParser::parseDirectiveOctaValue() { - if (getLexer().isNot(AsmToken::EndOfStatement)) { - checkForValidSection(); - - for (;;) { - if (getTok().is(AsmToken::Error)) - return true; - if (getTok().isNot(AsmToken::Integer) && getTok().isNot(AsmToken::BigNum)) - return TokError("unknown token in expression"); - SMLoc ExprLoc = getLexer().getLoc(); - APInt IntValue = getTok().getAPIntVal(); - Lex(); +bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) { + auto parseOp = [&]() -> bool { + if (checkForValidSection()) + return true; + if (getTok().isNot(AsmToken::Integer) && getTok().isNot(AsmToken::BigNum)) + return TokError("unknown token in expression"); + SMLoc ExprLoc = getTok().getLoc(); + APInt IntValue = getTok().getAPIntVal(); + uint64_t hi, lo; + Lex(); + if (!IntValue.isIntN(128)) + return Error(ExprLoc, "out of range literal value"); + if (!IntValue.isIntN(64)) { + hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue(); + lo = IntValue.getLoBits(64).getZExtValue(); + } else { + hi = 0; + lo = IntValue.getZExtValue(); + } + if (MAI.isLittleEndian()) { + getStreamer().EmitIntValue(lo, 8); + getStreamer().EmitIntValue(hi, 8); + } else { + getStreamer().EmitIntValue(hi, 8); + getStreamer().EmitIntValue(lo, 8); + } + return false; + }; - uint64_t hi, lo; - if (IntValue.isIntN(64)) { - hi = 0; - lo = IntValue.getZExtValue(); - } else if (IntValue.isIntN(128)) { - // It might actually have more than 128 bits, but the top ones are zero. - hi = IntValue.getHiBits(IntValue.getBitWidth() - 64).getZExtValue(); - lo = IntValue.getLoBits(64).getZExtValue(); - } else - return Error(ExprLoc, "literal value out of range for directive"); - - if (MAI.isLittleEndian()) { - getStreamer().EmitIntValue(lo, 8); - getStreamer().EmitIntValue(hi, 8); - } else { - getStreamer().EmitIntValue(hi, 8); - getStreamer().EmitIntValue(lo, 8); - } + if (parseMany(parseOp)) + return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); + return false; +} - if (getLexer().is(AsmToken::EndOfStatement)) - break; +bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) { + // We don't truly support arithmetic on floating point expressions, so we + // have to manually parse unary prefixes. + bool IsNeg = false; + if (getLexer().is(AsmToken::Minus)) { + Lexer.Lex(); + IsNeg = true; + } else if (getLexer().is(AsmToken::Plus)) + Lexer.Lex(); - // FIXME: Improve diagnostic. - if (parseToken(AsmToken::Comma, "unexpected token in directive")) - return true; - } - } + if (Lexer.is(AsmToken::Error)) + return TokError(Lexer.getErr()); + if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) && + Lexer.isNot(AsmToken::Identifier)) + return TokError("unexpected token in directive"); + // Convert to an APFloat. + APFloat Value(Semantics); + StringRef IDVal = getTok().getString(); + if (getLexer().is(AsmToken::Identifier)) { + if (!IDVal.compare_lower("infinity") || !IDVal.compare_lower("inf")) + Value = APFloat::getInf(Semantics); + else if (!IDVal.compare_lower("nan")) + Value = APFloat::getNaN(Semantics, false, ~0); + else + return TokError("invalid floating point literal"); + } else if (Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) == + APFloat::opInvalidOp) + return TokError("invalid floating point literal"); + if (IsNeg) + Value.changeSign(); + + // Consume the numeric token. Lex(); + + Res = Value.bitcastToAPInt(); + return false; } /// parseDirectiveRealValue /// ::= (.single | .double) [ expression (, expression)* ] -bool AsmParser::parseDirectiveRealValue(const fltSemantics &Semantics) { - if (getLexer().isNot(AsmToken::EndOfStatement)) { - checkForValidSection(); - - for (;;) { - // We don't truly support arithmetic on floating point expressions, so we - // have to manually parse unary prefixes. - bool IsNeg = false; - if (getLexer().is(AsmToken::Minus)) { - Lexer.Lex(); - IsNeg = true; - } else if (getLexer().is(AsmToken::Plus)) - Lexer.Lex(); - - if (Lexer.is(AsmToken::Error)) - return TokError(Lexer.getErr()); - if (Lexer.isNot(AsmToken::Integer) && Lexer.isNot(AsmToken::Real) && - Lexer.isNot(AsmToken::Identifier)) - return TokError("unexpected token in directive"); - - // Convert to an APFloat. - APFloat Value(Semantics); - StringRef IDVal = getTok().getString(); - if (getLexer().is(AsmToken::Identifier)) { - if (!IDVal.compare_lower("infinity") || !IDVal.compare_lower("inf")) - Value = APFloat::getInf(Semantics); - else if (!IDVal.compare_lower("nan")) - Value = APFloat::getNaN(Semantics, false, ~0); - else - return TokError("invalid floating point literal"); - } else if (Value.convertFromString(IDVal, APFloat::rmNearestTiesToEven) == - APFloat::opInvalidOp) - return TokError("invalid floating point literal"); - if (IsNeg) - Value.changeSign(); - - // Consume the numeric token. - Lex(); - - // Emit the value as an integer. - APInt AsInt = Value.bitcastToAPInt(); - getStreamer().EmitIntValue(AsInt.getLimitedValue(), - AsInt.getBitWidth() / 8); - - if (Lexer.is(AsmToken::EndOfStatement)) - break; - - if (parseToken(AsmToken::Comma, "unexpected token in directive")) - return true; - } - } +bool AsmParser::parseDirectiveRealValue(StringRef IDVal, + const fltSemantics &Semantics) { + auto parseOp = [&]() -> bool { + APInt AsInt; + if (checkForValidSection() || parseRealValue(Semantics, AsInt)) + return true; + getStreamer().EmitIntValue(AsInt.getLimitedValue(), + AsInt.getBitWidth() / 8); + return false; + }; - Lex(); + if (parseMany(parseOp)) + return addErrorSuffix(" in '" + Twine(IDVal) + "' directive"); return false; } /// parseDirectiveZero /// ::= .zero expression bool AsmParser::parseDirectiveZero() { - checkForValidSection(); - SMLoc NumBytesLoc = Lexer.getLoc(); const MCExpr *NumBytes; - if (parseExpression(NumBytes)) + if (checkForValidSection() || parseExpression(NumBytes)) return true; int64_t Val = 0; @@ -2786,32 +2920,29 @@ bool AsmParser::parseDirectiveZero() { /// parseDirectiveFill /// ::= .fill expression [ , expression [ , expression ] ] bool AsmParser::parseDirectiveFill() { - checkForValidSection(); - SMLoc NumValuesLoc = Lexer.getLoc(); const MCExpr *NumValues; - if (parseExpression(NumValues)) + if (checkForValidSection() || parseExpression(NumValues)) return true; int64_t FillSize = 1; int64_t FillExpr = 0; SMLoc SizeLoc, ExprLoc; - if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (parseToken(AsmToken::Comma, "unexpected token in '.fill' directive") || - getTokenLoc(SizeLoc) || parseAbsoluteExpression(FillSize)) + if (parseOptionalToken(AsmToken::Comma)) { + SizeLoc = getTok().getLoc(); + if (parseAbsoluteExpression(FillSize)) return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (parseToken(AsmToken::Comma, - "unexpected token in '.fill' directive") || - getTokenLoc(ExprLoc) || parseAbsoluteExpression(FillExpr) || - parseToken(AsmToken::EndOfStatement, - "unexpected token in '.fill' directive")) + if (parseOptionalToken(AsmToken::Comma)) { + ExprLoc = getTok().getLoc(); + if (parseAbsoluteExpression(FillExpr)) return true; } } + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.fill' directive")) + return true; if (FillSize < 0) { Warning(SizeLoc, "'.fill' directive with negative size has no effect"); @@ -2833,73 +2964,64 @@ bool AsmParser::parseDirectiveFill() { /// parseDirectiveOrg /// ::= .org expression [ , expression ] bool AsmParser::parseDirectiveOrg() { - checkForValidSection(); - const MCExpr *Offset; - if (parseExpression(Offset)) + SMLoc OffsetLoc = Lexer.getLoc(); + if (checkForValidSection() || parseExpression(Offset)) return true; // Parse optional fill expression. int64_t FillExpr = 0; - if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (parseToken(AsmToken::Comma, "unexpected token in '.org' directive") || - parseAbsoluteExpression(FillExpr)) - return true; - } + if (parseOptionalToken(AsmToken::Comma)) + if (parseAbsoluteExpression(FillExpr)) + return addErrorSuffix(" in '.org' directive"); + if (parseToken(AsmToken::EndOfStatement)) + return addErrorSuffix(" in '.org' directive"); - if (parseToken(AsmToken::EndOfStatement, - "unexpected token in '.org' directive")) - return true; - - getStreamer().emitValueToOffset(Offset, FillExpr); + getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc); return false; } /// parseDirectiveAlign /// ::= {.align, ...} expression [ , expression [ , expression ]] bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) { - checkForValidSection(); - SMLoc AlignmentLoc = getLexer().getLoc(); int64_t Alignment; - if (parseAbsoluteExpression(Alignment)) - return true; - SMLoc MaxBytesLoc; bool HasFillExpr = false; int64_t FillExpr = 0; int64_t MaxBytesToFill = 0; - if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (parseToken(AsmToken::Comma, "unexpected token in directive")) - return true; - - // The fill expression can be omitted while specifying a maximum number of - // alignment bytes, e.g: - // .align 3,,4 - if (getTok().isNot(AsmToken::Comma)) { - HasFillExpr = true; - if (parseAbsoluteExpression(FillExpr)) - return true; - } - if (getTok().isNot(AsmToken::EndOfStatement)) { - if (parseToken(AsmToken::Comma, "unexpected token in directive") || - getTokenLoc(MaxBytesLoc) || parseAbsoluteExpression(MaxBytesToFill)) - return true; + auto parseAlign = [&]() -> bool { + if (checkForValidSection() || parseAbsoluteExpression(Alignment)) + return true; + if (parseOptionalToken(AsmToken::Comma)) { + // The fill expression can be omitted while specifying a maximum number of + // alignment bytes, e.g: + // .align 3,,4 + if (getTok().isNot(AsmToken::Comma)) { + HasFillExpr = true; + if (parseAbsoluteExpression(FillExpr)) + return true; + } + if (parseOptionalToken(AsmToken::Comma)) + if (parseTokenLoc(MaxBytesLoc) || + parseAbsoluteExpression(MaxBytesToFill)) + return true; } - } + return parseToken(AsmToken::EndOfStatement); + }; - if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive")) - return true; + if (parseAlign()) + return addErrorSuffix(" in directive"); - if (!HasFillExpr) - FillExpr = 0; + // Always emit an alignment here even if we thrown an error. + bool ReturnVal = false; // Compute alignment in bytes. if (IsPow2) { // FIXME: Diagnose overflow. if (Alignment >= 32) { - Error(AlignmentLoc, "invalid alignment value"); + ReturnVal |= Error(AlignmentLoc, "invalid alignment value"); Alignment = 31; } @@ -2911,13 +3033,14 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) { if (Alignment == 0) Alignment = 1; if (!isPowerOf2_64(Alignment)) - Error(AlignmentLoc, "alignment must be a power of 2"); + ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2"); } // Diagnose non-sensical max bytes to align. if (MaxBytesLoc.isValid()) { if (MaxBytesToFill < 1) { - Error(MaxBytesLoc, "alignment directive can never be satisfied in this " + ReturnVal |= Error(MaxBytesLoc, + "alignment directive can never be satisfied in this " "many bytes, ignoring maximum bytes expression"); MaxBytesToFill = 0; } @@ -2931,7 +3054,7 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) { // Check whether we should use optimal code alignment for this .align // directive. - const MCSection *Section = getStreamer().getCurrentSection().first; + const MCSection *Section = getStreamer().getCurrentSectionOnly(); assert(Section && "must have section to emit alignment"); bool UseCodeAlign = Section->UseCodeAlign(); if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) && @@ -2943,7 +3066,7 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) { MaxBytesToFill); } - return false; + return ReturnVal; } /// parseDirectiveFile @@ -2997,7 +3120,7 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) { getContext().setGenDwarfForAssembly(false); else if (getStreamer().EmitDwarfFileDirective(FileNumber, Directory, Filename) == 0) - Error(FileNumberLoc, "file number already allocated"); + return Error(FileNumberLoc, "file number already allocated"); } return false; @@ -3007,7 +3130,7 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) { /// ::= .line [number] bool AsmParser::parseDirectiveLine() { int64_t LineNumber; - if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getLexer().is(AsmToken::Integer)) { if (parseIntToken(LineNumber, "unexpected token in '.line' directive")) return true; (void)LineNumber; @@ -3056,65 +3179,61 @@ bool AsmParser::parseDirectiveLoc() { unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; unsigned Isa = 0; int64_t Discriminator = 0; - if (getLexer().isNot(AsmToken::EndOfStatement)) { - for (;;) { - if (getLexer().is(AsmToken::EndOfStatement)) - break; - StringRef Name; - SMLoc Loc = getTok().getLoc(); - if (parseIdentifier(Name)) - return TokError("unexpected token in '.loc' directive"); - - if (Name == "basic_block") - Flags |= DWARF2_FLAG_BASIC_BLOCK; - else if (Name == "prologue_end") - Flags |= DWARF2_FLAG_PROLOGUE_END; - else if (Name == "epilogue_begin") - Flags |= DWARF2_FLAG_EPILOGUE_BEGIN; - else if (Name == "is_stmt") { - Loc = getTok().getLoc(); - const MCExpr *Value; - if (parseExpression(Value)) - return true; - // The expression must be the constant 0 or 1. - if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { - int Value = MCE->getValue(); - if (Value == 0) - Flags &= ~DWARF2_FLAG_IS_STMT; - else if (Value == 1) - Flags |= DWARF2_FLAG_IS_STMT; - else - return Error(Loc, "is_stmt value not 0 or 1"); - } else { - return Error(Loc, "is_stmt value not the constant value of 0 or 1"); - } - } else if (Name == "isa") { - Loc = getTok().getLoc(); - const MCExpr *Value; - if (parseExpression(Value)) - return true; - // The expression must be a constant greater or equal to 0. - if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { - int Value = MCE->getValue(); - if (Value < 0) - return Error(Loc, "isa number less than zero"); - Isa = Value; - } else { - return Error(Loc, "isa number not a constant value"); - } - } else if (Name == "discriminator") { - if (parseAbsoluteExpression(Discriminator)) - return true; + auto parseLocOp = [&]() -> bool { + StringRef Name; + SMLoc Loc = getTok().getLoc(); + if (parseIdentifier(Name)) + return TokError("unexpected token in '.loc' directive"); + + if (Name == "basic_block") + Flags |= DWARF2_FLAG_BASIC_BLOCK; + else if (Name == "prologue_end") + Flags |= DWARF2_FLAG_PROLOGUE_END; + else if (Name == "epilogue_begin") + Flags |= DWARF2_FLAG_EPILOGUE_BEGIN; + else if (Name == "is_stmt") { + Loc = getTok().getLoc(); + const MCExpr *Value; + if (parseExpression(Value)) + return true; + // The expression must be the constant 0 or 1. + if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { + int Value = MCE->getValue(); + if (Value == 0) + Flags &= ~DWARF2_FLAG_IS_STMT; + else if (Value == 1) + Flags |= DWARF2_FLAG_IS_STMT; + else + return Error(Loc, "is_stmt value not 0 or 1"); } else { - return Error(Loc, "unknown sub-directive in '.loc' directive"); + return Error(Loc, "is_stmt value not the constant value of 0 or 1"); } - - if (getLexer().is(AsmToken::EndOfStatement)) - break; + } else if (Name == "isa") { + Loc = getTok().getLoc(); + const MCExpr *Value; + if (parseExpression(Value)) + return true; + // The expression must be a constant greater or equal to 0. + if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { + int Value = MCE->getValue(); + if (Value < 0) + return Error(Loc, "isa number less than zero"); + Isa = Value; + } else { + return Error(Loc, "isa number not a constant value"); + } + } else if (Name == "discriminator") { + if (parseAbsoluteExpression(Discriminator)) + return true; + } else { + return Error(Loc, "unknown sub-directive in '.loc' directive"); } - } - Lex(); + return false; + }; + + if (parseMany(parseLocOp, false /*hasComma*/)) + return true; getStreamer().EmitDwarfLocDirective(FileNumber, LineNumber, ColumnPos, Flags, Isa, Discriminator, StringRef()); @@ -3144,11 +3263,113 @@ bool AsmParser::parseDirectiveCVFile() { // directory. Allow the strings to have escaped octal character sequence. parseEscapedString(Filename) || parseToken(AsmToken::EndOfStatement, - "unexpected token in '.cv_file' directive") || - check(getStreamer().EmitCVFileDirective(FileNumber, Filename) == 0, - FileNumberLoc, "file number already allocated")) + "unexpected token in '.cv_file' directive")) return true; + if (!getStreamer().EmitCVFileDirective(FileNumber, Filename)) + return Error(FileNumberLoc, "file number already allocated"); + + return false; +} + +bool AsmParser::parseCVFunctionId(int64_t &FunctionId, + StringRef DirectiveName) { + SMLoc Loc; + return parseTokenLoc(Loc) || + parseIntToken(FunctionId, "expected function id in '" + DirectiveName + + "' directive") || + check(FunctionId < 0 || FunctionId >= UINT_MAX, Loc, + "expected function id within range [0, UINT_MAX)"); +} + +bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) { + SMLoc Loc; + return parseTokenLoc(Loc) || + parseIntToken(FileNumber, "expected integer in '" + DirectiveName + + "' directive") || + check(FileNumber < 1, Loc, "file number less than one in '" + + DirectiveName + "' directive") || + check(!getCVContext().isValidFileNumber(FileNumber), Loc, + "unassigned file number in '" + DirectiveName + "' directive"); +} + +/// parseDirectiveCVFuncId +/// ::= .cv_func_id FunctionId +/// +/// Introduces a function ID that can be used with .cv_loc. +bool AsmParser::parseDirectiveCVFuncId() { + SMLoc FunctionIdLoc = getTok().getLoc(); + int64_t FunctionId; + + if (parseCVFunctionId(FunctionId, ".cv_func_id") || + parseToken(AsmToken::EndOfStatement, + "unexpected token in '.cv_func_id' directive")) + return true; + + if (!getStreamer().EmitCVFuncIdDirective(FunctionId)) + return Error(FunctionIdLoc, "function id already allocated"); + + return false; +} + +/// parseDirectiveCVInlineSiteId +/// ::= .cv_inline_site_id FunctionId +/// "within" IAFunc +/// "inlined_at" IAFile IALine [IACol] +/// +/// Introduces a function ID that can be used with .cv_loc. Includes "inlined +/// at" source location information for use in the line table of the caller, +/// whether the caller is a real function or another inlined call site. +bool AsmParser::parseDirectiveCVInlineSiteId() { + SMLoc FunctionIdLoc = getTok().getLoc(); + int64_t FunctionId; + int64_t IAFunc; + int64_t IAFile; + int64_t IALine; + int64_t IACol = 0; + + // FunctionId + if (parseCVFunctionId(FunctionId, ".cv_inline_site_id")) + return true; + + // "within" + if (check((getLexer().isNot(AsmToken::Identifier) || + getTok().getIdentifier() != "within"), + "expected 'within' identifier in '.cv_inline_site_id' directive")) + return true; + Lex(); + + // IAFunc + if (parseCVFunctionId(IAFunc, ".cv_inline_site_id")) + return true; + + // "inlined_at" + if (check((getLexer().isNot(AsmToken::Identifier) || + getTok().getIdentifier() != "inlined_at"), + "expected 'inlined_at' identifier in '.cv_inline_site_id' " + "directive") ) + return true; + Lex(); + + // IAFile IALine + if (parseCVFileId(IAFile, ".cv_inline_site_id") || + parseIntToken(IALine, "expected line number after 'inlined_at'")) + return true; + + // [IACol] + if (getLexer().is(AsmToken::Integer)) { + IACol = getTok().getIntVal(); + Lex(); + } + + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.cv_inline_site_id' directive")) + return true; + + if (!getStreamer().EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile, + IALine, IACol, FunctionIdLoc)) + return Error(FunctionIdLoc, "function id already allocated"); + return false; } @@ -3160,18 +3381,11 @@ bool AsmParser::parseDirectiveCVFile() { /// third number is a column position (zero if not specified). The remaining /// optional items are .loc sub-directives. bool AsmParser::parseDirectiveCVLoc() { + SMLoc DirectiveLoc = getTok().getLoc(); SMLoc Loc; int64_t FunctionId, FileNumber; - if (getTokenLoc(Loc) || - parseIntToken(FunctionId, "unexpected token in '.cv_loc' directive") || - check(FunctionId < 0, Loc, - "function id less than zero in '.cv_loc' directive") || - getTokenLoc(Loc) || - parseIntToken(FileNumber, "expected integer in '.cv_loc' directive") || - check(FileNumber < 1, Loc, - "file number less than one in '.cv_loc' directive") || - check(!getContext().isValidCVFileNumber(FileNumber), Loc, - "unassigned file number in '.cv_loc' directive")) + if (parseCVFunctionId(FunctionId, ".cv_loc") || + parseCVFileId(FileNumber, ".cv_loc")) return true; int64_t LineNumber = 0; @@ -3192,12 +3406,12 @@ bool AsmParser::parseDirectiveCVLoc() { bool PrologueEnd = false; uint64_t IsStmt = 0; - while (getLexer().isNot(AsmToken::EndOfStatement)) { + + auto parseOp = [&]() -> bool { StringRef Name; SMLoc Loc = getTok().getLoc(); if (parseIdentifier(Name)) return TokError("unexpected token in '.cv_loc' directive"); - if (Name == "prologue_end") PrologueEnd = true; else if (Name == "is_stmt") { @@ -3215,11 +3429,15 @@ bool AsmParser::parseDirectiveCVLoc() { } else { return Error(Loc, "unknown sub-directive in '.cv_loc' directive"); } - } - Lex(); + return false; + }; + + if (parseMany(parseOp, false /*hasComma*/)) + return true; getStreamer().EmitCVLocDirective(FunctionId, FileNumber, LineNumber, - ColumnPos, PrologueEnd, IsStmt, StringRef()); + ColumnPos, PrologueEnd, IsStmt, StringRef(), + DirectiveLoc); return false; } @@ -3229,18 +3447,15 @@ bool AsmParser::parseDirectiveCVLinetable() { int64_t FunctionId; StringRef FnStartName, FnEndName; SMLoc Loc = getTok().getLoc(); - if (parseIntToken(FunctionId, - "expected Integer in '.cv_linetable' directive") || - check(FunctionId < 0, Loc, - "function id less than zero in '.cv_linetable' directive") || + if (parseCVFunctionId(FunctionId, ".cv_linetable") || parseToken(AsmToken::Comma, "unexpected token in '.cv_linetable' directive") || - getTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc, - "expected identifier in directive") || + parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc, + "expected identifier in directive") || parseToken(AsmToken::Comma, "unexpected token in '.cv_linetable' directive") || - getTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc, - "expected identifier in directive")) + parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc, + "expected identifier in directive")) return true; MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName); @@ -3252,52 +3467,29 @@ bool AsmParser::parseDirectiveCVLinetable() { /// parseDirectiveCVInlineLinetable /// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd -/// ("contains" SecondaryFunctionId+)? bool AsmParser::parseDirectiveCVInlineLinetable() { int64_t PrimaryFunctionId, SourceFileId, SourceLineNum; StringRef FnStartName, FnEndName; SMLoc Loc = getTok().getLoc(); - if (parseIntToken( - PrimaryFunctionId, - "expected PrimaryFunctionId in '.cv_inline_linetable' directive") || - check(PrimaryFunctionId < 0, Loc, - "function id less than zero in '.cv_inline_linetable' directive") || - getTokenLoc(Loc) || + if (parseCVFunctionId(PrimaryFunctionId, ".cv_inline_linetable") || + parseTokenLoc(Loc) || parseIntToken( SourceFileId, "expected SourceField in '.cv_inline_linetable' directive") || check(SourceFileId <= 0, Loc, "File id less than zero in '.cv_inline_linetable' directive") || - getTokenLoc(Loc) || + parseTokenLoc(Loc) || parseIntToken( SourceLineNum, "expected SourceLineNum in '.cv_inline_linetable' directive") || check(SourceLineNum < 0, Loc, "Line number less than zero in '.cv_inline_linetable' directive") || - getTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc, - "expected identifier in directive") || - getTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc, - "expected identifier in directive")) + parseTokenLoc(Loc) || check(parseIdentifier(FnStartName), Loc, + "expected identifier in directive") || + parseTokenLoc(Loc) || check(parseIdentifier(FnEndName), Loc, + "expected identifier in directive")) return true; - SmallVector<unsigned, 8> SecondaryFunctionIds; - if (getLexer().is(AsmToken::Identifier)) { - if (getTok().getIdentifier() != "contains") - return TokError( - "unexpected identifier in '.cv_inline_linetable' directive"); - Lex(); - - while (getLexer().isNot(AsmToken::EndOfStatement)) { - int64_t SecondaryFunctionId = getTok().getIntVal(); - if (SecondaryFunctionId < 0) - return TokError( - "function id less than zero in '.cv_inline_linetable' directive"); - Lex(); - - SecondaryFunctionIds.push_back(SecondaryFunctionId); - } - } - if (parseToken(AsmToken::EndOfStatement, "Expected End of Statement")) return true; @@ -3305,7 +3497,7 @@ bool AsmParser::parseDirectiveCVInlineLinetable() { MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName); getStreamer().EmitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, - FnEndSym, SecondaryFunctionIds); + FnEndSym); return false; } @@ -3388,12 +3580,12 @@ bool AsmParser::parseDirectiveCFISections() { /// ::= .cfi_startproc [simple] bool AsmParser::parseDirectiveCFIStartProc() { StringRef Simple; - if (getLexer().isNot(AsmToken::EndOfStatement)) - if (parseIdentifier(Simple) || Simple != "simple") - return TokError("unexpected token in .cfi_startproc directive"); - - if (parseToken(AsmToken::EndOfStatement, "Expected end of statement")) - return true; + if (!parseOptionalToken(AsmToken::EndOfStatement)) { + if (check(parseIdentifier(Simple) || Simple != "simple", + "unexpected token") || + parseToken(AsmToken::EndOfStatement)) + return addErrorSuffix(" in '.cfi_startproc' directive"); + } getStreamer().EmitCFIStartProc(!Simple.empty()); return false; @@ -3728,7 +3920,7 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { AsmToken EndToken, StartToken = getTok(); unsigned MacroDepth = 0; // Lex the macro definition. - for (;;) { + while (true) { // Ignore Lexing errors in macros. while (Lexer.is(AsmToken::Error)) { Lexer.Lex(); @@ -3924,14 +4116,16 @@ bool AsmParser::parseDirectiveEndMacro(StringRef Directive) { bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) { StringRef Name; SMLoc Loc; - if (getTokenLoc(Loc) || check(parseIdentifier(Name), Loc, - "expected identifier in '.purgem' directive") || + if (parseTokenLoc(Loc) || + check(parseIdentifier(Name), Loc, + "expected identifier in '.purgem' directive") || parseToken(AsmToken::EndOfStatement, - "unexpected token in '.purgem' directive") || - check(!lookupMacro(Name), DirectiveLoc, - "macro '" + Name + "' is not defined")) + "unexpected token in '.purgem' directive")) return true; + if (!lookupMacro(Name)) + return Error(DirectiveLoc, "macro '" + Name + "' is not defined"); + undefineMacro(Name); return false; } @@ -3939,13 +4133,11 @@ bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) { /// parseDirectiveBundleAlignMode /// ::= {.bundle_align_mode} expression bool AsmParser::parseDirectiveBundleAlignMode() { - checkForValidSection(); - // Expect a single argument: an expression that evaluates to a constant // in the inclusive range 0-30. SMLoc ExprLoc = getLexer().getLoc(); int64_t AlignSizePow2; - if (parseAbsoluteExpression(AlignSizePow2) || + if (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) || parseToken(AsmToken::EndOfStatement, "unexpected token after expression " "in '.bundle_align_mode' " "directive") || @@ -3962,25 +4154,24 @@ bool AsmParser::parseDirectiveBundleAlignMode() { /// parseDirectiveBundleLock /// ::= {.bundle_lock} [align_to_end] bool AsmParser::parseDirectiveBundleLock() { - checkForValidSection(); + if (checkForValidSection()) + return true; bool AlignToEnd = false; - if (getLexer().isNot(AsmToken::EndOfStatement)) { - StringRef Option; - SMLoc Loc = getTok().getLoc(); - const char *kInvalidOptionError = - "invalid option for '.bundle_lock' directive"; + StringRef Option; + SMLoc Loc = getTok().getLoc(); + const char *kInvalidOptionError = + "invalid option for '.bundle_lock' directive"; + if (!parseOptionalToken(AsmToken::EndOfStatement)) { if (check(parseIdentifier(Option), Loc, kInvalidOptionError) || check(Option != "align_to_end", Loc, kInvalidOptionError) || - check(getTok().isNot(AsmToken::EndOfStatement), Loc, - "unexpected token after '.bundle_lock' directive option")) + parseToken(AsmToken::EndOfStatement, + "unexpected token after '.bundle_lock' directive option")) return true; AlignToEnd = true; } - Lex(); - getStreamer().EmitBundleLock(AlignToEnd); return false; } @@ -3988,9 +4179,8 @@ bool AsmParser::parseDirectiveBundleLock() { /// parseDirectiveBundleLock /// ::= {.bundle_lock} bool AsmParser::parseDirectiveBundleUnlock() { - checkForValidSection(); - - if (parseToken(AsmToken::EndOfStatement, + if (checkForValidSection() || + parseToken(AsmToken::EndOfStatement, "unexpected token in '.bundle_unlock' directive")) return true; @@ -4001,28 +4191,119 @@ bool AsmParser::parseDirectiveBundleUnlock() { /// parseDirectiveSpace /// ::= (.skip | .space) expression [ , expression ] bool AsmParser::parseDirectiveSpace(StringRef IDVal) { - checkForValidSection(); SMLoc NumBytesLoc = Lexer.getLoc(); const MCExpr *NumBytes; - if (parseExpression(NumBytes)) + if (checkForValidSection() || parseExpression(NumBytes)) return true; int64_t FillExpr = 0; - if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (parseOptionalToken(AsmToken::Comma)) + if (parseAbsoluteExpression(FillExpr)) + return addErrorSuffix("in '" + Twine(IDVal) + "' directive"); + if (parseToken(AsmToken::EndOfStatement)) + return addErrorSuffix("in '" + Twine(IDVal) + "' directive"); - if (parseToken(AsmToken::Comma, - "unexpected token in '" + Twine(IDVal) + "' directive") || - parseAbsoluteExpression(FillExpr)) - return true; + // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0. + getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc); + + return false; +} + +/// parseDirectiveDCB +/// ::= .dcb.{b, l, w} expression, expression +bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) { + SMLoc NumValuesLoc = Lexer.getLoc(); + int64_t NumValues; + if (checkForValidSection() || parseAbsoluteExpression(NumValues)) + return true; + + if (NumValues < 0) { + Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect"); + return false; + } + + if (parseToken(AsmToken::Comma, + "unexpected token in '" + Twine(IDVal) + "' directive")) + return true; + + const MCExpr *Value; + SMLoc ExprLoc = getLexer().getLoc(); + if (parseExpression(Value)) + return true; + + // Special case constant expressions to match code generator. + if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { + assert(Size <= 8 && "Invalid size"); + uint64_t IntValue = MCE->getValue(); + if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue)) + return Error(ExprLoc, "literal value out of range for directive"); + for (uint64_t i = 0, e = NumValues; i != e; ++i) + getStreamer().EmitIntValue(IntValue, Size); + } else { + for (uint64_t i = 0, e = NumValues; i != e; ++i) + getStreamer().EmitValue(Value, Size, ExprLoc); } if (parseToken(AsmToken::EndOfStatement, "unexpected token in '" + Twine(IDVal) + "' directive")) return true; - // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0. - getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc); + return false; +} + +/// parseDirectiveRealDCB +/// ::= .dcb.{d, s} expression, expression +bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) { + SMLoc NumValuesLoc = Lexer.getLoc(); + int64_t NumValues; + if (checkForValidSection() || parseAbsoluteExpression(NumValues)) + return true; + + if (NumValues < 0) { + Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect"); + return false; + } + + if (parseToken(AsmToken::Comma, + "unexpected token in '" + Twine(IDVal) + "' directive")) + return true; + + APInt AsInt; + if (parseRealValue(Semantics, AsInt)) + return true; + + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '" + Twine(IDVal) + "' directive")) + return true; + + for (uint64_t i = 0, e = NumValues; i != e; ++i) + getStreamer().EmitIntValue(AsInt.getLimitedValue(), + AsInt.getBitWidth() / 8); + + return false; +} + +/// parseDirectiveDS +/// ::= .ds.{b, d, l, p, s, w, x} expression +bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) { + + SMLoc NumValuesLoc = Lexer.getLoc(); + int64_t NumValues; + if (checkForValidSection() || parseAbsoluteExpression(NumValues)) + return true; + + if (NumValues < 0) { + Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect"); + return false; + } + + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '" + Twine(IDVal) + "' directive")) + return true; + + for (uint64_t i = 0, e = NumValues; i != e; ++i) + getStreamer().emitFill(Size, 0); return false; } @@ -4030,25 +4311,22 @@ bool AsmParser::parseDirectiveSpace(StringRef IDVal) { /// parseDirectiveLEB128 /// ::= (.sleb128 | .uleb128) [ expression (, expression)* ] bool AsmParser::parseDirectiveLEB128(bool Signed) { - checkForValidSection(); - const MCExpr *Value; + if (checkForValidSection()) + return true; - for (;;) { + auto parseOp = [&]() -> bool { + const MCExpr *Value; if (parseExpression(Value)) return true; - if (Signed) getStreamer().EmitSLEB128Value(Value); else getStreamer().EmitULEB128Value(Value); + return false; + }; - if (getLexer().is(AsmToken::EndOfStatement)) - break; - - if (parseToken(AsmToken::Comma, "unexpected token in directive")) - return true; - } - Lex(); + if (parseMany(parseOp)) + return addErrorSuffix(" in directive"); return false; } @@ -4056,39 +4334,32 @@ bool AsmParser::parseDirectiveLEB128(bool Signed) { /// parseDirectiveSymbolAttribute /// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) { - if (getLexer().isNot(AsmToken::EndOfStatement)) { - for (;;) { - StringRef Name; - SMLoc Loc = getTok().getLoc(); - - if (parseIdentifier(Name)) - 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"); - - if (!getStreamer().EmitSymbolAttribute(Sym, Attr)) - return Error(Loc, "unable to emit symbol attribute"); + auto parseOp = [&]() -> bool { + StringRef Name; + SMLoc Loc = getTok().getLoc(); + if (parseIdentifier(Name)) + return Error(Loc, "expected identifier"); + MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - if (getLexer().is(AsmToken::EndOfStatement)) - break; + // Assembler local symbols don't make any sense here. Complain loudly. + if (Sym->isTemporary()) + return Error(Loc, "non-local symbol required"); - if (parseToken(AsmToken::Comma, "unexpected token in directive")) - return true; - } - } + if (!getStreamer().EmitSymbolAttribute(Sym, Attr)) + return Error(Loc, "unable to emit symbol attribute"); + return false; + }; - Lex(); + if (parseMany(parseOp)) + return addErrorSuffix(" in directive"); return false; } /// parseDirectiveComm /// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ] bool AsmParser::parseDirectiveComm(bool IsLocal) { - checkForValidSection(); + if (checkForValidSection()) + return true; SMLoc IDLoc = getLexer().getLoc(); StringRef Name; @@ -4128,10 +4399,9 @@ bool AsmParser::parseDirectiveComm(bool IsLocal) { } } - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.comm' or '.lcomm' directive"); - - Lex(); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.comm' or '.lcomm' directive")) + return true; // NOTE: a size of zero for a .comm should create a undefined symbol // but a size of .lcomm creates a bss symbol of size zero. @@ -4171,9 +4441,9 @@ bool AsmParser::parseDirectiveAbort() { return true; if (Str.empty()) - Error(Loc, ".abort detected. Assembly stopping."); + return Error(Loc, ".abort detected. Assembly stopping."); else - Error(Loc, ".abort '" + Str + "' detected. Assembly stopping."); + return Error(Loc, ".abort '" + Str + "' detected. Assembly stopping."); // FIXME: Actually abort assembly here. return false; @@ -4201,20 +4471,43 @@ bool AsmParser::parseDirectiveInclude() { } /// parseDirectiveIncbin -/// ::= .incbin "filename" +/// ::= .incbin "filename" [ , skip [ , count ] ] bool AsmParser::parseDirectiveIncbin() { // Allow the strings to have escaped octal character sequence. std::string Filename; SMLoc IncbinLoc = getTok().getLoc(); if (check(getTok().isNot(AsmToken::String), "expected string in '.incbin' directive") || - parseEscapedString(Filename) || - parseToken(AsmToken::EndOfStatement, - "unexpected token in '.incbin' directive") || - // Attempt to process the included file. - check(processIncbinFile(Filename), IncbinLoc, - "Could not find incbin file '" + Filename + "'")) + parseEscapedString(Filename)) + return true; + + int64_t Skip = 0; + const MCExpr *Count = nullptr; + SMLoc SkipLoc, CountLoc; + if (parseOptionalToken(AsmToken::Comma)) { + // The skip expression can be omitted while specifying the count, e.g: + // .incbin "filename",,4 + if (getTok().isNot(AsmToken::Comma)) { + if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip)) + return true; + } + if (parseOptionalToken(AsmToken::Comma)) { + CountLoc = getTok().getLoc(); + if (parseExpression(Count)) + return true; + } + } + + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.incbin' directive")) + return true; + + if (check(Skip < 0, SkipLoc, "skip is negative")) return true; + + // Attempt to process the included file. + if (processIncbinFile(Filename, Skip, Count, CountLoc)) + return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'"); return false; } @@ -4317,11 +4610,8 @@ bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) { if (Lexer.isNot(AsmToken::String)) { if (ExpectEqual) - TokError("expected string parameter for '.ifeqs' directive"); - else - TokError("expected string parameter for '.ifnes' directive"); - eatToEndOfStatement(); - return true; + return TokError("expected string parameter for '.ifeqs' directive"); + return TokError("expected string parameter for '.ifnes' directive"); } StringRef String1 = getTok().getStringContents(); @@ -4329,22 +4619,17 @@ bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) { if (Lexer.isNot(AsmToken::Comma)) { if (ExpectEqual) - TokError("expected comma after first string for '.ifeqs' directive"); - else - TokError("expected comma after first string for '.ifnes' directive"); - eatToEndOfStatement(); - return true; + return TokError( + "expected comma after first string for '.ifeqs' directive"); + return TokError("expected comma after first string for '.ifnes' directive"); } Lex(); if (Lexer.isNot(AsmToken::String)) { if (ExpectEqual) - TokError("expected string parameter for '.ifeqs' directive"); - else - TokError("expected string parameter for '.ifnes' directive"); - eatToEndOfStatement(); - return true; + return TokError("expected string parameter for '.ifeqs' directive"); + return TokError("expected string parameter for '.ifnes' directive"); } StringRef String2 = getTok().getStringContents(); @@ -4389,8 +4674,8 @@ bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) { if (TheCondState.TheCond != AsmCond::IfCond && TheCondState.TheCond != AsmCond::ElseIfCond) - Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or " - " an .elseif"); + return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an" + " .if or an .elseif"); TheCondState.TheCond = AsmCond::ElseIfCond; bool LastIgnoreState = false; @@ -4404,10 +4689,10 @@ bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) { if (parseAbsoluteExpression(ExprValue)) return true; - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.elseif' directive"); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.elseif' directive")) + return true; - Lex(); TheCondState.CondMet = ExprValue; TheCondState.Ignore = !TheCondState.CondMet; } @@ -4424,8 +4709,8 @@ bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) { if (TheCondState.TheCond != AsmCond::IfCond && TheCondState.TheCond != AsmCond::ElseIfCond) - Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an " - ".elseif"); + return Error(DirectiveLoc, "Encountered a .else that doesn't follow " + " an .if or an .elseif"); TheCondState.TheCond = AsmCond::ElseCond; bool LastIgnoreState = false; if (!TheCondStack.empty()) @@ -4446,7 +4731,7 @@ bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) { return true; while (Lexer.isNot(AsmToken::Eof)) - Lex(); + Lexer.Lex(); return false; } @@ -4467,18 +4752,14 @@ bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) { StringRef Message = ".error directive invoked in source file"; if (Lexer.isNot(AsmToken::EndOfStatement)) { - if (Lexer.isNot(AsmToken::String)) { - TokError(".error argument must be a string"); - eatToEndOfStatement(); - return true; - } + if (Lexer.isNot(AsmToken::String)) + return TokError(".error argument must be a string"); Message = getTok().getStringContents(); Lex(); } - Error(L, Message); - return true; + return Error(L, Message); } /// parseDirectiveWarning @@ -4492,19 +4773,19 @@ bool AsmParser::parseDirectiveWarning(SMLoc L) { } StringRef Message = ".warning directive invoked in source file"; - if (Lexer.isNot(AsmToken::EndOfStatement)) { - if (Lexer.isNot(AsmToken::String)) { - TokError(".warning argument must be a string"); - eatToEndOfStatement(); - return true; - } + + if (!parseOptionalToken(AsmToken::EndOfStatement)) { + if (Lexer.isNot(AsmToken::String)) + return TokError(".warning argument must be a string"); Message = getTok().getStringContents(); Lex(); + if (parseToken(AsmToken::EndOfStatement, + "expected end of statement in '.warning' directive")) + return true; } - Warning(L, Message); - return false; + return Warning(L, Message); } /// parseDirectiveEndIf @@ -4515,8 +4796,8 @@ bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) { return true; if ((TheCondState.TheCond == AsmCond::NoCond) || TheCondStack.empty()) - Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or " - ".else"); + return Error(DirectiveLoc, "Encountered a .endif that doesn't follow " + "an .if or .else"); if (!TheCondStack.empty()) { TheCondState = TheCondStack.back(); TheCondStack.pop_back(); @@ -4610,9 +4891,11 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".loc"] = DK_LOC; DirectiveKindMap[".stabs"] = DK_STABS; DirectiveKindMap[".cv_file"] = DK_CV_FILE; + DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID; DirectiveKindMap[".cv_loc"] = DK_CV_LOC; DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE; DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE; + DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID; DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE; DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE; DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS; @@ -4649,16 +4932,39 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".error"] = DK_ERROR; DirectiveKindMap[".warning"] = DK_WARNING; DirectiveKindMap[".reloc"] = DK_RELOC; + DirectiveKindMap[".dc"] = DK_DC; + DirectiveKindMap[".dc.a"] = DK_DC_A; + DirectiveKindMap[".dc.b"] = DK_DC_B; + DirectiveKindMap[".dc.d"] = DK_DC_D; + DirectiveKindMap[".dc.l"] = DK_DC_L; + DirectiveKindMap[".dc.s"] = DK_DC_S; + DirectiveKindMap[".dc.w"] = DK_DC_W; + DirectiveKindMap[".dc.x"] = DK_DC_X; + DirectiveKindMap[".dcb"] = DK_DCB; + DirectiveKindMap[".dcb.b"] = DK_DCB_B; + DirectiveKindMap[".dcb.d"] = DK_DCB_D; + DirectiveKindMap[".dcb.l"] = DK_DCB_L; + DirectiveKindMap[".dcb.s"] = DK_DCB_S; + DirectiveKindMap[".dcb.w"] = DK_DCB_W; + DirectiveKindMap[".dcb.x"] = DK_DCB_X; + DirectiveKindMap[".ds"] = DK_DS; + DirectiveKindMap[".ds.b"] = DK_DS_B; + DirectiveKindMap[".ds.d"] = DK_DS_D; + DirectiveKindMap[".ds.l"] = DK_DS_L; + DirectiveKindMap[".ds.p"] = DK_DS_P; + DirectiveKindMap[".ds.s"] = DK_DS_S; + DirectiveKindMap[".ds.w"] = DK_DS_W; + DirectiveKindMap[".ds.x"] = DK_DS_X; } MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { AsmToken EndToken, StartToken = getTok(); unsigned NestLevel = 0; - for (;;) { + while (true) { // Check whether we have reached the end of the file. if (getLexer().is(AsmToken::Eof)) { - Error(DirectiveLoc, "no matching '.endr' in definition"); + printError(DirectiveLoc, "no matching '.endr' in definition"); return nullptr; } @@ -4675,7 +4981,8 @@ MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { EndToken = getTok(); Lex(); if (Lexer.isNot(AsmToken::EndOfStatement)) { - TokError("unexpected token in '.endr' directive"); + printError(getTok().getLoc(), + "unexpected token in '.endr' directive"); return nullptr; } break; @@ -4725,7 +5032,6 @@ bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) { int64_t Count; if (!CountExpr->evaluateAsAbsolute(Count)) { - eatToEndOfStatement(); return Error(CountLoc, "unexpected token in '" + Dir + "' directive"); } @@ -4928,11 +5234,16 @@ bool AsmParser::parseMSInlineAsm( continue; ParseStatementInfo Info(&AsmStrRewrites); - if (parseStatement(Info, &SI)) - return true; + bool StatementErr = parseStatement(Info, &SI); - if (Info.ParseError) + if (StatementErr || Info.ParseError) { + // Emit pending errors if any exist. + printPendingErrors(); return true; + } + + // No pending error should exist here. + assert(!hasPendingError() && "unexpected error from parseStatement"); if (Info.Opcode == ~0U) continue; @@ -5158,20 +5469,15 @@ bool parseAssignmentExpression(StringRef Name, bool allow_redef, SMLoc EqualLoc = Parser.getTok().getLoc(); if (Parser.parseExpression(Value)) { - Parser.TokError("missing expression"); - Parser.eatToEndOfStatement(); - return true; + return Parser.TokError("missing expression"); } // Note: we don't count b as used in "a = b". This is to allow // a = b // b = c - if (Parser.getTok().isNot(AsmToken::EndOfStatement)) - return Parser.TokError("unexpected token in assignment"); - - // Eat the end of statement marker. - Parser.Lex(); + if (Parser.parseToken(AsmToken::EndOfStatement)) + return true; // Validate that the LHS is allowed to be a variable (either it has not been // used as a symbol, or it is an absolute symbol). @@ -5197,7 +5503,7 @@ bool parseAssignmentExpression(StringRef Name, bool allow_redef, "invalid reassignment of non-absolute variable '" + Name + "'"); } else if (Name == ".") { - Parser.getStreamer().emitValueToOffset(Value, 0); + Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc); return false; } else Sym = Parser.getContext().getOrCreateSymbol(Name); @@ -5207,8 +5513,8 @@ bool parseAssignmentExpression(StringRef Name, bool allow_redef, return false; } -} // namespace MCParserUtils -} // namespace llvm +} // end namespace MCParserUtils +} // end namespace llvm /// \brief Create an MCAsmParser instance. MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C, |