mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-03-01 08:47:42 +00:00
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
This commit is contained in:
parent
25f31dcc8f
commit
0493b6982a
@ -82,7 +82,6 @@ class ARMAsmParser : public TargetAsmParser {
|
|||||||
|
|
||||||
/// }
|
/// }
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
|
ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
|
||||||
: TargetAsmParser(T), Parser(_Parser), TM(_TM) {
|
: TargetAsmParser(T), Parser(_Parser), TM(_TM) {
|
||||||
@ -93,7 +92,6 @@ public:
|
|||||||
|
|
||||||
virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
|
virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
|
||||||
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
|
||||||
|
|
||||||
virtual bool ParseDirective(AsmToken DirectiveID);
|
virtual bool ParseDirective(AsmToken DirectiveID);
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
@ -433,7 +431,8 @@ int ARMAsmParser::TryParseRegister() {
|
|||||||
ARMOperand *ARMAsmParser::TryParseRegisterWithWriteBack() {
|
ARMOperand *ARMAsmParser::TryParseRegisterWithWriteBack() {
|
||||||
SMLoc S = Parser.getTok().getLoc();
|
SMLoc S = Parser.getTok().getLoc();
|
||||||
int RegNo = TryParseRegister();
|
int RegNo = TryParseRegister();
|
||||||
if (RegNo == -1) return 0;
|
if (RegNo == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
SMLoc E = Parser.getTok().getLoc();
|
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
|
/// Parse a register list, return it if successful else return null. The first
|
||||||
/// token must be a '{' when called.
|
/// token must be a '{' when called.
|
||||||
ARMOperand *ARMAsmParser::ParseRegisterList() {
|
ARMOperand *ARMAsmParser::ParseRegisterList() {
|
||||||
SMLoc S, E;
|
|
||||||
assert(Parser.getTok().is(AsmToken::LCurly) &&
|
assert(Parser.getTok().is(AsmToken::LCurly) &&
|
||||||
"Token is not a Left Curly Brace");
|
"Token is not a Left Curly Brace");
|
||||||
S = Parser.getTok().getLoc();
|
SMLoc S = Parser.getTok().getLoc();
|
||||||
Parser.Lex(); // Eat left curly brace token.
|
Parser.Lex(); // Eat left curly brace token.
|
||||||
|
|
||||||
const AsmToken &RegTok = Parser.getTok();
|
const AsmToken &RegTok = Parser.getTok();
|
||||||
@ -463,18 +461,22 @@ ARMOperand *ARMAsmParser::ParseRegisterList() {
|
|||||||
Error(RegLoc, "register expected");
|
Error(RegLoc, "register expected");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RegNum = TryParseRegister();
|
int RegNum = TryParseRegister();
|
||||||
if (RegNum == -1) {
|
if (RegNum == -1) {
|
||||||
Error(RegLoc, "register expected");
|
Error(RegLoc, "register expected");
|
||||||
return 0;
|
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;
|
while (Parser.getTok().is(AsmToken::Comma) ||
|
||||||
// TODO ranges like "{Rn-Rm}"
|
Parser.getTok().is(AsmToken::Minus)) {
|
||||||
while (Parser.getTok().is(AsmToken::Comma)) {
|
bool IsRange = Parser.getTok().is(AsmToken::Minus);
|
||||||
Parser.Lex(); // Eat comma token.
|
Parser.Lex(); // Eat comma or minus token.
|
||||||
|
|
||||||
const AsmToken &RegTok = Parser.getTok();
|
const AsmToken &RegTok = Parser.getTok();
|
||||||
SMLoc RegLoc = RegTok.getLoc();
|
SMLoc RegLoc = RegTok.getLoc();
|
||||||
@ -482,33 +484,73 @@ ARMOperand *ARMAsmParser::ParseRegisterList() {
|
|||||||
Error(RegLoc, "register expected");
|
Error(RegLoc, "register expected");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RegNum = TryParseRegister();
|
int RegNum = TryParseRegister();
|
||||||
if (RegNum == -1) {
|
if (RegNum == -1) {
|
||||||
Error(RegLoc, "register expected");
|
Error(RegLoc, "register expected");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RegList & (1 << RegNum))
|
if (IsRange) {
|
||||||
Warning(RegLoc, "register duplicated in register list");
|
int Reg = PrevRegNum;
|
||||||
else if (RegNum <= HighRegNum)
|
do {
|
||||||
Warning(RegLoc, "register not in ascending order in register list");
|
++Reg;
|
||||||
RegList |= 1 << RegNum;
|
Registers.push_back(std::make_pair(Reg, RegLoc));
|
||||||
HighRegNum = RegNum;
|
} 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();
|
const AsmToken &RCurlyTok = Parser.getTok();
|
||||||
if (RCurlyTok.isNot(AsmToken::RCurly)) {
|
if (RCurlyTok.isNot(AsmToken::RCurly)) {
|
||||||
Error(RCurlyTok.getLoc(), "'}' expected");
|
Error(RCurlyTok.getLoc(), "'}' expected");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
E = RCurlyTok.getLoc();
|
|
||||||
Parser.Lex(); // Eat left curly brace token.
|
|
||||||
|
|
||||||
// FIXME: Need to return an operand!
|
SMLoc E = RCurlyTok.getLoc();
|
||||||
Error(E, "FIXME: register list parsing not implemented");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an arm memory expression, return false if successful else return true
|
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
|
||||||
/// or an error. The first token must be a '[' when called.
|
/// or an error. The first token must be a '[' when called.
|
||||||
/// TODO Only preindexing and postindexing addressing are started, unindexed
|
/// TODO Only preindexing and postindexing addressing are started, unindexed
|
||||||
/// with option, etc are still to do.
|
/// with option, etc are still to do.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user