[llvm] [RISC-V][MC] Accept an absolute variable value as a CSR number (PR #67377)

via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 25 14:59:22 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mc

<details>
<summary>Changes</summary>

This is used by https://github.com/riscv-non-isa/riscv-arch-test and is accepted by GCC so it seems like we should be doing the same here.

---
Full diff: https://github.com/llvm/llvm-project/pull/67377.diff


2 Files Affected:

- (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+28-11) 
- (added) llvm/test/MC/RISCV/csr-abs-sym.s (+48) 


``````````diff
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 7d8d82e381313bf..4b1a5745308dcc2 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -1762,6 +1762,19 @@ ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
   SMLoc S = getLoc();
   const MCExpr *Res;
 
+  auto SysRegFromConstantInt = [](const MCExpr *E, SMLoc S) {
+    if (auto *CE = dyn_cast<MCConstantExpr>(E)) {
+      int64_t Imm = CE->getValue();
+      if (isUInt<12>(Imm)) {
+        auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
+        // Accept an immediate representing a named or un-named Sys Reg
+        // if the range is valid, regardless of the required features.
+        return RISCVOperand::createSysReg(SysReg ? SysReg->Name : "", S, Imm);
+      }
+    }
+    return std::unique_ptr<RISCVOperand>();
+  };
+
   switch (getLexer().getKind()) {
   default:
     return ParseStatus::NoMatch;
@@ -1775,17 +1788,9 @@ ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
     if (getParser().parseExpression(Res))
       return ParseStatus::Failure;
 
-    auto *CE = dyn_cast<MCConstantExpr>(Res);
-    if (CE) {
-      int64_t Imm = CE->getValue();
-      if (isUInt<12>(Imm)) {
-        auto SysReg = RISCVSysReg::lookupSysRegByEncoding(Imm);
-        // Accept an immediate representing a named or un-named Sys Reg
-        // if the range is valid, regardless of the required features.
-        Operands.push_back(
-            RISCVOperand::createSysReg(SysReg ? SysReg->Name : "", S, Imm));
-        return ParseStatus::Success;
-      }
+    if (auto SysOpnd = SysRegFromConstantInt(Res, S)) {
+      Operands.push_back(std::move(SysOpnd));
+      return ParseStatus::Success;
     }
 
     return generateImmOutOfRangeError(S, 0, (1 << 12) - 1);
@@ -1851,6 +1856,18 @@ ParseStatus RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
       return ParseStatus::Success;
     }
 
+    // Accept a symbol name that evaluates to an absolute value.
+    MCSymbol *Sym = getContext().lookupSymbol(Identifier);
+    if (Sym && Sym->isVariable()) {
+      // Pass false for SetUsed, since redefining the value later does not
+      // affect this instruction.
+      if (auto SysOpnd = SysRegFromConstantInt(
+              Sym->getVariableValue(/*SetUsed=*/false), S)) {
+        Operands.push_back(std::move(SysOpnd));
+        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/csr-abs-sym.s b/llvm/test/MC/RISCV/csr-abs-sym.s
new file mode 100644
index 000000000000000..93ecab0db106ba9
--- /dev/null
+++ b/llvm/test/MC/RISCV/csr-abs-sym.s
@@ -0,0 +1,48 @@
+## Check that we can use an absolute symbol value as a CSR number
+# RUN: llvm-mc -triple riscv32 %s | FileCheck %s
+# RUN: not llvm-mc -triple riscv32 %s --defsym=CHECK_BAD=1 2>&1 | FileCheck %s --check-prefix=ERROR
+
+.set fflags_abs_sym, 1
+csrr a0, fflags_abs_sym
+# CHECK: csrr	a0, fflags
+
+csrr a0, (fflags_abs_sym+1)
+# CHECK: csrr	a0, frm
+
+.equ fplus_one_abs_sym, fflags_abs_sym + 1
+csrr a0, fplus_one_abs_sym
+# CHECK: csrr	a0, frm
+
+## Check that redefining the value is allowed
+## If we were to use Sym->getVariableValue(true) this code would assert with
+## Assertion `!IsUsed && "Cannot set a variable that has already been used."' failed.
+.set csr_index, 1
+# CHECK: csrr	a0, fflags
+csrr a0, csr_index
+.set csr_index, 2
+# CHECK: csrr	a0, frm
+csrr a0, csr_index
+
+.ifdef CHECK_BAD
+.set out_of_range, 4097
+csrr a0, out_of_range
+# ERROR: [[#@LINE-1]]:10: error: operand must be a valid system register name or an integer in the range [0, 4095]
+
+csrr a0, undef_symbol
+# ERROR: [[#@LINE-1]]:10: error: operand must be a valid system register name or an integer in the range [0, 4095]
+
+local_label:
+csrr a0, local_label
+# ERROR: [[#@LINE-1]]:10: error: operand must be a valid system register name or an integer in the range [0, 4095]
+
+.Lstart:
+.space 10
+.Lend:
+csrr a0, .Lstart-.Lend
+# ERROR: [[#@LINE-1]]:10: error: operand must be a valid system register name or an integer in the range [0, 4095]
+
+.set dot_set_sym_diff, .Lstart-.Lend
+csrr a0, dot_set_sym_diff
+# ERROR: [[#@LINE-1]]:10: error: operand must be a valid system register name or an integer in the range [0, 4095]
+
+.endif

``````````

</details>


https://github.com/llvm/llvm-project/pull/67377


More information about the llvm-commits mailing list