summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2010-11-06 22:36:58 +0000
committerBill Wendling <isanbard@gmail.com>2010-11-06 22:36:58 +0000
commite18980aeaacf34b0b57786656e9e3c5735a5c804 (patch)
tree7c1bcd4b83b68097f3ab7112415d3150dd877a61
parent9654e108d73532d6f9f022881cfb21a11aac3c3f (diff)
downloadbcm5719-llvm-e18980aeaacf34b0b57786656e9e3c5735a5c804.tar.gz
bcm5719-llvm-e18980aeaacf34b0b57786656e9e3c5735a5c804.zip
Add support for parsing register lists. We can't use a bitfield to keep track of
the registers, because the register numbers may be much greater than the number of bits available in the machine's register. I extracted the register list verification code out of the actual parsing of the registers. This made checking for errors much easier. It also limits the number of warnings that would be emitted for cascading infractions. llvm-svn: 118363
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp86
1 files changed, 64 insertions, 22 deletions
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 1744899a29b..a456d3ce524 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -82,7 +82,6 @@ class ARMAsmParser : public TargetAsmParser {
/// }
-
public:
ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
: TargetAsmParser(T), Parser(_Parser), TM(_TM) {
@@ -93,7 +92,6 @@ public:
virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
-
virtual bool ParseDirective(AsmToken DirectiveID);
};
} // end anonymous namespace
@@ -433,7 +431,8 @@ int ARMAsmParser::TryParseRegister() {
ARMOperand *ARMAsmParser::TryParseRegisterWithWriteBack() {
SMLoc S = Parser.getTok().getLoc();
int RegNo = TryParseRegister();
- if (RegNo == -1) return 0;
+ if (RegNo == -1)
+ return 0;
SMLoc E = Parser.getTok().getLoc();
@@ -451,10 +450,9 @@ ARMOperand *ARMAsmParser::TryParseRegisterWithWriteBack() {
/// Parse a register list, return it if successful else return null. The first
/// token must be a '{' when called.
ARMOperand *ARMAsmParser::ParseRegisterList() {
- SMLoc S, E;
assert(Parser.getTok().is(AsmToken::LCurly) &&
"Token is not a Left Curly Brace");
- S = Parser.getTok().getLoc();
+ SMLoc S = Parser.getTok().getLoc();
Parser.Lex(); // Eat left curly brace token.
const AsmToken &RegTok = Parser.getTok();
@@ -463,18 +461,22 @@ ARMOperand *ARMAsmParser::ParseRegisterList() {
Error(RegLoc, "register expected");
return 0;
}
+
int RegNum = TryParseRegister();
if (RegNum == -1) {
Error(RegLoc, "register expected");
return 0;
}
- unsigned RegList = 1 << RegNum;
+ unsigned PrevRegNum = RegNum;
+ std::vector<std::pair<unsigned, SMLoc> > Registers;
+ Registers.reserve(32);
+ Registers.push_back(std::make_pair(RegNum, RegLoc));
- int HighRegNum = RegNum;
- // TODO ranges like "{Rn-Rm}"
- while (Parser.getTok().is(AsmToken::Comma)) {
- Parser.Lex(); // Eat comma token.
+ while (Parser.getTok().is(AsmToken::Comma) ||
+ Parser.getTok().is(AsmToken::Minus)) {
+ bool IsRange = Parser.getTok().is(AsmToken::Minus);
+ Parser.Lex(); // Eat comma or minus token.
const AsmToken &RegTok = Parser.getTok();
SMLoc RegLoc = RegTok.getLoc();
@@ -482,33 +484,73 @@ ARMOperand *ARMAsmParser::ParseRegisterList() {
Error(RegLoc, "register expected");
return 0;
}
+
int RegNum = TryParseRegister();
if (RegNum == -1) {
Error(RegLoc, "register expected");
return 0;
}
- if (RegList & (1 << RegNum))
- Warning(RegLoc, "register duplicated in register list");
- else if (RegNum <= HighRegNum)
- Warning(RegLoc, "register not in ascending order in register list");
- RegList |= 1 << RegNum;
- HighRegNum = RegNum;
+ if (IsRange) {
+ int Reg = PrevRegNum;
+ do {
+ ++Reg;
+ Registers.push_back(std::make_pair(Reg, RegLoc));
+ } while (Reg != RegNum);
+ } else {
+ Registers.push_back(std::make_pair(RegNum, RegLoc));
+ }
+
+ PrevRegNum = RegNum;
}
+
+ // Process the right curly brace of the list.
const AsmToken &RCurlyTok = Parser.getTok();
if (RCurlyTok.isNot(AsmToken::RCurly)) {
Error(RCurlyTok.getLoc(), "'}' expected");
return 0;
}
- E = RCurlyTok.getLoc();
- Parser.Lex(); // Eat left curly brace token.
- // FIXME: Need to return an operand!
- Error(E, "FIXME: register list parsing not implemented");
- return 0;
+ SMLoc E = RCurlyTok.getLoc();
+ Parser.Lex(); // Eat right curly brace token.
+
+ // Verify the register list.
+ std::vector<std::pair<unsigned, SMLoc> >::iterator
+ RI = Registers.begin(), RE = Registers.end();
+
+ unsigned Number = Registers.size();
+ unsigned HighRegNum = RI->first;
+ unsigned RegStart = RI->first;
+
+ DenseMap<unsigned, bool> RegMap;
+ RegMap[RI->first] = true;
+
+ for (++RI; RI != RE; ++RI) {
+ std::pair<unsigned, SMLoc> &RegInfo = *RI;
+
+ if (RegMap[RegInfo.first]) {
+ Error(RegInfo.second, "register duplicated in register list");
+ return 0;
+ }
+
+ if (RegInfo.first < HighRegNum)
+ Warning(RegInfo.second,
+ "register not in ascending order in register list");
+
+ RegMap[RegInfo.first] = true;
+ HighRegNum = std::max(RegInfo.first, HighRegNum);
+ RegStart = std::min(RegInfo.first, RegStart);
+ }
+
+ if (RegStart + Number - 1 != HighRegNum) {
+ Error(RegLoc, "non-contiguous register range");
+ return 0;
+ }
+
+ return ARMOperand::CreateRegList(RegStart, Number, S, E);
}
-/// Parse an arm memory expression, return false if successful else return true
+/// 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.
OpenPOWER on IntegriCloud