X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FMC%2FMCParser%2FAsmParser.cpp;h=529ddb4577bd399d7fa5495a0348b742f5056998;hb=5dc48d726d5664e34e67089fb6082c638f4b6d08;hp=37b759e64f52005d9aaa774006469cb250417479;hpb=075a90a913e4f26ea074e720130ce8a0a892d235;p=oota-llvm.git diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 37b759e64f5..529ddb4577b 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -51,11 +51,18 @@ FatalAssemblerWarnings("fatal-assembler-warnings", MCAsmParserSemaCallback::~MCAsmParserSemaCallback() {} namespace { - /// \brief Helper types for tracking macro definitions. typedef std::vector MCAsmMacroArgument; typedef std::vector MCAsmMacroArguments; -typedef std::pair MCAsmMacroParameter; + +struct MCAsmMacroParameter { + StringRef Name; + MCAsmMacroArgument Value; + bool Required; + + MCAsmMacroParameter() : Required(false) { } +}; + typedef std::vector MCAsmMacroParameters; struct MCAsmMacro { @@ -64,11 +71,8 @@ struct MCAsmMacro { MCAsmMacroParameters Parameters; public: - MCAsmMacro(StringRef N, StringRef B, const MCAsmMacroParameters &P) : + MCAsmMacro(StringRef N, StringRef B, ArrayRef P) : Name(N), Body(B), Parameters(P) {} - - MCAsmMacro(const MCAsmMacro& Other) - : Name(Other.Name), Body(Other.Body), Parameters(Other.Parameters) {} }; /// \brief Helper class for storing information about an active macro @@ -186,10 +190,10 @@ public: const MCAsmInfo &MAI); virtual ~AsmParser(); - virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false); + bool Run(bool NoInitialTextSection, bool NoFinalize = false) override; - virtual void addDirectiveHandler(StringRef Directive, - ExtensionDirectiveHandler Handler) { + void addDirectiveHandler(StringRef Directive, + ExtensionDirectiveHandler Handler) override { ExtensionDirectiveMap[Directive] = Handler; } @@ -197,52 +201,52 @@ public: /// @name MCAsmParser Interface /// { - virtual SourceMgr &getSourceManager() { return SrcMgr; } - virtual MCAsmLexer &getLexer() { return Lexer; } - virtual MCContext &getContext() { return Ctx; } - virtual MCStreamer &getStreamer() { return Out; } - virtual unsigned getAssemblerDialect() { + SourceMgr &getSourceManager() override { return SrcMgr; } + MCAsmLexer &getLexer() override { return Lexer; } + MCContext &getContext() override { return Ctx; } + MCStreamer &getStreamer() override { return Out; } + unsigned getAssemblerDialect() override { if (AssemblerDialect == ~0U) return MAI.getAssemblerDialect(); else return AssemblerDialect; } - virtual void setAssemblerDialect(unsigned i) { + void setAssemblerDialect(unsigned i) override { AssemblerDialect = i; } - virtual void Note(SMLoc L, const Twine &Msg, ArrayRef Ranges = None); - virtual bool Warning(SMLoc L, const Twine &Msg, - ArrayRef Ranges = None); - virtual bool Error(SMLoc L, const Twine &Msg, - ArrayRef Ranges = None); + void Note(SMLoc L, const Twine &Msg, + ArrayRef Ranges = None) override; + bool Warning(SMLoc L, const Twine &Msg, + ArrayRef Ranges = None) override; + bool Error(SMLoc L, const Twine &Msg, + ArrayRef Ranges = None) override; - virtual const AsmToken &Lex(); + const AsmToken &Lex() override; - void setParsingInlineAsm(bool V) { ParsingInlineAsm = V; } - bool isParsingInlineAsm() { return ParsingInlineAsm; } + void setParsingInlineAsm(bool V) override { ParsingInlineAsm = V; } + bool isParsingInlineAsm() override { return ParsingInlineAsm; } bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, SmallVectorImpl > &OpDecls, SmallVectorImpl &Constraints, SmallVectorImpl &Clobbers, - const MCInstrInfo *MII, - const MCInstPrinter *IP, - MCAsmParserSemaCallback &SI); + const MCInstrInfo *MII, const MCInstPrinter *IP, + MCAsmParserSemaCallback &SI) override; bool parseExpression(const MCExpr *&Res); - virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc); - virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc); - virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc); - virtual bool parseAbsoluteExpression(int64_t &Res); + bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override; + bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override; + bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override; + bool parseAbsoluteExpression(int64_t &Res) override; /// \brief Parse an identifier or string (as a quoted identifier) /// and set \p Res to the identifier contents. - virtual bool parseIdentifier(StringRef &Res); - virtual void eatToEndOfStatement(); + bool parseIdentifier(StringRef &Res) override; + void eatToEndOfStatement() override; - virtual void checkForValidSection(); + void checkForValidSection() override; /// } private: @@ -252,10 +256,10 @@ private: bool parseCppHashLineFilenameComment(const SMLoc &L); void checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body, - MCAsmMacroParameters Parameters); + ArrayRef Parameters); bool expandMacro(raw_svector_ostream &OS, StringRef Body, - const MCAsmMacroParameters &Parameters, - const MCAsmMacroArguments &A, + ArrayRef Parameters, + ArrayRef A, const SMLoc &L); /// \brief Are macros enabled in the parser? @@ -318,7 +322,7 @@ private: /// \brief Parse up to the end of statement and a return the contents from the /// current token until the end of the statement; the current token on exit /// will be either the EndOfStatement or EOF. - virtual StringRef parseStringToEndOfStatement(); + StringRef parseStringToEndOfStatement() override; /// \brief Parse until the end of a statement or a comma is encountered, /// return the contents from the current token up to the end or comma. @@ -346,8 +350,8 @@ private: DK_REFERENCE, DK_WEAK_DEFINITION, DK_WEAK_REFERENCE, DK_WEAK_DEF_CAN_BE_HIDDEN, DK_COMM, DK_COMMON, DK_LCOMM, DK_ABORT, DK_INCLUDE, DK_INCBIN, DK_CODE16, DK_CODE16GCC, DK_REPT, DK_IRP, DK_IRPC, - DK_IF, DK_IFB, DK_IFNB, DK_IFC, DK_IFNC, DK_IFDEF, DK_IFNDEF, DK_IFNOTDEF, - DK_ELSEIF, DK_ELSE, DK_ENDIF, + DK_IF, DK_IFNE, DK_IFB, DK_IFNB, DK_IFC, DK_IFEQS, DK_IFNC, 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_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, @@ -357,6 +361,7 @@ private: DK_CFI_REGISTER, DK_CFI_WINDOW_SAVE, DK_MACROS_ON, DK_MACROS_OFF, DK_MACRO, DK_ENDM, DK_ENDMACRO, DK_PURGEM, DK_SLEB128, DK_ULEB128, + DK_ERR, DK_ERROR, DK_END }; @@ -433,17 +438,20 @@ private: bool parseDirectiveInclude(); // ".include" bool parseDirectiveIncbin(); // ".incbin" - bool parseDirectiveIf(SMLoc DirectiveLoc); // ".if" + // ".if" or ".ifne" + bool parseDirectiveIf(SMLoc DirectiveLoc); // ".ifb" or ".ifnb", depending on ExpectBlank. bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank); // ".ifc" or ".ifnc", depending on ExpectEqual. bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual); + // ".ifeqs" + bool parseDirectiveIfeqs(SMLoc DirectiveLoc); // ".ifdef" or ".ifndef", depending on expect_defined bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined); bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif" bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else" bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif - virtual bool parseEscapedString(std::string &Data); + bool parseEscapedString(std::string &Data) override; const MCExpr *applyModifierToExpr(const MCExpr *E, MCSymbolRefExpr::VariantKind Variant); @@ -467,6 +475,9 @@ private: // "end" bool parseDirectiveEnd(SMLoc DirectiveLoc); + // ".err" or ".error" + bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage); + void initializeDirectiveKindMap(); }; } @@ -681,10 +692,6 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { } } - // Callback to the target parser in case it needs to do anything. - if (!HadError) - getTargetParser().finishParse(); - // Finalize the output stream if there are no errors and if the client wants // us to. if (!HadError && !NoFinalize) @@ -798,9 +805,8 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { getContext()); EndLoc = FirstTokenLoc; return false; - } else - return Error(FirstTokenLoc, "invalid token in expression"); - return true; + } + return Error(FirstTokenLoc, "invalid token in expression"); } } // Parse symbol variant @@ -833,7 +839,6 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { } else if (MAI.doesAllowAtInName() && !MAI.useParensForSymbolVariant()) { Variant = MCSymbolRefExpr::VK_None; } else { - Variant = MCSymbolRefExpr::VK_None; return Error(SMLoc::getFromPointer(Split.second.begin()), "invalid variant '" + Split.second + "'"); } @@ -1227,6 +1232,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { default: break; case DK_IF: + case DK_IFNE: return parseDirectiveIf(IDLoc); case DK_IFB: return parseDirectiveIfb(IDLoc, true); @@ -1234,6 +1240,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { return parseDirectiveIfb(IDLoc, false); case DK_IFC: return parseDirectiveIfc(IDLoc, true); + case DK_IFEQS: + return parseDirectiveIfeqs(IDLoc); case DK_IFNC: return parseDirectiveIfc(IDLoc, false); case DK_IFDEF: @@ -1527,6 +1535,10 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { return parseDirectivePurgeMacro(IDLoc); case DK_END: return parseDirectiveEnd(IDLoc); + case DK_ERR: + return parseDirectiveError(IDLoc, false); + case DK_ERROR: + return parseDirectiveError(IDLoc, true); } return Error(IDLoc, "unknown directive"); @@ -1727,10 +1739,10 @@ static bool isIdentifierChar(char c) { } bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, - const MCAsmMacroParameters &Parameters, - const MCAsmMacroArguments &A, const SMLoc &L) { + ArrayRef Parameters, + ArrayRef A, const SMLoc &L) { unsigned NParameters = Parameters.size(); - if (NParameters != 0 && NParameters != A.size()) + if ((!IsDarwin || NParameters != 0) && NParameters != A.size()) return Error(L, "Wrong number of arguments"); // A macro without parameters is handled differently on Darwin: @@ -1740,7 +1752,7 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, std::size_t End = Body.size(), Pos = 0; for (; Pos != End; ++Pos) { // Check for a substitution or escape. - if (!NParameters) { + if (IsDarwin && !NParameters) { // This macro has no parameters, look for $0, $1, etc. if (Body[Pos] != '$' || Pos + 1 == End) continue; @@ -1763,7 +1775,7 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, if (Pos == End) break; - if (!NParameters) { + if (IsDarwin && !NParameters) { switch (Body[Pos + 1]) { // $$ => $ case '$': @@ -1800,7 +1812,7 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, StringRef Argument(Begin, I - (Pos + 1)); unsigned Index = 0; for (; Index < NParameters; ++Index) - if (Parameters[Index].first == Argument) + if (Parameters[Index].Name == Argument) break; if (Index == NParameters) { @@ -1943,40 +1955,99 @@ bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA) { bool AsmParser::parseMacroArguments(const MCAsmMacro *M, MCAsmMacroArguments &A) { const unsigned NParameters = M ? M->Parameters.size() : 0; + bool NamedParametersFound = false; + SmallVector FALocs; + + A.resize(NParameters); + FALocs.resize(NParameters); // Parse two kinds of macro invocations: // - macros defined without any parameters accept an arbitrary number of them // - macros defined with parameters accept at most that many of them for (unsigned Parameter = 0; !NParameters || Parameter < NParameters; ++Parameter) { - MCAsmMacroArgument MA; + SMLoc IDLoc = Lexer.getLoc(); + MCAsmMacroParameter FA; - if (parseMacroArgument(MA)) + 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 (!Lexer.is(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 (!MA.empty() || (!NParameters && !Lexer.is(AsmToken::EndOfStatement))) - A.push_back(MA); - else if (NParameters) { - if (!M->Parameters[Parameter].second.empty()) - A.push_back(M->Parameters[Parameter].second); - else - A.push_back(MA); + if (parseMacroArgument(FA.Value)) + return true; + + unsigned PI = Parameter; + if (!FA.Name.empty()) { + unsigned FAI = 0; + for (FAI = 0; FAI < NParameters; ++FAI) + if (M->Parameters[FAI].Name == FA.Name) + break; + + if (FAI >= NParameters) { + Error(IDLoc, + "parameter named '" + FA.Name + "' does not exist for macro '" + + M->Name + "'"); + return true; + } + PI = FAI; + } + + if (!FA.Value.empty()) { + if (A.size() <= PI) + A.resize(PI + 1); + A[PI] = FA.Value; + + if (FALocs.size() <= PI) + FALocs.resize(PI + 1); + + FALocs[PI] = Lexer.getLoc(); } // At the end of the statement, fill in remaining arguments that have // default values. If there aren't any, then the next argument is // required but missing if (Lexer.is(AsmToken::EndOfStatement)) { - if (NParameters && Parameter < NParameters - 1) { - continue; + bool Failure = false; + for (unsigned FAI = 0; FAI < NParameters; ++FAI) { + if (A[FAI].empty()) { + if (M->Parameters[FAI].Required) { + Error(FALocs[FAI].isValid() ? FALocs[FAI] : Lexer.getLoc(), + "missing value for required parameter " + "'" + M->Parameters[FAI].Name + "' in macro '" + M->Name + "'"); + Failure = true; + } + + if (!M->Parameters[FAI].Value.empty()) + A[FAI] = M->Parameters[FAI].Value; + } } - return false; + return Failure; } if (Lexer.is(AsmToken::Comma)) Lex(); } - return TokError("Too many arguments"); + + return TokError("too many positional arguments"); } const MCAsmMacro *AsmParser::lookupMacro(StringRef Name) { @@ -2085,12 +2156,6 @@ bool AsmParser::parseAssignment(StringRef Name, bool allow_redef, if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in assignment"); - // Error on assignment to '.'. - if (Name == ".") { - return Error(EqualLoc, ("assignment to pseudo-symbol '.' is unsupported " - "(use '.space' or '.org').)")); - } - // Eat the end of statement marker. Lex(); @@ -2118,11 +2183,15 @@ bool AsmParser::parseAssignment(StringRef Name, bool allow_redef, // Don't count these checks as uses. Sym->setUsed(false); + } else if (Name == ".") { + if (Out.EmitValueToOffset(Value, 0)) { + Error(EqualLoc, "expected absolute expression"); + eatToEndOfStatement(); + } + return false; } else Sym = getContext().GetOrCreateSymbol(Name); - // FIXME: Handle '.'. - // Do the assignment. Out.EmitAssignment(Sym, Value); if (NoDeadStrip) @@ -2335,7 +2404,8 @@ bool AsmParser::parseDirectiveOctaValue() { hi = 0; lo = IntValue.getZExtValue(); } else if (IntValue.isIntN(128)) { - hi = IntValue.getHiBits(64).getZExtValue(); + // 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"); @@ -3158,22 +3228,51 @@ bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) { } /// parseDirectiveMacro -/// ::= .macro name [parameters] +/// ::= .macro name[,] [parameters] bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { StringRef Name; if (parseIdentifier(Name)) return TokError("expected identifier in '.macro' directive"); + if (getLexer().is(AsmToken::Comma)) + Lex(); + MCAsmMacroParameters Parameters; while (getLexer().isNot(AsmToken::EndOfStatement)) { MCAsmMacroParameter Parameter; - if (parseIdentifier(Parameter.first)) + if (parseIdentifier(Parameter.Name)) return TokError("expected identifier in '.macro' directive"); + if (Lexer.is(AsmToken::Colon)) { + Lex(); // consume ':' + + SMLoc QualLoc; + StringRef Qualifier; + + QualLoc = Lexer.getLoc(); + if (parseIdentifier(Qualifier)) + return Error(QualLoc, "missing parameter qualifier for " + "'" + Parameter.Name + "' in macro '" + Name + "'"); + + if (Qualifier == "req") + Parameter.Required = true; + else + return Error(QualLoc, Qualifier + " is not a valid parameter qualifier " + "for '" + Parameter.Name + "' in macro '" + Name + "'"); + } + if (getLexer().is(AsmToken::Equal)) { Lex(); - if (parseMacroArgument(Parameter.second)) + + SMLoc ParamLoc; + + ParamLoc = Lexer.getLoc(); + if (parseMacroArgument(Parameter.Value)) return true; + + if (Parameter.Required) + Warning(ParamLoc, "pointless default value for required parameter " + "'" + Parameter.Name + "' in macro '" + Name + "'"); } Parameters.push_back(Parameter); @@ -3186,6 +3285,7 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { Lex(); AsmToken EndToken, StartToken = getTok(); + unsigned MacroDepth = 0; // Lex the macro definition. for (;;) { @@ -3194,15 +3294,25 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { return Error(DirectiveLoc, "no matching '.endmacro' in definition"); // Otherwise, check whether we have reach the .endmacro. - if (getLexer().is(AsmToken::Identifier) && - (getTok().getIdentifier() == ".endm" || - getTok().getIdentifier() == ".endmacro")) { - EndToken = getTok(); - Lex(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '" + EndToken.getIdentifier() + - "' directive"); - break; + if (getLexer().is(AsmToken::Identifier)) { + if (getTok().getIdentifier() == ".endm" || + getTok().getIdentifier() == ".endmacro") { + if (MacroDepth == 0) { // Outermost macro. + EndToken = getTok(); + Lex(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '" + EndToken.getIdentifier() + + "' directive"); + break; + } else { + // Otherwise we just found the end of an inner macro. + --MacroDepth; + } + } else if (getTok().getIdentifier() == ".macro") { + // We allow nested macros. Those aren't instantiated until the outermost + // macro is expanded so just ignore them for now. + ++MacroDepth; + } } // Otherwise, scan til the end of the statement. @@ -3237,7 +3347,7 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { /// and the strings like $1 are infact to simply to be passed trough unchanged. void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Body, - MCAsmMacroParameters Parameters) { + ArrayRef Parameters) { // If this macro is not defined with named parameters the warning we are // checking for here doesn't apply. unsigned NParameters = Parameters.size(); @@ -3299,7 +3409,7 @@ void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, StringRef Argument(Begin, I - (Pos + 1)); unsigned Index = 0; for (; Index < NParameters; ++Index) - if (Parameters[Index].first == Argument) + if (Parameters[Index].Name == Argument) break; if (Index == NParameters) { @@ -3663,6 +3773,7 @@ bool AsmParser::parseDirectiveIncbin() { /// parseDirectiveIf /// ::= .if expression +/// ::= .ifne expression bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc) { TheCondStack.push_back(TheCondState); TheCondState.TheCond = AsmCond::IfCond; @@ -3710,6 +3821,7 @@ bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { /// parseDirectiveIfc /// ::= .ifc string1, string2 +/// ::= .ifnc string1, string2 bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { TheCondStack.push_back(TheCondState); TheCondState.TheCond = AsmCond::IfCond; @@ -3731,13 +3843,50 @@ bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { Lex(); - TheCondState.CondMet = ExpectEqual == (Str1 == Str2); + TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim()); TheCondState.Ignore = !TheCondState.CondMet; } return false; } +/// parseDirectiveIfeqs +/// ::= .ifeqs string1, string2 +bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc) { + if (Lexer.isNot(AsmToken::String)) { + TokError("expected string parameter for '.ifeqs' directive"); + eatToEndOfStatement(); + return true; + } + + StringRef String1 = getTok().getStringContents(); + Lex(); + + if (Lexer.isNot(AsmToken::Comma)) { + TokError("expected comma after first string for '.ifeqs' directive"); + eatToEndOfStatement(); + return true; + } + + Lex(); + + if (Lexer.isNot(AsmToken::String)) { + TokError("expected string parameter for '.ifeqs' directive"); + eatToEndOfStatement(); + return true; + } + + StringRef String2 = getTok().getStringContents(); + Lex(); + + TheCondStack.push_back(TheCondState); + TheCondState.TheCond = AsmCond::IfCond; + TheCondState.CondMet = String1 == String2; + TheCondState.Ignore = !TheCondState.CondMet; + + return false; +} + /// parseDirectiveIfdef /// ::= .ifdef symbol bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { @@ -3834,6 +3983,36 @@ bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) { return false; } +/// parseDirectiveError +/// ::= .err +/// ::= .error [string] +bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) { + if (!TheCondStack.empty()) { + if (TheCondStack.back().Ignore) { + eatToEndOfStatement(); + return false; + } + } + + if (!WithMessage) + return Error(L, ".err encountered"); + + 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; + } + + Message = getTok().getStringContents(); + Lex(); + } + + Error(L, Message); + return true; +} + /// parseDirectiveEndIf /// ::= .endif bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) { @@ -3912,9 +4091,11 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK; DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK; DirectiveKindMap[".if"] = DK_IF; + DirectiveKindMap[".ifne"] = DK_IFNE; DirectiveKindMap[".ifb"] = DK_IFB; DirectiveKindMap[".ifnb"] = DK_IFNB; DirectiveKindMap[".ifc"] = DK_IFC; + DirectiveKindMap[".ifeqs"] = DK_IFEQS; DirectiveKindMap[".ifnc"] = DK_IFNC; DirectiveKindMap[".ifdef"] = DK_IFDEF; DirectiveKindMap[".ifndef"] = DK_IFNDEF; @@ -3957,6 +4138,8 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".endm"] = DK_ENDM; DirectiveKindMap[".endmacro"] = DK_ENDMACRO; DirectiveKindMap[".purgem"] = DK_PURGEM; + DirectiveKindMap[".err"] = DK_ERR; + DirectiveKindMap[".error"] = DK_ERROR; } MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { @@ -3998,9 +4181,7 @@ MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); // We Are Anonymous. - StringRef Name; - MCAsmMacroParameters Parameters; - MacroLikeBodies.push_back(MCAsmMacro(Name, Body, Parameters)); + MacroLikeBodies.push_back(MCAsmMacro(StringRef(), Body, None)); return &MacroLikeBodies.back(); } @@ -4054,11 +4235,9 @@ bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) { // Macro instantiation is lexical, unfortunately. We construct a new buffer // to hold the macro body with substitutions. SmallString<256> Buf; - MCAsmMacroParameters Parameters; - MCAsmMacroArguments A; raw_svector_ostream OS(Buf); while (Count--) { - if (expandMacro(OS, M->Body, Parameters, A, getTok().getLoc())) + if (expandMacro(OS, M->Body, None, None, getTok().getLoc())) return true; } instantiateMacroLikeBody(M, DirectiveLoc, OS); @@ -4069,14 +4248,11 @@ bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) { /// parseDirectiveIrp /// ::= .irp symbol,values bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) { - MCAsmMacroParameters Parameters; MCAsmMacroParameter Parameter; - if (parseIdentifier(Parameter.first)) + if (parseIdentifier(Parameter.Name)) return TokError("expected identifier in '.irp' directive"); - Parameters.push_back(Parameter); - if (Lexer.isNot(AsmToken::Comma)) return TokError("expected comma in '.irp' directive"); @@ -4100,10 +4276,7 @@ bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) { raw_svector_ostream OS(Buf); for (MCAsmMacroArguments::iterator i = A.begin(), e = A.end(); i != e; ++i) { - MCAsmMacroArguments Args; - Args.push_back(*i); - - if (expandMacro(OS, M->Body, Parameters, Args, getTok().getLoc())) + if (expandMacro(OS, M->Body, Parameter, *i, getTok().getLoc())) return true; } @@ -4115,14 +4288,11 @@ bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) { /// parseDirectiveIrpc /// ::= .irpc symbol,values bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) { - MCAsmMacroParameters Parameters; MCAsmMacroParameter Parameter; - if (parseIdentifier(Parameter.first)) + if (parseIdentifier(Parameter.Name)) return TokError("expected identifier in '.irpc' directive"); - Parameters.push_back(Parameter); - if (Lexer.isNot(AsmToken::Comma)) return TokError("expected comma in '.irpc' directive"); @@ -4149,15 +4319,11 @@ bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) { raw_svector_ostream OS(Buf); StringRef Values = A.front().front().getString(); - std::size_t I, End = Values.size(); - for (I = 0; I < End; ++I) { + for (std::size_t I = 0, End = Values.size(); I != End; ++I) { MCAsmMacroArgument Arg; Arg.push_back(AsmToken(AsmToken::Identifier, Values.slice(I, I + 1))); - MCAsmMacroArguments Args; - Args.push_back(Arg); - - if (expandMacro(OS, M->Body, Parameters, Args, getTok().getLoc())) + if (expandMacro(OS, M->Body, Parameter, Arg, getTok().getLoc())) return true; } @@ -4416,6 +4582,10 @@ bool AsmParser::parseMSInlineAsm( break; } case AOK_DotOperator: + // Insert the dot if the user omitted it. + OS.flush(); + if (AsmStringIR.back() != '.') + OS << '.'; OS << (*I).Val; break; }