llvm.org GIT mirror llvm / fafde7f
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 Bruno Cardoso Lopes 9 years ago
2 changed file(s) with 106 addition(s) and 31 deletion(s). Raw diff Collapse all Expand all
587587 let PrintMethod = "printNoHashImmediate";
588588 }
589589
590 def CoprocNumAsmOperand : AsmOperandClass {
591 let Name = "CoprocNum";
592 let SuperClasses = [];
593 let ParserMethod = "ParseCoprocNumOperand";
594 }
595
596 def CoprocRegAsmOperand : AsmOperandClass {
597 let Name = "CoprocReg";
598 let SuperClasses = [];
599 let ParserMethod = "ParseCoprocRegOperand";
600 }
601
590602 def p_imm : Operand {
591603 let PrintMethod = "printPImmediate";
604 let ParserMatchClass = CoprocNumAsmOperand;
592605 }
593606
594607 def c_imm : Operand {
595608 let PrintMethod = "printCImmediate";
609 let ParserMatchClass = CoprocRegAsmOperand;
596610 }
597611
598612 //===----------------------------------------------------------------------===//
5353
5454 int TryParseRegister();
5555 virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
56 bool TryParseCoprocessorOperandName(SmallVectorImpl&);
5756 bool TryParseRegisterWithWriteBack(SmallVectorImpl &);
57 bool ParseCoprocNumOperand(SmallVectorImpl&);
58 bool ParseCoprocRegOperand(SmallVectorImpl&);
5859 bool ParseRegisterList(SmallVectorImpl &);
5960 bool ParseMemory(SmallVectorImpl &);
60 bool ParseOperand(SmallVectorImpl &, bool hasCoprocOp);
61 bool ParseOperand(SmallVectorImpl &, StringRef Mnemonic);
6162 bool ParsePrefix(ARMMCExpr::VariantKind &RefKind);
6263 const MCExpr *ApplyPrefixToExpr(const MCExpr *E,
6364 MCSymbolRefExpr::VariantKind Variant);
114115 enum KindTy {
115116 CondCode,
116117 CCOut,
118 CoprocNum,
119 CoprocReg,
117120 Immediate,
118121 Memory,
119122 Register,
130133 struct {
131134 ARMCC::CondCodes Val;
132135 } CC;
136
137 struct {
138 unsigned Val;
139 } Cop;
133140
134141 struct {
135142 const char *Data;
184191 case SPRRegisterList:
185192 Registers = o.Registers;
186193 break;
194 case CoprocNum:
195 case CoprocReg:
196 Cop = o.Cop;
197 break;
187198 case Immediate:
188199 Imm = o.Imm;
189200 break;
203214 return CC.Val;
204215 }
205216
217 unsigned getCoproc() const {
218 assert((Kind == CoprocNum || Kind == CoprocReg) && "Invalid access!");
219 return Cop.Val;
220 }
221
206222 StringRef getToken() const {
207223 assert(Kind == Token && "Invalid access!");
208224 return StringRef(Tok.Data, Tok.Length);
258274
259275 /// @}
260276
277 bool isCoprocNum() const { return Kind == CoprocNum; }
278 bool isCoprocReg() const { return Kind == CoprocReg; }
261279 bool isCondCode() const { return Kind == CondCode; }
262280 bool isCCOut() const { return Kind == CCOut; }
263281 bool isImm() const { return Kind == Immediate; }
313331 Inst.addOperand(MCOperand::CreateReg(RegNum));
314332 }
315333
334 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
335 assert(N == 1 && "Invalid number of operands!");
336 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
337 }
338
339 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
340 assert(N == 1 && "Invalid number of operands!");
341 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
342 }
343
316344 void addCCOutOperands(MCInst &Inst, unsigned N) const {
317345 assert(N == 1 && "Invalid number of operands!");
318346 Inst.addOperand(MCOperand::CreateReg(getReg()));
385413 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
386414 ARMOperand *Op = new ARMOperand(CondCode);
387415 Op->CC.Val = CC;
416 Op->StartLoc = S;
417 Op->EndLoc = S;
418 return Op;
419 }
420
421 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
422 ARMOperand *Op = new ARMOperand(CoprocNum);
423 Op->Cop.Val = CopVal;
424 Op->StartLoc = S;
425 Op->EndLoc = S;
426 return Op;
427 }
428
429 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
430 ARMOperand *Op = new ARMOperand(CoprocReg);
431 Op->Cop.Val = CopVal;
388432 Op->StartLoc = S;
389433 Op->EndLoc = S;
390434 return Op;
490534 break;
491535 case CCOut:
492536 OS << "";
537 break;
538 case CoprocNum:
539 OS << "";
540 break;
541 case CoprocReg:
542 OS << "";
493543 break;
494544 case Immediate:
495545 getImm()->print(OS);
608658 return false;
609659 }
610660
611 static int MatchCoprocessorOperandName(StringRef Name) {
661 /// MatchCoprocessorOperandName - Try to parse an coprocessor related
662 /// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
663 /// "c5", ...
664 static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
612665 // Use the same layout as the tablegen'erated register name matcher. Ugly,
613666 // but efficient.
614667 switch (Name.size()) {
615668 default: break;
616669 case 2:
617 if (Name[0] != 'p' && Name[0] != 'c')
670 if (Name[0] != CoprocOp)
618671 return -1;
619672 switch (Name[1]) {
620673 default: return -1;
631684 }
632685 break;
633686 case 3:
634 if ((Name[0] != 'p' && Name[0] != 'c') || Name[1] != '1')
687 if (Name[0] != CoprocOp || Name[1] != '1')
635688 return -1;
636689 switch (Name[2]) {
637690 default: return -1;
649702 return -1;
650703 }
651704
652 /// TryParseCoprocessorOperandName - Try to parse an coprocessor related
653 /// instruction with a symbolic operand name. The token must be an Identifier
654 /// when called, and if it is a coprocessor related operand name, the token is
655 /// eaten and the operand is added to the operand list. Example: operands like
656 /// "p1", "p7", "c3", "c5", ...
705 /// ParseCoprocNumOperand - Try to parse an coprocessor number operand. The
706 /// token must be an Identifier when called, and if it is a coprocessor
707 /// number, the token is eaten and the operand is added to the operand list.
657708 bool ARMAsmParser::
658 TryParseCoprocessorOperandName(SmallVectorImpl &Operands) {
709 ParseCoprocNumOperand(SmallVectorImpl &Operands) {
659710 SMLoc S = Parser.getTok().getLoc();
660711 const AsmToken &Tok = Parser.getTok();
661712 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
662713
663 int Num = MatchCoprocessorOperandName(Tok.getString());
714 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
664715 if (Num == -1)
665716 return true;
666717
667718 Parser.Lex(); // Eat identifier token.
668 Operands.push_back(ARMOperand::CreateImm(
669 MCConstantExpr::Create(Num, getContext()), S, Parser.getTok().getLoc()));
719 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
720 return false;
721 }
722
723 /// ParseCoprocRegOperand - Try to parse an coprocessor register operand. The
724 /// token must be an Identifier when called, and if it is a coprocessor
725 /// number, the token is eaten and the operand is added to the operand list.
726 bool ARMAsmParser::
727 ParseCoprocRegOperand(SmallVectorImpl &Operands) {
728 SMLoc S = Parser.getTok().getLoc();
729 const AsmToken &Tok = Parser.getTok();
730 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
731
732 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
733 if (Reg == -1)
734 return true;
735
736 Parser.Lex(); // Eat identifier token.
737 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
670738 return false;
671739 }
672740
9731041 /// Parse a arm instruction operand. For now this parses the operand regardless
9741042 /// of the mnemonic.
9751043 bool ARMAsmParser::ParseOperand(SmallVectorImpl &Operands,
976 bool hasCoprocOp){
1044 StringRef Mnemonic) {
9771045 SMLoc S, E;
1046
1047 // Check if the current operand has a custom associated parser, if so, try to
1048 // custom parse the operand, or fallback to the general approach.
1049 MatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1050 if (ResTy == Match_Success)
1051 return false;
1052
9781053 switch (getLexer().getKind()) {
9791054 default:
9801055 Error(Parser.getTok().getLoc(), "unexpected token in operand");
9811056 return true;
9821057 case AsmToken::Identifier:
9831058 if (!TryParseRegisterWithWriteBack(Operands))
984 return false;
985 if (hasCoprocOp && !TryParseCoprocessorOperandName(Operands))
9861059 return false;
9871060
9881061 // Fall though for the Identifier case that is not a register or a
12721345 Operands.push_back(ARMOperand::CreateToken(Head, NameLoc));
12731346 }
12741347
1275 // Enable the parsing of instructions containing coprocessor related
1276 // asm syntax, such as coprocessor names "p7, p15, ..." and coprocessor
1277 // registers "c1, c3, ..."
1278 // FIXME: we probably want AsmOperandClass and ParserMatchClass declarations
1279 // in the .td file rather than hacking the ASMParser for every symbolic
1280 // operand type.
1281 bool hasCoprocOp = (Head == "mcr" || Head == "mcr2" ||
1282 Head == "mcrr" || Head == "mcrr2" ||
1283 Head == "mrc" || Head == "mrc2" ||
1284 Head == "mrrc" || Head == "mrrc2" ||
1285 Head == "cdp" || Head == "cdp2");
1286
12871348 // Read the remaining operands.
12881349 if (getLexer().isNot(AsmToken::EndOfStatement)) {
12891350 // Read the first operand.
1290 if (ParseOperand(Operands, hasCoprocOp)) {
1351 if (ParseOperand(Operands, Head)) {
12911352 Parser.EatToEndOfStatement();
12921353 return true;
12931354 }
12961357 Parser.Lex(); // Eat the comma.
12971358
12981359 // Parse and remember the operand.
1299 if (ParseOperand(Operands, hasCoprocOp)) {
1360 if (ParseOperand(Operands, Head)) {
13001361 Parser.EatToEndOfStatement();
13011362 return true;
13021363 }