Updates to the ARM target assembler for llvm-mc per review comments from

Daniel Dunbar.
- Reordered the fields in the ARMOperand Mem struct to make the struct smaller.
Making bool's into 1 bit fields and put the MCExpr* fields adjacent to each
other.
- Fixed a number of places in ARMAsmParser.cpp so they have doxygen comments.
- Change the name of ARMAsmParser::ParseRegister() to MaybeParseRegister and
added the bool ParseWriteBack parameter.
- Changed ARMAsmParser::ParseMemory() to call MaybeParseRegister().
- Added ARMAsmParser::ParseMemoryOffsetReg to factor out parsing the offset of a
memory operand.  And use it for both parsing both preindexed and post indexing
addressing forms in ARMAsmParser::ParseMemory.
- Changed the first argument to ParseShift() to a reference.
- Changed ParseShift() to check for Rrx first and return to reduce nesting.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85632 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Kevin Enderby 2009-10-30 22:55:57 +00:00
parent 5e8e2d7ad9
commit 9c41fa87ea

View File

@ -44,13 +44,21 @@ private:
bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
bool ParseRegister(ARMOperand &Op);
bool MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack);
bool ParseRegisterList(ARMOperand &Op);
bool ParseMemory(ARMOperand &Op);
bool ParseShift(enum ShiftType *St, const MCExpr *&ShiftAmount);
bool ParseMemoryOffsetReg(bool &Negative,
bool &OffsetRegShifted,
enum ShiftType &ShiftType,
const MCExpr *&ShiftAmount,
const MCExpr *&Offset,
bool &OffsetIsReg,
int OffsetRegNum);
bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount);
bool ParseOperand(ARMOperand &Op);
@ -123,16 +131,17 @@ struct ARMOperand {
// This is for all forms of ARM address expressions
struct {
unsigned BaseRegNum;
bool OffsetIsReg;
const MCExpr *Offset; // used when OffsetIsReg is false
unsigned OffsetRegNum; // used when OffsetIsReg is true
bool OffsetRegShifted; // only used when OffsetIsReg is true
enum ShiftType ShiftType; // used when OffsetRegShifted is true
const MCExpr *Offset; // used when OffsetIsReg is false
const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
bool Preindexed;
bool Postindexed;
bool Negative; // only used when OffsetIsReg is true
bool Writeback;
enum ShiftType ShiftType; // used when OffsetRegShifted is true
unsigned
OffsetRegShifted : 1, // only used when OffsetIsReg is true
Preindexed : 1,
Postindexed : 1,
OffsetIsReg : 1,
Negative : 1, // only used when OffsetIsReg is true
Writeback : 1;
} Mem;
};
@ -208,12 +217,12 @@ struct ARMOperand {
} // end anonymous namespace.
// Try to parse a register name. The token must be an Identifier when called,
// and if it is a register name a Reg operand is created, the token is eaten
// and false is returned. Else true is returned and no token is eaten.
// TODO this is likely to change to allow different register types and or to
// parse for a specific register type.
bool ARMAsmParser::ParseRegister(ARMOperand &Op) {
/// Try to parse a register name. The token must be an Identifier when called,
/// and if it is a register name a Reg operand is created, the token is eaten
/// and false is returned. Else true is returned and no token is eaten.
/// TODO this is likely to change to allow different register types and or to
/// parse for a specific register type.
bool ARMAsmParser::MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack) {
const AsmToken &Tok = getLexer().getTok();
assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
@ -227,19 +236,21 @@ bool ARMAsmParser::ParseRegister(ARMOperand &Op) {
getLexer().Lex(); // Eat identifier token.
bool Writeback = false;
if (ParseWriteBack) {
const AsmToken &ExclaimTok = getLexer().getTok();
if (ExclaimTok.is(AsmToken::Exclaim)) {
Writeback = true;
getLexer().Lex(); // Eat exclaim token
}
}
Op = ARMOperand::CreateReg(RegNum, Writeback);
return false;
}
// Parse a register list, return false if successful else return true or an
// error. The first token must be a '{' when called.
/// Parse a register list, return false if successful else return true or an
/// error. The first token must be a '{' when called.
bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) {
assert(getLexer().getTok().is(AsmToken::LCurly) &&
"Token is not an Left Curly Brace");
@ -285,10 +296,10 @@ bool ARMAsmParser::ParseRegisterList(ARMOperand &Op) {
return false;
}
// Parse an arm memory expression, return false if successful else return true
// or an error. The first token must be a '[' when called.
// TODO Only preindexing and postindexing addressing are started, unindexed
// with option, etc are still to do.
/// Parse an arm memory expression, return false if successful else return true
/// or an error. The first token must be a '[' when called.
/// TODO Only preindexing and postindexing addressing are started, unindexed
/// with option, etc are still to do.
bool ARMAsmParser::ParseMemory(ARMOperand &Op) {
assert(getLexer().getTok().is(AsmToken::LBrac) &&
"Token is not an Left Bracket");
@ -297,10 +308,9 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) {
const AsmToken &BaseRegTok = getLexer().getTok();
if (BaseRegTok.isNot(AsmToken::Identifier))
return Error(BaseRegTok.getLoc(), "register expected");
int BaseRegNum = MatchRegisterName(BaseRegTok.getString());
if (BaseRegNum == -1)
if (MaybeParseRegister(Op, false))
return Error(BaseRegTok.getLoc(), "register expected");
getLexer().Lex(); // Eat identifier token.
int BaseRegNum = Op.getReg();
bool Preindexed = false;
bool Postindexed = false;
@ -308,55 +318,20 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) {
bool Negative = false;
bool Writeback = false;
// First look for preindexed address forms:
// [Rn, +/-Rm]
// [Rn, #offset]
// [Rn, +/-Rm, shift]
// that is after the "[Rn" we now have see if the next token is a comma.
// First look for preindexed address forms, that is after the "[Rn" we now
// have to see if the next token is a comma.
const AsmToken &Tok = getLexer().getTok();
if (Tok.is(AsmToken::Comma)) {
Preindexed = true;
getLexer().Lex(); // Eat comma token.
const AsmToken &NextTok = getLexer().getTok();
if (NextTok.is(AsmToken::Plus))
getLexer().Lex(); // Eat plus token.
else if (NextTok.is(AsmToken::Minus)) {
Negative = true;
getLexer().Lex(); // Eat minus token
}
// See if there is a register following the "[Rn," we have so far.
const AsmToken &OffsetRegTok = getLexer().getTok();
int OffsetRegNum = MatchRegisterName(OffsetRegTok.getString());
bool OffsetRegShifted = false;
int OffsetRegNum;
bool OffsetRegShifted;
enum ShiftType ShiftType;
const MCExpr *ShiftAmount;
const MCExpr *Offset;
if (OffsetRegNum != -1) {
OffsetIsReg = true;
getLexer().Lex(); // Eat identifier token for the offset register.
// Look for a comma then a shift
const AsmToken &Tok = getLexer().getTok();
if (Tok.is(AsmToken::Comma)) {
getLexer().Lex(); // Eat comma token.
const AsmToken &Tok = getLexer().getTok();
if (ParseShift(&ShiftType, ShiftAmount))
return Error(Tok.getLoc(), "shift expected");
OffsetRegShifted = true;
}
}
else { // "[Rn," we have so far was not followed by "Rm"
// Look for #offset following the "[Rn,"
const AsmToken &HashTok = getLexer().getTok();
if (HashTok.isNot(AsmToken::Hash))
return Error(HashTok.getLoc(), "'#' expected");
getLexer().Lex(); // Eat hash token.
if (getParser().ParseExpression(Offset))
if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
Offset, OffsetIsReg, OffsetRegNum))
return true;
}
const AsmToken &RBracTok = getLexer().getTok();
if (RBracTok.isNot(AsmToken::RBrac))
return Error(RBracTok.getLoc(), "']' expected");
@ -374,11 +349,8 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) {
}
// The "[Rn" we have so far was not followed by a comma.
else if (Tok.is(AsmToken::RBrac)) {
// This is a post indexing addressing forms:
// [Rn], #offset
// [Rn], +/-Rm
// [Rn], +/-Rm, shift
// that is a ']' follows after the "[Rn".
// This is a post indexing addressing forms, that is a ']' follows after
// the "[Rn".
Postindexed = true;
Writeback = true;
getLexer().Lex(); // Eat right bracket token.
@ -394,43 +366,10 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) {
if (NextTok.isNot(AsmToken::Comma))
return Error(NextTok.getLoc(), "',' expected");
getLexer().Lex(); // Eat comma token.
const AsmToken &PlusMinusTok = getLexer().getTok();
if (PlusMinusTok.is(AsmToken::Plus))
getLexer().Lex(); // Eat plus token.
else if (PlusMinusTok.is(AsmToken::Minus)) {
Negative = true;
getLexer().Lex(); // Eat minus token
}
// See if there is a register following the "[Rn]," we have so far.
const AsmToken &OffsetRegTok = getLexer().getTok();
OffsetRegNum = MatchRegisterName(OffsetRegTok.getString());
if (OffsetRegNum != -1) {
OffsetIsReg = true;
getLexer().Lex(); // Eat identifier token for the offset register.
// Look for a comma then a shift
const AsmToken &Tok = getLexer().getTok();
if (Tok.is(AsmToken::Comma)) {
getLexer().Lex(); // Eat comma token.
const AsmToken &Tok = getLexer().getTok();
if (ParseShift(&ShiftType, ShiftAmount))
return Error(Tok.getLoc(), "shift expected");
OffsetRegShifted = true;
}
}
else { // "[Rn]," we have so far was not followed by "Rm"
// Look for #offset following the "[Rn],"
const AsmToken &HashTok = getLexer().getTok();
if (HashTok.isNot(AsmToken::Hash))
return Error(HashTok.getLoc(), "'#' expected");
getLexer().Lex(); // Eat hash token.
if (getParser().ParseExpression(Offset))
if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
ShiftAmount, Offset, OffsetIsReg, OffsetRegNum))
return true;
}
}
Op = ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
OffsetRegShifted, ShiftType, ShiftAmount,
@ -441,32 +380,93 @@ bool ARMAsmParser::ParseMemory(ARMOperand &Op) {
return true;
}
/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
/// we will parse the following (were +/- means that a plus or minus is
/// optional):
/// +/-Rm
/// +/-Rm, shift
/// #offset
/// we return false on success or an error otherwise.
bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
bool &OffsetRegShifted,
enum ShiftType &ShiftType,
const MCExpr *&ShiftAmount,
const MCExpr *&Offset,
bool &OffsetIsReg,
int OffsetRegNum) {
ARMOperand Op;
Negative = false;
OffsetRegShifted = false;
OffsetIsReg = false;
OffsetRegNum = -1;
const AsmToken &NextTok = getLexer().getTok();
if (NextTok.is(AsmToken::Plus))
getLexer().Lex(); // Eat plus token.
else if (NextTok.is(AsmToken::Minus)) {
Negative = true;
getLexer().Lex(); // Eat minus token
}
// See if there is a register following the "[Rn," or "[Rn]," we have so far.
const AsmToken &OffsetRegTok = getLexer().getTok();
if (OffsetRegTok.is(AsmToken::Identifier)) {
OffsetIsReg = !MaybeParseRegister(Op, false);
if (OffsetIsReg)
OffsetRegNum = Op.getReg();
}
// If we parsed a register as the offset then their can be a shift after that
if (OffsetRegNum != -1) {
// Look for a comma then a shift
const AsmToken &Tok = getLexer().getTok();
if (Tok.is(AsmToken::Comma)) {
getLexer().Lex(); // Eat comma token.
const AsmToken &Tok = getLexer().getTok();
if (ParseShift(ShiftType, ShiftAmount))
return Error(Tok.getLoc(), "shift expected");
OffsetRegShifted = true;
}
}
else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
// Look for #offset following the "[Rn," or "[Rn],"
const AsmToken &HashTok = getLexer().getTok();
if (HashTok.isNot(AsmToken::Hash))
return Error(HashTok.getLoc(), "'#' expected");
getLexer().Lex(); // Eat hash token.
if (getParser().ParseExpression(Offset))
return true;
}
return false;
}
/// ParseShift as one of these two:
/// ( lsl | lsr | asr | ror ) , # shift_amount
/// rrx
/// and returns true if it parses a shift otherwise it returns false.
bool ARMAsmParser::ParseShift(ShiftType *St, const MCExpr *&ShiftAmount) {
bool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount) {
const AsmToken &Tok = getLexer().getTok();
if (Tok.isNot(AsmToken::Identifier))
return true;
const StringRef &ShiftName = Tok.getString();
if (ShiftName == "lsl" || ShiftName == "LSL")
*St = Lsl;
St = Lsl;
else if (ShiftName == "lsr" || ShiftName == "LSR")
*St = Lsr;
St = Lsr;
else if (ShiftName == "asr" || ShiftName == "ASR")
*St = Asr;
St = Asr;
else if (ShiftName == "ror" || ShiftName == "ROR")
*St = Ror;
St = Ror;
else if (ShiftName == "rrx" || ShiftName == "RRX")
*St = Rrx;
St = Rrx;
else
return true;
getLexer().Lex(); // Eat shift type token.
// For all but a Rotate right there must be a '#' and a shift amount
if (*St != Rrx) {
// Look for # following the shift type
// Rrx stands alone.
if (St == Rrx)
return false;
// Otherwise, there must be a '#' and a shift amount.
const AsmToken &HashTok = getLexer().getTok();
if (HashTok.isNot(AsmToken::Hash))
return Error(HashTok.getLoc(), "'#' expected");
@ -474,12 +474,11 @@ bool ARMAsmParser::ParseShift(ShiftType *St, const MCExpr *&ShiftAmount) {
if (getParser().ParseExpression(ShiftAmount))
return true;
}
return false;
}
// A hack to allow some testing, to be replaced by a real table gen version.
/// A hack to allow some testing, to be replaced by a real table gen version.
int ARMAsmParser::MatchRegisterName(const StringRef &Name) {
if (Name == "r0" || Name == "R0")
return 0;
@ -518,7 +517,7 @@ int ARMAsmParser::MatchRegisterName(const StringRef &Name) {
return -1;
}
// A hack to allow some testing, to be replaced by a real table gen version.
/// A hack to allow some testing, to be replaced by a real table gen version.
bool ARMAsmParser::MatchInstruction(SmallVectorImpl<ARMOperand> &Operands,
MCInst &Inst) {
struct ARMOperand Op0 = Operands[0];
@ -549,12 +548,12 @@ bool ARMAsmParser::MatchInstruction(SmallVectorImpl<ARMOperand> &Operands,
return true;
}
// Parse a arm instruction operand. For now this parses the operand regardless
// of the mnemonic.
/// Parse a arm instruction operand. For now this parses the operand regardless
/// of the mnemonic.
bool ARMAsmParser::ParseOperand(ARMOperand &Op) {
switch (getLexer().getKind()) {
case AsmToken::Identifier:
if (!ParseRegister(Op))
if (!MaybeParseRegister(Op, true))
return false;
// This was not a register so parse other operands that start with an
// identifier (like labels) as expressions and create them as immediates.
@ -581,7 +580,7 @@ bool ARMAsmParser::ParseOperand(ARMOperand &Op) {
}
}
// Parse an arm instruction mnemonic followed by its operands.
/// Parse an arm instruction mnemonic followed by its operands.
bool ARMAsmParser::ParseInstruction(const StringRef &Name, MCInst &Inst) {
SmallVector<ARMOperand, 7> Operands;
@ -739,7 +738,7 @@ bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
return false;
}
// Force static initialization.
/// Force static initialization.
extern "C" void LLVMInitializeARMAsmParser() {
RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);