From 3bc0a0e24ab9d70ebcee84748629a821ee186b8a Mon Sep 17 00:00:00 2001 From: Nirav Dave Date: Wed, 2 Nov 2016 16:22:51 +0000 Subject: [PATCH] [ARM][MC] Cleanup ARM Target Assembly Parser Summary: Correctly parse end-of-statement tokens and handle preprocessor end-of-line comments in ARM assembly processor. Reviewers: rnk, majnemer Subscribers: aemerson, rengolin, llvm-commits Differential Revision: https://reviews.llvm.org/D26152 llvm-svn: 285830 --- .../llvm/MC/MCParser/MCAsmParserExtension.h | 23 +- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 883 +++++++----------- test/MC/ARM/directive-thumb_func.s | 2 +- test/MC/ARM/directive_parsing.s | 170 ++++ 4 files changed, 536 insertions(+), 542 deletions(-) create mode 100644 test/MC/ARM/directive_parsing.s diff --git a/include/llvm/MC/MCParser/MCAsmParserExtension.h b/include/llvm/MC/MCParser/MCAsmParserExtension.h index 586369d3351..13e58c12b32 100644 --- a/include/llvm/MC/MCParser/MCAsmParserExtension.h +++ b/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -80,10 +80,31 @@ public: const AsmToken &Lex() { return getParser().Lex(); } const AsmToken &getTok() { return getParser().getTok(); } - bool parseToken(AsmToken::TokenKind T, const Twine &Msg) { + bool parseToken(AsmToken::TokenKind T, + const Twine &Msg = "unexpected token") { return getParser().parseToken(T, Msg); } + bool parseMany(std::function parseOne, bool hasComma = true) { + return getParser().parseMany(parseOne, hasComma); + } + + bool parseOptionalToken(AsmToken::TokenKind T) { + return getParser().parseOptionalToken(T); + } + + bool check(bool P, const llvm::Twine &Msg) { + return getParser().check(P, Msg); + } + + bool check(bool P, SMLoc Loc, const llvm::Twine &Msg) { + return getParser().check(P, Loc, Msg); + } + + bool addErrorSuffix(const Twine &Suffix) { + return getParser().addErrorSuffix(Suffix); + } + bool HasBracketExpressions() const { return BracketExpressionsSupported; } /// @} diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 7a938babc70..9950daee579 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -3610,8 +3610,8 @@ static unsigned getDRegFromQReg(unsigned QReg) { /// Parse a register list. bool ARMAsmParser::parseRegisterList(OperandVector &Operands) { MCAsmParser &Parser = getParser(); - assert(Parser.getTok().is(AsmToken::LCurly) && - "Token is not a Left Curly Brace"); + if (Parser.getTok().isNot(AsmToken::LCurly)) + return TokError("Token is not a Left Curly Brace"); SMLoc S = Parser.getTok().getLoc(); Parser.Lex(); // Eat '{' token. SMLoc RegLoc = Parser.getTok().getLoc(); @@ -4996,8 +4996,8 @@ void ARMAsmParser::cvtThumbBranches(MCInst &Inst, bool ARMAsmParser::parseMemory(OperandVector &Operands) { MCAsmParser &Parser = getParser(); SMLoc S, E; - assert(Parser.getTok().is(AsmToken::LBrac) && - "Token is not a Left Bracket"); + if (Parser.getTok().isNot(AsmToken::LBrac)) + return TokError("Token is not a Left Bracket"); S = Parser.getTok().getLoc(); Parser.Lex(); // Eat left bracket token. @@ -6118,9 +6118,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, return true; } - while (getLexer().is(AsmToken::Comma)) { - Parser.Lex(); // Eat the comma. - + while (parseOptionalToken(AsmToken::Comma)) { // Parse and remember the operand. if (parseOperand(Operands, Mnemonic)) { return true; @@ -6128,11 +6126,8 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } } - if (getLexer().isNot(AsmToken::EndOfStatement)) { - return TokError("unexpected token in argument list"); - } - - Parser.Lex(); // Consume the EndOfStatement + if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list")) + return true; if (RequireVFPRegisterListCheck) { ARMOperand &Op = static_cast(*Operands.back()); @@ -6196,10 +6191,9 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // Rt2 must be Rt + 1 and Rt must be even. if (Rt + 1 != Rt2 || (Rt & 1)) { - Error(Op2.getStartLoc(), isLoad - ? "destination operands must be sequential" - : "source operands must be sequential"); - return true; + return Error(Op2.getStartLoc(), + isLoad ? "destination operands must be sequential" + : "source operands must be sequential"); } unsigned NewReg = MRI->getMatchingSuperReg(Reg1, ARM::gsub_0, &(MRI->getRegClass(ARM::GPRPairRegClassID))); @@ -9237,78 +9231,79 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { StringRef IDVal = DirectiveID.getIdentifier(); if (IDVal == ".word") - return parseLiteralValues(4, DirectiveID.getLoc()); + parseLiteralValues(4, DirectiveID.getLoc()); else if (IDVal == ".short" || IDVal == ".hword") - return parseLiteralValues(2, DirectiveID.getLoc()); + parseLiteralValues(2, DirectiveID.getLoc()); else if (IDVal == ".thumb") - return parseDirectiveThumb(DirectiveID.getLoc()); + parseDirectiveThumb(DirectiveID.getLoc()); else if (IDVal == ".arm") - return parseDirectiveARM(DirectiveID.getLoc()); + parseDirectiveARM(DirectiveID.getLoc()); else if (IDVal == ".thumb_func") - return parseDirectiveThumbFunc(DirectiveID.getLoc()); + parseDirectiveThumbFunc(DirectiveID.getLoc()); else if (IDVal == ".code") - return parseDirectiveCode(DirectiveID.getLoc()); + parseDirectiveCode(DirectiveID.getLoc()); else if (IDVal == ".syntax") - return parseDirectiveSyntax(DirectiveID.getLoc()); + parseDirectiveSyntax(DirectiveID.getLoc()); else if (IDVal == ".unreq") - return parseDirectiveUnreq(DirectiveID.getLoc()); + parseDirectiveUnreq(DirectiveID.getLoc()); else if (IDVal == ".fnend") - return parseDirectiveFnEnd(DirectiveID.getLoc()); + parseDirectiveFnEnd(DirectiveID.getLoc()); else if (IDVal == ".cantunwind") - return parseDirectiveCantUnwind(DirectiveID.getLoc()); + parseDirectiveCantUnwind(DirectiveID.getLoc()); else if (IDVal == ".personality") - return parseDirectivePersonality(DirectiveID.getLoc()); + parseDirectivePersonality(DirectiveID.getLoc()); else if (IDVal == ".handlerdata") - return parseDirectiveHandlerData(DirectiveID.getLoc()); + parseDirectiveHandlerData(DirectiveID.getLoc()); else if (IDVal == ".setfp") - return parseDirectiveSetFP(DirectiveID.getLoc()); + parseDirectiveSetFP(DirectiveID.getLoc()); else if (IDVal == ".pad") - return parseDirectivePad(DirectiveID.getLoc()); + parseDirectivePad(DirectiveID.getLoc()); else if (IDVal == ".save") - return parseDirectiveRegSave(DirectiveID.getLoc(), false); + parseDirectiveRegSave(DirectiveID.getLoc(), false); else if (IDVal == ".vsave") - return parseDirectiveRegSave(DirectiveID.getLoc(), true); + parseDirectiveRegSave(DirectiveID.getLoc(), true); else if (IDVal == ".ltorg" || IDVal == ".pool") - return parseDirectiveLtorg(DirectiveID.getLoc()); + parseDirectiveLtorg(DirectiveID.getLoc()); else if (IDVal == ".even") - return parseDirectiveEven(DirectiveID.getLoc()); + parseDirectiveEven(DirectiveID.getLoc()); else if (IDVal == ".personalityindex") - return parseDirectivePersonalityIndex(DirectiveID.getLoc()); + parseDirectivePersonalityIndex(DirectiveID.getLoc()); else if (IDVal == ".unwind_raw") - return parseDirectiveUnwindRaw(DirectiveID.getLoc()); + parseDirectiveUnwindRaw(DirectiveID.getLoc()); else if (IDVal == ".movsp") - return parseDirectiveMovSP(DirectiveID.getLoc()); + parseDirectiveMovSP(DirectiveID.getLoc()); else if (IDVal == ".arch_extension") - return parseDirectiveArchExtension(DirectiveID.getLoc()); + parseDirectiveArchExtension(DirectiveID.getLoc()); else if (IDVal == ".align") - return parseDirectiveAlign(DirectiveID.getLoc()); + return parseDirectiveAlign(DirectiveID.getLoc()); // Use Generic on failure. else if (IDVal == ".thumb_set") - return parseDirectiveThumbSet(DirectiveID.getLoc()); - - if (!IsMachO && !IsCOFF) { + parseDirectiveThumbSet(DirectiveID.getLoc()); + else if (!IsMachO && !IsCOFF) { if (IDVal == ".arch") - return parseDirectiveArch(DirectiveID.getLoc()); + parseDirectiveArch(DirectiveID.getLoc()); else if (IDVal == ".cpu") - return parseDirectiveCPU(DirectiveID.getLoc()); + parseDirectiveCPU(DirectiveID.getLoc()); else if (IDVal == ".eabi_attribute") - return parseDirectiveEabiAttr(DirectiveID.getLoc()); + parseDirectiveEabiAttr(DirectiveID.getLoc()); else if (IDVal == ".fpu") - return parseDirectiveFPU(DirectiveID.getLoc()); + parseDirectiveFPU(DirectiveID.getLoc()); else if (IDVal == ".fnstart") - return parseDirectiveFnStart(DirectiveID.getLoc()); + parseDirectiveFnStart(DirectiveID.getLoc()); else if (IDVal == ".inst") - return parseDirectiveInst(DirectiveID.getLoc()); + parseDirectiveInst(DirectiveID.getLoc()); else if (IDVal == ".inst.n") - return parseDirectiveInst(DirectiveID.getLoc(), 'n'); + parseDirectiveInst(DirectiveID.getLoc(), 'n'); else if (IDVal == ".inst.w") - return parseDirectiveInst(DirectiveID.getLoc(), 'w'); + parseDirectiveInst(DirectiveID.getLoc(), 'w'); else if (IDVal == ".object_arch") - return parseDirectiveObjectArch(DirectiveID.getLoc()); + parseDirectiveObjectArch(DirectiveID.getLoc()); else if (IDVal == ".tlsdescseq") - return parseDirectiveTLSDescSeq(DirectiveID.getLoc()); - } - - return true; + parseDirectiveTLSDescSeq(DirectiveID.getLoc()); + else + return true; + } else + return true; + return false; } /// parseLiteralValues @@ -9316,46 +9311,22 @@ bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) { /// ::= .short expression [, expression]* /// ::= .word expression [, expression]* bool ARMAsmParser::parseLiteralValues(unsigned Size, SMLoc L) { - MCAsmParser &Parser = getParser(); - if (getLexer().isNot(AsmToken::EndOfStatement)) { - for (;;) { - const MCExpr *Value; - if (getParser().parseExpression(Value)) { - return false; - } - - getParser().getStreamer().EmitValue(Value, Size, L); - - if (getLexer().is(AsmToken::EndOfStatement)) - break; - - // FIXME: Improve diagnostic. - if (getLexer().isNot(AsmToken::Comma)) { - Error(L, "unexpected token in directive"); - return false; - } - Parser.Lex(); - } - } - - Parser.Lex(); - return false; + auto parseOne = [&]() -> bool { + const MCExpr *Value; + if (getParser().parseExpression(Value)) + return true; + getParser().getStreamer().EmitValue(Value, Size, L); + return false; + }; + return (parseMany(parseOne)); } /// parseDirectiveThumb /// ::= .thumb bool ARMAsmParser::parseDirectiveThumb(SMLoc L) { - MCAsmParser &Parser = getParser(); - if (getLexer().isNot(AsmToken::EndOfStatement)) { - Error(L, "unexpected token in directive"); - return false; - } - Parser.Lex(); - - if (!hasThumb()) { - Error(L, "target does not support Thumb mode"); - return false; - } + if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive") || + check(!hasThumb(), L, "target does not support Thumb mode")) + return true; if (!isThumb()) SwitchMode(); @@ -9367,21 +9338,12 @@ bool ARMAsmParser::parseDirectiveThumb(SMLoc L) { /// parseDirectiveARM /// ::= .arm bool ARMAsmParser::parseDirectiveARM(SMLoc L) { - MCAsmParser &Parser = getParser(); - if (getLexer().isNot(AsmToken::EndOfStatement)) { - Error(L, "unexpected token in directive"); - return false; - } - Parser.Lex(); - - if (!hasARM()) { - Error(L, "target does not support ARM mode"); - return false; - } + if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive") || + check(!hasARM(), L, "target does not support ARM mode")) + return true; if (isThumb()) SwitchMode(); - getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32); return false; } @@ -9405,26 +9367,24 @@ bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) { // Darwin asm has (optionally) function name after .thumb_func direction // ELF doesn't - if (IsMachO) { - const AsmToken &Tok = Parser.getTok(); - if (Tok.isNot(AsmToken::EndOfStatement)) { - if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String)) { - Error(L, "unexpected token in .thumb_func directive"); - return false; - } - MCSymbol *Func = - getParser().getContext().getOrCreateSymbol(Tok.getIdentifier()); + if (IsMachO) { + if (Parser.getTok().is(AsmToken::Identifier) || + Parser.getTok().is(AsmToken::String)) { + MCSymbol *Func = getParser().getContext().getOrCreateSymbol( + Parser.getTok().getIdentifier()); getParser().getStreamer().EmitThumbFunc(Func); - Parser.Lex(); // Consume the identifier token. + Parser.Lex(); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.thumb_func' directive")) + return true; return false; } } - if (getLexer().isNot(AsmToken::EndOfStatement)) { - Error(Parser.getTok().getLoc(), "unexpected token in directive"); - return false; - } + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.thumb_func' directive")) + return true; NextSymbolIsThumb = true; return false; @@ -9441,21 +9401,13 @@ bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) { } StringRef Mode = Tok.getString(); - if (Mode == "unified" || Mode == "UNIFIED") { - Parser.Lex(); - } else if (Mode == "divided" || Mode == "DIVIDED") { - Error(L, "'.syntax divided' arm asssembly not supported"); - return false; - } else { - Error(L, "unrecognized syntax mode in .syntax directive"); - return false; - } - - if (getLexer().isNot(AsmToken::EndOfStatement)) { - Error(Parser.getTok().getLoc(), "unexpected token in directive"); - return false; - } Parser.Lex(); + if (check(Mode == "divided" || Mode == "DIVIDED", L, + "'.syntax divided' arm assembly not supported") || + check(Mode != "unified" && Mode != "UNIFIED", L, + "unrecognized syntax mode in .syntax directive") || + parseToken(AsmToken::EndOfStatement, "unexpected token in directive")) + return true; // TODO tell the MC streamer the mode // getParser().getStreamer().Emit???(); @@ -9467,10 +9419,8 @@ bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) { bool ARMAsmParser::parseDirectiveCode(SMLoc L) { MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); - if (Tok.isNot(AsmToken::Integer)) { - Error(L, "unexpected token in .code directive"); - return false; - } + if (Tok.isNot(AsmToken::Integer)) + return Error(L, "unexpected token in .code directive"); int64_t Val = Parser.getTok().getIntVal(); if (Val != 16 && Val != 32) { Error(L, "invalid operand to .code directive"); @@ -9478,26 +9428,19 @@ bool ARMAsmParser::parseDirectiveCode(SMLoc L) { } Parser.Lex(); - if (getLexer().isNot(AsmToken::EndOfStatement)) { - Error(Parser.getTok().getLoc(), "unexpected token in directive"); - return false; - } - Parser.Lex(); + if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive")) + return true; if (Val == 16) { - if (!hasThumb()) { - Error(L, "target does not support Thumb mode"); - return false; - } + if (!hasThumb()) + return Error(L, "target does not support Thumb mode"); if (!isThumb()) SwitchMode(); getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16); } else { - if (!hasARM()) { - Error(L, "target does not support ARM mode"); - return false; - } + if (!hasARM()) + return Error(L, "target does not support ARM mode"); if (isThumb()) SwitchMode(); @@ -9514,23 +9457,15 @@ bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) { Parser.Lex(); // Eat the '.req' token. unsigned Reg; SMLoc SRegLoc, ERegLoc; - if (ParseRegister(Reg, SRegLoc, ERegLoc)) { - Error(SRegLoc, "register name expected"); - return false; - } + if (check(ParseRegister(Reg, SRegLoc, ERegLoc), SRegLoc, + "register name expected") || + parseToken(AsmToken::EndOfStatement, + "unexpected input in .req directive.")) + return true; - // Shouldn't be anything else. - if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { - Error(Parser.getTok().getLoc(), "unexpected input in .req directive."); - return false; - } - - Parser.Lex(); // Consume the EndOfStatement - - if (RegisterReqs.insert(std::make_pair(Name, Reg)).first->second != Reg) { - Error(SRegLoc, "redefinition of '" + Name + "' does not match original."); - return false; - } + if (RegisterReqs.insert(std::make_pair(Name, Reg)).first->second != Reg) + return Error(SRegLoc, + "redefinition of '" + Name + "' does not match original."); return false; } @@ -9539,12 +9474,13 @@ bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) { /// ::= .unreq registername bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) { MCAsmParser &Parser = getParser(); - if (Parser.getTok().isNot(AsmToken::Identifier)) { - Error(L, "unexpected input in .unreq directive."); - return false; - } + if (Parser.getTok().isNot(AsmToken::Identifier)) + return Error(L, "unexpected input in .unreq directive."); RegisterReqs.erase(Parser.getTok().getIdentifier().lower()); Parser.Lex(); // Eat the identifier. + if (parseToken(AsmToken::EndOfStatement, + "unexpected input in '.unreq' directive")) + return true; return false; } @@ -9577,13 +9513,10 @@ void ARMAsmParser::FixModeAfterArchChange(bool WasThumb, SMLoc Loc) { /// ::= .arch token bool ARMAsmParser::parseDirectiveArch(SMLoc L) { StringRef Arch = getParser().parseStringToEndOfStatement().trim(); - unsigned ID = ARM::parseArch(Arch); - if (ID == ARM::AK_INVALID) { - Error(L, "Unknown arch name"); - return false; - } + if (ID == ARM::AK_INVALID) + return Error(L, "Unknown arch name"); bool WasThumb = isThumb(); Triple T; @@ -9616,24 +9549,18 @@ bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { const MCExpr *AttrExpr; TagLoc = Parser.getTok().getLoc(); - if (Parser.parseExpression(AttrExpr)) { - return false; - } + if (Parser.parseExpression(AttrExpr)) + return true; const MCConstantExpr *CE = dyn_cast(AttrExpr); - if (!CE) { - Error(TagLoc, "expected numeric constant"); - return false; - } + if (check(!CE, TagLoc, "expected numeric constant")) + return true; Tag = CE->getValue(); } - if (Parser.getTok().isNot(AsmToken::Comma)) { - Error(Parser.getTok().getLoc(), "comma expected"); - return false; - } - Parser.Lex(); // skip comma + if (Parser.parseToken(AsmToken::Comma, "comma expected")) + return true; StringRef StringValue = ""; bool IsStringValue = false; @@ -9656,40 +9583,32 @@ bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { if (IsIntegerValue) { const MCExpr *ValueExpr; SMLoc ValueExprLoc = Parser.getTok().getLoc(); - if (Parser.parseExpression(ValueExpr)) { - return false; - } + if (Parser.parseExpression(ValueExpr)) + return true; const MCConstantExpr *CE = dyn_cast(ValueExpr); - if (!CE) { - Error(ValueExprLoc, "expected numeric constant"); - return false; - } - + if (!CE) + return Error(ValueExprLoc, "expected numeric constant"); IntegerValue = CE->getValue(); } if (Tag == ARMBuildAttrs::compatibility) { - if (Parser.getTok().isNot(AsmToken::Comma)) - IsStringValue = false; - if (Parser.getTok().isNot(AsmToken::Comma)) { - Error(Parser.getTok().getLoc(), "comma expected"); - return false; - } else { - Parser.Lex(); - } + if (Parser.parseToken(AsmToken::Comma, "comma expected")) + return true; } if (IsStringValue) { - if (Parser.getTok().isNot(AsmToken::String)) { - Error(Parser.getTok().getLoc(), "bad string constant"); - return false; - } + if (Parser.getTok().isNot(AsmToken::String)) + return Error(Parser.getTok().getLoc(), "bad string constant"); StringValue = Parser.getTok().getStringContents(); Parser.Lex(); } + if (Parser.parseToken(AsmToken::EndOfStatement, + "unexpected token in '.eabi_attribute' directive")) + return true; + if (IsIntegerValue && IsStringValue) { assert(Tag == ARMBuildAttrs::compatibility); getTargetStreamer().emitIntTextAttribute(Tag, IntegerValue, StringValue); @@ -9708,10 +9627,8 @@ bool ARMAsmParser::parseDirectiveCPU(SMLoc L) { // FIXME: This is using table-gen data, but should be moved to // ARMTargetParser once that is table-gen'd. - if (!getSTI().isCPUStringValid(CPU)) { - Error(L, "Unknown CPU name"); - return false; - } + if (!getSTI().isCPUStringValid(CPU)) + return Error(L, "Unknown CPU name"); bool WasThumb = isThumb(); MCSubtargetInfo &STI = copySTI(); @@ -9729,10 +9646,8 @@ bool ARMAsmParser::parseDirectiveFPU(SMLoc L) { unsigned ID = ARM::parseFPU(FPU); std::vector Features; - if (!ARM::getFPUFeatures(ID, Features)) { - Error(FPUNameLoc, "Unknown FPU name"); - return false; - } + if (!ARM::getFPUFeatures(ID, Features)) + return Error(FPUNameLoc, "Unknown FPU name"); MCSubtargetInfo &STI = copySTI(); for (auto Feature : Features) @@ -9746,10 +9661,14 @@ bool ARMAsmParser::parseDirectiveFPU(SMLoc L) { /// parseDirectiveFnStart /// ::= .fnstart bool ARMAsmParser::parseDirectiveFnStart(SMLoc L) { + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.fnstart' directive")) + return true; + if (UC.hasFnStart()) { Error(L, ".fnstart starts before the end of previous one"); UC.emitFnStartLocNotes(); - return false; + return true; } // Reset the unwind directives parser state @@ -9764,11 +9683,12 @@ bool ARMAsmParser::parseDirectiveFnStart(SMLoc L) { /// parseDirectiveFnEnd /// ::= .fnend bool ARMAsmParser::parseDirectiveFnEnd(SMLoc L) { + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.fnend' directive")) + return true; // Check the ordering of unwind directives - if (!UC.hasFnStart()) { - Error(L, ".fnstart must precede .fnend directive"); - return false; - } + if (!UC.hasFnStart()) + return Error(L, ".fnstart must precede .fnend directive"); // Reset the unwind directives parser state getTargetStreamer().emitFnEnd(); @@ -9780,22 +9700,24 @@ bool ARMAsmParser::parseDirectiveFnEnd(SMLoc L) { /// parseDirectiveCantUnwind /// ::= .cantunwind bool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) { - UC.recordCantUnwind(L); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.cantunwind' directive")) + return true; + UC.recordCantUnwind(L); // Check the ordering of unwind directives - if (!UC.hasFnStart()) { - Error(L, ".fnstart must precede .cantunwind directive"); - return false; - } + if (check(!UC.hasFnStart(), L, ".fnstart must precede .cantunwind directive")) + return true; + if (UC.hasHandlerData()) { Error(L, ".cantunwind can't be used with .handlerdata directive"); UC.emitHandlerDataLocNotes(); - return false; + return true; } if (UC.hasPersonality()) { Error(L, ".cantunwind can't be used with .personality directive"); UC.emitPersonalityLocNotes(); - return false; + return true; } getTargetStreamer().emitCantUnwind(); @@ -9808,37 +9730,37 @@ bool ARMAsmParser::parseDirectivePersonality(SMLoc L) { MCAsmParser &Parser = getParser(); bool HasExistingPersonality = UC.hasPersonality(); + // Parse the name of the personality routine + if (Parser.getTok().isNot(AsmToken::Identifier)) + return Error(L, "unexpected input in .personality directive."); + StringRef Name(Parser.getTok().getIdentifier()); + Parser.Lex(); + + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.personality' directive")) + return true; + UC.recordPersonality(L); // Check the ordering of unwind directives - if (!UC.hasFnStart()) { - Error(L, ".fnstart must precede .personality directive"); - return false; - } + if (!UC.hasFnStart()) + return Error(L, ".fnstart must precede .personality directive"); if (UC.cantUnwind()) { Error(L, ".personality can't be used with .cantunwind directive"); UC.emitCantUnwindLocNotes(); - return false; + return true; } if (UC.hasHandlerData()) { Error(L, ".personality must precede .handlerdata directive"); UC.emitHandlerDataLocNotes(); - return false; + return true; } if (HasExistingPersonality) { Error(L, "multiple personality directives"); UC.emitPersonalityLocNotes(); - return false; + return true; } - // Parse the name of the personality routine - if (Parser.getTok().isNot(AsmToken::Identifier)) { - Error(L, "unexpected input in .personality directive."); - return false; - } - StringRef Name(Parser.getTok().getIdentifier()); - Parser.Lex(); - MCSymbol *PR = getParser().getContext().getOrCreateSymbol(Name); getTargetStreamer().emitPersonality(PR); return false; @@ -9847,17 +9769,18 @@ bool ARMAsmParser::parseDirectivePersonality(SMLoc L) { /// parseDirectiveHandlerData /// ::= .handlerdata bool ARMAsmParser::parseDirectiveHandlerData(SMLoc L) { - UC.recordHandlerData(L); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.handlerdata' directive")) + return true; + UC.recordHandlerData(L); // Check the ordering of unwind directives - if (!UC.hasFnStart()) { - Error(L, ".fnstart must precede .personality directive"); - return false; - } + if (!UC.hasFnStart()) + return Error(L, ".fnstart must precede .personality directive"); if (UC.cantUnwind()) { Error(L, ".handlerdata can't be used with .cantunwind directive"); UC.emitCantUnwindLocNotes(); - return false; + return true; } getTargetStreamer().emitHandlerData(); @@ -9869,74 +9792,52 @@ bool ARMAsmParser::parseDirectiveHandlerData(SMLoc L) { bool ARMAsmParser::parseDirectiveSetFP(SMLoc L) { MCAsmParser &Parser = getParser(); // Check the ordering of unwind directives - if (!UC.hasFnStart()) { - Error(L, ".fnstart must precede .setfp directive"); - return false; - } - if (UC.hasHandlerData()) { - Error(L, ".setfp must precede .handlerdata directive"); - return false; - } + if (check(!UC.hasFnStart(), L, ".fnstart must precede .setfp directive") || + check(UC.hasHandlerData(), L, + ".setfp must precede .handlerdata directive")) + return true; // Parse fpreg SMLoc FPRegLoc = Parser.getTok().getLoc(); int FPReg = tryParseRegister(); - if (FPReg == -1) { - Error(FPRegLoc, "frame pointer register expected"); - return false; - } - // Consume comma - if (Parser.getTok().isNot(AsmToken::Comma)) { - Error(Parser.getTok().getLoc(), "comma expected"); - return false; - } - Parser.Lex(); // skip comma + if (check(FPReg == -1, FPRegLoc, "frame pointer register expected") || + Parser.parseToken(AsmToken::Comma, "comma expected")) + return true; // Parse spreg SMLoc SPRegLoc = Parser.getTok().getLoc(); int SPReg = tryParseRegister(); - if (SPReg == -1) { - Error(SPRegLoc, "stack pointer register expected"); - return false; - } - - if (SPReg != ARM::SP && SPReg != UC.getFPReg()) { - Error(SPRegLoc, "register should be either $sp or the latest fp register"); - return false; - } + if (check(SPReg == -1, SPRegLoc, "stack pointer register expected") || + check(SPReg != ARM::SP && SPReg != UC.getFPReg(), SPRegLoc, + "register should be either $sp or the latest fp register")) + return true; // Update the frame pointer register UC.saveFPReg(FPReg); // Parse offset int64_t Offset = 0; - if (Parser.getTok().is(AsmToken::Comma)) { - Parser.Lex(); // skip comma - + if (Parser.parseOptionalToken(AsmToken::Comma)) { if (Parser.getTok().isNot(AsmToken::Hash) && - Parser.getTok().isNot(AsmToken::Dollar)) { - Error(Parser.getTok().getLoc(), "'#' expected"); - return false; - } + Parser.getTok().isNot(AsmToken::Dollar)) + return Error(Parser.getTok().getLoc(), "'#' expected"); Parser.Lex(); // skip hash token. const MCExpr *OffsetExpr; SMLoc ExLoc = Parser.getTok().getLoc(); SMLoc EndLoc; - if (getParser().parseExpression(OffsetExpr, EndLoc)) { - Error(ExLoc, "malformed setfp offset"); - return false; - } + if (getParser().parseExpression(OffsetExpr, EndLoc)) + return Error(ExLoc, "malformed setfp offset"); const MCConstantExpr *CE = dyn_cast(OffsetExpr); - if (!CE) { - Error(ExLoc, "setfp offset must be an immediate"); - return false; - } - + if (check(!CE, ExLoc, "setfp offset must be an immediate")) + return true; Offset = CE->getValue(); } + if (Parser.parseToken(AsmToken::EndOfStatement)) + return true; + getTargetStreamer().emitSetFP(static_cast(FPReg), static_cast(SPReg), Offset); return false; @@ -9947,35 +9848,29 @@ bool ARMAsmParser::parseDirectiveSetFP(SMLoc L) { bool ARMAsmParser::parseDirectivePad(SMLoc L) { MCAsmParser &Parser = getParser(); // Check the ordering of unwind directives - if (!UC.hasFnStart()) { - Error(L, ".fnstart must precede .pad directive"); - return false; - } - if (UC.hasHandlerData()) { - Error(L, ".pad must precede .handlerdata directive"); - return false; - } + if (!UC.hasFnStart()) + return Error(L, ".fnstart must precede .pad directive"); + if (UC.hasHandlerData()) + return Error(L, ".pad must precede .handlerdata directive"); // Parse the offset if (Parser.getTok().isNot(AsmToken::Hash) && - Parser.getTok().isNot(AsmToken::Dollar)) { - Error(Parser.getTok().getLoc(), "'#' expected"); - return false; - } + Parser.getTok().isNot(AsmToken::Dollar)) + return Error(Parser.getTok().getLoc(), "'#' expected"); Parser.Lex(); // skip hash token. const MCExpr *OffsetExpr; SMLoc ExLoc = Parser.getTok().getLoc(); SMLoc EndLoc; - if (getParser().parseExpression(OffsetExpr, EndLoc)) { - Error(ExLoc, "malformed pad offset"); - return false; - } + if (getParser().parseExpression(OffsetExpr, EndLoc)) + return Error(ExLoc, "malformed pad offset"); const MCConstantExpr *CE = dyn_cast(OffsetExpr); - if (!CE) { - Error(ExLoc, "pad offset must be an immediate"); - return false; - } + if (!CE) + return Error(ExLoc, "pad offset must be an immediate"); + + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.pad' directive")) + return true; getTargetStreamer().emitPad(CE->getValue()); return false; @@ -9986,30 +9881,23 @@ bool ARMAsmParser::parseDirectivePad(SMLoc L) { /// ::= .vsave { registers } bool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) { // Check the ordering of unwind directives - if (!UC.hasFnStart()) { - Error(L, ".fnstart must precede .save or .vsave directives"); - return false; - } - if (UC.hasHandlerData()) { - Error(L, ".save or .vsave must precede .handlerdata directive"); - return false; - } + if (!UC.hasFnStart()) + return Error(L, ".fnstart must precede .save or .vsave directives"); + if (UC.hasHandlerData()) + return Error(L, ".save or .vsave must precede .handlerdata directive"); // RAII object to make sure parsed operands are deleted. SmallVector, 1> Operands; // Parse the register list - if (parseRegisterList(Operands)) - return false; + if (parseRegisterList(Operands) || + parseToken(AsmToken::EndOfStatement, "unexpected token in directive")) + return true; ARMOperand &Op = (ARMOperand &)*Operands[0]; - if (!IsVector && !Op.isRegList()) { - Error(L, ".save expects GPR registers"); - return false; - } - if (IsVector && !Op.isDPRRegList()) { - Error(L, ".vsave expects DPR registers"); - return false; - } + if (!IsVector && !Op.isRegList()) + return Error(L, ".save expects GPR registers"); + if (IsVector && !Op.isDPRRegList()) + return Error(L, ".vsave expects DPR registers"); getTargetStreamer().emitRegSave(Op.getRegList(), IsVector); return false; @@ -10020,8 +9908,7 @@ bool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) { /// ::= .inst.n opcode [, ...] /// ::= .inst.w opcode [, ...] bool ARMAsmParser::parseDirectiveInst(SMLoc Loc, char Suffix) { - MCAsmParser &Parser = getParser(); - int Width; + int Width = 4; if (isThumb()) { switch (Suffix) { @@ -10029,78 +9916,55 @@ bool ARMAsmParser::parseDirectiveInst(SMLoc Loc, char Suffix) { Width = 2; break; case 'w': - Width = 4; break; default: - Error(Loc, "cannot determine Thumb instruction size, " - "use inst.n/inst.w instead"); - return false; + return Error(Loc, "cannot determine Thumb instruction size, " + "use inst.n/inst.w instead"); } } else { - if (Suffix) { - Error(Loc, "width suffixes are invalid in ARM mode"); - return false; - } - Width = 4; + if (Suffix) + return Error(Loc, "width suffixes are invalid in ARM mode"); } - if (getLexer().is(AsmToken::EndOfStatement)) { - Error(Loc, "expected expression following directive"); - return false; - } - - for (;;) { + auto parseOne = [&]() -> bool { const MCExpr *Expr; - - if (getParser().parseExpression(Expr)) { - Error(Loc, "expected expression"); - return false; - } - + if (getParser().parseExpression(Expr)) + return true; const MCConstantExpr *Value = dyn_cast_or_null(Expr); if (!Value) { - Error(Loc, "expected constant expression"); - return false; + return Error(Loc, "expected constant expression"); } switch (Width) { case 2: - if (Value->getValue() > 0xffff) { - Error(Loc, "inst.n operand is too big, use inst.w instead"); - return false; - } + if (Value->getValue() > 0xffff) + return Error(Loc, "inst.n operand is too big, use inst.w instead"); break; case 4: - if (Value->getValue() > 0xffffffff) { - Error(Loc, - StringRef(Suffix ? "inst.w" : "inst") + " operand is too big"); - return false; - } + if (Value->getValue() > 0xffffffff) + return Error(Loc, StringRef(Suffix ? "inst.w" : "inst") + + " operand is too big"); break; default: llvm_unreachable("only supported widths are 2 and 4"); } getTargetStreamer().emitInst(Value->getValue(), Suffix); + return false; + }; - if (getLexer().is(AsmToken::EndOfStatement)) - break; - - if (getLexer().isNot(AsmToken::Comma)) { - Error(Loc, "unexpected token in directive"); - return false; - } - - Parser.Lex(); - } - - Parser.Lex(); + if (parseOptionalToken(AsmToken::EndOfStatement)) + return Error(Loc, "expected expression following directive"); + if (parseMany(parseOne)) + return true; return false; } /// parseDirectiveLtorg /// ::= .ltorg | .pool bool ARMAsmParser::parseDirectiveLtorg(SMLoc L) { + if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive")) + return true; getTargetStreamer().emitCurrentConstantPool(); return false; } @@ -10108,10 +9972,8 @@ bool ARMAsmParser::parseDirectiveLtorg(SMLoc L) { bool ARMAsmParser::parseDirectiveEven(SMLoc L) { const MCSection *Section = getStreamer().getCurrentSectionOnly(); - if (getLexer().isNot(AsmToken::EndOfStatement)) { - TokError("unexpected token in directive"); - return false; - } + if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive")) + return true; if (!Section) { getStreamer().InitSections(false); @@ -10133,44 +9995,41 @@ bool ARMAsmParser::parseDirectivePersonalityIndex(SMLoc L) { MCAsmParser &Parser = getParser(); bool HasExistingPersonality = UC.hasPersonality(); + const MCExpr *IndexExpression; + SMLoc IndexLoc = Parser.getTok().getLoc(); + if (Parser.parseExpression(IndexExpression) || + parseToken(AsmToken::EndOfStatement, + "unexpected token in '.personalityindex' directive")) { + return true; + } + UC.recordPersonalityIndex(L); if (!UC.hasFnStart()) { - Error(L, ".fnstart must precede .personalityindex directive"); - return false; + return Error(L, ".fnstart must precede .personalityindex directive"); } if (UC.cantUnwind()) { Error(L, ".personalityindex cannot be used with .cantunwind"); UC.emitCantUnwindLocNotes(); - return false; + return true; } if (UC.hasHandlerData()) { Error(L, ".personalityindex must precede .handlerdata directive"); UC.emitHandlerDataLocNotes(); - return false; + return true; } if (HasExistingPersonality) { Error(L, "multiple personality directives"); UC.emitPersonalityLocNotes(); - return false; - } - - const MCExpr *IndexExpression; - SMLoc IndexLoc = Parser.getTok().getLoc(); - if (Parser.parseExpression(IndexExpression)) { - return false; + return true; } const MCConstantExpr *CE = dyn_cast(IndexExpression); - if (!CE) { - Error(IndexLoc, "index must be a constant number"); - return false; - } - if (CE->getValue() < 0 || - CE->getValue() >= ARM::EHABI::NUM_PERSONALITY_INDEX) { - Error(IndexLoc, "personality routine index should be in range [0-3]"); - return false; - } + if (!CE) + return Error(IndexLoc, "index must be a constant number"); + if (CE->getValue() < 0 || CE->getValue() >= ARM::EHABI::NUM_PERSONALITY_INDEX) + return Error(IndexLoc, + "personality routine index should be in range [0-3]"); getTargetStreamer().emitPersonalityIndex(CE->getValue()); return false; @@ -10180,73 +10039,51 @@ bool ARMAsmParser::parseDirectivePersonalityIndex(SMLoc L) { /// ::= .unwind_raw offset, opcode [, opcode...] bool ARMAsmParser::parseDirectiveUnwindRaw(SMLoc L) { MCAsmParser &Parser = getParser(); - if (!UC.hasFnStart()) { - Error(L, ".fnstart must precede .unwind_raw directives"); - return false; - } - int64_t StackOffset; - const MCExpr *OffsetExpr; SMLoc OffsetLoc = getLexer().getLoc(); - if (getLexer().is(AsmToken::EndOfStatement) || - getParser().parseExpression(OffsetExpr)) { - Error(OffsetLoc, "expected expression"); - return false; - } + + if (!UC.hasFnStart()) + return Error(L, ".fnstart must precede .unwind_raw directives"); + if (getParser().parseExpression(OffsetExpr)) + return Error(OffsetLoc, "expected expression"); const MCConstantExpr *CE = dyn_cast(OffsetExpr); - if (!CE) { - Error(OffsetLoc, "offset must be a constant"); - return false; - } + if (!CE) + return Error(OffsetLoc, "offset must be a constant"); StackOffset = CE->getValue(); - if (getLexer().isNot(AsmToken::Comma)) { - Error(getLexer().getLoc(), "expected comma"); - return false; - } - Parser.Lex(); + if (Parser.parseToken(AsmToken::Comma, "expected comma")) + return true; SmallVector Opcodes; - for (;;) { + + auto parseOne = [&]() -> bool { const MCExpr *OE; - SMLoc OpcodeLoc = getLexer().getLoc(); - if (getLexer().is(AsmToken::EndOfStatement) || Parser.parseExpression(OE)) { - Error(OpcodeLoc, "expected opcode expression"); - return false; - } - + if (check(getLexer().is(AsmToken::EndOfStatement) || + Parser.parseExpression(OE), + OpcodeLoc, "expected opcode expression")) + return true; const MCConstantExpr *OC = dyn_cast(OE); - if (!OC) { - Error(OpcodeLoc, "opcode value must be a constant"); - return false; - } - + if (!OC) + return Error(OpcodeLoc, "opcode value must be a constant"); const int64_t Opcode = OC->getValue(); - if (Opcode & ~0xff) { - Error(OpcodeLoc, "invalid opcode"); - return false; - } - + if (Opcode & ~0xff) + return Error(OpcodeLoc, "invalid opcode"); Opcodes.push_back(uint8_t(Opcode)); + return false; + }; - if (getLexer().is(AsmToken::EndOfStatement)) - break; - - if (getLexer().isNot(AsmToken::Comma)) { - Error(getLexer().getLoc(), "unexpected token in directive"); - return false; - } - - Parser.Lex(); - } + // Must have at least 1 element + SMLoc OpcodeLoc = getLexer().getLoc(); + if (parseOptionalToken(AsmToken::EndOfStatement)) + return Error(OpcodeLoc, "expected opcode expression"); + if (parseMany(parseOne)) + return true; getTargetStreamer().emitUnwindRaw(StackOffset, Opcodes); - - Parser.Lex(); return false; } @@ -10255,20 +10092,17 @@ bool ARMAsmParser::parseDirectiveUnwindRaw(SMLoc L) { bool ARMAsmParser::parseDirectiveTLSDescSeq(SMLoc L) { MCAsmParser &Parser = getParser(); - if (getLexer().isNot(AsmToken::Identifier)) { - TokError("expected variable after '.tlsdescseq' directive"); - return false; - } + if (getLexer().isNot(AsmToken::Identifier)) + return TokError("expected variable after '.tlsdescseq' directive"); const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Parser.getTok().getIdentifier(), MCSymbolRefExpr::VK_ARM_TLSDESCSEQ, getContext()); Lex(); - if (getLexer().isNot(AsmToken::EndOfStatement)) { - Error(Parser.getTok().getLoc(), "unexpected token"); - return false; - } + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.tlsdescseq' directive")) + return true; getTargetStreamer().AnnotateTLSDescriptorSequence(SRE); return false; @@ -10278,53 +10112,40 @@ bool ARMAsmParser::parseDirectiveTLSDescSeq(SMLoc L) { /// ::= .movsp reg [, #offset] bool ARMAsmParser::parseDirectiveMovSP(SMLoc L) { MCAsmParser &Parser = getParser(); - if (!UC.hasFnStart()) { - Error(L, ".fnstart must precede .movsp directives"); - return false; - } - if (UC.getFPReg() != ARM::SP) { - Error(L, "unexpected .movsp directive"); - return false; - } + if (!UC.hasFnStart()) + return Error(L, ".fnstart must precede .movsp directives"); + if (UC.getFPReg() != ARM::SP) + return Error(L, "unexpected .movsp directive"); SMLoc SPRegLoc = Parser.getTok().getLoc(); int SPReg = tryParseRegister(); - if (SPReg == -1) { - Error(SPRegLoc, "register expected"); - return false; - } - - if (SPReg == ARM::SP || SPReg == ARM::PC) { - Error(SPRegLoc, "sp and pc are not permitted in .movsp directive"); - return false; - } + if (SPReg == -1) + return Error(SPRegLoc, "register expected"); + if (SPReg == ARM::SP || SPReg == ARM::PC) + return Error(SPRegLoc, "sp and pc are not permitted in .movsp directive"); int64_t Offset = 0; - if (Parser.getTok().is(AsmToken::Comma)) { - Parser.Lex(); - - if (Parser.getTok().isNot(AsmToken::Hash)) { - Error(Parser.getTok().getLoc(), "expected #constant"); - return false; - } - Parser.Lex(); + if (Parser.parseOptionalToken(AsmToken::Comma)) { + if (Parser.parseToken(AsmToken::Hash, "expected #constant")) + return true; const MCExpr *OffsetExpr; SMLoc OffsetLoc = Parser.getTok().getLoc(); - if (Parser.parseExpression(OffsetExpr)) { - Error(OffsetLoc, "malformed offset expression"); - return false; - } + + if (Parser.parseExpression(OffsetExpr)) + return Error(OffsetLoc, "malformed offset expression"); const MCConstantExpr *CE = dyn_cast(OffsetExpr); - if (!CE) { - Error(OffsetLoc, "offset must be an immediate constant"); - return false; - } + if (!CE) + return Error(OffsetLoc, "offset must be an immediate constant"); Offset = CE->getValue(); } + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.movsp' directive")) + return true; + getTargetStreamer().emitMovSP(SPReg, Offset); UC.saveFPReg(SPReg); @@ -10335,10 +10156,8 @@ bool ARMAsmParser::parseDirectiveMovSP(SMLoc L) { /// ::= .object_arch name bool ARMAsmParser::parseDirectiveObjectArch(SMLoc L) { MCAsmParser &Parser = getParser(); - if (getLexer().isNot(AsmToken::Identifier)) { - Error(getLexer().getLoc(), "unexpected token"); - return false; - } + if (getLexer().isNot(AsmToken::Identifier)) + return Error(getLexer().getLoc(), "unexpected token"); StringRef Arch = Parser.getTok().getString(); SMLoc ArchLoc = Parser.getTok().getLoc(); @@ -10346,17 +10165,12 @@ bool ARMAsmParser::parseDirectiveObjectArch(SMLoc L) { unsigned ID = ARM::parseArch(Arch); - if (ID == ARM::AK_INVALID) { - Error(ArchLoc, "unknown architecture '" + Arch + "'"); - return false; - } + if (ID == ARM::AK_INVALID) + return Error(ArchLoc, "unknown architecture '" + Arch + "'"); + if (parseToken(AsmToken::EndOfStatement)) + return true; getTargetStreamer().emitObjectArch(ID); - - if (getLexer().isNot(AsmToken::EndOfStatement)) { - Error(getLexer().getLoc(), "unexpected token"); - } - return false; } @@ -10365,18 +10179,17 @@ bool ARMAsmParser::parseDirectiveObjectArch(SMLoc L) { bool ARMAsmParser::parseDirectiveAlign(SMLoc L) { // NOTE: if this is not the end of the statement, fall back to the target // agnostic handling for this directive which will correctly handle this. - if (getLexer().isNot(AsmToken::EndOfStatement)) - return true; - - // '.align' is target specifically handled to mean 2**2 byte alignment. - const MCSection *Section = getStreamer().getCurrentSectionOnly(); - assert(Section && "must have section to emit alignment"); - if (Section->UseCodeAlign()) - getStreamer().EmitCodeAlignment(4, 0); - else - getStreamer().EmitValueToAlignment(4, 0, 1, 0); - - return false; + if (parseOptionalToken(AsmToken::EndOfStatement)) { + // '.align' is target specifically handled to mean 2**2 byte alignment. + const MCSection *Section = getStreamer().getCurrentSectionOnly(); + assert(Section && "must have section to emit alignment"); + if (Section->UseCodeAlign()) + getStreamer().EmitCodeAlignment(4, 0); + else + getStreamer().EmitValueToAlignment(4, 0, 1, 0); + return false; + } + return true; } /// parseDirectiveThumbSet @@ -10385,16 +10198,10 @@ bool ARMAsmParser::parseDirectiveThumbSet(SMLoc L) { MCAsmParser &Parser = getParser(); StringRef Name; - if (Parser.parseIdentifier(Name)) { - TokError("expected identifier after '.thumb_set'"); - return false; - } - - if (getLexer().isNot(AsmToken::Comma)) { - TokError("expected comma after name '" + Name + "'"); - return false; - } - Lex(); + if (check(Parser.parseIdentifier(Name), + "expected identifier after '.thumb_set'") || + parseToken(AsmToken::Comma, "expected comma after name '" + Name + "'")) + return true; MCSymbol *Sym; const MCExpr *Value; @@ -10453,40 +10260,37 @@ static const struct { bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { MCAsmParser &Parser = getParser(); - if (getLexer().isNot(AsmToken::Identifier)) { - Error(getLexer().getLoc(), "expected architecture extension name"); - return false; - } + if (getLexer().isNot(AsmToken::Identifier)) + return Error(getLexer().getLoc(), "expected architecture extension name"); StringRef Name = Parser.getTok().getString(); SMLoc ExtLoc = Parser.getTok().getLoc(); Lex(); + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.arch_extension' directive")) + return true; + bool EnableFeature = true; if (Name.startswith_lower("no")) { EnableFeature = false; Name = Name.substr(2); } unsigned FeatureKind = ARM::parseArchExt(Name); - if (FeatureKind == ARM::AEK_INVALID) { - Error(ExtLoc, "unknown architectural extension: " + Name); - return false; - } + if (FeatureKind == ARM::AEK_INVALID) + return Error(ExtLoc, "unknown architectural extension: " + Name); for (const auto &Extension : Extensions) { if (Extension.Kind != FeatureKind) continue; - if (Extension.Features.none()) { - Error(ExtLoc, "unsupported architectural extension: " + Name); - return false; - } + if (Extension.Features.none()) + return Error(ExtLoc, "unsupported architectural extension: " + Name); - if ((getAvailableFeatures() & Extension.ArchCheck) != Extension.ArchCheck) { - Error(ExtLoc, "architectural extension '" + Name + "' is not " - "allowed for the current base architecture"); - return false; - } + if ((getAvailableFeatures() & Extension.ArchCheck) != Extension.ArchCheck) + return Error(ExtLoc, "architectural extension '" + Name + + "' is not " + "allowed for the current base architecture"); MCSubtargetInfo &STI = copySTI(); FeatureBitset ToggleFeatures = EnableFeature @@ -10499,8 +10303,7 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { return false; } - Error(ExtLoc, "unknown architectural extension: " + Name); - return false; + return Error(ExtLoc, "unknown architectural extension: " + Name); } // Define this matcher function after the auto-generated include so we diff --git a/test/MC/ARM/directive-thumb_func.s b/test/MC/ARM/directive-thumb_func.s index f82e0d1b60a..e8390188835 100644 --- a/test/MC/ARM/directive-thumb_func.s +++ b/test/MC/ARM/directive-thumb_func.s @@ -14,7 +14,7 @@ no_suffix: suffix: bx lr -// CHECK-EABI: error: unexpected token in directive +// CHECK-EABI: error: unexpected token in '.thumb_func' directive // CHECK-EABI: .thumb_func suffix // CHECK-EABI: ^ diff --git a/test/MC/ARM/directive_parsing.s b/test/MC/ARM/directive_parsing.s new file mode 100644 index 00000000000..f49201c8b6d --- /dev/null +++ b/test/MC/ARM/directive_parsing.s @@ -0,0 +1,170 @@ +// RUN: not llvm-mc -triple armv7--none-eabi %s 2>&1 | FileCheck %s +// RUN: not llvm-mc -triple armv7--none-eabi %s 2>&1 | grep "error:" | count 33 + +// CHECK: [[@LINE+1]]:10: error: unexpected token + .word 0 $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .word 0 # EOL COMMENT +// CHECK: [[@LINE+1]]:11: error: unexpected token + .short 0 $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .short 0 # EOL COMMENT +// CHECK: [[@LINE+1]]:11: error: unexpected token + .hword 0 $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .hword 0 # EOL COMMENT + + .arch armv7-a +// CHECK: [[@LINE+1]]:9: error: unexpected token in directive + .thumb $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .thumb # EOL COMMENT + +// CHECK: [[@LINE+1]]:7: error: unexpected token in directive + .arm $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .arm # EOL COMMENT +// CHECK: [[@LINE+1]]:14: error: unexpected token in '.thumb_func' directive + .thumb_func $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .thumb_func # EOL COMMENT +// CHECK: [[@LINE+1]]:11: error: unexpected token in directive + .code 16 $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .code 16 # EOL COMMENTS +// CHECK: [[@LINE+1]]:18: error: unexpected token in directive + .syntax unified $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .syntax unified # EOL COMMENT + fred .req r5 +// CHECK: [[@LINE+1]]:14: error: unexpected input in '.unreq' directive + .unreq fred $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .unreq fred # EOL COMMENTS + +// CHECK: [[@LINE+1]]:18: error: unexpected token in '.fnstart' directive + .fnstart $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .fnstart # EOL COMMENT +// CHECK: [[@LINE+1]]:23: error: unexpected token in '.cantunwind' directive + .cantunwind $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .cantunwind # EOL COMMENT + + +// CHECK: [[@LINE+1]]:18: error: unexpected token in '.fnend' directive + .fnend $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .fnend # EOL COMMENT + + .fnstart +// CHECK: [[@LINE+1]]:43: error: unexpected token in '.personality' directive + .personality __gxx_personality_v0 $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .personality __gxx_personality_v0 # EOL COMMENET + +// CHECK: [[@LINE+1]]:28: error: unexpected token + .setfp fp, sp, #0 $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .setfp fp, sp, #0 # EOL COMMENT + + +// CHECK: [[@LINE+1]]:17: error: unexpected token in '.pad' directive + .pad #0 $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .pad #0 # EOL COMMENT + +// CHECK: [[@LINE+1]]:20: error: unexpected token in directive + .save {r0} $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .save {r0} # EOL COMMENT + +// CHECK: [[@LINE+1]]:21: error: unexpected token in directive + .vsave {d0} $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .vsave {d0} # EOL COMMENT + + +// CHECK: [[@LINE+1]]:22: error: unexpected token in '.handlerdata' directive + .handlerdata $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .handlerdata # EOL COMMENT + + .fnend + +// CHECK: [[@LINE+1]]:9: error: unexpected token in directive + .ltorg $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .ltorg # EOL COMMENT +// CHECK: [[@LINE+1]]:8: error: unexpected token in directive + .pool $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .pool # EOL COMMENT +// CHECK: [[@LINE+1]]:8: error: unexpected token in directive + .even $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .even # EOL COMMENT + .fnstart +// CHECK: [[@LINE+1]]:22: error: unexpected token in '.personalityindex' directive + .personalityindex 0 $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .personalityindex 0 # EOL COMMENT + .fnend + + .fnstart +// CHECK: [[@LINE+1]]:19: error: unexpected token + .unwind_raw 0, 0 $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .unwind_raw 0, 0 # EOL COMMENT + +// CHECK: [[@LINE+1]]:12: error: unexpected token in '.movsp' directive + .movsp r0 $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .movsp r1 # EOL COMMENT + .fnend + +// CHECK: [[@LINE+1]]:21: error: unexpected token in '.arch_extension' directive + .arch_extension mp $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .arch_extension mp # EOL COMMENT + +// CHECK: [[@LINE+1]]:21: error: unexpected token in '.arch_extension' directive + .arch_extension mp $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .arch_extension mp # EOL COMMENT + + .type arm_func,%function +arm_func: + nop +// CHECK: [[@LINE+1]]:45: error: unexpected token + .thumb_set alias_arm_func, arm_func $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .thumb_set alias_arm_func, arm_func # EOL COMMENT + +// CHECK: [[@LINE+1]]:23: error: unexpected token in '.eabi_attribute' directive + .eabi_attribute 0, 0 $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .eabi_attribute 0, 0 # EOL COMMENT + +.arm +// CHECK: [[@LINE+1]]:10: error: unexpected token + .inst 2 $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .inst 2 # EOL COMMENT +.thumb +// CHECK: [[@LINE+1]]:12: error: unexpected token + .inst.n 2 $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .inst.n 2 # EOL COMMENT +// CHECK: [[@LINE+1]]:12: error: unexpected token + .inst.w 4 $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .inst.w 4 # EOL COMMENT +// CHECK: [[@LINE+1]]:21: error: unexpected token + .object_arch armv7 $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .object_arch armv7 # EOL COMMENT +// CHECK: [[@LINE+1]]:23: error: unexpected token in '.tlsdescseq' directive + .tlsdescseq variable $ +// CHECK-NOT: [[@LINE+1]]:{{[0-9]+}}: error: + .tlsdescseq variable # EOL COMMENT