[llvm-branch-commits] [RISCV] Replace @plt/@gotpcrel in data directives with %plt %gotpcrel (PR #132569)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Mar 22 15:04:10 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

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

Author: Fangrui Song (MaskRay)

<details>
<summary>Changes</summary>

clang -fexperimental-relative-c++-abi-vtables might generate @<!-- -->plt and
@<!-- -->gotpcrel specifiers in data directives. The syntax is not used in
humand-written assembly code, and is not supported by GNU assembler.
Note: the `@<!-- -->plt` in `.word foo@<!-- -->plt` is different from
the legacy `call func@<!-- -->plt` (where `@<!-- -->plt` is simply ignored).

The @<!-- -->plt syntax was selected was simply due to a quirk of AsmParser:
the syntax was supported by all targets until I updated it
to be an opt-in feature in a0671758eb6e52a758bd1b096a9b421eec60204c

RISC-V favors the `%specifier(expr)` syntax following MIPS and Sparc,
and we should follow this convention.

This PR adds support for `.word %plt(foo-.)` and
`.word %gotpcreel(foo)` and drops `@<!-- -->plt` `@<!-- -->gotpcrel`.

* MCValue::SymA can no longer have a SymbolVariant. Add an assert
  similar to that of AArch64ELFObjectWriter.cpp before
  https://reviews.llvm.org/D81446 (see my analysis at
  https://maskray.me/blog/2025-03-16-relocation-generation-in-assemblers
  if intrigued)
* `jump foo@<!-- -->plt, x31` now has a different diagnostic.


---

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


20 Files Affected:

- (modified) lld/test/ELF/riscv-reloc-plt32.s (+3-3) 
- (modified) lld/test/ELF/riscv-undefined-weak.s (+1-1) 
- (modified) lld/test/ELF/riscv64-reloc-got32-pcrel.s (+8-8) 
- (modified) llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h (+6) 
- (modified) llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h (+6) 
- (modified) llvm/include/llvm/Target/TargetLoweringObjectFile.h (+1) 
- (modified) llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (+6-5) 
- (modified) llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (+23-7) 
- (modified) llvm/lib/MC/MCAssembler.cpp (+1-1) 
- (modified) llvm/lib/MC/MCParser/AsmParser.cpp (+1-1) 
- (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+24-7) 
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp (+11-8) 
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp (-7) 
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp (+11-4) 
- (modified) llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp (+8) 
- (modified) llvm/lib/Target/RISCV/RISCVTargetObjectFile.h (+3) 
- (modified) llvm/test/CodeGen/RISCV/dso_local_equivalent.ll (+1-1) 
- (modified) llvm/test/MC/RISCV/data-directive-specifier.s (+11-11) 
- (modified) llvm/test/MC/RISCV/pseudo-jump-invalid.s (+1-1) 
- (modified) llvm/test/MC/RISCV/rv32i-invalid.s (+1) 


``````````diff
diff --git a/lld/test/ELF/riscv-reloc-plt32.s b/lld/test/ELF/riscv-reloc-plt32.s
index 8cbc2d3f442c0..a50b9fe3f137a 100644
--- a/lld/test/ELF/riscv-reloc-plt32.s
+++ b/lld/test/ELF/riscv-reloc-plt32.s
@@ -18,6 +18,6 @@
 .globl _start
 _start:
 .data
-  .word foo at PLT - .
-  .word foo at PLT - . + 1
-  .word foo at PLT - . - 1
+  .word %plt(foo - .)
+  .word %plt(foo - . + 1)
+  .word %plt(foo - . - 1)
diff --git a/lld/test/ELF/riscv-undefined-weak.s b/lld/test/ELF/riscv-undefined-weak.s
index 8a78e1f838338..d78f55394b619 100644
--- a/lld/test/ELF/riscv-undefined-weak.s
+++ b/lld/test/ELF/riscv-undefined-weak.s
@@ -97,4 +97,4 @@ branch:
 # PC-NOT:      .plt:
 # PLT:         .plt:
 
-.word target at plt - .
+.word %plt(target - .)
diff --git a/lld/test/ELF/riscv64-reloc-got32-pcrel.s b/lld/test/ELF/riscv64-reloc-got32-pcrel.s
index 24bd828235b25..a8f42ae6df2b9 100644
--- a/lld/test/ELF/riscv64-reloc-got32-pcrel.s
+++ b/lld/test/ELF/riscv64-reloc-got32-pcrel.s
@@ -12,16 +12,16 @@ bar:
 
   .globl _start
 _start:  // PC = 0x33a8
-// bar at GOTPCREL   = 0x2398 (got entry for `bar`) - 0x33a8 (.) = 0xf0efffff
-// bar at GOTPCREL+4 = 0x2398 (got entry for `bar`) - 0x33ac (.) + 4 = 0xf0efffff
-// bar at GOTPCREL-4 = 0x2398 (got entry for `bar`) - 0x33b0 (.) - 4 = 0xe4efffff
+// %gotpcrel(bar)   = 0x2398 (got entry for `bar`) - 0x33a8 (.) = 0xf0efffff
+// %gotpcrel(bar+4) = 0x2398 (got entry for `bar`) - 0x33ac (.) + 4 = 0xf0efffff
+// %gotpcrel(bar-4) = 0x2398 (got entry for `bar`) - 0x33b0 (.) - 4 = 0xe4efffff
 // CHECK:      Contents of section .data:
 // CHECK-NEXT:  {{.*}} f0efffff f0efffff e4efffff
-  .word bar at GOTPCREL
-  .word bar at GOTPCREL+4
-  .word bar at GOTPCREL-4
+  .word %gotpcrel(bar)
+  .word %gotpcrel(bar+4)
+  .word %gotpcrel(bar-4)
 
 // WARN: relocation R_RISCV_GOT32_PCREL out of range: {{.*}} is not in [-2147483648, 2147483647]; references 'baz'
 // WARN: relocation R_RISCV_GOT32_PCREL out of range: {{.*}} is not in [-2147483648, 2147483647]; references 'baz'
-  .word baz at GOTPCREL+0xffffffff
-  .word baz at GOTPCREL-0xffffffff
+  .word %gotpcrel(baz+0xffffffff)
+  .word %gotpcrel(baz-0xffffffff)
diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 7392963bd341f..f6e875e7ad373 100644
--- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -38,6 +38,7 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
 
 protected:
   uint8_t PLTRelativeSpecifier = 0;
+  bool UseTargetMCExprForPLTRelative = true;
 
 public:
   TargetLoweringObjectFileELF();
@@ -112,11 +113,16 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
   MCSection *getStaticDtorSection(unsigned Priority,
                                   const MCSymbol *KeySym) const override;
 
+  virtual const MCExpr *createTargetMCExpr(const MCExpr *Expr,
+                                           uint8_t Specifier) const {
+    return nullptr;
+  }
   const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
                                        const GlobalValue *RHS,
                                        const TargetMachine &TM) const override;
 
   const MCExpr *lowerDSOLocalEquivalent(const DSOLocalEquivalent *Equiv,
+                                        const MCSymbolRefExpr *RHS,
                                         const TargetMachine &TM) const override;
 
   MCSection *getSectionForCommandLines() const override;
diff --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
index 59cee18bfdf42..c7f098be70945 100644
--- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -396,6 +396,12 @@ class MCTargetAsmParser : public MCAsmParserExtension {
   virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
     return getParser().parsePrimaryExpr(Res, EndLoc, nullptr);
   }
+  // Parse an expression in a data directive, possibly with a relocation
+  // specifier.
+  virtual bool parseDataExpr(const MCExpr *&Res) {
+    SMLoc EndLoc;
+    return getParser().parseExpression(Res, EndLoc);
+  }
 
   virtual bool parseRegister(MCRegister &Reg, SMLoc &StartLoc,
                              SMLoc &EndLoc) = 0;
diff --git a/llvm/include/llvm/Target/TargetLoweringObjectFile.h b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
index a5ed1b29dc1bc..77148320ccfd5 100644
--- a/llvm/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
@@ -209,6 +209,7 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
   }
 
   virtual const MCExpr *lowerDSOLocalEquivalent(const DSOLocalEquivalent *Equiv,
+                                                const MCSymbolRefExpr *RHS,
                                                 const TargetMachine &TM) const {
     return nullptr;
   }
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 743551822a8fc..c5e8aa39a9115 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -3382,7 +3382,7 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) {
     return lowerBlockAddressConstant(*BA);
 
   if (const auto *Equiv = dyn_cast<DSOLocalEquivalent>(CV))
-    return getObjFileLowering().lowerDSOLocalEquivalent(Equiv, TM);
+    return getObjFileLowering().lowerDSOLocalEquivalent(Equiv, nullptr, TM);
 
   if (const NoCFIValue *NC = dyn_cast<NoCFIValue>(CV))
     return MCSymbolRefExpr::create(getSymbol(NC->getGlobalValue()), Ctx);
@@ -3481,12 +3481,13 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) {
         if (!RelocExpr) {
           const MCExpr *LHSExpr =
               MCSymbolRefExpr::create(getSymbol(LHSGV), Ctx);
+          auto *RHSExpr = MCSymbolRefExpr::create(getSymbol(RHSGV), Ctx);
           if (DSOEquiv &&
               getObjFileLowering().supportDSOLocalEquivalentLowering())
-            LHSExpr =
-                getObjFileLowering().lowerDSOLocalEquivalent(DSOEquiv, TM);
-          RelocExpr = MCBinaryExpr::createSub(
-              LHSExpr, MCSymbolRefExpr::create(getSymbol(RHSGV), Ctx), Ctx);
+            RelocExpr = getObjFileLowering().lowerDSOLocalEquivalent(
+                DSOEquiv, RHSExpr, TM);
+          else
+            RelocExpr = MCBinaryExpr::createSub(LHSExpr, RHSExpr, Ctx);
         }
         int64_t Addend = (LHSOffset - RHSOffset).getSExtValue();
         if (Addend != 0)
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 27a70e6f775b3..ee0db578d55b8 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -1194,18 +1194,34 @@ const MCExpr *TargetLoweringObjectFileELF::lowerRelativeReference(
       MCSymbolRefExpr::create(TM.getSymbol(RHS), getContext()), getContext());
 }
 
+// Reference the function or its PLT entry (`Equiv`), optionally with a
+// subtrahend (`RHS`).
 const MCExpr *TargetLoweringObjectFileELF::lowerDSOLocalEquivalent(
-    const DSOLocalEquivalent *Equiv, const TargetMachine &TM) const {
+    const DSOLocalEquivalent *Equiv, const MCSymbolRefExpr *RHS,
+    const TargetMachine &TM) const {
   assert(supportDSOLocalEquivalentLowering());
 
+  // If GV is dso_local, reference the function itself. Return GV or GV-RHS.
   const auto *GV = Equiv->getGlobalValue();
-
-  // A PLT entry is not needed for dso_local globals.
+  const MCExpr *Res = MCSymbolRefExpr::create(TM.getSymbol(GV), getContext());
+  if (RHS)
+    Res = MCBinaryExpr::createSub(Res, RHS, getContext());
   if (GV->isDSOLocal() || GV->isImplicitDSOLocal())
-    return MCSymbolRefExpr::create(TM.getSymbol(GV), getContext());
-
-  return MCSymbolRefExpr::create(TM.getSymbol(GV), PLTRelativeSpecifier,
-                                 getContext());
+    return Res;
+
+  // Otherwise, reference the PLT. Return a relocatable expression with the PLT
+  // specifier, %plt(GV) or %plt(GV-RHS).
+  Res = createTargetMCExpr(Res, PLTRelativeSpecifier);
+  if (Res)
+    return Res;
+
+  // If the target only supports the legacy syntax @plt, return GV at plt or
+  // GV at plt - RHS.
+  Res = MCSymbolRefExpr::create(TM.getSymbol(GV), PLTRelativeSpecifier,
+                                getContext());
+  if (RHS)
+    Res = MCBinaryExpr::createSub(Res, RHS, getContext());
+  return Res;
 }
 
 MCSection *TargetLoweringObjectFileELF::getSectionForCommandLines() const {
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index fb85accf267b4..06f94d5e89198 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -237,7 +237,7 @@ bool MCAssembler::evaluateFixup(const MCFixup &Fixup, const MCFragment *DF,
   // A linker relaxation target may emit ADD/SUB relocations for A-B+C. Let
   // recordRelocation handle non-VK_None cases like A at plt-B+C.
   if (!IsResolved && Target.getSymA() && Target.getSymB() &&
-      Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None &&
+      Target.getRefKind() == 0 &&
       getBackend().handleAddSubRelocations(*this, *DF, Fixup, Target, Value))
     return true;
 
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index c11c01e52fc2e..87d9a7b8727df 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -3144,7 +3144,7 @@ bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
   auto parseOp = [&]() -> bool {
     const MCExpr *Value;
     SMLoc ExprLoc = getLexer().getLoc();
-    if (checkForValidSection() || parseExpression(Value))
+    if (checkForValidSection() || getTargetParser().parseDataExpr(Value))
       return true;
     // Special case constant expressions to match code generator.
     if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 05997cf78c6b1..5f673574c200d 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -225,6 +225,8 @@ class RISCVAsmParser : public MCTargetAsmParser {
   }
 
   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
+  bool parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E);
+  bool parseDataExpr(const MCExpr *&Res) override;
 
   bool parseDirectiveOption();
   bool parseDirectiveAttribute();
@@ -2233,8 +2235,17 @@ ParseStatus RISCVAsmParser::parseOperandWithSpecifier(OperandVector &Operands) {
   SMLoc S = getLoc();
   SMLoc E;
 
-  if (!parseOptionalToken(AsmToken::Percent) ||
-      getLexer().getKind() != AsmToken::Identifier)
+  if (!parseOptionalToken(AsmToken::Percent))
+    return Error(getLoc(), "expected '%' relocation specifier");
+  const MCExpr *Expr = nullptr;
+  bool Failed = parseExprWithSpecifier(Expr, E);
+  if (!Failed)
+    Operands.push_back(RISCVOperand::createImm(Expr, S, E, isRV64()));
+  return Failed;
+}
+
+bool RISCVAsmParser::parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E) {
+  if (getLexer().getKind() != AsmToken::Identifier)
     return Error(getLoc(), "expected '%' relocation specifier");
   StringRef Identifier = getParser().getTok().getIdentifier();
   auto Spec = RISCVMCExpr::getSpecifierForName(Identifier);
@@ -2243,15 +2254,21 @@ ParseStatus RISCVAsmParser::parseOperandWithSpecifier(OperandVector &Operands) {
 
   getParser().Lex(); // Eat the identifier
   if (parseToken(AsmToken::LParen, "expected '('"))
-    return ParseStatus::Failure;
+    return true;
 
   const MCExpr *SubExpr;
   if (getParser().parseParenExpression(SubExpr, E))
-    return ParseStatus::Failure;
+    return true;
 
-  const MCExpr *ModExpr = RISCVMCExpr::create(SubExpr, *Spec, getContext());
-  Operands.push_back(RISCVOperand::createImm(ModExpr, S, E, isRV64()));
-  return ParseStatus::Success;
+  Res = RISCVMCExpr::create(SubExpr, *Spec, getContext());
+  return false;
+}
+
+bool RISCVAsmParser::parseDataExpr(const MCExpr *&Res) {
+  SMLoc E;
+  if (parseOptionalToken(AsmToken::Percent))
+    return parseExprWithSpecifier(Res, E);
+  return getParser().parseExpression(Res);
 }
 
 ParseStatus RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
index f8841dd657568..afd5d3e4893f1 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
@@ -50,6 +50,9 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
                                             const MCValue &Target,
                                             const MCFixup &Fixup,
                                             bool IsPCRel) const {
+  assert((!Target.getSymA() ||
+          Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None) &&
+         "sym at specifier should have been rejected");
   const MCExpr *Expr = Fixup.getValue();
   // Determine the type of the relocation
   unsigned Kind = Fixup.getTargetKind();
@@ -73,9 +76,8 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
       return ELF::R_RISCV_NONE;
     case FK_Data_4:
     case FK_PCRel_4:
-      return uint8_t(Target.getAccessVariant()) == RISCVMCExpr::VK_PLT
-                 ? ELF::R_RISCV_PLT32
-                 : ELF::R_RISCV_32_PCREL;
+      return Target.getRefKind() == RISCVMCExpr::VK_PLT ? ELF::R_RISCV_PLT32
+                                                        : ELF::R_RISCV_32_PCREL;
     case RISCV::fixup_riscv_pcrel_hi20:
       return ELF::R_RISCV_PCREL_HI20;
     case RISCV::fixup_riscv_pcrel_lo12_i:
@@ -129,11 +131,12 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
     Ctx.reportError(Fixup.getLoc(), "2-byte data relocations not supported");
     return ELF::R_RISCV_NONE;
   case FK_Data_4:
-    if (Expr->getKind() == MCExpr::Target &&
-        cast<RISCVMCExpr>(Expr)->getSpecifier() == RISCVMCExpr::VK_32_PCREL)
-      return ELF::R_RISCV_32_PCREL;
-    if (getSpecifier(Target.getSymA()) == RISCVMCExpr::VK_GOTPCREL)
-      return ELF::R_RISCV_GOT32_PCREL;
+    if (Expr->getKind() == MCExpr::Target) {
+      if (cast<RISCVMCExpr>(Expr)->getSpecifier() == RISCVMCExpr::VK_32_PCREL)
+        return ELF::R_RISCV_32_PCREL;
+      if (cast<RISCVMCExpr>(Expr)->getSpecifier() == RISCVMCExpr::VK_GOTPCREL)
+        return ELF::R_RISCV_GOT32_PCREL;
+    }
     return ELF::R_RISCV_32;
   case FK_Data_8:
     return ELF::R_RISCV_64;
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
index c327f9d5f0f1e..7e9b312d3c25e 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
@@ -18,11 +18,6 @@
 #include "llvm/TargetParser/Triple.h"
 using namespace llvm;
 
-const MCAsmInfo::VariantKindDesc variantKindDescs[] = {
-    {RISCVMCExpr::VK_GOTPCREL, "GOTPCREL"},
-    {RISCVMCExpr::VK_PLT, "PLT"},
-};
-
 void RISCVMCAsmInfo::anchor() {}
 
 RISCVMCAsmInfo::RISCVMCAsmInfo(const Triple &TT) {
@@ -33,8 +28,6 @@ RISCVMCAsmInfo::RISCVMCAsmInfo(const Triple &TT) {
   ExceptionsType = ExceptionHandling::DwarfCFI;
   Data16bitsDirective = "\t.half\t";
   Data32bitsDirective = "\t.word\t";
-
-  initializeVariantKinds(variantKindDescs);
 }
 
 const MCExpr *RISCVMCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
index 7de53e6d3f479..ce365d0036ce3 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
@@ -94,8 +94,10 @@ bool RISCVMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
 
   Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(),
                      getSpecifier());
-  // Custom fixup types are not valid with symbol difference expressions.
-  return Res.getSymB() ? getSpecifier() == VK_None : true;
+  // When the subtrahend (SymB) is present, the relocatable expression
+  // only allows None and PLT as the specifier.
+  return !Res.getSymB() ||
+         llvm::is_contained({VK_None, VK_PLT}, getSpecifier());
 }
 
 void RISCVMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
@@ -119,14 +121,15 @@ RISCVMCExpr::getSpecifierForName(StringRef name) {
       .Case("tlsdesc_load_lo", VK_TLSDESC_LOAD_LO)
       .Case("tlsdesc_add_lo", VK_TLSDESC_ADD_LO)
       .Case("tlsdesc_call", VK_TLSDESC_CALL)
+      // Used in data directives
+      .Case("plt", VK_PLT)
+      .Case("gotpcrel", VK_GOTPCREL)
       .Default(std::nullopt);
 }
 
 StringRef RISCVMCExpr::getSpecifierName(Specifier S) {
   switch (S) {
   case VK_None:
-  case VK_PLT:
-  case VK_GOTPCREL:
     llvm_unreachable("not used as %specifier()");
   case VK_LO:
     return "lo";
@@ -162,6 +165,10 @@ StringRef RISCVMCExpr::getSpecifierName(Specifier S) {
     return "call_plt";
   case VK_32_PCREL:
     return "32_pcrel";
+  case VK_PLT:
+    return "plt";
+  case VK_GOTPCREL:
+    return "gotpcrel";
   }
   llvm_unreachable("Invalid ELF symbol kind");
 }
diff --git a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp
index e546815b70935..7e98f1124d2e5 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp
@@ -28,6 +28,7 @@ void RISCVELFTargetObjectFile::Initialize(MCContext &Ctx,
   TargetLoweringObjectFileELF::Initialize(Ctx, TM);
 
   PLTRelativeSpecifier = RISCVMCExpr::VK_PLT;
+  UseTargetMCExprForPLTRelative = true;
   SupportIndirectSymViaGOTPCRel = true;
 
   SmallDataSection = getContext().getELFSection(
@@ -180,3 +181,10 @@ MCSection *RISCVELFTargetObjectFile::getSectionForConstant(
   return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C,
                                                             Alignment);
 }
+
+const MCExpr *
+RISCVELFTargetObjectFile::createTargetMCExpr(const MCExpr *Expr,
+                                             uint8_t Specifier) const {
+  return RISCVMCExpr::create(Expr, RISCVMCExpr::Specifier(Specifier),
+                             getContext());
+}
diff --git a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h
index ff7e3e4c752c3..b6da3f4721f4b 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h
+++ b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h
@@ -48,6 +48,9 @@ class RISCVELFTargetObjectFile : public TargetLoweringObjectFileELF {
 
   bool isInSmallSection(uint64_t Size) const;
 
+  const MCExpr *createTargetMCExpr(const MCExpr *Expr,
+                                   uint8_t Specifier) const override;
+
   const MCExpr *getIndirectSymViaGOTPCRel(const GlobalValue *GV,
                                           const MCSymbol *Sym,
                                           const MCValue &MV, int64_t Offset,
diff --git a/llvm/test/CodeGen/RISCV/dso_local_equivalent.ll b/llvm/test/CodeGen/RISCV/dso_local_equivalent.ll
index 0979967614b8a..9823e8b33fd9d 100644
--- a/llvm/test/CodeGen/RISCV/dso_local_equivalent.ll
+++ b/llvm/test/CodeGen/RISCV/dso_local_equivalent.ll
@@ -4,7 +4,7 @@
 declare void @extern_func()
 
 ; CHECK-LABEL: const:
-; CHECK-NEXT:    .word   extern_func at PLT-const
+; CHECK-NEXT:    .word   %plt(extern_func-const)
 
 ;; Note that for riscv32, the ptrtoint will actually upcast the ptr it to an
 ;; oversized 64-bit pointer that eventually gets truncated. This isn't needed
diff --git a/llvm/test/MC/RISCV/data-directive-specifier.s b/llvm/test/MC/RISCV/data-directive-specifier.s
index a578f9720eccd..9d0f66ee384d9 100644
--- a/llvm/test/MC/RISCV/data-directive-specifier.s
+++ b/llvm/test/MC/RISCV/data-directive-specifier.s
@@ -15,12 +15,12 @@ l:
 # CHECK-NEXT:   0x10 R_RISCV_PLT32 g 0x18
 # CHECK-NEXT: }
 .data
-.word l at plt - .
-.word l at plt - .data
+.word %plt(l - .)
+.word %plt(l - .data)
 
-.word extern at plt - . + 4
-.word g at plt - . + 8
-.word g at plt - .data + 8
+.word %plt(extern - . + 4)
+.word %plt(g - . + 8)
+.word %plt(g - .data + 8)
 
 # CHECK:      Section ({{.*}}) .rela.data1 {
 # CHECK-NEXT:   0x0 R_RISCV_GOT32_PCREL data1 0x0
@@ -30,14 +30,14 @@ l:
 # CHE...
[truncated]

``````````

</details>


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


More information about the llvm-branch-commits mailing list