Skip to content

Commit 5df9658

Browse files
authored
[RISCV] Refactor register list parsing and improve error messages. (llvm#134938)
Structure the code into a loop that parses a series of ranges and gives an error when there are too many ranges. Give errors when ABI and non-ABI names are mixed. Properly diagnose 'x1-` starting a list. Use a default bool argument to merge parseRegListCommon and parseRegList.
1 parent 9cdc3aa commit 5df9658

File tree

5 files changed

+140
-99
lines changed

5 files changed

+140
-99
lines changed

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

Lines changed: 70 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,10 @@ class RISCVAsmParser : public MCTargetAsmParser {
216216
ParseStatus parseGPRPair(OperandVector &Operands, bool IsRV64Inst);
217217
ParseStatus parseFRMArg(OperandVector &Operands);
218218
ParseStatus parseFenceArg(OperandVector &Operands);
219-
ParseStatus parseRegList(OperandVector &Operands) {
220-
return parseRegListCommon(Operands, /*MustIncludeS0=*/false);
221-
}
219+
ParseStatus parseRegList(OperandVector &Operands, bool MustIncludeS0 = false);
222220
ParseStatus parseRegListS0(OperandVector &Operands) {
223-
return parseRegListCommon(Operands, /*MustIncludeS0=*/true);
221+
return parseRegList(Operands, /*MustIncludeS0=*/true);
224222
}
225-
ParseStatus parseRegListCommon(OperandVector &Operands, bool MustIncludeS0);
226223

227224
ParseStatus parseRegReg(OperandVector &Operands);
228225
ParseStatus parseRetval(OperandVector &Operands);
@@ -2636,96 +2633,95 @@ ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
26362633
return ParseStatus::Success;
26372634
}
26382635

2639-
ParseStatus RISCVAsmParser::parseRegListCommon(OperandVector &Operands,
2640-
bool MustIncludeS0) {
2641-
// RegList: {ra [, s0[-sN]]}
2642-
// XRegList: {x1 [, x8[-x9][, x18[-xN]]]}
2643-
2644-
// When MustIncludeS0 = true (not the default) (used for `qc.cm.pushfp`) which
2645-
// must include `fp`/`s0` in the list:
2646-
// RegList: {ra, s0[-sN]}
2647-
// XRegList: {x1, x8[-x9][, x18[-xN]]}
2636+
// RegList: {ra [, s0[-sN]]}
2637+
// XRegList: {x1 [, x8[-x9][, x18[-xN]]]}
26482638

2639+
// When MustIncludeS0 = true (not the default) (used for `qc.cm.pushfp`) which
2640+
// must include `fp`/`s0` in the list:
2641+
// RegList: {ra, s0[-sN]}
2642+
// XRegList: {x1, x8[-x9][, x18[-xN]]}
2643+
ParseStatus RISCVAsmParser::parseRegList(OperandVector &Operands,
2644+
bool MustIncludeS0) {
26492645
if (getTok().isNot(AsmToken::LCurly))
26502646
return ParseStatus::NoMatch;
26512647

26522648
SMLoc S = getLoc();
2649+
26532650
Lex();
26542651

2655-
bool IsRVE = isRVE();
2652+
bool UsesXRegs;
2653+
MCRegister RegEnd;
2654+
do {
2655+
if (getTok().isNot(AsmToken::Identifier))
2656+
return Error(getLoc(), "invalid register");
26562657

2657-
if (getLexer().isNot(AsmToken::Identifier))
2658-
return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2658+
StringRef RegName = getTok().getIdentifier();
2659+
MCRegister Reg = matchRegisterNameHelper(RegName);
2660+
if (!Reg)
2661+
return Error(getLoc(), "invalid register");
26592662

2660-
StringRef RegName = getLexer().getTok().getIdentifier();
2661-
MCRegister RegEnd = matchRegisterNameHelper(RegName);
2662-
if (RegEnd != RISCV::X1)
2663-
return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2664-
getLexer().Lex();
2663+
if (!RegEnd) {
2664+
UsesXRegs = RegName[0] == 'x';
2665+
if (Reg != RISCV::X1)
2666+
return Error(getLoc(), "register list must start from 'ra' or 'x1'");
2667+
} else if (RegEnd == RISCV::X1) {
2668+
if (Reg != RISCV::X8 || (UsesXRegs != (RegName[0] == 'x')))
2669+
return Error(getLoc(), Twine("register must be '") +
2670+
(UsesXRegs ? "x8" : "s0") + "'");
2671+
} else if (RegEnd == RISCV::X9 && UsesXRegs) {
2672+
if (Reg != RISCV::X18 || (RegName[0] != 'x'))
2673+
return Error(getLoc(), "register must be 'x18'");
2674+
} else {
2675+
return Error(getLoc(), "too many register ranges");
2676+
}
26652677

2666-
// parse case like ,s0 (knowing the comma must be there if required)
2667-
if (parseOptionalToken(AsmToken::Comma)) {
2668-
if (getLexer().isNot(AsmToken::Identifier))
2669-
return Error(getLoc(), "invalid register");
2670-
StringRef RegName = getLexer().getTok().getIdentifier();
2671-
RegEnd = matchRegisterNameHelper(RegName);
2672-
if (!RegEnd)
2673-
return Error(getLoc(), "invalid register");
2674-
if (RegEnd != RISCV::X8)
2675-
return Error(getLoc(),
2676-
"continuous register list must start from 's0' or 'x8'");
2677-
getLexer().Lex(); // eat reg
2678+
RegEnd = Reg;
26782679

2679-
// parse case like -s1
2680+
Lex();
2681+
2682+
SMLoc MinusLoc = getLoc();
26802683
if (parseOptionalToken(AsmToken::Minus)) {
2681-
StringRef EndName = getLexer().getTok().getIdentifier();
2682-
// FIXME: the register mapping and checks of RVE is wrong
2683-
RegEnd = matchRegisterNameHelper(EndName);
2684-
if (!(RegEnd == RISCV::X9 ||
2685-
(RegEnd >= RISCV::X18 && RegEnd <= RISCV::X27)))
2686-
return Error(getLoc(), "invalid register");
2687-
getLexer().Lex();
2688-
}
2684+
if (RegEnd == RISCV::X1)
2685+
return Error(MinusLoc, Twine("register '") + (UsesXRegs ? "x1" : "ra") +
2686+
"' cannot start a multiple register range");
26892687

2690-
// parse extra part like ', x18[-x20]' for XRegList
2691-
if (parseOptionalToken(AsmToken::Comma)) {
2692-
if (RegEnd != RISCV::X9)
2693-
return Error(
2694-
getLoc(),
2695-
"first contiguous registers pair of register list must be 'x8-x9'");
2688+
if (getTok().isNot(AsmToken::Identifier))
2689+
return Error(getLoc(), "invalid register");
26962690

2697-
// parse ', x18' for extra part
2698-
if (getLexer().isNot(AsmToken::Identifier) || IsRVE)
2691+
StringRef RegName = getTok().getIdentifier();
2692+
MCRegister Reg = matchRegisterNameHelper(RegName);
2693+
if (!Reg)
26992694
return Error(getLoc(), "invalid register");
2700-
StringRef EndName = getLexer().getTok().getIdentifier();
2701-
RegEnd = MatchRegisterName(EndName);
2702-
if (RegEnd != RISCV::X18)
2703-
return Error(getLoc(),
2704-
"second contiguous registers pair of register list "
2705-
"must start from 'x18'");
2706-
getLexer().Lex();
2707-
2708-
// parse '-x20' for extra part
2709-
if (parseOptionalToken(AsmToken::Minus)) {
2710-
if (getLexer().isNot(AsmToken::Identifier) || IsRVE)
2711-
return Error(getLoc(), "invalid register");
2712-
EndName = getLexer().getTok().getIdentifier();
2713-
RegEnd = MatchRegisterName(EndName);
2714-
if (!(RegEnd >= RISCV::X19 && RegEnd <= RISCV::X27))
2715-
return Error(getLoc(), "invalid register");
2716-
getLexer().Lex();
2717-
}
2695+
2696+
if (RegEnd == RISCV::X8) {
2697+
if ((Reg != RISCV::X9 &&
2698+
(UsesXRegs || Reg < RISCV::X18 || Reg > RISCV::X27)) ||
2699+
(UsesXRegs != (RegName[0] == 'x'))) {
2700+
if (UsesXRegs)
2701+
return Error(getLoc(), "register must be 'x9'");
2702+
return Error(getLoc(), "register must be in the range 's1' to 's11'");
2703+
}
2704+
} else if (RegEnd == RISCV::X18) {
2705+
if (Reg < RISCV::X19 || Reg > RISCV::X27 || (RegName[0] != 'x'))
2706+
return Error(getLoc(),
2707+
"register must be in the range 'x19' to 'x27'");
2708+
} else
2709+
llvm_unreachable("unexpected register");
2710+
2711+
RegEnd = Reg;
2712+
2713+
Lex();
27182714
}
2719-
}
2715+
} while (parseOptionalToken(AsmToken::Comma));
27202716

2721-
if (parseToken(AsmToken::RCurly, "register list must end with '}'"))
2717+
if (parseToken(AsmToken::RCurly, "expected ',' or '}'"))
27222718
return ParseStatus::Failure;
27232719

27242720
if (RegEnd == RISCV::X26)
2725-
return Error(S, "invalid register list, {ra, s0-s10} or {x1, x8-x9, "
2726-
"x18-x26} is not supported");
2721+
return Error(S, "invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, "
2722+
"x18-x26}' is not supported");
27272723

2728-
auto Encode = RISCVZC::encodeRegList(RegEnd, IsRVE);
2724+
auto Encode = RISCVZC::encodeRegList(RegEnd, isRVE());
27292725
assert(Encode != RISCVZC::INVALID_RLIST);
27302726

27312727
if (MustIncludeS0 && Encode == RISCVZC::RA)

llvm/test/MC/RISCV/rv32xqccmp-invalid.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ qc.cm.mvsa01 s0, s0
1010
# CHECK-ERROR: :[[@LINE+1]]:14: error: invalid operand for instruction
1111
qc.cm.mva01s a1, a2
1212

13-
# CHECK-ERROR: :[[@LINE+1]]:15: error: invalid register list, {ra, s0-s10} or {x1, x8-x9, x18-x26} is not supported
13+
# CHECK-ERROR: :[[@LINE+1]]:15: error: invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, x18-x26}' is not supported
1414
qc.cm.popretz {ra, s0-s10}, 112
1515

1616
# CHECK-ERROR: :[[@LINE+1]]:28: error: stack adjustment for register list must be a multiple of 16 bytes in the range [16, 64]

llvm/test/MC/RISCV/rv32zcmp-invalid.s

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ cm.mvsa01 s0, s0
1010
# CHECK-ERROR: :[[@LINE+1]]:11: error: invalid operand for instruction
1111
cm.mva01s a1, a2
1212

13-
# CHECK-ERROR: :[[@LINE+1]]:12: error: invalid register list, {ra, s0-s10} or {x1, x8-x9, x18-x26} is not supported
13+
# CHECK-ERROR: :[[@LINE+1]]:12: error: invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, x18-x26}' is not supported
1414
cm.popretz {ra, s0-s10}, 112
1515

1616
# CHECK-ERROR: :[[@LINE+1]]:25: error: stack adjustment for register list must be a multiple of 16 bytes in the range [16, 64]
@@ -28,23 +28,26 @@ cm.push {ra}, -8
2828
# CHECK-ERROR: :[[@LINE+1]]:9: error: register list must start from 'ra' or 'x1'
2929
cm.pop {s0}, -40
3030

31-
# CHECK-ERROR: :[[@LINE+1]]:13: error: continuous register list must start from 's0' or 'x8'
31+
# CHECK-ERROR: :[[@LINE+1]]:13: error: register must be 's0'
3232
cm.pop {ra, t1}, -40
3333

34-
# CHECK-ERROR: :[[@LINE+1]]:16: error: invalid register
34+
# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be in the range 's1' to 's11'
3535
cm.pop {ra, s0-t1}, -40
3636

37-
# CHECK-ERROR: :[[@LINE+1]]:20: error: second contiguous registers pair of register list must start from 'x18'
38-
cm.pop {ra, x8-x9, x28}, -40
37+
# CHECK-ERROR: :[[@LINE+1]]:20: error: register must be 'x18'
38+
cm.pop {x1, x8-x9, x28}, -40
3939

40-
# CHECK-ERROR: :[[@LINE+1]]:24: error: invalid register
41-
cm.pop {ra, x8-x9, x18-x28}, -40
40+
# CHECK-ERROR: :[[@LINE+1]]:24: error: register must be in the range 'x19' to 'x27'
41+
cm.pop {x1, x8-x9, x18-x28}, -40
4242

43-
# CHECK-ERROR: :[[@LINE+1]]:24: error: invalid register
44-
cm.pop {ra, x8-x9, x18-x17}, -40
43+
# CHECK-ERROR: :[[@LINE+1]]:24: error: register must be in the range 'x19' to 'x27'
44+
cm.pop {x1, x8-x9, x18-x17}, -40
4545

46-
# CHECK-ERROR: :[[@LINE+1]]:16: error: invalid register
47-
cm.pop {ra, x8-f8, x18-x17}, -40
46+
# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be 'x9'
47+
cm.pop {x1, x8-f8, x18-x17}, -40
4848

4949
# CHECK-ERROR: :[[@LINE+1]]:9: error: operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}
5050
cm.push x1, -16
51+
52+
# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be in the range 's1' to 's11'
53+
cm.pop {ra, s0-f8}, -40

llvm/test/MC/RISCV/rv64xqccmp-invalid.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ qc.cm.mvsa01 s0, s0
1010
# CHECK-ERROR: :[[@LINE+1]]:14: error: invalid operand for instruction
1111
qc.cm.mva01s a1, a2
1212

13-
# CHECK-ERROR: :[[@LINE+1]]:15: error: invalid register list, {ra, s0-s10} or {x1, x8-x9, x18-x26} is not supported
13+
# CHECK-ERROR: :[[@LINE+1]]:15: error: invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, x18-x26}' is not supported
1414
qc.cm.popretz {ra, s0-s10}, 112
1515

1616
# CHECK-ERROR: :[[@LINE+1]]:28: error: stack adjustment for register list must be a multiple of 16 bytes in the range [32, 80]

llvm/test/MC/RISCV/rv64zcmp-invalid.s

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ cm.mvsa01 s0, s0
1010
# CHECK-ERROR: :[[@LINE+1]]:11: error: invalid operand for instruction
1111
cm.mva01s a1, a2
1212

13-
# CHECK-ERROR: :[[@LINE+1]]:12: error: invalid register list, {ra, s0-s10} or {x1, x8-x9, x18-x26} is not supported
13+
# CHECK-ERROR: :[[@LINE+1]]:12: error: invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, x18-x26}' is not supported
1414
cm.popretz {ra, s0-s10}, 112
1515

1616
# CHECK-ERROR: :[[@LINE+1]]:25: error: stack adjustment for register list must be a multiple of 16 bytes in the range [32, 80]
@@ -31,29 +31,71 @@ cm.pop {ra, s0-s1}, -33
3131
# CHECK-ERROR: :[[@LINE+1]]:9: error: register list must start from 'ra' or 'x1'
3232
cm.pop {s0}, -40
3333

34-
# CHECK-ERROR: :[[@LINE+1]]:13: error: continuous register list must start from 's0' or 'x8'
34+
# CHECK-ERROR: :[[@LINE+1]]:13: error: register must be 's0'
3535
cm.pop {ra, t1}, -40
3636

37-
# CHECK-ERROR: :[[@LINE+1]]:16: error: invalid register
37+
# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be in the range 's1' to 's11'
3838
cm.pop {ra, s0-t1}, -40
3939

40-
# CHECK-ERROR: :[[@LINE+1]]:20: error: second contiguous registers pair of register list must start from 'x18'
41-
cm.pop {ra, x8-x9, x28}, -40
40+
# CHECK-ERROR: :[[@LINE+1]]:20: error: register must be 'x18'
41+
cm.pop {x1, x8-x9, x28}, -40
4242

43-
# CHECK-ERROR: :[[@LINE+1]]:24: error: invalid register
44-
cm.pop {ra, x8-x9, x18-x28}, -40
43+
# CHECK-ERROR: :[[@LINE+1]]:24: error: register must be in the range 'x19' to 'x27'
44+
cm.pop {x1, x8-x9, x18-x28}, -40
4545

46-
# CHECK-ERROR: :[[@LINE+1]]:24: error: invalid register
47-
cm.pop {ra, x8-x9, x18-x17}, -40
46+
# CHECK-ERROR: :[[@LINE+1]]:24: error: register must be in the range 'x19' to 'x27'
47+
cm.pop {x1, x8-x9, x18-x17}, -40
4848

49-
# CHECK-ERROR: :[[@LINE+1]]:16: error: invalid register
50-
cm.pop {ra, x8-f8, x18-x17}, -40
49+
# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be 'x9'
50+
cm.pop {x1, x8-f8, x18-x17}, -40
5151

5252
# CHECK-ERROR: :[[@LINE+1]]:15: error: stack adjustment is invalid for this instruction and register list
5353
cm.pop {ra}, -x1
5454

5555
# CHECK-ERROR: :[[@LINE+1]]:15: error: stack adjustment is invalid for this instruction and register list
5656
cm.push {ra}, x1
5757

58-
# CHECK-ERROR: :[[@LINE+1]]:12: error: register list must end with '}'
58+
# CHECK-ERROR: :[[@LINE+1]]:12: error: register 'x1' cannot start a multiple register range
5959
cm.push {x1-x9}, -32
60+
61+
# CHECK-ERROR: :[[@LINE+1]]:12: error: register 'ra' cannot start a multiple register range
62+
cm.push {ra-s0}, -32
63+
64+
# CHECK-ERROR: :[[@LINE+1]]:13: error: register must be 'x8'
65+
cm.push {x1,s0}, -32
66+
67+
# CHECK-ERROR: :[[@LINE+1]]:13: error: register must be 's0'
68+
cm.push {ra,x8}, -32
69+
70+
# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be 'x9'
71+
cm.push {x1,x8-s1}, -32
72+
73+
# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be in the range 's1' to 's11'
74+
cm.push {ra,s0-x9}, -32
75+
76+
# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be 'x9'
77+
cm.push {x1,x8-x18}, -32
78+
79+
# CHECK-ERROR: :[[@LINE+1]]:19: error: register must be 'x18'
80+
cm.push {x1,x8-x9,s2}, -32
81+
82+
# CHECK-ERROR: :[[@LINE+1]]:19: error: too many register ranges
83+
cm.push {ra,s0-s1,x18}, -32
84+
85+
# CHECK-ERROR: :[[@LINE+1]]:19: error: too many register ranges
86+
cm.push {ra,s0-s1,s2}, -32
87+
88+
# CHECK-ERROR: :[[@LINE+1]]:23: error: register must be in the range 'x19' to 'x27'
89+
cm.push {x1,x8-x9,x18-s3}, -32
90+
91+
# CHECK-ERROR: :[[@LINE+1]]:27: error: too many register ranges
92+
cm.push {x1,x8-x9,x18-x19,x20}, -32
93+
94+
# CHECK-ERROR: :[[@LINE+1]]:19: error: too many register ranges
95+
cm.push {ra,s0-s1,s3}, -32
96+
97+
# CHECK-ERROR: :[[@LINE+1]]:18: error: expected ',' or '}'
98+
cm.push {ra,s0-s1-s2}, -32
99+
100+
# CHECK-ERROR: :[[@LINE+1]]:16: error: expected ',' or '}'
101+
cm.push {ra, s0+s11}, -32

0 commit comments

Comments
 (0)