Skip to content

Conversation

lenary
Copy link
Member

@lenary lenary commented Sep 20, 2025

I find it very confusing that we have two different kinds of "immediates":

  • MCOperands in the backend that are isImm() which can only be numbers
  • RISCVOperands in the parser that are isImm() which can contain expressions

This change aims to make it clearer that in the AsmParser, we are dealing with expressions, rather than just numbers.

Unfortunately, isImm comes from the MCParsedAsmOperand, which is needed for Microsoft Inline Asm, so we cannot fully get rid of it.

I find it very confusing that we have two different kinds of "immediates":
- MCOperands that have `isImm`, which can only be numbers
- RISCVOperands in the parser that can contain expressions

This change aims to make it clearer that in the AsmParser, we are
dealing with expressions, rather than just numbers.

Unfortunately, `isImm` comes from the `MCParsedAsmOperand`, which is
needed for Microsoft Inline Asm, so we cannot fully get rid of it.
@llvmbot
Copy link
Member

llvmbot commented Sep 20, 2025

@llvm/pr-subscribers-backend-risc-v

Author: Sam Elliott (lenary)

Changes

I find it very confusing that we have two different kinds of "immediates":

  • MCOperands in the backend that are isImm() which can only be numbers
  • RISCVOperands in the parser that are isImm() which can contain expressions

This change aims to make it clearer that in the AsmParser, we are dealing with expressions, rather than just numbers.

Unfortunately, isImm comes from the MCParsedAsmOperand, which is needed for Microsoft Inline Asm, so we cannot fully get rid of it.


Patch is 25.93 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/159888.diff

1 Files Affected:

  • (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+113-110)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 2b5f18d611524..50891da333f01 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -195,7 +195,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
 
   ParseStatus parseCSRSystemRegister(OperandVector &Operands);
   ParseStatus parseFPImm(OperandVector &Operands);
-  ParseStatus parseImmediate(OperandVector &Operands);
+  ParseStatus parseExpression(OperandVector &Operands);
   ParseStatus parseRegister(OperandVector &Operands, bool AllowParens = false);
   ParseStatus parseMemOpBaseReg(OperandVector &Operands);
   ParseStatus parseZeroOffsetMemOp(OperandVector &Operands);
@@ -340,7 +340,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   enum class KindTy {
     Token,
     Register,
-    Immediate,
+    Expression,
     FPImmediate,
     SystemRegister,
     VType,
@@ -356,8 +356,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
     bool IsGPRAsFPR;
   };
 
-  struct ImmOp {
-    const MCExpr *Val;
+  struct ExprOp {
+    const MCExpr *Expr;
     bool IsRV64;
   };
 
@@ -402,7 +402,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   union {
     StringRef Tok;
     RegOp Reg;
-    ImmOp Imm;
+    ExprOp Expr;
     FPImmOp FPImm;
     SysRegOp SysReg;
     VTypeOp VType;
@@ -424,8 +424,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
     case KindTy::Register:
       Reg = o.Reg;
       break;
-    case KindTy::Immediate:
-      Imm = o.Imm;
+    case KindTy::Expression:
+      Expr = o.Expr;
       break;
     case KindTy::FPImmediate:
       FPImm = o.FPImm;
@@ -459,6 +459,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
 
   bool isToken() const override { return Kind == KindTy::Token; }
   bool isReg() const override { return Kind == KindTy::Register; }
+  bool isExpr() const { return Kind == KindTy::Expression; }
   bool isV0Reg() const {
     return Kind == KindTy::Register && Reg.RegNum == RISCV::V0;
   }
@@ -475,7 +476,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
             RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
                 Reg.RegNum));
   }
-  bool isImm() const override { return Kind == KindTy::Immediate; }
+  bool isImm() const override { return isExpr(); }
   bool isMem() const override { return false; }
   bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
   bool isRegReg() const { return Kind == KindTy::RegReg; }
@@ -523,7 +524,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   bool isGPRAsFPR32() const { return isGPRF32() && Reg.IsGPRAsFPR; }
   bool isGPRPairAsFPR64() const { return isGPRPair() && Reg.IsGPRAsFPR; }
 
-  static bool evaluateConstantImm(const MCExpr *Expr, int64_t &Imm) {
+  static bool evaluateConstantExpr(const MCExpr *Expr, int64_t &Imm) {
     if (auto CE = dyn_cast<MCConstantExpr>(Expr)) {
       Imm = CE->getValue();
       return true;
@@ -535,30 +536,30 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   // True if operand is a symbol with no modifiers, or a constant with no
   // modifiers and isShiftedInt<N-1, 1>(Op).
   template <int N> bool isBareSimmNLsb0() const {
-    if (!isImm())
+    if (!isExpr())
       return false;
 
     int64_t Imm;
-    if (evaluateConstantImm(getImm(), Imm))
-      return isShiftedInt<N - 1, 1>(fixImmediateForRV32(Imm, isRV64Imm()));
+    if (evaluateConstantExpr(getExpr(), Imm))
+      return isShiftedInt<N - 1, 1>(fixImmediateForRV32(Imm, isRV64Expr()));
 
     RISCV::Specifier VK = RISCV::S_None;
-    return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
+    return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
            VK == RISCV::S_None;
   }
 
   // True if operand is a symbol with no modifiers, or a constant with no
   // modifiers and isInt<N>(Op).
   template <int N> bool isBareSimmN() const {
-    if (!isImm())
+    if (!isExpr())
       return false;
 
     int64_t Imm;
-    if (evaluateConstantImm(getImm(), Imm))
-      return isInt<N>(fixImmediateForRV32(Imm, isRV64Imm()));
+    if (evaluateConstantExpr(getExpr(), Imm))
+      return isInt<N>(fixImmediateForRV32(Imm, isRV64Expr()));
 
     RISCV::Specifier VK = RISCV::S_None;
-    return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
+    return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
            VK == RISCV::S_None;
   }
 
@@ -567,55 +568,55 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   bool isBareSymbol() const {
     int64_t Imm;
     // Must be of 'immediate' type but not a constant.
-    if (!isImm() || evaluateConstantImm(getImm(), Imm))
+    if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))
       return false;
 
     RISCV::Specifier VK = RISCV::S_None;
-    return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
+    return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
            VK == RISCV::S_None;
   }
 
   bool isCallSymbol() const {
     int64_t Imm;
     // Must be of 'immediate' type but not a constant.
-    if (!isImm() || evaluateConstantImm(getImm(), Imm))
+    if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))
       return false;
 
     RISCV::Specifier VK = RISCV::S_None;
-    return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
+    return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
            VK == ELF::R_RISCV_CALL_PLT;
   }
 
   bool isPseudoJumpSymbol() const {
     int64_t Imm;
     // Must be of 'immediate' type but not a constant.
-    if (!isImm() || evaluateConstantImm(getImm(), Imm))
+    if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))
       return false;
 
     RISCV::Specifier VK = RISCV::S_None;
-    return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
+    return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
            VK == ELF::R_RISCV_CALL_PLT;
   }
 
   bool isTPRelAddSymbol() const {
     int64_t Imm;
     // Must be of 'immediate' type but not a constant.
-    if (!isImm() || evaluateConstantImm(getImm(), Imm))
+    if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))
       return false;
 
     RISCV::Specifier VK = RISCV::S_None;
-    return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
+    return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
            VK == ELF::R_RISCV_TPREL_ADD;
   }
 
   bool isTLSDESCCallSymbol() const {
     int64_t Imm;
     // Must be of 'immediate' type but not a constant.
-    if (!isImm() || evaluateConstantImm(getImm(), Imm))
+    if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))
       return false;
 
     RISCV::Specifier VK = RISCV::S_None;
-    return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
+    return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
            VK == ELF::R_RISCV_TLSDESC_CALL;
   }
 
@@ -649,7 +650,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
 
   /// Return true if the operand is a valid fli.s floating-point immediate.
   bool isLoadFPImm() const {
-    if (isImm())
+    if (isExpr())
       return isUImm5();
     if (Kind != KindTy::FPImmediate)
       return false;
@@ -662,64 +663,64 @@ struct RISCVOperand final : public MCParsedAsmOperand {
 
   bool isImmXLenLI() const {
     int64_t Imm;
-    if (!isImm())
+    if (!isExpr())
       return false;
     // Given only Imm, ensuring that the actually specified constant is either
     // a signed or unsigned 64-bit number is unfortunately impossible.
-    if (evaluateConstantImm(getImm(), Imm))
-      return isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm));
+    if (evaluateConstantExpr(getExpr(), Imm))
+      return isRV64Expr() || (isInt<32>(Imm) || isUInt<32>(Imm));
 
-    return RISCVAsmParser::isSymbolDiff(getImm());
+    return RISCVAsmParser::isSymbolDiff(getExpr());
   }
 
   bool isImmXLenLI_Restricted() const {
     int64_t Imm;
-    if (!isImm())
+    if (!isExpr())
       return false;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
+    bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);
     // 'la imm' supports constant immediates only.
     return IsConstantImm &&
-           (isRV64Imm() || (isInt<32>(Imm) || isUInt<32>(Imm)));
+           (isRV64Expr() || (isInt<32>(Imm) || isUInt<32>(Imm)));
   }
 
   template <unsigned N> bool isUImm() const {
     int64_t Imm;
-    if (!isImm())
+    if (!isExpr())
       return false;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
+    bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);
     return IsConstantImm && isUInt<N>(Imm);
   }
 
   template <unsigned N, unsigned S> bool isUImmShifted() const {
     int64_t Imm;
-    if (!isImm())
+    if (!isExpr())
       return false;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
+    bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);
     return IsConstantImm && isShiftedUInt<N, S>(Imm);
   }
 
   template <class Pred> bool isUImmPred(Pred p) const {
     int64_t Imm;
-    if (!isImm())
+    if (!isExpr())
       return false;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
+    bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);
     return IsConstantImm && p(Imm);
   }
 
   bool isUImmLog2XLen() const {
-    if (isImm() && isRV64Imm())
+    if (isExpr() && isRV64Expr())
       return isUImm<6>();
     return isUImm<5>();
   }
 
   bool isUImmLog2XLenNonZero() const {
-    if (isImm() && isRV64Imm())
+    if (isExpr() && isRV64Expr())
       return isUImmPred([](int64_t Imm) { return Imm != 0 && isUInt<6>(Imm); });
     return isUImmPred([](int64_t Imm) { return Imm != 0 && isUInt<5>(Imm); });
   }
 
   bool isUImmLog2XLenHalf() const {
-    if (isImm() && isRV64Imm())
+    if (isExpr() && isRV64Expr())
       return isUImm<5>();
     return isUImm<4>();
   }
@@ -792,18 +793,18 @@ struct RISCVOperand final : public MCParsedAsmOperand {
 
   template <unsigned N> bool isSImm() const {
     int64_t Imm;
-    if (!isImm())
+    if (!isExpr())
       return false;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
-    return IsConstantImm && isInt<N>(fixImmediateForRV32(Imm, isRV64Imm()));
+    bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);
+    return IsConstantImm && isInt<N>(fixImmediateForRV32(Imm, isRV64Expr()));
   }
 
   template <class Pred> bool isSImmPred(Pred p) const {
     int64_t Imm;
-    if (!isImm())
+    if (!isExpr())
       return false;
-    bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
-    return IsConstantImm && p(fixImmediateForRV32(Imm, isRV64Imm()));
+    bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);
+    return IsConstantImm && p(fixImmediateForRV32(Imm, isRV64Expr()));
   }
 
   bool isSImm5() const { return isSImm<5>(); }
@@ -859,15 +860,15 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   }
 
   bool isSImm12() const {
-    if (!isImm())
+    if (!isExpr())
       return false;
 
     int64_t Imm;
-    if (evaluateConstantImm(getImm(), Imm))
-      return isInt<12>(fixImmediateForRV32(Imm, isRV64Imm()));
+    if (evaluateConstantExpr(getExpr(), Imm))
+      return isInt<12>(fixImmediateForRV32(Imm, isRV64Expr()));
 
     RISCV::Specifier VK = RISCV::S_None;
-    return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
+    return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
            (VK == RISCV::S_LO || VK == RISCV::S_PCREL_LO ||
             VK == RISCV::S_TPREL_LO || VK == ELF::R_RISCV_TLSDESC_LOAD_LO12 ||
             VK == ELF::R_RISCV_TLSDESC_ADD_LO12);
@@ -891,15 +892,15 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   }
 
   bool isSImm20LI() const {
-    if (!isImm())
+    if (!isExpr())
       return false;
 
     int64_t Imm;
-    if (evaluateConstantImm(getImm(), Imm))
-      return isInt<20>(fixImmediateForRV32(Imm, isRV64Imm()));
+    if (evaluateConstantExpr(getExpr(), Imm))
+      return isInt<20>(fixImmediateForRV32(Imm, isRV64Expr()));
 
     RISCV::Specifier VK = RISCV::S_None;
-    return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
+    return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
            VK == RISCV::S_QC_ABS20;
   }
 
@@ -907,28 +908,28 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   bool isSImm10Unsigned() const { return isSImm<10>() || isUImm<10>(); }
 
   bool isUImm20LUI() const {
-    if (!isImm())
+    if (!isExpr())
       return false;
 
     int64_t Imm;
-    if (evaluateConstantImm(getImm(), Imm))
+    if (evaluateConstantExpr(getExpr(), Imm))
       return isUInt<20>(Imm);
 
     RISCV::Specifier VK = RISCV::S_None;
-    return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
+    return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
            (VK == ELF::R_RISCV_HI20 || VK == ELF::R_RISCV_TPREL_HI20);
   }
 
   bool isUImm20AUIPC() const {
-    if (!isImm())
+    if (!isExpr())
       return false;
 
     int64_t Imm;
-    if (evaluateConstantImm(getImm(), Imm))
+    if (evaluateConstantExpr(getExpr(), Imm))
       return isUInt<20>(Imm);
 
     RISCV::Specifier VK = RISCV::S_None;
-    return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
+    return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
            (VK == ELF::R_RISCV_PCREL_HI20 || VK == ELF::R_RISCV_GOT_HI20 ||
             VK == ELF::R_RISCV_TLS_GOT_HI20 || VK == ELF::R_RISCV_TLS_GD_HI20 ||
             VK == ELF::R_RISCV_TLSDESC_HI20);
@@ -980,10 +981,11 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   SMLoc getStartLoc() const override { return StartLoc; }
   /// getEndLoc - Gets location of the last token of this operand
   SMLoc getEndLoc() const override { return EndLoc; }
+
   /// True if this operand is for an RV64 instruction
-  bool isRV64Imm() const {
-    assert(Kind == KindTy::Immediate && "Invalid type access!");
-    return Imm.IsRV64;
+  bool isRV64Expr() const {
+    assert(Kind == KindTy::Expression && "Invalid type access!");
+    return Expr.IsRV64;
   }
 
   MCRegister getReg() const override {
@@ -996,9 +998,9 @@ struct RISCVOperand final : public MCParsedAsmOperand {
     return StringRef(SysReg.Data, SysReg.Length);
   }
 
-  const MCExpr *getImm() const {
-    assert(Kind == KindTy::Immediate && "Invalid type access!");
-    return Imm.Val;
+  const MCExpr *getExpr() const {
+    assert(Kind == KindTy::Expression && "Invalid type access!");
+    return Expr.Expr;
   }
 
   uint64_t getFPConst() const {
@@ -1035,10 +1037,10 @@ struct RISCVOperand final : public MCParsedAsmOperand {
     };
 
     switch (Kind) {
-    case KindTy::Immediate:
+    case KindTy::Expression:
       OS << "<imm: ";
-      MAI.printExpr(OS, *Imm.Val);
-      OS << ' ' << (Imm.IsRV64 ? "rv64" : "rv32") << '>';
+      MAI.printExpr(OS, *Expr.Expr);
+      OS << ' ' << (Expr.IsRV64 ? "rv64" : "rv32") << '>';
       break;
     case KindTy::FPImmediate:
       OS << "<fpimm: " << FPImm.Val << ">";
@@ -1103,11 +1105,11 @@ struct RISCVOperand final : public MCParsedAsmOperand {
     return Op;
   }
 
-  static std::unique_ptr<RISCVOperand> createImm(const MCExpr *Val, SMLoc S,
-                                                 SMLoc E, bool IsRV64) {
-    auto Op = std::make_unique<RISCVOperand>(KindTy::Immediate);
-    Op->Imm.Val = Val;
-    Op->Imm.IsRV64 = IsRV64;
+  static std::unique_ptr<RISCVOperand> createExpr(const MCExpr *Val, SMLoc S,
+                                                  SMLoc E, bool IsRV64) {
+    auto Op = std::make_unique<RISCVOperand>(KindTy::Expression);
+    Op->Expr.Expr = Val;
+    Op->Expr.IsRV64 = IsRV64;
     Op->StartLoc = S;
     Op->EndLoc = E;
     return Op;
@@ -1185,7 +1187,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   static void addExpr(MCInst &Inst, const MCExpr *Expr, bool IsRV64Imm) {
     assert(Expr && "Expr shouldn't be null!");
     int64_t Imm = 0;
-    bool IsConstant = evaluateConstantImm(Expr, Imm);
+    bool IsConstant = evaluateConstantExpr(Expr, Imm);
 
     if (IsConstant)
       Inst.addOperand(
@@ -1202,13 +1204,13 @@ struct RISCVOperand final : public MCParsedAsmOperand {
 
   void addImmOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
-    addExpr(Inst, getImm(), isRV64Imm());
+    addExpr(Inst, getExpr(), isRV64Expr());
   }
 
   void addSImm8UnsignedOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     int64_t Imm;
-    [[maybe_unused]] bool IsConstant = evaluateConstantImm(getImm(), Imm);
+    [[maybe_unused]] bool IsConstant = evaluateConstantExpr(getExpr(), Imm);
     assert(IsConstant);
     Inst.addOperand(MCOperand::createImm(SignExtend64<8>(Imm)));
   }
@@ -1216,15 +1218,15 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   void addSImm10UnsignedOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     int64_t Imm;
-    [[maybe_unused]] bool IsConstant = evaluateConstantImm(getImm(), Imm);
+    [[maybe_unused]] bool IsConstant = evaluateConstantExpr(getExpr(), Imm);
     assert(IsConstant);
     Inst.addOperand(MCOperand::createImm(SignExtend64<10>(Imm)));
   }
 
   void addFPImmOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
-    if (isImm()) {
-      addExpr(Inst, getImm(), isRV64Imm());
+    if (isExpr()) {
+      addExpr(Inst, getExpr(), isRV64Expr());
       return;
     }
 
@@ -1249,8 +1251,9 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   void addVTypeIOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     int64_t Imm = 0;
-    if (Kind == KindTy::Immediate) {
-      [[maybe_unused]] bool IsConstantImm = evaluateConstantImm(getImm(), Imm);
+    if (Kind == KindTy::Expression) {
+      [[maybe_unused]] bool IsConstantImm =
+          evaluateConstantExpr(getExpr(), Imm);
       assert(IsConstantImm && "Invalid VTypeI Operand!");
     } else {
       Imm = getVType();
@@ -1826,7 +1829,7 @@ ParseStatus RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
     if (CE) {
       int64_t Imm = CE->getValue();
       if (isUInt<7>(Imm)) {
-        Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
+        Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
         return ParseStatus::Success;
       }
     }
@@ -1844,7 +1847,7 @@ ParseStatus RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
              "Unexpected opcode");
       Res = MCConstantExpr::create(Opcode->Value, getContext());
       E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
-      Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
+      Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
       return ParseStatus::Success;
     }
 
@@ -1881,7 +1884,7 @@ ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {
     if (CE) {
       int64_t Imm = CE->getValue();
       if (Imm >= 0 && Imm <= 2) {
-        Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
+        Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
         return ParseStatus::Success;
       }
     }
@@ -1905,7 +1908,7 @@ ParseStatus RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {
 
     Res = MCConstantExpr::create(Opcode, getContext());
     E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
-    Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
+    Operands.push_back(RISCVOperand::createExpr(Res, S, E, isRV64()));
     return ParseStatus::Success;
   }
   case AsmToken::Percent: {
@@ -2039,16 +2042,16 @@ ParseStatus RISCVAsmParser::parseFPImm(OperandVector &Operands) {
     StringRef Identifier = getTok().getIdentifier();
     if (Identifier.compare_insensitive("inf") == 0) {
       Operands.push_back(
-          RISCVOperand::createImm(MCConstantExpr::create(30, getContext()), S,
-                                  getTok().getEndLoc(), isRV64()));
+          RISCVOperand::createExpr(MCConstantExpr::create(30, getContext()), S,
+                                   getTok().getEndLoc(), isRV64()));
     } else if (Identifier.compare_insensitive("nan") == 0) {
       Operands.push_back(
-          RISCVOperand::createImm(MCConstantExpr::create(31, getContext()), S,
-    ...
[truncated]

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@lenary lenary merged commit 81f83a8 into llvm:main Sep 21, 2025
11 checks passed
@lenary lenary deleted the pr/riscv-asmparser-isexpr branch September 21, 2025 21:30
@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 21, 2025

LLVM Buildbot has detected a new failure on builder clang-ppc64le-linux-test-suite running on ppc64le-clang-test-suite while building llvm at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/95/builds/18351

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'LeakSanitizer-Standalone-powerpc64le :: TestCases/create_thread_leak.cpp' FAILED ********************
Exit Code: 2

Command Output (stderr):
--
/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/./bin/clang  --driver-mode=g++ -O0  -m64 -fno-function-sections  -gline-tables-only -fsanitize=leak -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test/lsan/../ -pthread /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test/lsan/TestCases/create_thread_leak.cpp -o /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/runtimes/runtimes-bins/compiler-rt/test/lsan/POWERPC64LELsanConfig/TestCases/Output/create_thread_leak.cpp.tmp # RUN: at line 3
+ /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/./bin/clang --driver-mode=g++ -O0 -m64 -fno-function-sections -gline-tables-only -fsanitize=leak -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test/lsan/../ -pthread /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test/lsan/TestCases/create_thread_leak.cpp -o /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/runtimes/runtimes-bins/compiler-rt/test/lsan/POWERPC64LELsanConfig/TestCases/Output/create_thread_leak.cpp.tmp
not  /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/runtimes/runtimes-bins/compiler-rt/test/lsan/POWERPC64LELsanConfig/TestCases/Output/create_thread_leak.cpp.tmp 10 1 0 0 2>&1 | FileCheck /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test/lsan/TestCases/create_thread_leak.cpp --check-prefixes=LEAK,LEAK123 # RUN: at line 4
+ not /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/runtimes/runtimes-bins/compiler-rt/test/lsan/POWERPC64LELsanConfig/TestCases/Output/create_thread_leak.cpp.tmp 10 1 0 0
+ FileCheck /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test/lsan/TestCases/create_thread_leak.cpp --check-prefixes=LEAK,LEAK123
not  /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/runtimes/runtimes-bins/compiler-rt/test/lsan/POWERPC64LELsanConfig/TestCases/Output/create_thread_leak.cpp.tmp 10 0 1 0 2>&1 | FileCheck /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test/lsan/TestCases/create_thread_leak.cpp --check-prefixes=LEAK,LEAK234 # RUN: at line 5
+ FileCheck /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test/lsan/TestCases/create_thread_leak.cpp --check-prefixes=LEAK,LEAK234
+ not /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/runtimes/runtimes-bins/compiler-rt/test/lsan/POWERPC64LELsanConfig/TestCases/Output/create_thread_leak.cpp.tmp 10 0 1 0
not  /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/runtimes/runtimes-bins/compiler-rt/test/lsan/POWERPC64LELsanConfig/TestCases/Output/create_thread_leak.cpp.tmp 10 0 0 1 2>&1 | FileCheck /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test/lsan/TestCases/create_thread_leak.cpp --check-prefixes=LEAK,LEAK234 # RUN: at line 6
+ FileCheck /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test/lsan/TestCases/create_thread_leak.cpp --check-prefixes=LEAK,LEAK234
+ not /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/build/runtimes/runtimes-bins/compiler-rt/test/lsan/POWERPC64LELsanConfig/TestCases/Output/create_thread_leak.cpp.tmp 10 0 0 1
FileCheck error: '<stdin>' is empty.
FileCheck command line:  FileCheck /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-test-suite/clang-ppc64le-test-suite/llvm-project/compiler-rt/test/lsan/TestCases/create_thread_leak.cpp --check-prefixes=LEAK,LEAK234

--

********************


SeongjaeP pushed a commit to SeongjaeP/llvm-project that referenced this pull request Sep 23, 2025
I find it very confusing that we have two different kinds of
"immediates":
- MCOperands in the backend that are `isImm()` which can only be numbers
- RISCVOperands in the parser that are `isImm()` which can contain
expressions

This change aims to make it clearer that in the AsmParser, we are
dealing with expressions, rather than just numbers.

Unfortunately, `isImm` comes from the `MCParsedAsmOperand`, which is
needed for Microsoft Inline Asm, so we cannot fully get rid of it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants