[llvm] 5df9658 - [RISCV] Refactor register list parsing and improve error messages. (#134938)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 14 17:49:32 PDT 2025
Author: Craig Topper
Date: 2025-04-14T17:49:28-07:00
New Revision: 5df9658d4009e500be1421231b48b210e8c2cd69
URL: https://github.com/llvm/llvm-project/commit/5df9658d4009e500be1421231b48b210e8c2cd69
DIFF: https://github.com/llvm/llvm-project/commit/5df9658d4009e500be1421231b48b210e8c2cd69.diff
LOG: [RISCV] Refactor register list parsing and improve error messages. (#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.
Added:
Modified:
llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
llvm/test/MC/RISCV/rv32xqccmp-invalid.s
llvm/test/MC/RISCV/rv32zcmp-invalid.s
llvm/test/MC/RISCV/rv64xqccmp-invalid.s
llvm/test/MC/RISCV/rv64zcmp-invalid.s
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index f246aee4da394..2f8e002f291db 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -216,13 +216,10 @@ class RISCVAsmParser : public MCTargetAsmParser {
ParseStatus parseGPRPair(OperandVector &Operands, bool IsRV64Inst);
ParseStatus parseFRMArg(OperandVector &Operands);
ParseStatus parseFenceArg(OperandVector &Operands);
- ParseStatus parseRegList(OperandVector &Operands) {
- return parseRegListCommon(Operands, /*MustIncludeS0=*/false);
- }
+ ParseStatus parseRegList(OperandVector &Operands, bool MustIncludeS0 = false);
ParseStatus parseRegListS0(OperandVector &Operands) {
- return parseRegListCommon(Operands, /*MustIncludeS0=*/true);
+ return parseRegList(Operands, /*MustIncludeS0=*/true);
}
- ParseStatus parseRegListCommon(OperandVector &Operands, bool MustIncludeS0);
ParseStatus parseRegReg(OperandVector &Operands);
ParseStatus parseRetval(OperandVector &Operands);
@@ -2636,96 +2633,95 @@ ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
return ParseStatus::Success;
}
-ParseStatus RISCVAsmParser::parseRegListCommon(OperandVector &Operands,
- bool MustIncludeS0) {
- // RegList: {ra [, s0[-sN]]}
- // XRegList: {x1 [, x8[-x9][, x18[-xN]]]}
-
- // When MustIncludeS0 = true (not the default) (used for `qc.cm.pushfp`) which
- // must include `fp`/`s0` in the list:
- // RegList: {ra, s0[-sN]}
- // XRegList: {x1, x8[-x9][, x18[-xN]]}
+// RegList: {ra [, s0[-sN]]}
+// XRegList: {x1 [, x8[-x9][, x18[-xN]]]}
+// When MustIncludeS0 = true (not the default) (used for `qc.cm.pushfp`) which
+// must include `fp`/`s0` in the list:
+// RegList: {ra, s0[-sN]}
+// XRegList: {x1, x8[-x9][, x18[-xN]]}
+ParseStatus RISCVAsmParser::parseRegList(OperandVector &Operands,
+ bool MustIncludeS0) {
if (getTok().isNot(AsmToken::LCurly))
return ParseStatus::NoMatch;
SMLoc S = getLoc();
+
Lex();
- bool IsRVE = isRVE();
+ bool UsesXRegs;
+ MCRegister RegEnd;
+ do {
+ if (getTok().isNot(AsmToken::Identifier))
+ return Error(getLoc(), "invalid register");
- if (getLexer().isNot(AsmToken::Identifier))
- return Error(getLoc(), "register list must start from 'ra' or 'x1'");
+ StringRef RegName = getTok().getIdentifier();
+ MCRegister Reg = matchRegisterNameHelper(RegName);
+ if (!Reg)
+ return Error(getLoc(), "invalid register");
- StringRef RegName = getLexer().getTok().getIdentifier();
- MCRegister RegEnd = matchRegisterNameHelper(RegName);
- if (RegEnd != RISCV::X1)
- return Error(getLoc(), "register list must start from 'ra' or 'x1'");
- getLexer().Lex();
+ if (!RegEnd) {
+ UsesXRegs = RegName[0] == 'x';
+ if (Reg != RISCV::X1)
+ return Error(getLoc(), "register list must start from 'ra' or 'x1'");
+ } else if (RegEnd == RISCV::X1) {
+ if (Reg != RISCV::X8 || (UsesXRegs != (RegName[0] == 'x')))
+ return Error(getLoc(), Twine("register must be '") +
+ (UsesXRegs ? "x8" : "s0") + "'");
+ } else if (RegEnd == RISCV::X9 && UsesXRegs) {
+ if (Reg != RISCV::X18 || (RegName[0] != 'x'))
+ return Error(getLoc(), "register must be 'x18'");
+ } else {
+ return Error(getLoc(), "too many register ranges");
+ }
- // parse case like ,s0 (knowing the comma must be there if required)
- if (parseOptionalToken(AsmToken::Comma)) {
- if (getLexer().isNot(AsmToken::Identifier))
- return Error(getLoc(), "invalid register");
- StringRef RegName = getLexer().getTok().getIdentifier();
- RegEnd = matchRegisterNameHelper(RegName);
- if (!RegEnd)
- return Error(getLoc(), "invalid register");
- if (RegEnd != RISCV::X8)
- return Error(getLoc(),
- "continuous register list must start from 's0' or 'x8'");
- getLexer().Lex(); // eat reg
+ RegEnd = Reg;
- // parse case like -s1
+ Lex();
+
+ SMLoc MinusLoc = getLoc();
if (parseOptionalToken(AsmToken::Minus)) {
- StringRef EndName = getLexer().getTok().getIdentifier();
- // FIXME: the register mapping and checks of RVE is wrong
- RegEnd = matchRegisterNameHelper(EndName);
- if (!(RegEnd == RISCV::X9 ||
- (RegEnd >= RISCV::X18 && RegEnd <= RISCV::X27)))
- return Error(getLoc(), "invalid register");
- getLexer().Lex();
- }
+ if (RegEnd == RISCV::X1)
+ return Error(MinusLoc, Twine("register '") + (UsesXRegs ? "x1" : "ra") +
+ "' cannot start a multiple register range");
- // parse extra part like ', x18[-x20]' for XRegList
- if (parseOptionalToken(AsmToken::Comma)) {
- if (RegEnd != RISCV::X9)
- return Error(
- getLoc(),
- "first contiguous registers pair of register list must be 'x8-x9'");
+ if (getTok().isNot(AsmToken::Identifier))
+ return Error(getLoc(), "invalid register");
- // parse ', x18' for extra part
- if (getLexer().isNot(AsmToken::Identifier) || IsRVE)
+ StringRef RegName = getTok().getIdentifier();
+ MCRegister Reg = matchRegisterNameHelper(RegName);
+ if (!Reg)
return Error(getLoc(), "invalid register");
- StringRef EndName = getLexer().getTok().getIdentifier();
- RegEnd = MatchRegisterName(EndName);
- if (RegEnd != RISCV::X18)
- return Error(getLoc(),
- "second contiguous registers pair of register list "
- "must start from 'x18'");
- getLexer().Lex();
-
- // parse '-x20' for extra part
- if (parseOptionalToken(AsmToken::Minus)) {
- if (getLexer().isNot(AsmToken::Identifier) || IsRVE)
- return Error(getLoc(), "invalid register");
- EndName = getLexer().getTok().getIdentifier();
- RegEnd = MatchRegisterName(EndName);
- if (!(RegEnd >= RISCV::X19 && RegEnd <= RISCV::X27))
- return Error(getLoc(), "invalid register");
- getLexer().Lex();
- }
+
+ if (RegEnd == RISCV::X8) {
+ if ((Reg != RISCV::X9 &&
+ (UsesXRegs || Reg < RISCV::X18 || Reg > RISCV::X27)) ||
+ (UsesXRegs != (RegName[0] == 'x'))) {
+ if (UsesXRegs)
+ return Error(getLoc(), "register must be 'x9'");
+ return Error(getLoc(), "register must be in the range 's1' to 's11'");
+ }
+ } else if (RegEnd == RISCV::X18) {
+ if (Reg < RISCV::X19 || Reg > RISCV::X27 || (RegName[0] != 'x'))
+ return Error(getLoc(),
+ "register must be in the range 'x19' to 'x27'");
+ } else
+ llvm_unreachable("unexpected register");
+
+ RegEnd = Reg;
+
+ Lex();
}
- }
+ } while (parseOptionalToken(AsmToken::Comma));
- if (parseToken(AsmToken::RCurly, "register list must end with '}'"))
+ if (parseToken(AsmToken::RCurly, "expected ',' or '}'"))
return ParseStatus::Failure;
if (RegEnd == RISCV::X26)
- return Error(S, "invalid register list, {ra, s0-s10} or {x1, x8-x9, "
- "x18-x26} is not supported");
+ return Error(S, "invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, "
+ "x18-x26}' is not supported");
- auto Encode = RISCVZC::encodeRegList(RegEnd, IsRVE);
+ auto Encode = RISCVZC::encodeRegList(RegEnd, isRVE());
assert(Encode != RISCVZC::INVALID_RLIST);
if (MustIncludeS0 && Encode == RISCVZC::RA)
diff --git a/llvm/test/MC/RISCV/rv32xqccmp-invalid.s b/llvm/test/MC/RISCV/rv32xqccmp-invalid.s
index ece3513120392..a955a33dc5a55 100644
--- a/llvm/test/MC/RISCV/rv32xqccmp-invalid.s
+++ b/llvm/test/MC/RISCV/rv32xqccmp-invalid.s
@@ -10,7 +10,7 @@ qc.cm.mvsa01 s0, s0
# CHECK-ERROR: :[[@LINE+1]]:14: error: invalid operand for instruction
qc.cm.mva01s a1, a2
-# CHECK-ERROR: :[[@LINE+1]]:15: error: invalid register list, {ra, s0-s10} or {x1, x8-x9, x18-x26} is not supported
+# CHECK-ERROR: :[[@LINE+1]]:15: error: invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, x18-x26}' is not supported
qc.cm.popretz {ra, s0-s10}, 112
# CHECK-ERROR: :[[@LINE+1]]:28: error: stack adjustment for register list must be a multiple of 16 bytes in the range [16, 64]
diff --git a/llvm/test/MC/RISCV/rv32zcmp-invalid.s b/llvm/test/MC/RISCV/rv32zcmp-invalid.s
index b4261f865fae7..68aa7fc548f61 100644
--- a/llvm/test/MC/RISCV/rv32zcmp-invalid.s
+++ b/llvm/test/MC/RISCV/rv32zcmp-invalid.s
@@ -10,7 +10,7 @@ cm.mvsa01 s0, s0
# CHECK-ERROR: :[[@LINE+1]]:11: error: invalid operand for instruction
cm.mva01s a1, a2
-# CHECK-ERROR: :[[@LINE+1]]:12: error: invalid register list, {ra, s0-s10} or {x1, x8-x9, x18-x26} is not supported
+# CHECK-ERROR: :[[@LINE+1]]:12: error: invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, x18-x26}' is not supported
cm.popretz {ra, s0-s10}, 112
# 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
# CHECK-ERROR: :[[@LINE+1]]:9: error: register list must start from 'ra' or 'x1'
cm.pop {s0}, -40
-# CHECK-ERROR: :[[@LINE+1]]:13: error: continuous register list must start from 's0' or 'x8'
+# CHECK-ERROR: :[[@LINE+1]]:13: error: register must be 's0'
cm.pop {ra, t1}, -40
-# CHECK-ERROR: :[[@LINE+1]]:16: error: invalid register
+# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be in the range 's1' to 's11'
cm.pop {ra, s0-t1}, -40
-# CHECK-ERROR: :[[@LINE+1]]:20: error: second contiguous registers pair of register list must start from 'x18'
-cm.pop {ra, x8-x9, x28}, -40
+# CHECK-ERROR: :[[@LINE+1]]:20: error: register must be 'x18'
+cm.pop {x1, x8-x9, x28}, -40
-# CHECK-ERROR: :[[@LINE+1]]:24: error: invalid register
-cm.pop {ra, x8-x9, x18-x28}, -40
+# CHECK-ERROR: :[[@LINE+1]]:24: error: register must be in the range 'x19' to 'x27'
+cm.pop {x1, x8-x9, x18-x28}, -40
-# CHECK-ERROR: :[[@LINE+1]]:24: error: invalid register
-cm.pop {ra, x8-x9, x18-x17}, -40
+# CHECK-ERROR: :[[@LINE+1]]:24: error: register must be in the range 'x19' to 'x27'
+cm.pop {x1, x8-x9, x18-x17}, -40
-# CHECK-ERROR: :[[@LINE+1]]:16: error: invalid register
-cm.pop {ra, x8-f8, x18-x17}, -40
+# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be 'x9'
+cm.pop {x1, x8-f8, x18-x17}, -40
# CHECK-ERROR: :[[@LINE+1]]:9: error: operand must be {ra [, s0[-sN]]} or {x1 [, x8[-x9][, x18[-xN]]]}
cm.push x1, -16
+
+# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be in the range 's1' to 's11'
+cm.pop {ra, s0-f8}, -40
diff --git a/llvm/test/MC/RISCV/rv64xqccmp-invalid.s b/llvm/test/MC/RISCV/rv64xqccmp-invalid.s
index 953887cc77e47..24ffc6b9fc02a 100644
--- a/llvm/test/MC/RISCV/rv64xqccmp-invalid.s
+++ b/llvm/test/MC/RISCV/rv64xqccmp-invalid.s
@@ -10,7 +10,7 @@ qc.cm.mvsa01 s0, s0
# CHECK-ERROR: :[[@LINE+1]]:14: error: invalid operand for instruction
qc.cm.mva01s a1, a2
-# CHECK-ERROR: :[[@LINE+1]]:15: error: invalid register list, {ra, s0-s10} or {x1, x8-x9, x18-x26} is not supported
+# CHECK-ERROR: :[[@LINE+1]]:15: error: invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, x18-x26}' is not supported
qc.cm.popretz {ra, s0-s10}, 112
# CHECK-ERROR: :[[@LINE+1]]:28: error: stack adjustment for register list must be a multiple of 16 bytes in the range [32, 80]
diff --git a/llvm/test/MC/RISCV/rv64zcmp-invalid.s b/llvm/test/MC/RISCV/rv64zcmp-invalid.s
index c66415cb49b34..e806da81ea6d3 100644
--- a/llvm/test/MC/RISCV/rv64zcmp-invalid.s
+++ b/llvm/test/MC/RISCV/rv64zcmp-invalid.s
@@ -10,7 +10,7 @@ cm.mvsa01 s0, s0
# CHECK-ERROR: :[[@LINE+1]]:11: error: invalid operand for instruction
cm.mva01s a1, a2
-# CHECK-ERROR: :[[@LINE+1]]:12: error: invalid register list, {ra, s0-s10} or {x1, x8-x9, x18-x26} is not supported
+# CHECK-ERROR: :[[@LINE+1]]:12: error: invalid register list, '{ra, s0-s10}' or '{x1, x8-x9, x18-x26}' is not supported
cm.popretz {ra, s0-s10}, 112
# CHECK-ERROR: :[[@LINE+1]]:25: error: stack adjustment for register list must be a multiple of 16 bytes in the range [32, 80]
@@ -31,23 +31,23 @@ cm.pop {ra, s0-s1}, -33
# CHECK-ERROR: :[[@LINE+1]]:9: error: register list must start from 'ra' or 'x1'
cm.pop {s0}, -40
-# CHECK-ERROR: :[[@LINE+1]]:13: error: continuous register list must start from 's0' or 'x8'
+# CHECK-ERROR: :[[@LINE+1]]:13: error: register must be 's0'
cm.pop {ra, t1}, -40
-# CHECK-ERROR: :[[@LINE+1]]:16: error: invalid register
+# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be in the range 's1' to 's11'
cm.pop {ra, s0-t1}, -40
-# CHECK-ERROR: :[[@LINE+1]]:20: error: second contiguous registers pair of register list must start from 'x18'
-cm.pop {ra, x8-x9, x28}, -40
+# CHECK-ERROR: :[[@LINE+1]]:20: error: register must be 'x18'
+cm.pop {x1, x8-x9, x28}, -40
-# CHECK-ERROR: :[[@LINE+1]]:24: error: invalid register
-cm.pop {ra, x8-x9, x18-x28}, -40
+# CHECK-ERROR: :[[@LINE+1]]:24: error: register must be in the range 'x19' to 'x27'
+cm.pop {x1, x8-x9, x18-x28}, -40
-# CHECK-ERROR: :[[@LINE+1]]:24: error: invalid register
-cm.pop {ra, x8-x9, x18-x17}, -40
+# CHECK-ERROR: :[[@LINE+1]]:24: error: register must be in the range 'x19' to 'x27'
+cm.pop {x1, x8-x9, x18-x17}, -40
-# CHECK-ERROR: :[[@LINE+1]]:16: error: invalid register
-cm.pop {ra, x8-f8, x18-x17}, -40
+# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be 'x9'
+cm.pop {x1, x8-f8, x18-x17}, -40
# CHECK-ERROR: :[[@LINE+1]]:15: error: stack adjustment is invalid for this instruction and register list
cm.pop {ra}, -x1
@@ -55,5 +55,47 @@ cm.pop {ra}, -x1
# CHECK-ERROR: :[[@LINE+1]]:15: error: stack adjustment is invalid for this instruction and register list
cm.push {ra}, x1
-# CHECK-ERROR: :[[@LINE+1]]:12: error: register list must end with '}'
+# CHECK-ERROR: :[[@LINE+1]]:12: error: register 'x1' cannot start a multiple register range
cm.push {x1-x9}, -32
+
+# CHECK-ERROR: :[[@LINE+1]]:12: error: register 'ra' cannot start a multiple register range
+cm.push {ra-s0}, -32
+
+# CHECK-ERROR: :[[@LINE+1]]:13: error: register must be 'x8'
+cm.push {x1,s0}, -32
+
+# CHECK-ERROR: :[[@LINE+1]]:13: error: register must be 's0'
+cm.push {ra,x8}, -32
+
+# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be 'x9'
+cm.push {x1,x8-s1}, -32
+
+# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be in the range 's1' to 's11'
+cm.push {ra,s0-x9}, -32
+
+# CHECK-ERROR: :[[@LINE+1]]:16: error: register must be 'x9'
+cm.push {x1,x8-x18}, -32
+
+# CHECK-ERROR: :[[@LINE+1]]:19: error: register must be 'x18'
+cm.push {x1,x8-x9,s2}, -32
+
+# CHECK-ERROR: :[[@LINE+1]]:19: error: too many register ranges
+cm.push {ra,s0-s1,x18}, -32
+
+# CHECK-ERROR: :[[@LINE+1]]:19: error: too many register ranges
+cm.push {ra,s0-s1,s2}, -32
+
+# CHECK-ERROR: :[[@LINE+1]]:23: error: register must be in the range 'x19' to 'x27'
+cm.push {x1,x8-x9,x18-s3}, -32
+
+# CHECK-ERROR: :[[@LINE+1]]:27: error: too many register ranges
+cm.push {x1,x8-x9,x18-x19,x20}, -32
+
+# CHECK-ERROR: :[[@LINE+1]]:19: error: too many register ranges
+cm.push {ra,s0-s1,s3}, -32
+
+# CHECK-ERROR: :[[@LINE+1]]:18: error: expected ',' or '}'
+cm.push {ra,s0-s1-s2}, -32
+
+# CHECK-ERROR: :[[@LINE+1]]:16: error: expected ',' or '}'
+cm.push {ra, s0+s11}, -32
More information about the llvm-commits
mailing list