diff options
Diffstat (limited to 'contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 1384 |
1 files changed, 715 insertions, 669 deletions
diff --git a/contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index f5de8a3..c243a2d 100644 --- a/contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -40,6 +40,7 @@ #include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/ARMEHABI.h" #include "llvm/Support/COFF.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/MathExtras.h" @@ -52,6 +53,20 @@ using namespace llvm; namespace { +enum class ImplicitItModeTy { Always, Never, ARMOnly, ThumbOnly }; + +static cl::opt<ImplicitItModeTy> ImplicitItMode( + "arm-implicit-it", cl::init(ImplicitItModeTy::ARMOnly), + cl::desc("Allow conditional instructions outdside of an IT block"), + cl::values(clEnumValN(ImplicitItModeTy::Always, "always", + "Accept in both ISAs, emit implicit ITs in Thumb"), + clEnumValN(ImplicitItModeTy::Never, "never", + "Warn in ARM, reject in Thumb"), + clEnumValN(ImplicitItModeTy::ARMOnly, "arm", + "Accept in ARM, reject in Thumb"), + clEnumValN(ImplicitItModeTy::ThumbOnly, "thumb", + "Warn in ARM, emit implicit ITs in Thumb"))); + class ARMOperand; enum VectorLaneTy { NoLanes, AllLanes, IndexedLane }; @@ -145,6 +160,16 @@ class ARMAsmParser : public MCTargetAsmParser { bool NextSymbolIsThumb; + bool useImplicitITThumb() const { + return ImplicitItMode == ImplicitItModeTy::Always || + ImplicitItMode == ImplicitItModeTy::ThumbOnly; + } + + bool useImplicitITARM() const { + return ImplicitItMode == ImplicitItModeTy::Always || + ImplicitItMode == ImplicitItModeTy::ARMOnly; + } + struct { ARMCC::CondCodes Cond; // Condition for IT block. unsigned Mask:4; // Condition mask for instructions. @@ -153,40 +178,174 @@ class ARMAsmParser : public MCTargetAsmParser { // '0' inverse of condition (else). // Count of instructions in IT block is // 4 - trailingzeroes(mask) - - bool FirstCond; // Explicit flag for when we're parsing the - // First instruction in the IT block. It's - // implied in the mask, so needs special - // handling. + // Note that this does not have the same encoding + // as in the IT instruction, which also depends + // on the low bit of the condition code. unsigned CurPosition; // Current position in parsing of IT - // block. In range [0,3]. Initialized - // according to count of instructions in block. - // ~0U if no active IT block. + // block. In range [0,4], with 0 being the IT + // instruction itself. Initialized according to + // count of instructions in block. ~0U if no + // active IT block. + + bool IsExplicit; // true - The IT instruction was present in the + // input, we should not modify it. + // false - The IT instruction was added + // implicitly, we can extend it if that + // would be legal. } ITState; + + llvm::SmallVector<MCInst, 4> PendingConditionalInsts; + + void flushPendingInstructions(MCStreamer &Out) override { + if (!inImplicitITBlock()) { + assert(PendingConditionalInsts.size() == 0); + return; + } + + // Emit the IT instruction + unsigned Mask = getITMaskEncoding(); + MCInst ITInst; + ITInst.setOpcode(ARM::t2IT); + ITInst.addOperand(MCOperand::createImm(ITState.Cond)); + ITInst.addOperand(MCOperand::createImm(Mask)); + Out.EmitInstruction(ITInst, getSTI()); + + // Emit the conditonal instructions + assert(PendingConditionalInsts.size() <= 4); + for (const MCInst &Inst : PendingConditionalInsts) { + Out.EmitInstruction(Inst, getSTI()); + } + PendingConditionalInsts.clear(); + + // Clear the IT state + ITState.Mask = 0; + ITState.CurPosition = ~0U; + } + bool inITBlock() { return ITState.CurPosition != ~0U; } + bool inExplicitITBlock() { return inITBlock() && ITState.IsExplicit; } + bool inImplicitITBlock() { return inITBlock() && !ITState.IsExplicit; } bool lastInITBlock() { return ITState.CurPosition == 4 - countTrailingZeros(ITState.Mask); } void forwardITPosition() { if (!inITBlock()) return; // Move to the next instruction in the IT block, if there is one. If not, - // mark the block as done. + // mark the block as done, except for implicit IT blocks, which we leave + // open until we find an instruction that can't be added to it. unsigned TZ = countTrailingZeros(ITState.Mask); - if (++ITState.CurPosition == 5 - TZ) + if (++ITState.CurPosition == 5 - TZ && ITState.IsExplicit) ITState.CurPosition = ~0U; // Done with the IT block after this. } - void Note(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges = None) { - return getParser().Note(L, Msg, Ranges); + // Rewind the state of the current IT block, removing the last slot from it. + void rewindImplicitITPosition() { + assert(inImplicitITBlock()); + assert(ITState.CurPosition > 1); + ITState.CurPosition--; + unsigned TZ = countTrailingZeros(ITState.Mask); + unsigned NewMask = 0; + NewMask |= ITState.Mask & (0xC << TZ); + NewMask |= 0x2 << TZ; + ITState.Mask = NewMask; + } + + // Rewind the state of the current IT block, removing the last slot from it. + // If we were at the first slot, this closes the IT block. + void discardImplicitITBlock() { + assert(inImplicitITBlock()); + assert(ITState.CurPosition == 1); + ITState.CurPosition = ~0U; + return; } - bool Warning(SMLoc L, const Twine &Msg, - ArrayRef<SMRange> Ranges = None) { - return getParser().Warning(L, Msg, Ranges); + + // Get the encoding of the IT mask, as it will appear in an IT instruction. + unsigned getITMaskEncoding() { + assert(inITBlock()); + unsigned Mask = ITState.Mask; + unsigned TZ = countTrailingZeros(Mask); + if ((ITState.Cond & 1) == 0) { + assert(Mask && TZ <= 3 && "illegal IT mask value!"); + Mask ^= (0xE << TZ) & 0xF; + } + return Mask; } - bool Error(SMLoc L, const Twine &Msg, - ArrayRef<SMRange> Ranges = None) { - return getParser().Error(L, Msg, Ranges); + + // Get the condition code corresponding to the current IT block slot. + ARMCC::CondCodes currentITCond() { + unsigned MaskBit; + if (ITState.CurPosition == 1) + MaskBit = 1; + else + MaskBit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1; + + return MaskBit ? ITState.Cond : ARMCC::getOppositeCondition(ITState.Cond); + } + + // Invert the condition of the current IT block slot without changing any + // other slots in the same block. + void invertCurrentITCondition() { + if (ITState.CurPosition == 1) { + ITState.Cond = ARMCC::getOppositeCondition(ITState.Cond); + } else { + ITState.Mask ^= 1 << (5 - ITState.CurPosition); + } + } + + // Returns true if the current IT block is full (all 4 slots used). + bool isITBlockFull() { + return inITBlock() && (ITState.Mask & 1); + } + + // Extend the current implicit IT block to have one more slot with the given + // condition code. + void extendImplicitITBlock(ARMCC::CondCodes Cond) { + assert(inImplicitITBlock()); + assert(!isITBlockFull()); + assert(Cond == ITState.Cond || + Cond == ARMCC::getOppositeCondition(ITState.Cond)); + unsigned TZ = countTrailingZeros(ITState.Mask); + unsigned NewMask = 0; + // Keep any existing condition bits. + NewMask |= ITState.Mask & (0xE << TZ); + // Insert the new condition bit. + NewMask |= (Cond == ITState.Cond) << TZ; + // Move the trailing 1 down one bit. + NewMask |= 1 << (TZ - 1); + ITState.Mask = NewMask; + } + + // Create a new implicit IT block with a dummy condition code. + void startImplicitITBlock() { + assert(!inITBlock()); + ITState.Cond = ARMCC::AL; + ITState.Mask = 8; + ITState.CurPosition = 1; + ITState.IsExplicit = false; + return; + } + + // Create a new explicit IT block with the given condition and mask. The mask + // should be in the parsed format, with a 1 implying 't', regardless of the + // low bit of the condition. + void startExplicitITBlock(ARMCC::CondCodes Cond, unsigned Mask) { + assert(!inITBlock()); + ITState.Cond = Cond; + ITState.Mask = Mask; + ITState.CurPosition = 0; + ITState.IsExplicit = true; + return; + } + + void Note(SMLoc L, const Twine &Msg, SMRange Range = None) { + return getParser().Note(L, Msg, Range); + } + bool Warning(SMLoc L, const Twine &Msg, SMRange Range = None) { + return getParser().Warning(L, Msg, Range); + } + bool Error(SMLoc L, const Twine &Msg, SMRange Range = None) { + return getParser().Error(L, Msg, Range); } bool validatetLDMRegList(const MCInst &Inst, const OperandVector &Operands, @@ -355,6 +514,7 @@ class ARMAsmParser : public MCTargetAsmParser { bool processInstruction(MCInst &Inst, const OperandVector &Ops, MCStreamer &Out); bool shouldOmitCCOutOperand(StringRef Mnemonic, OperandVector &Operands); bool shouldOmitPredicateOperand(StringRef Mnemonic, OperandVector &Operands); + bool isITBlockTerminator(MCInst &Inst) const; public: enum ARMMatchResultTy { @@ -363,6 +523,7 @@ public: Match_RequiresV6, Match_RequiresThumb2, Match_RequiresV8, + Match_RequiresFlagSetting, #define GET_OPERAND_DIAGNOSTIC_TYPES #include "ARMGenAsmMatcher.inc" @@ -399,6 +560,9 @@ public: OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm) override; + unsigned MatchInstruction(OperandVector &Operands, MCInst &Inst, + uint64_t &ErrorInfo, bool MatchingInlineAsm, + bool &EmitInITBlock, MCStreamer &Out); void onLabelParsed(MCSymbol *Symbol) override; }; } // end anonymous namespace @@ -3286,7 +3450,7 @@ static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) { } /// parseITCondCode - Try to parse a condition code for an IT instruction. -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseITCondCode(OperandVector &Operands) { MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); @@ -3324,7 +3488,7 @@ ARMAsmParser::parseITCondCode(OperandVector &Operands) { /// parseCoprocNumOperand - Try to parse an coprocessor number operand. The /// token must be an Identifier when called, and if it is a coprocessor /// number, the token is eaten and the operand is added to the operand list. -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseCoprocNumOperand(OperandVector &Operands) { MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); @@ -3347,7 +3511,7 @@ ARMAsmParser::parseCoprocNumOperand(OperandVector &Operands) { /// parseCoprocRegOperand - Try to parse an coprocessor register operand. The /// token must be an Identifier when called, and if it is a coprocessor /// number, the token is eaten and the operand is added to the operand list. -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseCoprocRegOperand(OperandVector &Operands) { MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); @@ -3366,7 +3530,7 @@ ARMAsmParser::parseCoprocRegOperand(OperandVector &Operands) { /// parseCoprocOptionOperand - Try to parse an coprocessor option operand. /// coproc_option : '{' imm0_255 '}' -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseCoprocOptionOperand(OperandVector &Operands) { MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); @@ -3447,8 +3611,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(); @@ -3576,7 +3740,7 @@ bool ARMAsmParser::parseRegisterList(OperandVector &Operands) { } // Helper function to parse the lane index for vector lists. -ARMAsmParser::OperandMatchResultTy ARMAsmParser:: +OperandMatchResultTy ARMAsmParser:: parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index, SMLoc &EndLoc) { MCAsmParser &Parser = getParser(); Index = 0; // Always return a defined index value. @@ -3628,7 +3792,7 @@ parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index, SMLoc &EndLoc) { } // parse a vector register list -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseVectorList(OperandVector &Operands) { MCAsmParser &Parser = getParser(); VectorLaneTy LaneKind; @@ -3880,7 +4044,7 @@ ARMAsmParser::parseVectorList(OperandVector &Operands) { } /// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options. -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseMemBarrierOptOperand(OperandVector &Operands) { MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); @@ -3952,7 +4116,7 @@ ARMAsmParser::parseMemBarrierOptOperand(OperandVector &Operands) { } /// parseInstSyncBarrierOptOperand - Try to parse ISB inst sync barrier options. -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseInstSyncBarrierOptOperand(OperandVector &Operands) { MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); @@ -4004,7 +4168,7 @@ ARMAsmParser::parseInstSyncBarrierOptOperand(OperandVector &Operands) { /// parseProcIFlagsOperand - Try to parse iflags from CPS instruction. -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseProcIFlagsOperand(OperandVector &Operands) { MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); @@ -4039,7 +4203,7 @@ ARMAsmParser::parseProcIFlagsOperand(OperandVector &Operands) { } /// parseMSRMaskOperand - Try to parse mask flags from MSR instruction. -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); @@ -4192,7 +4356,7 @@ ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { /// parseBankedRegOperand - Try to parse a banked register (e.g. "lr_irq") for /// use in the MRS/MSR instructions added to support virtualization. -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseBankedRegOperand(OperandVector &Operands) { MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); @@ -4247,7 +4411,7 @@ ARMAsmParser::parseBankedRegOperand(OperandVector &Operands) { return MatchOperand_Success; } -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parsePKHImm(OperandVector &Operands, StringRef Op, int Low, int High) { MCAsmParser &Parser = getParser(); @@ -4296,7 +4460,7 @@ ARMAsmParser::parsePKHImm(OperandVector &Operands, StringRef Op, int Low, return MatchOperand_Success; } -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseSetEndImm(OperandVector &Operands) { MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); @@ -4326,7 +4490,7 @@ ARMAsmParser::parseSetEndImm(OperandVector &Operands) { /// lsl #n 'n' in [0,31] /// asr #n 'n' in [1,32] /// n == 32 encoded as n == 0. -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseShifterImm(OperandVector &Operands) { MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); @@ -4397,7 +4561,7 @@ ARMAsmParser::parseShifterImm(OperandVector &Operands) { /// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family /// of instructions. Legal values are: /// ror #n 'n' in {0, 8, 16, 24} -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseRotImm(OperandVector &Operands) { MCAsmParser &Parser = getParser(); const AsmToken &Tok = Parser.getTok(); @@ -4444,7 +4608,7 @@ ARMAsmParser::parseRotImm(OperandVector &Operands) { return MatchOperand_Success; } -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseModImm(OperandVector &Operands) { MCAsmParser &Parser = getParser(); MCAsmLexer &Lexer = getLexer(); @@ -4561,7 +4725,7 @@ ARMAsmParser::parseModImm(OperandVector &Operands) { } } -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseBitfield(OperandVector &Operands) { MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); @@ -4630,7 +4794,7 @@ ARMAsmParser::parseBitfield(OperandVector &Operands) { return MatchOperand_Success; } -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parsePostIdxReg(OperandVector &Operands) { // Check for a post-index addressing register operand. Specifically: // postidx_reg := '+' register {, shift} @@ -4680,7 +4844,7 @@ ARMAsmParser::parsePostIdxReg(OperandVector &Operands) { return MatchOperand_Success; } -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseAM3Offset(OperandVector &Operands) { // Check for a post-index addressing register operand. Specifically: // am3offset := '+' register @@ -4833,8 +4997,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. @@ -5082,7 +5246,7 @@ bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St, } /// parseFPImm - A floating point immediate expression operand. -ARMAsmParser::OperandMatchResultTy +OperandMatchResultTy ARMAsmParser::parseFPImm(OperandVector &Operands) { MCAsmParser &Parser = getParser(); // Anything that can accept a floating point constant as an operand @@ -5131,7 +5295,7 @@ ARMAsmParser::parseFPImm(OperandVector &Operands) { const AsmToken &Tok = Parser.getTok(); SMLoc Loc = Tok.getLoc(); if (Tok.is(AsmToken::Real) && isVmovf) { - APFloat RealVal(APFloat::IEEEsingle, Tok.getString()); + APFloat RealVal(APFloat::IEEEsingle(), Tok.getString()); uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue(); // If we had a '-' in front, toggle the sign bit. IntVal ^= (uint64_t)isNegative << 31; @@ -5259,7 +5423,7 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { return false; } // w/ a ':' after the '#', it's just like a plain ':'. - // FALLTHROUGH + LLVM_FALLTHROUGH; } case AsmToken::Colon: { S = Parser.getTok().getLoc(); @@ -5289,6 +5453,9 @@ bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { if (getParser().parseExpression(SubExprVal)) return true; E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + + // execute-only: we assume that assembly programmers know what they are + // doing and allow literal pool creation here Operands.push_back(ARMOperand::CreateConstantPoolImm(SubExprVal, S, E)); return false; } @@ -5842,7 +6009,6 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // In Thumb1, only the branch (B) instruction can be predicated. if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") { - Parser.eatToEndOfStatement(); return Error(NameLoc, "conditional execution not supported in Thumb1"); } @@ -5856,14 +6022,12 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, if (Mnemonic == "it") { SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2); if (ITMask.size() > 3) { - Parser.eatToEndOfStatement(); return Error(Loc, "too many conditions on IT instruction"); } unsigned Mask = 8; for (unsigned i = ITMask.size(); i != 0; --i) { char pos = ITMask[i - 1]; if (pos != 't' && pos != 'e') { - Parser.eatToEndOfStatement(); return Error(Loc, "illegal IT block condition mask '" + ITMask + "'"); } Mask >>= 1; @@ -5889,14 +6053,12 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // If we had a carry-set on an instruction that can't do that, issue an // error. if (!CanAcceptCarrySet && CarrySetting) { - Parser.eatToEndOfStatement(); return Error(NameLoc, "instruction '" + Mnemonic + "' can not set flags, but 's' suffix specified"); } // If we had a predication code on an instruction that can't do that, issue an // error. if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) { - Parser.eatToEndOfStatement(); return Error(NameLoc, "instruction '" + Mnemonic + "' is not predicable, but condition code specified"); } @@ -5940,7 +6102,6 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // For for ARM mode generate an error if the .n qualifier is used. if (ExtraToken == ".n" && !isThumb()) { SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start); - Parser.eatToEndOfStatement(); return Error(Loc, "instruction with .n (narrow) qualifier not allowed in " "arm mode"); } @@ -5958,28 +6119,19 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, if (getLexer().isNot(AsmToken::EndOfStatement)) { // Read the first operand. if (parseOperand(Operands, Mnemonic)) { - Parser.eatToEndOfStatement(); 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)) { - Parser.eatToEndOfStatement(); return true; } } } - if (getLexer().isNot(AsmToken::EndOfStatement)) { - SMLoc Loc = getLexer().getLoc(); - Parser.eatToEndOfStatement(); - return Error(Loc, "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<ARMOperand &>(*Operands.back()); @@ -6043,10 +6195,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))); @@ -6188,18 +6339,11 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, // NOTE: BKPT and HLT instructions have the interesting property of being // allowed in IT blocks, but not being predicable. They just always execute. if (inITBlock() && !instIsBreakpoint(Inst)) { - unsigned Bit = 1; - if (ITState.FirstCond) - ITState.FirstCond = false; - else - Bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1; // The instruction must be predicable. if (!MCID.isPredicable()) return Error(Loc, "instructions in IT block must be predicable"); unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm(); - unsigned ITCond = Bit ? ITState.Cond : - ARMCC::getOppositeCondition(ITState.Cond); - if (Cond != ITCond) { + if (Cond != currentITCond()) { // Find the condition code Operand to get its SMLoc information. SMLoc CondLoc; for (unsigned I = 1; I < Operands.size(); ++I) @@ -6208,14 +6352,19 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, return Error(CondLoc, "incorrect condition in IT block; got '" + StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) + "', but expected '" + - ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'"); + ARMCondCodeToString(ARMCC::CondCodes(currentITCond())) + "'"); } // Check for non-'al' condition codes outside of the IT block. } else if (isThumbTwo() && MCID.isPredicable() && Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() != ARMCC::AL && Inst.getOpcode() != ARM::tBcc && - Inst.getOpcode() != ARM::t2Bcc) + Inst.getOpcode() != ARM::t2Bcc) { return Error(Loc, "predicated instructions must be in IT block"); + } else if (!isThumb() && !useImplicitITARM() && MCID.isPredicable() && + Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() != + ARMCC::AL) { + return Warning(Loc, "predicated instructions should be in IT block"); + } const unsigned Opcode = Inst.getOpcode(); switch (Opcode) { @@ -6520,6 +6669,12 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, return Error(Operands[Op]->getStartLoc(), "branch target out of range"); break; } + case ARM::tCBZ: + case ARM::tCBNZ: { + if (!static_cast<ARMOperand &>(*Operands[2]).isUnsignedOffset<6, 1>()) + return Error(Operands[2]->getStartLoc(), "branch target out of range"); + break; + } case ARM::MOVi16: case ARM::t2MOVi16: case ARM::t2MOVTi16: @@ -8639,27 +8794,15 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, } case ARM::ITasm: case ARM::t2IT: { - // The mask bits for all but the first condition are represented as - // the low bit of the condition code value implies 't'. We currently - // always have 1 implies 't', so XOR toggle the bits if the low bit - // of the condition code is zero. MCOperand &MO = Inst.getOperand(1); unsigned Mask = MO.getImm(); - unsigned OrigMask = Mask; - unsigned TZ = countTrailingZeros(Mask); - if ((Inst.getOperand(0).getImm() & 1) == 0) { - assert(Mask && TZ <= 3 && "illegal IT mask value!"); - Mask ^= (0xE << TZ) & 0xF; - } - MO.setImm(Mask); + ARMCC::CondCodes Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm()); // Set up the IT block state according to the IT instruction we just // matched. assert(!inITBlock() && "nested IT blocks?!"); - ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm()); - ITState.Mask = OrigMask; // Use the original mask, not the updated one. - ITState.CurPosition = 0; - ITState.FirstCond = true; + startExplicitITBlock(Cond, Mask); + MO.setImm(getITMaskEncoding()); break; } case ARM::t2LSLrr: @@ -8766,7 +8909,7 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) { ; // If we're parsing Thumb1, reject it completely. if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR) - return Match_MnemonicFail; + return Match_RequiresFlagSetting; // If we're parsing Thumb2, which form is legal depends on whether we're // in an IT block. if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR && @@ -8807,6 +8950,132 @@ template <> inline bool IsCPSRDead<MCInst>(MCInst *Instr) { } } +// Returns true if Inst is unpredictable if it is in and IT block, but is not +// the last instruction in the block. +bool ARMAsmParser::isITBlockTerminator(MCInst &Inst) const { + const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); + + // All branch & call instructions terminate IT blocks. + if (MCID.isTerminator() || MCID.isCall() || MCID.isReturn() || + MCID.isBranch() || MCID.isIndirectBranch()) + return true; + + // Any arithmetic instruction which writes to the PC also terminates the IT + // block. + for (unsigned OpIdx = 0; OpIdx < MCID.getNumDefs(); ++OpIdx) { + MCOperand &Op = Inst.getOperand(OpIdx); + if (Op.isReg() && Op.getReg() == ARM::PC) + return true; + } + + if (MCID.hasImplicitDefOfPhysReg(ARM::PC, MRI)) + return true; + + // Instructions with variable operand lists, which write to the variable + // operands. We only care about Thumb instructions here, as ARM instructions + // obviously can't be in an IT block. + switch (Inst.getOpcode()) { + case ARM::t2LDMIA: + case ARM::t2LDMIA_UPD: + case ARM::t2LDMDB: + case ARM::t2LDMDB_UPD: + if (listContainsReg(Inst, 3, ARM::PC)) + return true; + break; + case ARM::tPOP: + if (listContainsReg(Inst, 2, ARM::PC)) + return true; + break; + } + + return false; +} + +unsigned ARMAsmParser::MatchInstruction(OperandVector &Operands, MCInst &Inst, + uint64_t &ErrorInfo, + bool MatchingInlineAsm, + bool &EmitInITBlock, + MCStreamer &Out) { + // If we can't use an implicit IT block here, just match as normal. + if (inExplicitITBlock() || !isThumbTwo() || !useImplicitITThumb()) + return MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); + + // Try to match the instruction in an extension of the current IT block (if + // there is one). + if (inImplicitITBlock()) { + extendImplicitITBlock(ITState.Cond); + if (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm) == + Match_Success) { + // The match succeded, but we still have to check that the instruction is + // valid in this implicit IT block. + const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); + if (MCID.isPredicable()) { + ARMCC::CondCodes InstCond = + (ARMCC::CondCodes)Inst.getOperand(MCID.findFirstPredOperandIdx()) + .getImm(); + ARMCC::CondCodes ITCond = currentITCond(); + if (InstCond == ITCond) { + EmitInITBlock = true; + return Match_Success; + } else if (InstCond == ARMCC::getOppositeCondition(ITCond)) { + invertCurrentITCondition(); + EmitInITBlock = true; + return Match_Success; + } + } + } + rewindImplicitITPosition(); + } + + // Finish the current IT block, and try to match outside any IT block. + flushPendingInstructions(Out); + unsigned PlainMatchResult = + MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); + if (PlainMatchResult == Match_Success) { + const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); + if (MCID.isPredicable()) { + ARMCC::CondCodes InstCond = + (ARMCC::CondCodes)Inst.getOperand(MCID.findFirstPredOperandIdx()) + .getImm(); + // Some forms of the branch instruction have their own condition code + // fields, so can be conditionally executed without an IT block. + if (Inst.getOpcode() == ARM::tBcc || Inst.getOpcode() == ARM::t2Bcc) { + EmitInITBlock = false; + return Match_Success; + } + if (InstCond == ARMCC::AL) { + EmitInITBlock = false; + return Match_Success; + } + } else { + EmitInITBlock = false; + return Match_Success; + } + } + + // Try to match in a new IT block. The matcher doesn't check the actual + // condition, so we create an IT block with a dummy condition, and fix it up + // once we know the actual condition. + startImplicitITBlock(); + if (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm) == + Match_Success) { + const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); + if (MCID.isPredicable()) { + ITState.Cond = + (ARMCC::CondCodes)Inst.getOperand(MCID.findFirstPredOperandIdx()) + .getImm(); + EmitInITBlock = true; + return Match_Success; + } + } + discardImplicitITBlock(); + + // If none of these succeed, return the error we got when trying to match + // outside any IT blocks. + EmitInITBlock = false; + return PlainMatchResult; +} + static const char *getSubtargetFeatureName(uint64_t Val); bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, @@ -8814,9 +9083,11 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, bool MatchingInlineAsm) { MCInst Inst; unsigned MatchResult; + bool PendConditionalInstruction = false; + + MatchResult = MatchInstruction(Operands, Inst, ErrorInfo, MatchingInlineAsm, + PendConditionalInstruction, Out); - MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, - MatchingInlineAsm); switch (MatchResult) { case Match_Success: // Context sensitive operand constraints aren't handled by the matcher, @@ -8856,7 +9127,13 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return false; Inst.setLoc(IDLoc); - Out.EmitInstruction(Inst, getSTI()); + if (PendConditionalInstruction) { + PendingConditionalInsts.push_back(Inst); + if (isITBlockFull() || isITBlockTerminator(Inst)) + flushPendingInstructions(Out); + } else { + Out.EmitInstruction(Inst, getSTI()); + } return false; case Match_MissingFeature: { assert(ErrorInfo && "Unknown missing feature!"); @@ -8898,6 +9175,8 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return Error(IDLoc, "instruction variant requires Thumb2"); case Match_RequiresV8: return Error(IDLoc, "instruction variant requires ARMv8 or later"); + case Match_RequiresFlagSetting: + return Error(IDLoc, "no flag-preserving variant of this instruction available"); case Match_ImmRange0_15: { SMLoc ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getStartLoc(); if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc; @@ -8958,78 +9237,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 @@ -9037,47 +9317,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)) { - Parser.eatToEndOfStatement(); - 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(); @@ -9089,26 +9344,20 @@ 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; } void ARMAsmParser::onLabelParsed(MCSymbol *Symbol) { + // We need to flush the current implicit IT block on a label, because it is + // not legal to branch into an IT block. + flushPendingInstructions(getStreamer()); if (NextSymbolIsThumb) { getParser().getStreamer().EmitThumbFunc(Symbol); NextSymbolIsThumb = false; @@ -9124,27 +9373,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"); - Parser.eatToEndOfStatement(); - return false; - } + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.thumb_func' directive")) + return true; NextSymbolIsThumb = true; return false; @@ -9161,21 +9407,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???(); @@ -9187,10 +9425,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"); @@ -9198,26 +9434,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(); @@ -9234,25 +9463,15 @@ bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) { Parser.Lex(); // Eat the '.req' token. unsigned Reg; SMLoc SRegLoc, ERegLoc; - if (ParseRegister(Reg, SRegLoc, ERegLoc)) { - Parser.eatToEndOfStatement(); - Error(SRegLoc, "register name expected"); - return false; - } - - // Shouldn't be anything else. - if (Parser.getTok().isNot(AsmToken::EndOfStatement)) { - Parser.eatToEndOfStatement(); - Error(Parser.getTok().getLoc(), "unexpected input in .req directive."); - return false; - } - - Parser.Lex(); // Consume the EndOfStatement + if (check(ParseRegister(Reg, SRegLoc, ERegLoc), SRegLoc, + "register name expected") || + parseToken(AsmToken::EndOfStatement, + "unexpected input in .req directive.")) + return true; - 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; } @@ -9261,13 +9480,13 @@ bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) { /// ::= .unreq registername bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) { MCAsmParser &Parser = getParser(); - if (Parser.getTok().isNot(AsmToken::Identifier)) { - Parser.eatToEndOfStatement(); - 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; } @@ -9300,13 +9519,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; @@ -9332,7 +9548,6 @@ bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { Tag = ARMBuildAttrs::AttrTypeFromString(Name); if (Tag == -1) { Error(TagLoc, "attribute name not recognised: " + Name); - Parser.eatToEndOfStatement(); return false; } Parser.Lex(); @@ -9340,27 +9555,18 @@ bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { const MCExpr *AttrExpr; TagLoc = Parser.getTok().getLoc(); - if (Parser.parseExpression(AttrExpr)) { - Parser.eatToEndOfStatement(); - return false; - } + if (Parser.parseExpression(AttrExpr)) + return true; const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr); - if (!CE) { - Error(TagLoc, "expected numeric constant"); - Parser.eatToEndOfStatement(); - 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"); - Parser.eatToEndOfStatement(); - return false; - } - Parser.Lex(); // skip comma + if (Parser.parseToken(AsmToken::Comma, "comma expected")) + return true; StringRef StringValue = ""; bool IsStringValue = false; @@ -9383,44 +9589,32 @@ bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) { if (IsIntegerValue) { const MCExpr *ValueExpr; SMLoc ValueExprLoc = Parser.getTok().getLoc(); - if (Parser.parseExpression(ValueExpr)) { - Parser.eatToEndOfStatement(); - return false; - } + if (Parser.parseExpression(ValueExpr)) + return true; const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr); - if (!CE) { - Error(ValueExprLoc, "expected numeric constant"); - Parser.eatToEndOfStatement(); - 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"); - Parser.eatToEndOfStatement(); - 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"); - Parser.eatToEndOfStatement(); - 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); @@ -9439,10 +9633,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(); @@ -9459,11 +9651,9 @@ bool ARMAsmParser::parseDirectiveFPU(SMLoc L) { StringRef FPU = getParser().parseStringToEndOfStatement().trim(); unsigned ID = ARM::parseFPU(FPU); - std::vector<const char *> Features; - if (!ARM::getFPUFeatures(ID, Features)) { - Error(FPUNameLoc, "Unknown FPU name"); - return false; - } + std::vector<StringRef> Features; + if (!ARM::getFPUFeatures(ID, Features)) + return Error(FPUNameLoc, "Unknown FPU name"); MCSubtargetInfo &STI = copySTI(); for (auto Feature : Features) @@ -9477,10 +9667,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 @@ -9495,11 +9689,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(); @@ -9511,22 +9706,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(); @@ -9539,38 +9736,36 @@ 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) { - Parser.eatToEndOfStatement(); Error(L, "multiple personality directives"); UC.emitPersonalityLocNotes(); - return false; - } - - // Parse the name of the personality routine - if (Parser.getTok().isNot(AsmToken::Identifier)) { - Parser.eatToEndOfStatement(); - Error(L, "unexpected input in .personality directive."); - return false; + return true; } - StringRef Name(Parser.getTok().getIdentifier()); - Parser.Lex(); MCSymbol *PR = getParser().getContext().getOrCreateSymbol(Name); getTargetStreamer().emitPersonality(PR); @@ -9580,17 +9775,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(); @@ -9602,74 +9798,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<MCConstantExpr>(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<unsigned>(FPReg), static_cast<unsigned>(SPReg), Offset); return false; @@ -9680,35 +9854,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<MCConstantExpr>(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; @@ -9719,30 +9887,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<std::unique_ptr<MCParsedAsmOperand>, 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; @@ -9753,8 +9914,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) { @@ -9762,96 +9922,68 @@ bool ARMAsmParser::parseDirectiveInst(SMLoc Loc, char Suffix) { Width = 2; break; case 'w': - Width = 4; break; default: - Parser.eatToEndOfStatement(); - 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) { - Parser.eatToEndOfStatement(); - Error(Loc, "width suffixes are invalid in ARM mode"); - return false; - } - Width = 4; - } - - if (getLexer().is(AsmToken::EndOfStatement)) { - Parser.eatToEndOfStatement(); - Error(Loc, "expected expression following directive"); - return false; + if (Suffix) + return Error(Loc, "width suffixes are invalid in ARM mode"); } - 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<MCConstantExpr>(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; } bool ARMAsmParser::parseDirectiveEven(SMLoc L) { - const MCSection *Section = getStreamer().getCurrentSection().first; + 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); - Section = getStreamer().getCurrentSection().first; + Section = getStreamer().getCurrentSectionOnly(); } assert(Section && "must have section to emit alignment"); @@ -9869,51 +10001,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()) { - Parser.eatToEndOfStatement(); - Error(L, ".fnstart must precede .personalityindex directive"); - return false; + return Error(L, ".fnstart must precede .personalityindex directive"); } if (UC.cantUnwind()) { - Parser.eatToEndOfStatement(); Error(L, ".personalityindex cannot be used with .cantunwind"); UC.emitCantUnwindLocNotes(); - return false; + return true; } if (UC.hasHandlerData()) { - Parser.eatToEndOfStatement(); Error(L, ".personalityindex must precede .handlerdata directive"); UC.emitHandlerDataLocNotes(); - return false; + return true; } if (HasExistingPersonality) { - Parser.eatToEndOfStatement(); Error(L, "multiple personality directives"); UC.emitPersonalityLocNotes(); - return false; - } - - const MCExpr *IndexExpression; - SMLoc IndexLoc = Parser.getTok().getLoc(); - if (Parser.parseExpression(IndexExpression)) { - Parser.eatToEndOfStatement(); - return false; + return true; } const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(IndexExpression); - if (!CE) { - Parser.eatToEndOfStatement(); - Error(IndexLoc, "index must be a constant number"); - return false; - } - if (CE->getValue() < 0 || - CE->getValue() >= ARM::EHABI::NUM_PERSONALITY_INDEX) { - Parser.eatToEndOfStatement(); - 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; @@ -9923,81 +10045,51 @@ bool ARMAsmParser::parseDirectivePersonalityIndex(SMLoc L) { /// ::= .unwind_raw offset, opcode [, opcode...] bool ARMAsmParser::parseDirectiveUnwindRaw(SMLoc L) { MCAsmParser &Parser = getParser(); - if (!UC.hasFnStart()) { - Parser.eatToEndOfStatement(); - 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"); - Parser.eatToEndOfStatement(); - 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<MCConstantExpr>(OffsetExpr); - if (!CE) { - Error(OffsetLoc, "offset must be a constant"); - Parser.eatToEndOfStatement(); - 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"); - Parser.eatToEndOfStatement(); - return false; - } - Parser.Lex(); + if (Parser.parseToken(AsmToken::Comma, "expected comma")) + return true; SmallVector<uint8_t, 16> Opcodes; - for (;;) { - const MCExpr *OE; + auto parseOne = [&]() -> bool { + const MCExpr *OE; SMLoc OpcodeLoc = getLexer().getLoc(); - if (getLexer().is(AsmToken::EndOfStatement) || Parser.parseExpression(OE)) { - Error(OpcodeLoc, "expected opcode expression"); - Parser.eatToEndOfStatement(); - return false; - } - + if (check(getLexer().is(AsmToken::EndOfStatement) || + Parser.parseExpression(OE), + OpcodeLoc, "expected opcode expression")) + return true; const MCConstantExpr *OC = dyn_cast<MCConstantExpr>(OE); - if (!OC) { - Error(OpcodeLoc, "opcode value must be a constant"); - Parser.eatToEndOfStatement(); - 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"); - Parser.eatToEndOfStatement(); - 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"); - Parser.eatToEndOfStatement(); - 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; } @@ -10006,22 +10098,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"); - Parser.eatToEndOfStatement(); - 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"); - Parser.eatToEndOfStatement(); - return false; - } + if (parseToken(AsmToken::EndOfStatement, + "unexpected token in '.tlsdescseq' directive")) + return true; getTargetStreamer().AnnotateTLSDescriptorSequence(SRE); return false; @@ -10031,60 +10118,40 @@ bool ARMAsmParser::parseDirectiveTLSDescSeq(SMLoc L) { /// ::= .movsp reg [, #offset] bool ARMAsmParser::parseDirectiveMovSP(SMLoc L) { MCAsmParser &Parser = getParser(); - if (!UC.hasFnStart()) { - Parser.eatToEndOfStatement(); - Error(L, ".fnstart must precede .movsp directives"); - return false; - } - if (UC.getFPReg() != ARM::SP) { - Parser.eatToEndOfStatement(); - 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) { - Parser.eatToEndOfStatement(); - Error(SPRegLoc, "register expected"); - return false; - } - - if (SPReg == ARM::SP || SPReg == ARM::PC) { - Parser.eatToEndOfStatement(); - 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"); - Parser.eatToEndOfStatement(); - 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)) { - Parser.eatToEndOfStatement(); - Error(OffsetLoc, "malformed offset expression"); - return false; - } + + if (Parser.parseExpression(OffsetExpr)) + return Error(OffsetLoc, "malformed offset expression"); const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr); - if (!CE) { - Parser.eatToEndOfStatement(); - 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); @@ -10095,11 +10162,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"); - Parser.eatToEndOfStatement(); - return false; - } + if (getLexer().isNot(AsmToken::Identifier)) + return Error(getLexer().getLoc(), "unexpected token"); StringRef Arch = Parser.getTok().getString(); SMLoc ArchLoc = Parser.getTok().getLoc(); @@ -10107,19 +10171,12 @@ bool ARMAsmParser::parseDirectiveObjectArch(SMLoc L) { unsigned ID = ARM::parseArch(Arch); - if (ID == ARM::AK_INVALID) { - Error(ArchLoc, "unknown architecture '" + Arch + "'"); - Parser.eatToEndOfStatement(); - 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"); - Parser.eatToEndOfStatement(); - } - return false; } @@ -10128,18 +10185,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().getCurrentSection().first; - 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 @@ -10148,18 +10204,10 @@ bool ARMAsmParser::parseDirectiveThumbSet(SMLoc L) { MCAsmParser &Parser = getParser(); StringRef Name; - if (Parser.parseIdentifier(Name)) { - TokError("expected identifier after '.thumb_set'"); - Parser.eatToEndOfStatement(); - return false; - } - - if (getLexer().isNot(AsmToken::Comma)) { - TokError("expected comma after name '" + Name + "'"); - Parser.eatToEndOfStatement(); - 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; @@ -10173,10 +10221,10 @@ bool ARMAsmParser::parseDirectiveThumbSet(SMLoc L) { /// Force static initialization. extern "C" void LLVMInitializeARMAsmParser() { - RegisterMCAsmParser<ARMAsmParser> X(TheARMLETarget); - RegisterMCAsmParser<ARMAsmParser> Y(TheARMBETarget); - RegisterMCAsmParser<ARMAsmParser> A(TheThumbLETarget); - RegisterMCAsmParser<ARMAsmParser> B(TheThumbBETarget); + RegisterMCAsmParser<ARMAsmParser> X(getTheARMLETarget()); + RegisterMCAsmParser<ARMAsmParser> Y(getTheARMBETarget()); + RegisterMCAsmParser<ARMAsmParser> A(getTheThumbLETarget()); + RegisterMCAsmParser<ARMAsmParser> B(getTheThumbBETarget()); } #define GET_REGISTER_MATCHER @@ -10218,16 +10266,17 @@ static const struct { bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { MCAsmParser &Parser = getParser(); - if (getLexer().isNot(AsmToken::Identifier)) { - Error(getLexer().getLoc(), "unexpected token"); - Parser.eatToEndOfStatement(); - 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; @@ -10235,20 +10284,19 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { } unsigned FeatureKind = ARM::parseArchExt(Name); if (FeatureKind == ARM::AEK_INVALID) - Error(ExtLoc, "unknown architectural extension: " + Name); + return Error(ExtLoc, "unknown architectural extension: " + Name); for (const auto &Extension : Extensions) { if (Extension.Kind != FeatureKind) continue; if (Extension.Features.none()) - report_fatal_error("unsupported architectural extension: " + Name); + 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 @@ -10261,9 +10309,7 @@ bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) { return false; } - Error(ExtLoc, "unknown architectural extension: " + Name); - Parser.eatToEndOfStatement(); - return false; + return Error(ExtLoc, "unknown architectural extension: " + Name); } // Define this matcher function after the auto-generated include so we |