[lld] [llvm] [RISCV] add new relocation type for global array accesses with non-constant indices (PR #207901)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 6 22:57:20 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-risc-v
Author: LiqinWeng (LiqinWeng)
<details>
<summary>Changes</summary>
psABI: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/489
This MR is split from: https://github.com/llvm/llvm-project/pull/185353
---
Patch is 23.24 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/207901.diff
14 Files Affected:
- (modified) lld/ELF/Arch/RISCV.cpp (+47)
- (added) lld/test/ELF/riscv-base-idx-add.s (+71)
- (added) lld/test/ELF/riscv-base-idx-shxadd.s (+69)
- (modified) llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def (+3)
- (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+13-1)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h (+2)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h (+1)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp (+94-5)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp (+6)
- (modified) llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp (+6)
- (modified) llvm/lib/Target/RISCV/RISCVInstrFormats.td (+11)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.cpp (+2)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.td (+21-1)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZb.td (+17)
``````````diff
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 576e7a4614572..a91c7bcb99224 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -74,6 +74,9 @@ class RISCV final : public TargetInfo {
#define INTERNAL_R_RISCV_GPREL_S 257
#define INTERNAL_R_RISCV_X0REL_I 258
#define INTERNAL_R_RISCV_X0REL_S 259
+#define INTERNAL_R_RISCV_BASE_IDX_ADD 260
+#define INTERNAL_R_RISCV_BASE_IDX_LO12_I 261
+#define INTERNAL_R_RISCV_BASE_IDX_LO12_S 262
const uint64_t dtpOffset = 0x800;
@@ -344,6 +347,9 @@ void RISCV::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
case R_RISCV_HI20:
case R_RISCV_LO12_I:
case R_RISCV_LO12_S:
+ case R_RISCV_BASE_IDX_ADD:
+ case R_RISCV_BASE_IDX_LO12_I:
+ case R_RISCV_BASE_IDX_LO12_S:
expr = R_ABS;
break;
@@ -586,6 +592,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
case R_RISCV_TLSDESC_LOAD_LO12:
case R_RISCV_TLSDESC_ADD_LO12:
case R_RISCV_TPREL_LO12_I:
+ case R_RISCV_BASE_IDX_LO12_I:
case R_RISCV_LO12_I: {
uint64_t hi = (val + 0x800) >> 12;
uint64_t lo = val - (hi << 12);
@@ -595,6 +602,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
case R_RISCV_PCREL_LO12_S:
case R_RISCV_TPREL_LO12_S:
+ case R_RISCV_BASE_IDX_LO12_S:
case R_RISCV_LO12_S: {
uint64_t hi = (val + 0x800) >> 12;
uint64_t lo = val - (hi << 12);
@@ -602,6 +610,31 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
return;
}
+ case R_RISCV_BASE_IDX_ADD: {
+ write32le(loc, read32le(loc));
+ }
+
+ case INTERNAL_R_RISCV_BASE_IDX_ADD: {
+ uint32_t insn = (read32le(loc) & ~(31 << 20)) | (X_GP << 20);
+ write32le(loc, insn);
+ return;
+ }
+
+ case INTERNAL_R_RISCV_BASE_IDX_LO12_I:
+ case INTERNAL_R_RISCV_BASE_IDX_LO12_S: {
+ Defined *gp = ctx.sym.riscvGlobalPointer;
+ int64_t displace = SignExtend64(val - gp->getVA(ctx), bits);
+ checkInt(ctx, loc, displace, 12, rel);
+ uint32_t insn = read32le(loc);
+ if (rel.type == INTERNAL_R_RISCV_BASE_IDX_LO12_I)
+ insn = setLO12_I(insn, displace);
+ else
+ insn = setLO12_S(insn, displace);
+
+ write32le(loc, insn);
+ return;
+ }
+
case INTERNAL_R_RISCV_X0REL_I:
case INTERNAL_R_RISCV_X0REL_S: {
checkInt(ctx, loc, val, 12, rel);
@@ -989,6 +1022,14 @@ static void relaxHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
break;
case R_RISCV_LO12_S:
sec.relaxAux->relocTypes[i] = INTERNAL_R_RISCV_GPREL_S;
+ case R_RISCV_BASE_IDX_ADD:
+ sec.relaxAux->relocTypes[i] = INTERNAL_R_RISCV_BASE_IDX_ADD;
+ break;
+ case R_RISCV_BASE_IDX_LO12_I:
+ sec.relaxAux->relocTypes[i] = INTERNAL_R_RISCV_BASE_IDX_LO12_I;
+ break;
+ case R_RISCV_BASE_IDX_LO12_S:
+ sec.relaxAux->relocTypes[i] = INTERNAL_R_RISCV_BASE_IDX_LO12_S;
break;
}
}
@@ -1045,6 +1086,9 @@ static bool relax(Ctx &ctx, int pass, InputSection &sec) {
case R_RISCV_HI20:
case R_RISCV_LO12_I:
case R_RISCV_LO12_S:
+ case R_RISCV_BASE_IDX_ADD:
+ case R_RISCV_BASE_IDX_LO12_I:
+ case R_RISCV_BASE_IDX_LO12_S:
if (relaxable(relocs, i))
relaxHi20Lo12(ctx, sec, i, loc, r, remove);
break;
@@ -1298,6 +1342,9 @@ void RISCV::finalizeRelax(int passes) const {
case INTERNAL_R_RISCV_GPREL_S:
case INTERNAL_R_RISCV_X0REL_I:
case INTERNAL_R_RISCV_X0REL_S:
+ case INTERNAL_R_RISCV_BASE_IDX_ADD:
+ case INTERNAL_R_RISCV_BASE_IDX_LO12_I:
+ case INTERNAL_R_RISCV_BASE_IDX_LO12_S:
break;
case R_RISCV_RELAX:
// Used by relaxTlsLe to indicate the relocation is ignored.
diff --git a/lld/test/ELF/riscv-base-idx-add.s b/lld/test/ELF/riscv-base-idx-add.s
new file mode 100644
index 0000000000000..17db2ce3e0a3a
--- /dev/null
+++ b/lld/test/ELF/riscv-base-idx-add.s
@@ -0,0 +1,71 @@
+# REQUIRES: riscv
+# RUN: rm -rf %t && split-file %s %t && cd %t
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf -mattr=+relax a.s -o rv32.o
+# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf -mattr=+relax a.s -o rv64.o
+
+# RUN: ld.lld --relax-gp --undefined=__global_pointer$ rv32.o lds -o rv32
+# RUN: ld.lld --relax-gp --undefined=__global_pointer$ rv64.o lds -o rv64
+# RUN: llvm-objdump -td -M no-aliases --no-show-raw-insn rv32 | FileCheck %s
+# RUN: llvm-objdump -td -M no-aliases --no-show-raw-insn rv64 | FileCheck %s
+
+# CHECK: 00000000 l .text {{0*}}0 $x
+
+# CHECK-NOT: lui
+# CHECK: addi a1, a1, -0x800
+# CHECK-NEXT: add a0, a0, gp
+# CHECK-NEXT: lw a0, -0x800(a0)
+# CHECK-NEXT: sw a0, -0x800(a0)
+# CHECK-NOT: lui
+# CHECK-NEXT: addi a1, a1, 0x7fa
+# CHECK-NEXT: add a0, a0, gp
+# CHECK-NEXT: lw a0, 0x7fa(a0)
+# CHECK-NEXT: sw a0, 0x7fa(a0)
+# CHECK-NEXT: lui a1, 0x201
+# CHECK-NEXT: addi a1, a1, 0xe
+# CHECK-NEXT: add a0, a0, a1
+# CHECK-NEXT: lw a0, 0xe(a0)
+# CHECK-NEXT: sw a0, 0xe(a0)
+# CHECK-EMPTY:
+# CHECK-NEXT: <a>:
+# CHECK-NEXT: addi a0, a0, 0x1
+
+#--- a.s
+.global _start
+_start:
+ slli a0, a0, 2
+ lui a1, %hi(array)
+ addi a1, a1, %base_idx_lo(array)
+ add a0, a0, a1, %base_idx_add(array)
+ lw a0, %base_idx_lo(array)(a0)
+ sw a0, %base_idx_lo(array)(a0)
+ lui a1, %hi(array1+10)
+ addi a1, a1, %base_idx_lo(array1+10)
+ add a0, a0, a1, %base_idx_add(array1+10)
+ lw a0, %base_idx_lo(array1+10)(a0)
+ sw a0, %base_idx_lo(array1+10)(a0)
+ lui a1, %hi(norelax+10)
+ addi a1, a1, %base_idx_lo(norelax+10)
+ add a0, a0, a1, %base_idx_add(norelax+10)
+ lw a0, %base_idx_lo(norelax+10)(a0)
+ sw a0, %base_idx_lo(norelax+10)(a0)
+a:
+ addi a0, a0, 1
+
+.section .sdata,"aw"
+array:
+ .zero 4080
+ .size array, 4080
+array1:
+ .zero 20
+ .size array, 20
+norelax:
+ .zero 6
+ .size array, 6
+
+#--- lds
+SECTIONS {
+ .text : {*(.text) }
+ .sdata 0x200000 : { }
+}
+
diff --git a/lld/test/ELF/riscv-base-idx-shxadd.s b/lld/test/ELF/riscv-base-idx-shxadd.s
new file mode 100644
index 0000000000000..32f2d97e668df
--- /dev/null
+++ b/lld/test/ELF/riscv-base-idx-shxadd.s
@@ -0,0 +1,69 @@
+# REQUIRES: riscv
+# RUN: rm -rf %t && split-file %s %t && cd %t
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf -mattr=+relax,+zba a.s -o rv32.o
+# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf -mattr=+relax,+zba a.s -o rv64.o
+
+# RUN: ld.lld --relax-gp --undefined=__global_pointer$ rv32.o lds -o rv32
+# RUN: ld.lld --relax-gp --undefined=__global_pointer$ rv64.o lds -o rv64
+# RUN: llvm-objdump --mattr=+zba -td -M no-aliases --no-show-raw-insn rv32 | FileCheck %s
+# RUN: llvm-objdump --mattr=+zba -td -M no-aliases --no-show-raw-insn rv64 | FileCheck %s
+
+# CHECK: 00000000 l .text {{0*}}0 $x
+
+# CHECK-NOT: lui
+# CHECK: addi a1, a1, -0x800
+# CHECK-NEXT: sh1add a0, a0, gp
+# CHECK-NEXT: lw a0, -0x800(a0)
+# CHECK-NEXT: sw a0, -0x800(a0)
+# CHECK-NOT: lui
+# CHECK-NEXT: addi a1, a1, 0x7fa
+# CHECK-NEXT: sh1add a0, a0, gp
+# CHECK-NEXT: lw a0, 0x7fa(a0)
+# CHECK-NEXT: sw a0, 0x7fa(a0)
+# CHECK-NEXT: lui a1, 0x201
+# CHECK-NEXT: addi a1, a1, 0xe
+# CHECK-NEXT: sh1add a0, a0, a1
+# CHECK-NEXT: lw a0, 0xe(a0)
+# CHECK-NEXT: sw a0, 0xe(a0)
+# CHECK-EMPTY:
+# CHECK-NEXT: <a>:
+# CHECK-NEXT: addi a0, a0, 0x1
+
+#--- a.s
+.global _start
+_start:
+ lui a1, %hi(array)
+ addi a1, a1, %base_idx_lo(array)
+ sh1add a0, a0, a1, %base_idx_add(array)
+ lw a0, %base_idx_lo(array)(a0)
+ sw a0, %base_idx_lo(array)(a0)
+ lui a1, %hi(array1+10)
+ addi a1, a1, %base_idx_lo(array1+10)
+ sh1add a0, a0, a1, %base_idx_add(array1+10)
+ lw a0, %base_idx_lo(array1+10)(a0)
+ sw a0, %base_idx_lo(array1+10)(a0)
+ lui a1, %hi(norelax+10)
+ addi a1, a1, %base_idx_lo(norelax+10)
+ sh1add a0, a0, a1, %base_idx_add(norelax+10)
+ lw a0, %base_idx_lo(norelax+10)(a0)
+ sw a0, %base_idx_lo(norelax+10)(a0)
+a:
+ addi a0, a0, 1
+
+.section .sdata,"aw"
+array:
+ .zero 4080
+ .size array, 4080
+array1:
+ .zero 20
+ .size array, 20
+norelax:
+ .zero 6
+ .size array, 6
+
+#--- lds
+SECTIONS {
+ .text : {*(.text) }
+ .sdata 0x200000 : { }
+}
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def
index ac9a089e853a6..1e9610ea1fe67 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def
@@ -60,6 +60,9 @@ ELF_RELOC(R_RISCV_TLSDESC_HI20, 62)
ELF_RELOC(R_RISCV_TLSDESC_LOAD_LO12, 63)
ELF_RELOC(R_RISCV_TLSDESC_ADD_LO12, 64)
ELF_RELOC(R_RISCV_TLSDESC_CALL, 65)
+ELF_RELOC(R_RISCV_BASE_IDX_LO12_I, 77)
+ELF_RELOC(R_RISCV_BASE_IDX_LO12_S, 78)
+ELF_RELOC(R_RISCV_BASE_IDX_ADD, 79)
ELF_RELOC(R_RISCV_VENDOR, 191)
ELF_RELOC(R_RISCV_CUSTOM192, 192)
ELF_RELOC(R_RISCV_CUSTOM193, 193)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 605a155f20e71..af71d95ff1689 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -629,6 +629,17 @@ struct RISCVOperand final : public MCParsedAsmOperand {
VK == ELF::R_RISCV_TPREL_ADD;
}
+ bool isBaseIdxAddSymbol() const {
+ int64_t Imm;
+ // Must be of 'immediate' type but not a constant.
+ if (!isExpr() || evaluateConstantExpr(getExpr(), Imm))
+ return false;
+
+ RISCV::Specifier VK = RISCV::S_None;
+ return RISCVAsmParser::classifySymbolRef(getExpr(), VK) &&
+ (VK == ELF::R_RISCV_BASE_IDX_ADD);
+ }
+
bool isTLSDESCCallSymbol() const {
int64_t Imm;
// Must be of 'immediate' type but not a constant.
@@ -930,7 +941,8 @@ struct RISCVOperand final : public MCParsedAsmOperand {
RISCV::Specifier VK = RISCV::S_None;
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 == RISCV::S_BASE_IDX_LO || VK == RISCV::S_TPREL_LO ||
+ VK == ELF::R_RISCV_TLSDESC_LOAD_LO12 ||
VK == ELF::R_RISCV_TLSDESC_ADD_LO12);
}
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index adf5d5d8b3759..d0f3d248bcdfa 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -478,6 +478,8 @@ enum {
MO_TLSDESC_ADD_LO = 15,
MO_TLSDESC_CALL = 16,
MO_QC_ACCESS = 17,
+ MO_BASE_IDX_LO = 18,
+ MO_BASE_IDX_ADD = 19,
// Used to differentiate between target-specific "direct" flags and "bitmask"
// flags. A machine operand can only have one "direct" flag, but can have
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h
index ee1fffc4886c8..834ea4cb248c7 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h
@@ -43,6 +43,7 @@ enum {
S_LO = FirstTargetFixupKind,
S_PCREL_LO,
S_PCREL_HI,
+ S_BASE_IDX_LO,
S_TPREL_LO,
S_CALL_PLT,
S_GOT_HI,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
index 23cbbf0954cd7..21c431030a6d9 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
@@ -64,6 +64,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ void expandAddBaseIdx(const MCInst &MI, SmallVectorImpl<char> &CB,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
void expandLongCondBr(const MCInst &MI, SmallVectorImpl<char> &CB,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
@@ -321,6 +325,68 @@ void RISCVMCCodeEmitter::expandAddTPRel(const MCInst &MI,
support::endian::write(CB, Binary, llvm::endianness::little);
}
+static unsigned getAddOpAndFixups(unsigned AddOp) {
+ switch (AddOp) {
+ default:
+ llvm_unreachable("Unexpected ADD or SHXADD Opcode on GP-relative!");
+ case RISCV::PseudoAddBaseIdx:
+ return RISCV::ADD;
+ case RISCV::PseudoAddUWBaseIdx:
+ return RISCV::ADD_UW;
+ case RISCV::PseudoSh1AddBaseIdx:
+ return RISCV::SH1ADD;
+ case RISCV::PseudoSh2AddBaseIdx:
+ return RISCV::SH2ADD;
+ case RISCV::PseudoSh3AddBaseIdx:
+ return RISCV::SH3ADD;
+ case RISCV::PseudoSh1AddUWBaseIdx:
+ return RISCV::SH1ADD_UW;
+ case RISCV::PseudoSh2AddUWBaseIdx:
+ return RISCV::SH2ADD_UW;
+ case RISCV::PseudoSh3AddUWBaseIdx:
+ return RISCV::SH3ADD_UW;
+ }
+}
+
+// Pseudo ADD/SHXADD (base-index variant) to a simple ADD or SHXADD with the
+// correct relocation.
+void RISCVMCCodeEmitter::expandAddBaseIdx(const MCInst &MI,
+ SmallVectorImpl<char> &CB,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ MCOperand DestReg = MI.getOperand(0);
+ // At link time rs2 of the add/shXadd may be rewritten to gp (or zero for
+ // abs-near) when the symbol can be reached via gp-relative addressing.
+ MCOperand Src1 = MI.getOperand(1);
+ MCOperand Src2 = MI.getOperand(2);
+
+ MCOperand SrcSymbol = MI.getOperand(3);
+ assert(SrcSymbol.isExpr() &&
+ "Expected expression as third input to GP-relative add");
+
+ const auto *Expr = dyn_cast<MCSpecifierExpr>(SrcSymbol.getExpr());
+ assert(Expr && (Expr->getSpecifier() == ELF::R_RISCV_BASE_IDX_ADD) &&
+ "Expected expression as third input to base+index add");
+
+ unsigned BuildOpcode = getAddOpAndFixups(MI.getOpcode());
+
+ // Emit the correct base_idx_add relocation for the symbol.
+ addFixup(Fixups, 0, Expr, ELF::R_RISCV_BASE_IDX_ADD);
+
+ // Emit base_idx_add where the relax feature is enabled.
+ if (STI.hasFeature(RISCV::FeatureRelax)) {
+ Fixups.back().setLinkerRelaxable();
+ }
+
+ // Emit a normal ADD or SHXADD instruction with the given operands.
+ MCInst TmpInst = MCInstBuilder(BuildOpcode)
+ .addOperand(DestReg)
+ .addOperand(Src1)
+ .addOperand(Src2);
+ uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
+ support::endian::write(CB, Binary, llvm::endianness::little);
+}
+
static unsigned getInvertedBranchOp(unsigned BrOp) {
switch (BrOp) {
default:
@@ -589,6 +655,17 @@ void RISCVMCCodeEmitter::encodeInstruction(const MCInst &MI,
expandAddTPRel(MI, CB, Fixups, STI);
MCNumEmitted += 1;
return;
+ case RISCV::PseudoAddBaseIdx:
+ case RISCV::PseudoAddUWBaseIdx:
+ case RISCV::PseudoSh1AddBaseIdx:
+ case RISCV::PseudoSh2AddBaseIdx:
+ case RISCV::PseudoSh3AddBaseIdx:
+ case RISCV::PseudoSh1AddUWBaseIdx:
+ case RISCV::PseudoSh2AddUWBaseIdx:
+ case RISCV::PseudoSh3AddUWBaseIdx:
+ expandAddBaseIdx(MI, CB, Fixups, STI);
+ MCNumEmitted += 1;
+ return;
case RISCV::PseudoLongBEQ:
case RISCV::PseudoLongBNE:
case RISCV::PseudoLongBEQI:
@@ -807,12 +884,16 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
"invalid specifier");
break;
case ELF::R_RISCV_TPREL_ADD:
- // tprel_add is only used to indicate that a relocation should be emitted
- // for an add instruction used in TP-relative addressing. It should not be
- // expanded as if representing an actual instruction operand and so to
- // encounter it here is an error.
+ case ELF::R_RISCV_BASE_IDX_ADD:
+ // tprel_add / base_idx_add are only used to indicate that a relocation
+ // should be emitted for an add instruction used in TP-relative or
+ // base+index addressing. They should not be expanded as if representing
+ // an actual instruction operand and so to encounter them here is an
+ // error.
+
llvm_unreachable(
- "ELF::R_RISCV_TPREL_ADD should not represent an instruction operand");
+ "R_RISCV_TPREL_ADD or R_RISCV_BASE_IDX_ADD should not represent "
+ "an instruction operand");
case RISCV::S_QC_ACCESS:
// The same logic for tprel_add applies to S_QC_ACCESS, for similar
// reasons, but we use a specifier becuase %qc.access() gets expanded
@@ -832,6 +913,14 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
FixupKind = RISCV::fixup_riscv_hi20;
RelaxCandidate = true;
break;
+ case RISCV::S_BASE_IDX_LO:
+ if (MIFrm == RISCVII::InstFormatI)
+ FixupKind = ELF::R_RISCV_BASE_IDX_LO12_I;
+ else if (MIFrm == RISCVII::InstFormatS)
+ FixupKind = ELF::R_RISCV_BASE_IDX_LO12_S;
+ else
+ llvm_unreachable(
+ "S_BASE_IDX_LO used with unexpected instruction format");
case RISCV::S_PCREL_LO:
if (MIFrm == RISCVII::InstFormatI)
FixupKind = RISCV::fixup_riscv_pcrel_lo12_i;
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
index cf9db21a47dcb..8781906b46e83 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp
@@ -24,6 +24,8 @@ RISCV::Specifier RISCV::parseSpecifierName(StringRef name) {
return StringSwitch<RISCV::Specifier>(name)
.Case("lo", RISCV::S_LO)
.Case("hi", ELF::R_RISCV_HI20)
+ .Case("base_idx_lo", RISCV::S_BASE_IDX_LO)
+ .Case("base_idx_add", ELF::R_RISCV_BASE_IDX_ADD)
.Case("pcrel_lo", RISCV::S_PCREL_LO)
.Case("pcrel_hi", RISCV::S_PCREL_HI)
.Case("got_pcrel_hi", RISCV::S_GOT_HI)
@@ -52,6 +54,10 @@ StringRef RISCV::getSpecifierName(Specifier S) {
return "lo";
case ELF::R_RISCV_HI20:
return "hi";
+ case RISCV::S_BASE_IDX_LO:
+ return "base_idx_lo";
+ case ELF::R_RISCV_BASE_IDX_ADD:
+ return "base_idx_add";
case RISCV::S_PCREL_LO:
return "pcrel_lo";
case RISCV::S_PCREL_HI:
diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
index e37ea27364e6e..e0c4cb85431d0 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -1079,6 +1079,12 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
case RISCVII::MO_HI:
Kind = ELF::R_RISCV_HI20;
break;
+ case RISCVII::MO_BASE_IDX_LO:
+ Kind = RISCV::S_BASE_IDX_LO;
+ break;
+ case RISCVII::MO_BASE_IDX_ADD:
+ Kind = ELF::R_RISCV_BASE_IDX_ADD;
+ break;
case RISCVII::MO_PCREL_LO:
Kind = RISCV::S_PCREL_LO;
break;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormats.td b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
index e3c93dc93a686..5bc8890777177 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrFormats.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
@@ -353,6 +353,17 @@ class PseudoStore<string opcodestr, DAGOperand rsty = GPR>
let isCodeGenOnly = 0;
}
+// Pseudo add or shxadd instructions.
+class PseudoBaseIdx<string opcodestr>
+ : Pseudo<(outs GPR:$rd),
+ (ins GPR:$rs1, GPR:$rs2, base_idx_add_symbol:$src), [], opcodestr,
+ "$rd, $rs1, $rs2, $src"> {
+ let hasSideEffects = 0;
+ let mayLoad = 1;
+ let mayStore = 0;
+ let isCodeGenOnly = 0;
+}
+
// Instruction formats are listed in the order they appear in the RISC-V
// instruction set manual (R, R4, I, S, B, U, J).
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 4de0a27790eca..84232d0459853 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -3598,6 +3598,8 @@ RISCVInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
{MO_CALL, "riscv-call"},
{MO_LO, "riscv-lo"},
{MO_HI, "riscv-hi"},
+ {MO_BASE_IDX_LO, "riscv-base-idx-lo"},
+ {MO_BASE_IDX_ADD, "riscv-base-idx-add"},
{MO_PCREL_LO, "riscv-pcrel-lo"},
{MO_PCREL_HI, "riscv-pcrel-hi"},
{MO_GOT_HI, ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/207901
More information about the llvm-commits
mailing list