Skip to content

Commit 20d52e3

Browse files
committed
[AMDGPU][MC] Corrected parsing of registers
See bug 41280: https://bugs.llvm.org/show_bug.cgi?id=41280 Reviewers: artem.tamazov, arsenm Differential Revision: https://reviews.llvm.org/D60621 llvm-svn: 358581
1 parent 59e8bd3 commit 20d52e3

File tree

3 files changed

+191
-28
lines changed

3 files changed

+191
-28
lines changed

llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp

Lines changed: 126 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,8 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
908908
bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg,
909909
unsigned& RegNum, unsigned& RegWidth,
910910
unsigned *DwordRegIndex);
911+
bool isRegister();
912+
bool isRegister(const AsmToken &Token, const AsmToken &NextToken) const;
911913
Optional<StringRef> getGprCountSymbolName(RegisterKind RegKind);
912914
void initializeGprCountSymbol(RegisterKind RegKind);
913915
bool updateGprCountSymbols(RegisterKind RegKind, unsigned DwordRegIndex,
@@ -1125,11 +1127,19 @@ class AMDGPUAsmParser : public MCTargetAsmParser {
11251127
bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
11261128
unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const;
11271129

1130+
bool isId(const StringRef Id) const;
1131+
bool isId(const AsmToken &Token, const StringRef Id) const;
1132+
bool isToken(const AsmToken::TokenKind Kind) const;
11281133
bool trySkipId(const StringRef Id);
11291134
bool trySkipToken(const AsmToken::TokenKind Kind);
11301135
bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg);
11311136
bool parseString(StringRef &Val, const StringRef ErrMsg = "expected a string");
1137+
AsmToken::TokenKind getTokenKind() const;
11321138
bool parseExpr(int64_t &Imm);
1139+
AsmToken peekToken();
1140+
AsmToken getToken() const;
1141+
SMLoc getLoc() const;
1142+
void lex();
11331143

11341144
public:
11351145
OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
@@ -1748,6 +1758,51 @@ bool AMDGPUAsmParser::AddNextRegisterToList(unsigned &Reg, unsigned &RegWidth,
17481758
}
17491759
}
17501760

1761+
static const StringRef Registers[] = {
1762+
{ "v" },
1763+
{ "s" },
1764+
{ "ttmp" },
1765+
};
1766+
1767+
bool
1768+
AMDGPUAsmParser::isRegister(const AsmToken &Token,
1769+
const AsmToken &NextToken) const {
1770+
1771+
// A list of consecutive registers: [s0,s1,s2,s3]
1772+
if (Token.is(AsmToken::LBrac))
1773+
return true;
1774+
1775+
if (!Token.is(AsmToken::Identifier))
1776+
return false;
1777+
1778+
// A single register like s0 or a range of registers like s[0:1]
1779+
1780+
StringRef RegName = Token.getString();
1781+
1782+
for (StringRef Reg : Registers) {
1783+
if (RegName.startswith(Reg)) {
1784+
if (Reg.size() < RegName.size()) {
1785+
unsigned RegNum;
1786+
// A single register with an index: rXX
1787+
if (!RegName.substr(Reg.size()).getAsInteger(10, RegNum))
1788+
return true;
1789+
} else {
1790+
// A range of registers: r[XX:YY].
1791+
if (NextToken.is(AsmToken::LBrac))
1792+
return true;
1793+
}
1794+
}
1795+
}
1796+
1797+
return getSpecialRegForName(RegName);
1798+
}
1799+
1800+
bool
1801+
AMDGPUAsmParser::isRegister()
1802+
{
1803+
return isRegister(getToken(), peekToken());
1804+
}
1805+
17511806
bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg,
17521807
unsigned &RegNum, unsigned &RegWidth,
17531808
unsigned *DwordRegIndex) {
@@ -1933,6 +1988,8 @@ std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
19331988
unsigned Reg, RegNum, RegWidth, DwordRegIndex;
19341989

19351990
if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, &DwordRegIndex)) {
1991+
//FIXME: improve error messages (bug 41303).
1992+
Error(StartLoc, "not a valid operand.");
19361993
return nullptr;
19371994
}
19381995
if (AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
@@ -2012,23 +2069,24 @@ AMDGPUAsmParser::parseImm(OperandVector &Operands, bool AbsMod) {
20122069

20132070
OperandMatchResultTy
20142071
AMDGPUAsmParser::parseReg(OperandVector &Operands) {
2072+
if (!isRegister())
2073+
return MatchOperand_NoMatch;
2074+
20152075
if (auto R = parseRegister()) {
20162076
assert(R->isReg());
20172077
R->Reg.IsForcedVOP3 = isForcedVOP3();
20182078
Operands.push_back(std::move(R));
20192079
return MatchOperand_Success;
20202080
}
2021-
return MatchOperand_NoMatch;
2081+
return MatchOperand_ParseFail;
20222082
}
20232083

20242084
OperandMatchResultTy
20252085
AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands, bool AbsMod) {
2026-
auto res = parseImm(Operands, AbsMod);
2027-
if (res != MatchOperand_NoMatch) {
2028-
return res;
2029-
}
2030-
2031-
return parseReg(Operands);
2086+
auto res = parseReg(Operands);
2087+
return (res == MatchOperand_NoMatch)?
2088+
parseImm(Operands, AbsMod) :
2089+
res;
20322090
}
20332091

20342092
OperandMatchResultTy
@@ -2195,21 +2253,24 @@ AMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) {
21952253
}
21962254

21972255
OperandMatchResultTy AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) {
2256+
auto Loc = getLoc();
2257+
if (trySkipId("off")) {
2258+
Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Loc,
2259+
AMDGPUOperand::ImmTyOff, false));
2260+
return MatchOperand_Success;
2261+
}
2262+
2263+
if (!isRegister())
2264+
return MatchOperand_NoMatch;
2265+
21982266
std::unique_ptr<AMDGPUOperand> Reg = parseRegister();
21992267
if (Reg) {
22002268
Operands.push_back(std::move(Reg));
22012269
return MatchOperand_Success;
22022270
}
22032271

2204-
const AsmToken &Tok = Parser.getTok();
2205-
if (Tok.getString() == "off") {
2206-
Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Tok.getLoc(),
2207-
AMDGPUOperand::ImmTyOff, false));
2208-
Parser.Lex();
2209-
return MatchOperand_Success;
2210-
}
2272+
return MatchOperand_ParseFail;
22112273

2212-
return MatchOperand_NoMatch;
22132274
}
22142275

22152276
unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
@@ -3520,7 +3581,7 @@ AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
35203581

35213582
ResTy = parseRegOrImm(Operands);
35223583

3523-
if (ResTy == MatchOperand_Success)
3584+
if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail)
35243585
return ResTy;
35253586

35263587
const auto &Tok = Parser.getTok();
@@ -4491,20 +4552,34 @@ bool AMDGPUOperand::isSendMsg() const {
44914552
// parser helpers
44924553
//===----------------------------------------------------------------------===//
44934554

4555+
bool
4556+
AMDGPUAsmParser::isId(const AsmToken &Token, const StringRef Id) const {
4557+
return Token.is(AsmToken::Identifier) && Token.getString() == Id;
4558+
}
4559+
4560+
bool
4561+
AMDGPUAsmParser::isId(const StringRef Id) const {
4562+
return isId(getToken(), Id);
4563+
}
4564+
4565+
bool
4566+
AMDGPUAsmParser::isToken(const AsmToken::TokenKind Kind) const {
4567+
return getTokenKind() == Kind;
4568+
}
4569+
44944570
bool
44954571
AMDGPUAsmParser::trySkipId(const StringRef Id) {
4496-
if (getLexer().getKind() == AsmToken::Identifier &&
4497-
Parser.getTok().getString() == Id) {
4498-
Parser.Lex();
4572+
if (isId(Id)) {
4573+
lex();
44994574
return true;
45004575
}
45014576
return false;
45024577
}
45034578

45044579
bool
45054580
AMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) {
4506-
if (getLexer().getKind() == Kind) {
4507-
Parser.Lex();
4581+
if (isToken(Kind)) {
4582+
lex();
45084583
return true;
45094584
}
45104585
return false;
@@ -4514,7 +4589,7 @@ bool
45144589
AMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind,
45154590
const StringRef ErrMsg) {
45164591
if (!trySkipToken(Kind)) {
4517-
Error(Parser.getTok().getLoc(), ErrMsg);
4592+
Error(getLoc(), ErrMsg);
45184593
return false;
45194594
}
45204595
return true;
@@ -4527,17 +4602,41 @@ AMDGPUAsmParser::parseExpr(int64_t &Imm) {
45274602

45284603
bool
45294604
AMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) {
4530-
SMLoc S = Parser.getTok().getLoc();
4531-
if (getLexer().getKind() == AsmToken::String) {
4532-
Val = Parser.getTok().getStringContents();
4533-
Parser.Lex();
4605+
if (isToken(AsmToken::String)) {
4606+
Val = getToken().getStringContents();
4607+
lex();
45344608
return true;
45354609
} else {
4536-
Error(S, ErrMsg);
4610+
Error(getLoc(), ErrMsg);
45374611
return false;
45384612
}
45394613
}
45404614

4615+
AsmToken
4616+
AMDGPUAsmParser::getToken() const {
4617+
return Parser.getTok();
4618+
}
4619+
4620+
AsmToken
4621+
AMDGPUAsmParser::peekToken() {
4622+
return getLexer().peekTok();
4623+
}
4624+
4625+
AsmToken::TokenKind
4626+
AMDGPUAsmParser::getTokenKind() const {
4627+
return getLexer().getKind();
4628+
}
4629+
4630+
SMLoc
4631+
AMDGPUAsmParser::getLoc() const {
4632+
return getToken().getLoc();
4633+
}
4634+
4635+
void
4636+
AMDGPUAsmParser::lex() {
4637+
Parser.Lex();
4638+
}
4639+
45414640
//===----------------------------------------------------------------------===//
45424641
// swizzle
45434642
//===----------------------------------------------------------------------===//

llvm/test/MC/AMDGPU/reg-syntax-err.s

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// RUN: not llvm-mc -arch=amdgcn -mcpu=tonga %s 2>&1 | FileCheck -check-prefix=NOVI %s
2+
3+
s_mov_b32 s1, s 1
4+
// NOVI: error: invalid operand for instruction
5+
6+
s_mov_b32 s1, s[0 1
7+
// NOVI: error: failed parsing operand
8+
9+
s_mov_b32 s1, s[0:0 1
10+
// NOVI: error: failed parsing operand
11+
12+
s_mov_b32 s1, [s[0 1
13+
// NOVI: error: failed parsing operand
14+
15+
s_mov_b32 s1, [s[0:1] 1
16+
// NOVI: error: failed parsing operand
17+
18+
s_mov_b32 s1, [s0, 1
19+
// NOVI: error: failed parsing operand
20+
21+
s_mov_b32 s1, s999 1
22+
// NOVI: error: failed parsing operand
23+
24+
s_mov_b32 s1, s[1:2] 1
25+
// NOVI: error: failed parsing operand
26+
27+
s_mov_b32 s1, s[0:2] 1
28+
// NOVI: error: failed parsing operand
29+
30+
s_mov_b32 s1, xnack_mask_lo 1
31+
// NOVI: error: failed parsing operand
32+
33+
s_mov_b32 s1, s s0
34+
// NOVI: error: invalid operand for instruction
35+
36+
s_mov_b32 s1, s[0 s0
37+
// NOVI: error: failed parsing operand
38+
39+
s_mov_b32 s1, s[0:0 s0
40+
// NOVI: error: failed parsing operand
41+
42+
s_mov_b32 s1, [s[0 s0
43+
// NOVI: error: failed parsing operand
44+
45+
s_mov_b32 s1, [s[0:1] s0
46+
// NOVI: error: failed parsing operand
47+
48+
s_mov_b32 s1, [s0, s0
49+
// NOVI: error: failed parsing operand
50+
51+
s_mov_b32 s1, s999 s0
52+
// NOVI: error: failed parsing operand
53+
54+
s_mov_b32 s1, s[1:2] s0
55+
// NOVI: error: failed parsing operand
56+
57+
s_mov_b32 s1, s[0:2] vcc_lo
58+
// NOVI: error: failed parsing operand
59+
60+
s_mov_b32 s1, xnack_mask_lo s1
61+
// NOVI: error: failed parsing operand
62+
63+
exp mrt0 v1, v2, v3, v4000 off
64+
// NOVI: error: failed parsing operand

llvm/test/MC/AMDGPU/sop1-err.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ s_mov_b64 s[0:1], s1
2828

2929
// FIXME: This shoudl probably say failed to parse.
3030
s_mov_b32 s
31-
// GCN: error: not a valid operand
31+
// GCN: error: invalid operand for instruction
3232
// Out of range register
3333

3434
s_mov_b32 s102, 1

0 commit comments

Comments
 (0)