aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/ARM/AsmParser
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2011-02-07 21:41:25 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2011-02-07 21:41:25 +0000
commitfafde7f0b7c70e08de719d9e33ce9f6fdaefc984 (patch)
tree2287f87641bf7f5e64153190be4ed2e73ad14e6b /lib/Target/ARM/AsmParser
parenteb59ca976c6400936ee28b7c8687bda9c4ea1cdf (diff)
downloadexternal_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.cpp123
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;
}