diff options
author | Bruno Cardoso Lopes <bruno.cardoso@gmail.com> | 2011-02-07 21:41:25 +0000 |
---|---|---|
committer | Bruno Cardoso Lopes <bruno.cardoso@gmail.com> | 2011-02-07 21:41:25 +0000 |
commit | fafde7f0b7c70e08de719d9e33ce9f6fdaefc984 (patch) | |
tree | 2287f87641bf7f5e64153190be4ed2e73ad14e6b /lib/Target/ARM/AsmParser | |
parent | eb59ca976c6400936ee28b7c8687bda9c4ea1cdf (diff) | |
download | external_llvm-fafde7f0b7c70e08de719d9e33ce9f6fdaefc984.zip external_llvm-fafde7f0b7c70e08de719d9e33ce9f6fdaefc984.tar.gz external_llvm-fafde7f0b7c70e08de719d9e33ce9f6fdaefc984.tar.bz2 |
Remove the MCR asm parser hack and start using the custom target specific asm
parsing of operands introduced in r125030. As a small note, besides using a more
generic approach we can also have more descriptive output when debugging
llvm-mc, example:
mcr p7, #1, r5, c1, c1, #4
note: parsed instruction:
['mcr', <ARMCC::al>,
<coprocessor number: 7>,
1,
<register 73>,
<coprocessor register: 1>,
<coprocessor register: 1>,
4]
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125052 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM/AsmParser')
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 123 |
1 files changed, 92 insertions, 31 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 28fdb60..3280e77 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -54,11 +54,12 @@ class ARMAsmParser : public TargetAsmParser { int TryParseRegister(); virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc); - bool TryParseCoprocessorOperandName(SmallVectorImpl<MCParsedAsmOperand*>&); bool TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &); + bool ParseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*>&); + bool ParseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*>&); bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &); bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &); - bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, bool hasCoprocOp); + bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic); bool ParsePrefix(ARMMCExpr::VariantKind &RefKind); const MCExpr *ApplyPrefixToExpr(const MCExpr *E, MCSymbolRefExpr::VariantKind Variant); @@ -115,6 +116,8 @@ class ARMOperand : public MCParsedAsmOperand { enum KindTy { CondCode, CCOut, + CoprocNum, + CoprocReg, Immediate, Memory, Register, @@ -133,6 +136,10 @@ class ARMOperand : public MCParsedAsmOperand { } CC; struct { + unsigned Val; + } Cop; + + struct { const char *Data; unsigned Length; } Tok; @@ -185,6 +192,10 @@ public: case SPRRegisterList: Registers = o.Registers; break; + case CoprocNum: + case CoprocReg: + Cop = o.Cop; + break; case Immediate: Imm = o.Imm; break; @@ -204,6 +215,11 @@ public: return CC.Val; } + unsigned getCoproc() const { + assert((Kind == CoprocNum || Kind == CoprocReg) && "Invalid access!"); + return Cop.Val; + } + StringRef getToken() const { assert(Kind == Token && "Invalid access!"); return StringRef(Tok.Data, Tok.Length); @@ -259,6 +275,8 @@ public: /// @} + bool isCoprocNum() const { return Kind == CoprocNum; } + bool isCoprocReg() const { return Kind == CoprocReg; } bool isCondCode() const { return Kind == CondCode; } bool isCCOut() const { return Kind == CCOut; } bool isImm() const { return Kind == Immediate; } @@ -314,6 +332,16 @@ public: Inst.addOperand(MCOperand::CreateReg(RegNum)); } + void addCoprocNumOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(getCoproc())); + } + + void addCoprocRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateImm(getCoproc())); + } + void addCCOutOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateReg(getReg())); @@ -391,6 +419,22 @@ public: return Op; } + static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) { + ARMOperand *Op = new ARMOperand(CoprocNum); + Op->Cop.Val = CopVal; + Op->StartLoc = S; + Op->EndLoc = S; + return Op; + } + + static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) { + ARMOperand *Op = new ARMOperand(CoprocReg); + Op->Cop.Val = CopVal; + Op->StartLoc = S; + Op->EndLoc = S; + return Op; + } + static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) { ARMOperand *Op = new ARMOperand(CCOut); Op->Reg.RegNum = RegNum; @@ -492,6 +536,12 @@ void ARMOperand::dump(raw_ostream &OS) const { case CCOut: OS << "<ccout " << getReg() << ">"; break; + case CoprocNum: + OS << "<coprocessor number: " << getCoproc() << ">"; + break; + case CoprocReg: + OS << "<coprocessor register: " << getCoproc() << ">"; + break; case Immediate: getImm()->print(OS); break; @@ -609,13 +659,16 @@ TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { return false; } -static int MatchCoprocessorOperandName(StringRef Name) { +/// MatchCoprocessorOperandName - Try to parse an coprocessor related +/// instruction with a symbolic operand name. Example: "p1", "p7", "c3", +/// "c5", ... +static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) { // Use the same layout as the tablegen'erated register name matcher. Ugly, // but efficient. switch (Name.size()) { default: break; case 2: - if (Name[0] != 'p' && Name[0] != 'c') + if (Name[0] != CoprocOp) return -1; switch (Name[1]) { default: return -1; @@ -632,7 +685,7 @@ static int MatchCoprocessorOperandName(StringRef Name) { } break; case 3: - if ((Name[0] != 'p' && Name[0] != 'c') || Name[1] != '1') + if (Name[0] != CoprocOp || Name[1] != '1') return -1; switch (Name[2]) { default: return -1; @@ -650,24 +703,39 @@ static int MatchCoprocessorOperandName(StringRef Name) { return -1; } -/// TryParseCoprocessorOperandName - Try to parse an coprocessor related -/// instruction with a symbolic operand name. The token must be an Identifier -/// when called, and if it is a coprocessor related operand name, the token is -/// eaten and the operand is added to the operand list. Example: operands like -/// "p1", "p7", "c3", "c5", ... +/// 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. bool ARMAsmParser:: -TryParseCoprocessorOperandName(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { +ParseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); - int Num = MatchCoprocessorOperandName(Tok.getString()); + int Num = MatchCoprocessorOperandName(Tok.getString(), 'p'); if (Num == -1) return true; Parser.Lex(); // Eat identifier token. - Operands.push_back(ARMOperand::CreateImm( - MCConstantExpr::Create(Num, getContext()), S, Parser.getTok().getLoc())); + Operands.push_back(ARMOperand::CreateCoprocNum(Num, S)); + return false; +} + +/// 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. +bool ARMAsmParser:: +ParseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) { + SMLoc S = Parser.getTok().getLoc(); + const AsmToken &Tok = Parser.getTok(); + assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier"); + + int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c'); + if (Reg == -1) + return true; + + Parser.Lex(); // Eat identifier token. + Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S)); return false; } @@ -974,8 +1042,15 @@ bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount, /// Parse a arm instruction operand. For now this parses the operand regardless /// of the mnemonic. bool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, - bool hasCoprocOp){ + StringRef Mnemonic) { SMLoc S, E; + + // Check if the current operand has a custom associated parser, if so, try to + // custom parse the operand, or fallback to the general approach. + MatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); + if (ResTy == Match_Success) + return false; + switch (getLexer().getKind()) { default: Error(Parser.getTok().getLoc(), "unexpected token in operand"); @@ -983,8 +1058,6 @@ bool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands, case AsmToken::Identifier: if (!TryParseRegisterWithWriteBack(Operands)) return false; - if (hasCoprocOp && !TryParseCoprocessorOperandName(Operands)) - return false; // Fall though for the Identifier case that is not a register or a // special name. @@ -1273,22 +1346,10 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, Operands.push_back(ARMOperand::CreateToken(Head, NameLoc)); } - // Enable the parsing of instructions containing coprocessor related - // asm syntax, such as coprocessor names "p7, p15, ..." and coprocessor - // registers "c1, c3, ..." - // FIXME: we probably want AsmOperandClass and ParserMatchClass declarations - // in the .td file rather than hacking the ASMParser for every symbolic - // operand type. - bool hasCoprocOp = (Head == "mcr" || Head == "mcr2" || - Head == "mcrr" || Head == "mcrr2" || - Head == "mrc" || Head == "mrc2" || - Head == "mrrc" || Head == "mrrc2" || - Head == "cdp" || Head == "cdp2"); - // Read the remaining operands. if (getLexer().isNot(AsmToken::EndOfStatement)) { // Read the first operand. - if (ParseOperand(Operands, hasCoprocOp)) { + if (ParseOperand(Operands, Head)) { Parser.EatToEndOfStatement(); return true; } @@ -1297,7 +1358,7 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc, Parser.Lex(); // Eat the comma. // Parse and remember the operand. - if (ParseOperand(Operands, hasCoprocOp)) { + if (ParseOperand(Operands, Head)) { Parser.EatToEndOfStatement(); return true; } |