Remove the MCR asm parser hack and start using the custom target specific asm
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Mon, 7 Feb 2011 21:41:25 +0000 (21:41 +0000)
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>
Mon, 7 Feb 2011 21:41:25 +0000 (21:41 +0000)
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

lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/AsmParser/ARMAsmParser.cpp

index e8887652ee11fe570fcc1b368c1b502af008f785..01ae5dfaf2ee2c460803b56bfe9f427010f71f05 100644 (file)
@@ -588,12 +588,26 @@ def nohash_imm : Operand<i32> {
   let PrintMethod = "printNoHashImmediate";
 }
 
+def CoprocNumAsmOperand : AsmOperandClass {
+  let Name = "CoprocNum";
+  let SuperClasses = [];
+  let ParserMethod = "ParseCoprocNumOperand";
+}
+
+def CoprocRegAsmOperand : AsmOperandClass {
+  let Name = "CoprocReg";
+  let SuperClasses = [];
+  let ParserMethod = "ParseCoprocRegOperand";
+}
+
 def p_imm : Operand<i32> {
   let PrintMethod = "printPImmediate";
+  let ParserMatchClass = CoprocNumAsmOperand;
 }
 
 def c_imm : Operand<i32> {
   let PrintMethod = "printCImmediate";
+  let ParserMatchClass = CoprocRegAsmOperand;
 }
 
 //===----------------------------------------------------------------------===//
index 28fdb60f8a084c8daea2b84b5a12cede038f027c..3280e7792af47eb61fc23c53c3d705927565fff0 100644 (file)
@@ -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,
@@ -132,6 +135,10 @@ class ARMOperand : public MCParsedAsmOperand {
       ARMCC::CondCodes Val;
     } CC;
 
+    struct {
+      unsigned Val;
+    } Cop;
+
     struct {
       const char *Data;
       unsigned Length;
@@ -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;
       }