summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r--contrib/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp1384
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
OpenPOWER on IntegriCloud