diff options
Diffstat (limited to 'lib/Target/ARM/AsmParser/ARMAsmParser.cpp')
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 269 |
1 files changed, 134 insertions, 135 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 403f96c..894f913a 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -44,13 +44,21 @@ private: bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); } - bool ParseRegister(ARMOperand &Op); + bool MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack); bool ParseRegisterList(ARMOperand &Op); bool ParseMemory(ARMOperand &Op); - bool ParseShift(enum ShiftType *St, const MCExpr *&ShiftAmount); + bool ParseMemoryOffsetReg(bool &Negative, + bool &OffsetRegShifted, + enum ShiftType &ShiftType, + const MCExpr *&ShiftAmount, + const MCExpr *&Offset, + bool &OffsetIsReg, + int &OffsetRegNum); + + bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount); bool ParseOperand(ARMOperand &Op); @@ -123,16 +131,17 @@ struct ARMOperand { // This is for all forms of ARM address expressions struct { unsigned BaseRegNum; - bool OffsetIsReg; - const MCExpr *Offset; // used when OffsetIsReg is false unsigned OffsetRegNum; // used when OffsetIsReg is true - bool OffsetRegShifted; // only used when OffsetIsReg is true - enum ShiftType ShiftType; // used when OffsetRegShifted is true + const MCExpr *Offset; // used when OffsetIsReg is false const MCExpr *ShiftAmount; // used when OffsetRegShifted is true - bool Preindexed; - bool Postindexed; - bool Negative; // only used when OffsetIsReg is true - bool Writeback; + enum ShiftType ShiftType; // used when OffsetRegShifted is true + unsigned + OffsetRegShifted : 1, // only used when OffsetIsReg is true + Preindexed : 1, + Postindexed : 1, + OffsetIsReg : 1, + Negative : 1, // only used when OffsetIsReg is true + Writeback : 1; } Mem; }; @@ -208,12 +217,12 @@ struct ARMOperand { } // end anonymous namespace. -// Try to parse a register name. The token must be an Identifier when called, -// and if it is a register name a Reg operand is created, the token is eaten -// and false is returned. Else true is returned and no token is eaten. -// TODO this is likely to change to allow different register types and or to -// parse for a specific register type. -bool ARMAsmParser::ParseRegister(ARMOperand &Op) { +/// Try to parse a register name. The token must be an Identifier when called, +/// and if it is a register name a Reg operand is created, the token is eaten +/// and false is returned. Else true is returned and no token is eaten. +/// TODO this is likely to change to allow different register types and or to +/// parse for a specific register type. +bool ARMAsmParser::MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack) { const AsmToken &Tok = getLexer().getTok(); assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); @@ -227,10 +236,12 @@ bool ARMAsmParser::ParseRegister(ARMOperand &Op) { getLexer().Lex(); // Eat identifier token. bool Writeback = false; - const AsmToken &ExclaimTok = getLexer().getTok(); - if (ExclaimTok.is(AsmToken::Exclaim)) { - Writeback = true; - getLexer().Lex(); // Eat exclaim token + if (ParseWriteBack) { + const AsmToken &ExclaimTok = getLexer().getTok(); + if (ExclaimTok.is(AsmToken::Exclaim)) { + Writeback = true; + getLexer().Lex(); // Eat exclaim token + } } Op = ARMOperand::CreateReg(RegNum, Writeback); @@ -238,8 +249,8 @@ bool ARMAsmParser::ParseRegister(ARMOperand &Op) { return false; } -// Parse a register list, return false if successful else return true or an -// error. The first token must be a '{' when called. +/// Parse a register list, return false if successful else return true or an +/// error. The first token must be a '{' when called. bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) { assert(getLexer().getTok().is(AsmToken::LCurly) && "Token is not an Left Curly Brace"); @@ -285,10 +296,10 @@ bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) { return false; } -// Parse an arm memory expression, return false if successful else return true -// or an error. The first token must be a '[' when called. -// TODO Only preindexing and postindexing addressing are started, unindexed -// with option, etc are still to do. +/// Parse an arm memory expression, return false if successful else return true +/// or an error. The first token must be a '[' when called. +/// TODO Only preindexing and postindexing addressing are started, unindexed +/// with option, etc are still to do. bool ARMAsmParser::ParseMemory(ARMOperand &Op) { assert(getLexer().getTok().is(AsmToken::LBrac) && "Token is not an Left Bracket"); @@ -297,10 +308,9 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) { const AsmToken &BaseRegTok = getLexer().getTok(); if (BaseRegTok.isNot(AsmToken::Identifier)) return Error(BaseRegTok.getLoc(), "register expected"); - int BaseRegNum = MatchRegisterName(BaseRegTok.getString()); - if (BaseRegNum == -1) + if (MaybeParseRegister(Op, false)) return Error(BaseRegTok.getLoc(), "register expected"); - getLexer().Lex(); // Eat identifier token. + int BaseRegNum = Op.getReg(); bool Preindexed = false; bool Postindexed = false; @@ -308,55 +318,20 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) { bool Negative = false; bool Writeback = false; - // First look for preindexed address forms: - // [Rn, +/-Rm] - // [Rn, #offset] - // [Rn, +/-Rm, shift] - // that is after the "[Rn" we now have see if the next token is a comma. + // First look for preindexed address forms, that is after the "[Rn" we now + // have to see if the next token is a comma. const AsmToken &Tok = getLexer().getTok(); if (Tok.is(AsmToken::Comma)) { Preindexed = true; getLexer().Lex(); // Eat comma token. - - const AsmToken &NextTok = getLexer().getTok(); - if (NextTok.is(AsmToken::Plus)) - getLexer().Lex(); // Eat plus token. - else if (NextTok.is(AsmToken::Minus)) { - Negative = true; - getLexer().Lex(); // Eat minus token - } - - // See if there is a register following the "[Rn," we have so far. - const AsmToken &OffsetRegTok = getLexer().getTok(); - int OffsetRegNum = MatchRegisterName(OffsetRegTok.getString()); - bool OffsetRegShifted = false; + int OffsetRegNum; + bool OffsetRegShifted; enum ShiftType ShiftType; const MCExpr *ShiftAmount; const MCExpr *Offset; - if (OffsetRegNum != -1) { - OffsetIsReg = true; - getLexer().Lex(); // Eat identifier token for the offset register. - // Look for a comma then a shift - const AsmToken &Tok = getLexer().getTok(); - if (Tok.is(AsmToken::Comma)) { - getLexer().Lex(); // Eat comma token. - - const AsmToken &Tok = getLexer().getTok(); - if (ParseShift(&ShiftType, ShiftAmount)) - return Error(Tok.getLoc(), "shift expected"); - OffsetRegShifted = true; - } - } - else { // "[Rn," we have so far was not followed by "Rm" - // Look for #offset following the "[Rn," - const AsmToken &HashTok = getLexer().getTok(); - if (HashTok.isNot(AsmToken::Hash)) - return Error(HashTok.getLoc(), "'#' expected"); - getLexer().Lex(); // Eat hash token. - - if (getParser().ParseExpression(Offset)) - return true; - } + if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount, + Offset, OffsetIsReg, OffsetRegNum)) + return true; const AsmToken &RBracTok = getLexer().getTok(); if (RBracTok.isNot(AsmToken::RBrac)) return Error(RBracTok.getLoc(), "']' expected"); @@ -374,11 +349,8 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) { } // The "[Rn" we have so far was not followed by a comma. else if (Tok.is(AsmToken::RBrac)) { - // This is a post indexing addressing forms: - // [Rn], #offset - // [Rn], +/-Rm - // [Rn], +/-Rm, shift - // that is a ']' follows after the "[Rn". + // This is a post indexing addressing forms, that is a ']' follows after + // the "[Rn". Postindexed = true; Writeback = true; getLexer().Lex(); // Eat right bracket token. @@ -394,42 +366,9 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) { if (NextTok.isNot(AsmToken::Comma)) return Error(NextTok.getLoc(), "',' expected"); getLexer().Lex(); // Eat comma token. - - const AsmToken &PlusMinusTok = getLexer().getTok(); - if (PlusMinusTok.is(AsmToken::Plus)) - getLexer().Lex(); // Eat plus token. - else if (PlusMinusTok.is(AsmToken::Minus)) { - Negative = true; - getLexer().Lex(); // Eat minus token - } - - // See if there is a register following the "[Rn]," we have so far. - const AsmToken &OffsetRegTok = getLexer().getTok(); - OffsetRegNum = MatchRegisterName(OffsetRegTok.getString()); - if (OffsetRegNum != -1) { - OffsetIsReg = true; - getLexer().Lex(); // Eat identifier token for the offset register. - // Look for a comma then a shift - const AsmToken &Tok = getLexer().getTok(); - if (Tok.is(AsmToken::Comma)) { - getLexer().Lex(); // Eat comma token. - - const AsmToken &Tok = getLexer().getTok(); - if (ParseShift(&ShiftType, ShiftAmount)) - return Error(Tok.getLoc(), "shift expected"); - OffsetRegShifted = true; - } - } - else { // "[Rn]," we have so far was not followed by "Rm" - // Look for #offset following the "[Rn]," - const AsmToken &HashTok = getLexer().getTok(); - if (HashTok.isNot(AsmToken::Hash)) - return Error(HashTok.getLoc(), "'#' expected"); - getLexer().Lex(); // Eat hash token. - - if (getParser().ParseExpression(Offset)) - return true; - } + if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, + ShiftAmount, Offset, OffsetIsReg, OffsetRegNum)) + return true; } Op = ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum, @@ -441,45 +380,105 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) { return true; } +/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn]," +/// we will parse the following (were +/- means that a plus or minus is +/// optional): +/// +/-Rm +/// +/-Rm, shift +/// #offset +/// we return false on success or an error otherwise. +bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative, + bool &OffsetRegShifted, + enum ShiftType &ShiftType, + const MCExpr *&ShiftAmount, + const MCExpr *&Offset, + bool &OffsetIsReg, + int &OffsetRegNum) { + ARMOperand Op; + Negative = false; + OffsetRegShifted = false; + OffsetIsReg = false; + OffsetRegNum = -1; + const AsmToken &NextTok = getLexer().getTok(); + if (NextTok.is(AsmToken::Plus)) + getLexer().Lex(); // Eat plus token. + else if (NextTok.is(AsmToken::Minus)) { + Negative = true; + getLexer().Lex(); // Eat minus token + } + // See if there is a register following the "[Rn," or "[Rn]," we have so far. + const AsmToken &OffsetRegTok = getLexer().getTok(); + if (OffsetRegTok.is(AsmToken::Identifier)) { + OffsetIsReg = !MaybeParseRegister(Op, false); + if (OffsetIsReg) + OffsetRegNum = Op.getReg(); + } + // If we parsed a register as the offset then their can be a shift after that + if (OffsetRegNum != -1) { + // Look for a comma then a shift + const AsmToken &Tok = getLexer().getTok(); + if (Tok.is(AsmToken::Comma)) { + getLexer().Lex(); // Eat comma token. + + const AsmToken &Tok = getLexer().getTok(); + if (ParseShift(ShiftType, ShiftAmount)) + return Error(Tok.getLoc(), "shift expected"); + OffsetRegShifted = true; + } + } + else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm" + // Look for #offset following the "[Rn," or "[Rn]," + const AsmToken &HashTok = getLexer().getTok(); + if (HashTok.isNot(AsmToken::Hash)) + return Error(HashTok.getLoc(), "'#' expected"); + getLexer().Lex(); // Eat hash token. + + if (getParser().ParseExpression(Offset)) + return true; + } + return false; +} + /// ParseShift as one of these two: /// ( lsl | lsr | asr | ror ) , # shift_amount /// rrx /// and returns true if it parses a shift otherwise it returns false. -bool ARMAsmParser::ParseShift(ShiftType *St, const MCExpr *&ShiftAmount) { +bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount) { const AsmToken &Tok = getLexer().getTok(); if (Tok.isNot(AsmToken::Identifier)) return true; const StringRef &ShiftName = Tok.getString(); if (ShiftName == "lsl" || ShiftName == "LSL") - *St = Lsl; + St = Lsl; else if (ShiftName == "lsr" || ShiftName == "LSR") - *St = Lsr; + St = Lsr; else if (ShiftName == "asr" || ShiftName == "ASR") - *St = Asr; + St = Asr; else if (ShiftName == "ror" || ShiftName == "ROR") - *St = Ror; + St = Ror; else if (ShiftName == "rrx" || ShiftName == "RRX") - *St = Rrx; + St = Rrx; else return true; getLexer().Lex(); // Eat shift type token. - // For all but a Rotate right there must be a '#' and a shift amount - if (*St != Rrx) { - // Look for # following the shift type - const AsmToken &HashTok = getLexer().getTok(); - if (HashTok.isNot(AsmToken::Hash)) - return Error(HashTok.getLoc(), "'#' expected"); - getLexer().Lex(); // Eat hash token. + // Rrx stands alone. + if (St == Rrx) + return false; - if (getParser().ParseExpression(ShiftAmount)) - return true; - } + // Otherwise, there must be a '#' and a shift amount. + const AsmToken &HashTok = getLexer().getTok(); + if (HashTok.isNot(AsmToken::Hash)) + return Error(HashTok.getLoc(), "'#' expected"); + getLexer().Lex(); // Eat hash token. + + if (getParser().ParseExpression(ShiftAmount)) + return true; return false; } -// A hack to allow some testing, to be replaced by a real table gen version. +/// A hack to allow some testing, to be replaced by a real table gen version. int ARMAsmParser::MatchRegisterName(const StringRef &Name) { if (Name == "r0" || Name == "R0") return 0; @@ -518,7 +517,7 @@ int ARMAsmParser::MatchRegisterName(const StringRef &Name) { return -1; } -// A hack to allow some testing, to be replaced by a real table gen version. +/// A hack to allow some testing, to be replaced by a real table gen version. bool ARMAsmParser::MatchInstruction(SmallVectorImpl<ARMOperand> &Operands, MCInst &Inst) { struct ARMOperand Op0 = Operands[0]; @@ -549,12 +548,12 @@ bool ARMAsmParser::MatchInstruction(SmallVectorImpl<ARMOperand> &Operands, return true; } -// Parse a arm instruction operand. For now this parses the operand regardless -// of the mnemonic. +/// Parse a arm instruction operand. For now this parses the operand regardless +/// of the mnemonic. bool ARMAsmParser::ParseOperand(ARMOperand &Op) { switch (getLexer().getKind()) { case AsmToken::Identifier: - if (!ParseRegister(Op)) + if (!MaybeParseRegister(Op, true)) return false; // This was not a register so parse other operands that start with an // identifier (like labels) as expressions and create them as immediates. @@ -581,7 +580,7 @@ bool ARMAsmParser::ParseOperand(ARMOperand &Op) { } } -// Parse an arm instruction mnemonic followed by its operands. +/// Parse an arm instruction mnemonic followed by its operands. bool ARMAsmParser::ParseInstruction(const StringRef &Name, MCInst &Inst) { SmallVector<ARMOperand, 7> Operands; @@ -739,7 +738,7 @@ bool ARMAsmParser::ParseDirectiveCode(SMLoc L) { return false; } -// Force static initialization. +/// Force static initialization. extern "C" void LLVMInitializeARMAsmParser() { RegisterAsmParser<ARMAsmParser> X(TheARMTarget); RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget); |