forked from OSchip/llvm-project
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] llvm-svn: 125052
This commit is contained in:
parent
05a975d777
commit
c9253b4deb
|
@ -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;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue