@@ -215,7 +215,14 @@ class RISCVAsmParser : public MCTargetAsmParser {
215215 ParseStatus parseGPRPair (OperandVector &Operands, bool IsRV64Inst);
216216 ParseStatus parseFRMArg (OperandVector &Operands);
217217 ParseStatus parseFenceArg (OperandVector &Operands);
218- ParseStatus parseReglist (OperandVector &Operands);
218+ ParseStatus parseReglist (OperandVector &Operands) {
219+ return parseRegListCommon (Operands, /* MustIncludeS0=*/ false );
220+ }
221+ ParseStatus parseReglistS0 (OperandVector &Operands) {
222+ return parseRegListCommon (Operands, /* MustIncludeS0=*/ true );
223+ }
224+ ParseStatus parseRegListCommon (OperandVector &Operands, bool MustIncludeS0);
225+
219226 ParseStatus parseRegReg (OperandVector &Operands);
220227 ParseStatus parseRetval (OperandVector &Operands);
221228 ParseStatus parseZcmpStackAdj (OperandVector &Operands,
@@ -474,6 +481,9 @@ struct RISCVOperand final : public MCParsedAsmOperand {
474481 bool isSystemRegister () const { return Kind == KindTy::SystemRegister; }
475482 bool isRegReg () const { return Kind == KindTy::RegReg; }
476483 bool isRlist () const { return Kind == KindTy::Rlist; }
484+ bool isRlistS0 () const {
485+ return Kind == KindTy::Rlist && Rlist.Val != RISCVZC::RA;
486+ }
477487 bool isSpimm () const { return Kind == KindTy::Spimm; }
478488
479489 bool isGPR () const {
@@ -2794,9 +2804,15 @@ ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
27942804 return ParseStatus::Success;
27952805}
27962806
2797- ParseStatus RISCVAsmParser::parseReglist (OperandVector &Operands) {
2807+ ParseStatus RISCVAsmParser::parseRegListCommon (OperandVector &Operands,
2808+ bool MustIncludeS0) {
27982809 // Rlist: {ra [, s0[-sN]]}
27992810 // XRlist: {x1 [, x8[-x9][, x18[-xN]]]}
2811+
2812+ // When MustIncludeS0 = true (not the default) (used for `qc.cm.pushfp`) which
2813+ // must include `fp`/`s0` in the list:
2814+ // Rlist: {ra, s0[-sN]}
2815+ // XRlist: {x1, x8[-x9][, x18[-xN]]}
28002816 SMLoc S = getLoc ();
28012817
28022818 if (parseToken (AsmToken::LCurly, " register list must start with '{'" ))
@@ -2814,8 +2830,20 @@ ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
28142830 return Error (getLoc (), " register list must start from 'ra' or 'x1'" );
28152831 getLexer ().Lex ();
28162832
2817- // parse case like ,s0
2818- if (parseOptionalToken (AsmToken::Comma)) {
2833+ bool SeenComma = parseOptionalToken (AsmToken::Comma);
2834+
2835+ // There are two choices here:
2836+ // - `s0` is not required (usual case), so only try to parse `s0` if there is
2837+ // a comma
2838+ // - `s0` is required (qc.cm.pushfp), and so we must see the comma between
2839+ // `ra` and `s0` and must always try to parse `s0`, below
2840+ if (MustIncludeS0 && !SeenComma) {
2841+ Error (getLoc (), " register list must include 's0' or 'x8'" );
2842+ return ParseStatus::Failure;
2843+ }
2844+
2845+ // parse case like ,s0 (knowing the comma must be there if required)
2846+ if (SeenComma) {
28192847 if (getLexer ().isNot (AsmToken::Identifier))
28202848 return Error (getLoc (), " invalid register" );
28212849 StringRef RegName = getLexer ().getTok ().getIdentifier ();
@@ -2884,6 +2912,8 @@ ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
28842912
28852913 auto Encode = RISCVZC::encodeRlist (RegEnd, IsEABI);
28862914 assert (Encode != RISCVZC::INVALID_RLIST);
2915+ if (MustIncludeS0)
2916+ assert (Encode != RISCVZC::RA);
28872917 Operands.push_back (RISCVOperand::createRlist (Encode, S));
28882918
28892919 return ParseStatus::Success;
0 commit comments