[llvm] [RISCV][MC] Support imm symbol in parseCSRSystemRegister (PR #112007)

Mark Zhuang via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 11 08:04:40 PDT 2024


https://github.com/zqb-all created https://github.com/llvm/llvm-project/pull/112007

None

>From 51b0ce729e9c924ca925f2fe2ada36c78c803fea Mon Sep 17 00:00:00 2001
From: Mark Zhuang <mark.zhuang at spacemit.com>
Date: Thu, 10 Oct 2024 17:37:32 +0800
Subject: [PATCH] [RISCV][MC] Support imm symbol in parseCSRSystemRegister

---
 .../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 84 ++++++++++---------
 llvm/test/MC/RISCV/rv32i-invalid.s            | 14 ++--
 llvm/test/MC/RISCV/rv32i-valid.s              |  3 +
 3 files changed, 53 insertions(+), 48 deletions(-)

diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index e68674e830436f..95f3fc0d473238 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -1877,10 +1877,13 @@ ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {
 ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
   SMLoc S = getLoc();
   const MCExpr *Res;
+  auto Kind = getLexer().getKind();
 
-  switch (getLexer().getKind()) {
+  switch (Kind) {
   default:
     return ParseStatus::NoMatch;
+
+  case AsmToken::Identifier:
   case AsmToken::LParen:
   case AsmToken::Minus:
   case AsmToken::Plus:
@@ -1891,6 +1894,45 @@ ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
     if (getParser().parseExpression(Res))
       return ParseStatus::Failure;
 
+    if (Kind == AsmToken::Identifier) {
+      auto SRE = dyn_cast<MCSymbolRefExpr>(Res);
+      if (SRE) {
+        auto Identifier = SRE->getSymbol().getName();
+        const auto *SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
+        if (!SysReg)
+          SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier);
+        if (!SysReg)
+          if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
+            Warning(S, "'" + Identifier + "' is a deprecated alias for '" +
+                           SysReg->Name + "'");
+
+        // Accept a named Sys Reg if the required features are present.
+        if (SysReg) {
+          const auto &FeatureBits = getSTI().getFeatureBits();
+          if (!SysReg->haveRequiredFeatures(FeatureBits)) {
+            const auto *Feature = llvm::find_if(RISCVFeatureKV, [&](auto Feature) {
+              return SysReg->FeaturesRequired[Feature.Value];
+            });
+            auto ErrorMsg = std::string("system register '") + SysReg->Name + "' ";
+            if (SysReg->isRV32Only && FeatureBits[RISCV::Feature64Bit]) {
+              ErrorMsg += "is RV32 only";
+              if (Feature != std::end(RISCVFeatureKV))
+                ErrorMsg += " and ";
+            }
+            if (Feature != std::end(RISCVFeatureKV)) {
+              ErrorMsg +=
+                  "requires '" + std::string(Feature->Key) + "' to be enabled";
+            }
+
+            return Error(S, ErrorMsg);
+          }
+          Operands.push_back(
+              RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
+          return ParseStatus::Success;
+        }
+      }
+    }
+
     auto *CE = dyn_cast<MCConstantExpr>(Res);
     if (CE) {
       int64_t Imm = CE->getValue();
@@ -1911,46 +1953,6 @@ ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
       }
     }
 
-    return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
-  }
-  case AsmToken::Identifier: {
-    StringRef Identifier;
-    if (getParser().parseIdentifier(Identifier))
-      return ParseStatus::Failure;
-
-    const auto *SysReg = RISCVSysReg::lookupSysRegByName(Identifier);
-    if (!SysReg)
-      SysReg = RISCVSysReg::lookupSysRegByAltName(Identifier);
-    if (!SysReg)
-      if ((SysReg = RISCVSysReg::lookupSysRegByDeprecatedName(Identifier)))
-        Warning(S, "'" + Identifier + "' is a deprecated alias for '" +
-                       SysReg->Name + "'");
-
-    // Accept a named Sys Reg if the required features are present.
-    if (SysReg) {
-      const auto &FeatureBits = getSTI().getFeatureBits();
-      if (!SysReg->haveRequiredFeatures(FeatureBits)) {
-        const auto *Feature = llvm::find_if(RISCVFeatureKV, [&](auto Feature) {
-          return SysReg->FeaturesRequired[Feature.Value];
-        });
-        auto ErrorMsg = std::string("system register '") + SysReg->Name + "' ";
-        if (SysReg->isRV32Only && FeatureBits[RISCV::Feature64Bit]) {
-          ErrorMsg += "is RV32 only";
-          if (Feature != std::end(RISCVFeatureKV))
-            ErrorMsg += " and ";
-        }
-        if (Feature != std::end(RISCVFeatureKV)) {
-          ErrorMsg +=
-              "requires '" + std::string(Feature->Key) + "' to be enabled";
-        }
-
-        return Error(S, ErrorMsg);
-      }
-      Operands.push_back(
-          RISCVOperand::createSysReg(Identifier, S, SysReg->Encoding));
-      return ParseStatus::Success;
-    }
-
     return generateImmOutOfRangeError(S, 0, (1 << 12) - 1,
                                       "operand must be a valid system register "
                                       "name or an integer in the range");
diff --git a/llvm/test/MC/RISCV/rv32i-invalid.s b/llvm/test/MC/RISCV/rv32i-invalid.s
index 80a59df94e36a3..a33b53b8237e5f 100644
--- a/llvm/test/MC/RISCV/rv32i-invalid.s
+++ b/llvm/test/MC/RISCV/rv32i-invalid.s
@@ -21,13 +21,13 @@ ori a0, a1, -2049 # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %
 andi ra, sp, 2048 # CHECK: :[[@LINE]]:14: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
 
 ## uimm12
-csrrw a0, -1, a0 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 4095]
-csrrs a0, 4096, a0 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 4095]
-csrrs a0, -0xf, a0 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 4095]
-csrrc a0, 0x1000, a0 # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 4095]
-csrrwi a0, -50, 0 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [0, 4095]
-csrrsi a0, 4097, a0 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [0, 4095]
-csrrci a0, 0xffff, a0 # CHECK: :[[@LINE]]:12: error: immediate must be an integer in the range [0, 4095]
+csrrw a0, -1, a0 # CHECK: :[[@LINE]]:11: error: operand must be a valid system register name or an integer in the range [0, 4095]
+csrrs a0, 4096, a0 # CHECK: :[[@LINE]]:11: error: operand must be a valid system register name or an integer in the range [0, 4095]
+csrrs a0, -0xf, a0 # CHECK: :[[@LINE]]:11: error: operand must be a valid system register name or an integer in the range [0, 4095]
+csrrc a0, 0x1000, a0 # CHECK: :[[@LINE]]:11: error: operand must be a valid system register name or an integer in the range [0, 4095]
+csrrwi a0, -50, 0 # CHECK: :[[@LINE]]:12: error: operand must be a valid system register name or an integer in the range [0, 4095]
+csrrsi a0, 4097, a0 # CHECK: :[[@LINE]]:12: error: operand must be a valid system register name or an integer in the range [0, 4095]
+csrrci a0, 0xffff, a0 # CHECK: :[[@LINE]]:12: error: operand must be a valid system register name or an integer in the range [0, 4095]
 
 ## simm13_lsb0
 beq t0, t1, -4098 # CHECK: :[[@LINE]]:13: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
diff --git a/llvm/test/MC/RISCV/rv32i-valid.s b/llvm/test/MC/RISCV/rv32i-valid.s
index f03c2e1c23cf3b..c5bad80e79de2d 100644
--- a/llvm/test/MC/RISCV/rv32i-valid.s
+++ b/llvm/test/MC/RISCV/rv32i-valid.s
@@ -373,3 +373,6 @@ csrrsi t2, 0xfff, 31
 # CHECK-ASM-AND-OBJ: csrrci t1, sscratch, 5
 # CHECK-ASM: encoding: [0x73,0xf3,0x02,0x14]
 csrrci t1, 0x140, 5
+# CHECK-ASM-AND-OBJ: csrrw t0, 16, t1
+# CHECK-ASM: encoding: [0xf3,0x12,0x03,0x01]
+csrrw t0, CONST, t1



More information about the llvm-commits mailing list