[lld] [RISC-V][LLD] Add Support for RISC-V TLSDESC Relocations (PR #66916)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 20 08:19:49 PDT 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld
<details>
<summary>Changes</summary>
This patch adds basic support to LLD for the TLSDESC relocations outlined in new https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/373.
---
Patch is 42.54 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/66916.diff
23 Files Affected:
- (modified) lld/ELF/Arch/RISCV.cpp (+20)
- (modified) lld/ELF/InputSection.cpp (+1)
- (modified) lld/ELF/Relocations.cpp (+2-2)
- (modified) lld/ELF/Relocations.h (+4)
- (modified) lld/ELF/Writer.cpp (+2-1)
- (added) lld/test/ELF/riscv-tlsdesc-le.s (+43)
- (modified) llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def (+4)
- (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+88-9)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp (+9)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h (+5-1)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp (+15)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h (+12)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp (+46)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.cpp (+18)
- (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCExpr.h (+4)
- (modified) llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp (+12)
- (modified) llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp (+53)
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+22-1)
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.h (+3)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.cpp (+5-1)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.td (+36)
- (modified) llvm/lib/Target/RISCV/RISCVTargetMachine.cpp (+4)
- (modified) llvm/test/CodeGen/RISCV/tls-models.ll (+96)
``````````diff
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index d0d75118e30ddd7..019bb62b3001dbe 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -43,6 +43,7 @@ class RISCV final : public TargetInfo {
const uint8_t *loc) const override;
void relocate(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
+ RelExpr adjustTlsExpr(RelType type, RelExpr expr) const override;
bool relaxOnce(int pass) const override;
};
@@ -119,6 +120,8 @@ RISCV::RISCV() {
}
gotRel = symbolicRel;
+ tlsDescRel = R_RISCV_TLSDESC_CALL;
+
// .got[0] = _DYNAMIC
gotHeaderEntriesNum = 1;
@@ -297,6 +300,13 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
return R_TLSGD_PC;
case R_RISCV_TLS_GOT_HI20:
return R_GOT_PC;
+ case R_RISCV_TLSDESC_HI20:
+ return R_TLSDESC_PC;
+ case R_RISCV_TLSDESC_LOAD_LO12:
+ case R_RISCV_TLSDESC_ADD_LO12:
+ return R_TLSDESC;
+ case R_RISCV_TLSDESC_CALL:
+ return R_TLSDESC_CALL;
case R_RISCV_TPREL_HI20:
case R_RISCV_TPREL_LO12_I:
case R_RISCV_TPREL_LO12_S:
@@ -416,6 +426,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
case R_RISCV_PCREL_HI20:
case R_RISCV_TLS_GD_HI20:
case R_RISCV_TLS_GOT_HI20:
+ case R_RISCV_TLSDESC_HI20:
case R_RISCV_TPREL_HI20:
case R_RISCV_HI20: {
uint64_t hi = val + 0x800;
@@ -426,6 +437,8 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
case R_RISCV_PCREL_LO12_I:
case R_RISCV_TPREL_LO12_I:
+ case R_RISCV_TLSDESC_LOAD_LO12:
+ case R_RISCV_TLSDESC_ADD_LO12:
case R_RISCV_LO12_I: {
uint64_t hi = (val + 0x800) >> 12;
uint64_t lo = val - (hi << 12);
@@ -513,6 +526,13 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
}
}
+RelExpr RISCV::adjustTlsExpr(RelType type, RelExpr expr) const {
+ if (expr == R_RELAX_TLS_GD_TO_IE) {
+ return R_RELAX_TLS_GD_TO_IE_ABS;
+ }
+ return expr;
+}
+
namespace {
struct SymbolAnchor {
uint64_t offset;
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index f97ca96bf4a852e..64ec3ba7274f4b8 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -846,6 +846,7 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
return sym.getSize() + a;
case R_TLSDESC:
return in.got->getTlsDescAddr(sym) + a;
+ case R_RISCV_TLSDESC_HI:
case R_TLSDESC_PC:
return in.got->getTlsDescAddr(sym) + a - p;
case R_TLSDESC_GOTPLT:
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 9305c959d0f0f68..01b961ed22d57c1 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1263,7 +1263,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
return handleMipsTlsRelocation(type, sym, c, offset, addend, expr);
if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
- R_TLSDESC_GOTPLT>(expr) &&
+ R_TLSDESC_GOTPLT, R_RISCV_TLSDESC_HI>(expr) &&
config->shared) {
if (expr != R_TLSDESC_CALL) {
sym.setFlags(NEEDS_TLSDESC);
@@ -1327,7 +1327,7 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
R_TLSDESC_GOTPLT, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC,
- R_LOONGARCH_TLSGD_PAGE_PC>(expr)) {
+ R_LOONGARCH_TLSGD_PAGE_PC, R_RISCV_TLSDESC_HI>(expr)) {
if (!toExecRelax) {
sym.setFlags(NEEDS_TLSGD);
c.addReloc({expr, type, offset, addend, &sym});
diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h
index 0559245a8f2c006..cc05a567f4a8d91 100644
--- a/lld/ELF/Relocations.h
+++ b/lld/ELF/Relocations.h
@@ -102,6 +102,10 @@ enum RelExpr {
R_PPC64_RELAX_GOT_PC,
R_RISCV_ADD,
R_RISCV_PC_INDIRECT,
+ R_RISCV_TLSDESC_HI,
+ R_RISCV_TLSDESC_LOAD_LO,
+ R_RISCV_TLSDESC_ADD_LO,
+ R_RISCV_TLSDESC_CALLER,
// Same as R_PC but with page-aligned semantics.
R_LOONGARCH_PAGE_PC,
// Same as R_PLT_PC but with page-aligned semantics.
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 40f7d7981d9d441..3c51ae4e1bfe7f9 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1897,7 +1897,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
}
}
- if (config->emachine == EM_386 || config->emachine == EM_X86_64) {
+ if (config->emachine == EM_386 || config->emachine == EM_X86_64 ||
+ config->emachine == EM_RISCV) {
// On targets that support TLSDESC, _TLS_MODULE_BASE_ is defined in such a
// way that:
//
diff --git a/lld/test/ELF/riscv-tlsdesc-le.s b/lld/test/ELF/riscv-tlsdesc-le.s
new file mode 100644
index 000000000000000..6aa670cffb59b84
--- /dev/null
+++ b/lld/test/ELF/riscv-tlsdesc-le.s
@@ -0,0 +1,43 @@
+// RUN: llvm-mc -filetype=obj -triple=riscv64-pc-linux %s -o %t.o
+// RUN: ld.lld -shared %t.o -o %t.so
+// RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t.so | FileCheck %s
+// RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=REL %s
+
+// CHECK: 00000000000012d8 <_start>:
+// CHECK-NEXT: 12d8: auipc a0, 1
+// CHECK-NEXT: 12dc: ld a1, 920(a0)
+// CHECK-NEXT: 12e0: addi a0, a0, 920
+// CHECK-NEXT: 12e4: jalr t0, a1
+// CHECK-NEXT: 12e8: add a0, a0, tp
+// CHECK-NEXT: 12ec: ret
+
+// REL: Relocation section '.rela.dyn' at offset 0x{{[0-9a-f]+}} contains 2 entries
+// REL: R_RISCV_TLSDESC_CALL ffffffffffffffe8
+// REL-NEXT: R_RISCV_TLSDESC_CALL 0
+
+ .text
+ .attribute 4, 16
+ .attribute 5, "rv64i2p1"
+ .file "<stdin>"
+ .globl _start # -- Begin function _start
+ .p2align 2
+ .type _start, at function
+_start: # @_start
+# %bb.0: # %entry
+.Ltlsdesc_hi0:
+ auipc a0, %tlsdesc_hi(unspecified)
+ ld a1, %tlsdesc_load_lo(.Ltlsdesc_hi0)(a0)
+ addi a0, a0, %tlsdesc_add_lo(.Ltlsdesc_hi0)
+ jalr t0, 0(a1), %tlsdesc_call(.Ltlsdesc_hi0)
+ add a0, a0, tp
+ ret
+.Lfunc_end0:
+ .size _start, .Lfunc_end0-_start
+ # -- End function
+ .section ".note.GNU-stack","", at progbits
+
+ .section .tbss,"awT", at nobits
+ .p2align 2
+
+unspecified:
+ .zero 4
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def
index 9a126df01531195..94420395fa0fadd 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/RISCV.def
@@ -55,3 +55,7 @@ ELF_RELOC(R_RISCV_SET32, 56)
ELF_RELOC(R_RISCV_32_PCREL, 57)
ELF_RELOC(R_RISCV_IRELATIVE, 58)
ELF_RELOC(R_RISCV_PLT32, 59)
+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)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 7d8d82e381313bf..1303f5e85aeeb65 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -152,6 +152,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
// Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
// addressing.
void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
+ void emitLoadTLSDescAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
// Helper to emit pseudo load/store instruction with a symbol.
void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
@@ -170,6 +171,12 @@ class RISCVAsmParser : public MCTargetAsmParser {
// 'add' is an overloaded mnemonic.
bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands);
+ // Checks that a PseudoTLSDESCCall is using x5/t0 in its output operand.
+ // Enforcing this using a restricted register class for the output
+ // operand of PseudoTLSDESCCall results in a poor diagnostic due to the fact
+ // 'jalr' is an overloaded mnemonic.
+ bool checkPseudoTLSDESCCall(MCInst &Inst, OperandVector &Operands);
+
// Check instruction constraints.
bool validateInstruction(MCInst &Inst, OperandVector &Operands);
@@ -533,6 +540,16 @@ struct RISCVOperand final : public MCParsedAsmOperand {
VK == RISCVMCExpr::VK_RISCV_TPREL_ADD;
}
+ bool isTLSDESCCallSymbol() const {
+ int64_t Imm;
+ RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
+ // Must be of 'immediate' type but not a constant.
+ if (!isImm() || evaluateConstantImm(getImm(), Imm, VK))
+ return false;
+ return RISCVAsmParser::classifySymbolRef(getImm(), VK) &&
+ VK == RISCVMCExpr::VK_RISCV_TLSDESC_CALL;
+ }
+
bool isCSRSystemRegister() const { return isSystemRegister(); }
bool isVTypeImm(unsigned N) const {
@@ -584,7 +601,10 @@ struct RISCVOperand final : public MCParsedAsmOperand {
if (!isImm())
return false;
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
- if (VK == RISCVMCExpr::VK_RISCV_LO || VK == RISCVMCExpr::VK_RISCV_PCREL_LO)
+ if (VK == RISCVMCExpr::VK_RISCV_LO ||
+ VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||
+ VK == RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO ||
+ VK == RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO)
return true;
// Given only Imm, ensuring that the actually specified constant is either
// a signed or unsigned 64-bit number is unfortunately impossible.
@@ -837,7 +857,9 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return IsValid && ((IsConstantImm && VK == RISCVMCExpr::VK_RISCV_None) ||
VK == RISCVMCExpr::VK_RISCV_LO ||
VK == RISCVMCExpr::VK_RISCV_PCREL_LO ||
- VK == RISCVMCExpr::VK_RISCV_TPREL_LO);
+ VK == RISCVMCExpr::VK_RISCV_TPREL_LO ||
+ VK == RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO ||
+ VK == RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO);
}
bool isSImm12Lsb0() const { return isBareSimmNLsb0<12>(); }
@@ -894,14 +916,16 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return IsValid && (VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
VK == RISCVMCExpr::VK_RISCV_GOT_HI ||
VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI ||
- VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI);
- } else {
- return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
- VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
- VK == RISCVMCExpr::VK_RISCV_GOT_HI ||
- VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI ||
- VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI);
+ VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI ||
+ VK == RISCVMCExpr::VK_RISCV_TLSDESC_HI);
}
+
+ return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
+ VK == RISCVMCExpr::VK_RISCV_PCREL_HI ||
+ VK == RISCVMCExpr::VK_RISCV_GOT_HI ||
+ VK == RISCVMCExpr::VK_RISCV_TLS_GOT_HI ||
+ VK == RISCVMCExpr::VK_RISCV_TLS_GD_HI ||
+ VK == RISCVMCExpr::VK_RISCV_TLSDESC_HI);
}
bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
@@ -1515,6 +1539,11 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
return Error(ErrorLoc, "operand must be a symbol with %tprel_add modifier");
}
+ case Match_InvalidTLSDESCCallSymbol: {
+ SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
+ return Error(ErrorLoc,
+ "operand must be a symbol with %tlsdesc_call modifier");
+ }
case Match_InvalidRTZArg: {
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
return Error(ErrorLoc, "operand must be 'rtz' floating-point rounding mode");
@@ -3107,6 +3136,41 @@ void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
RISCV::ADDI, IDLoc, Out);
}
+void RISCVAsmParser::emitLoadTLSDescAddress(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out) {
+ // The load TLS GD address pseudo-instruction "la.tlsdesc" is used in
+ // global-dynamic TLS model addressing of global symbols:
+ // la.tlsdesc rdest, symbol
+ // expands to
+ // TmpLabel: AUIPC rdest, %tlsdesc_hi(symbol)
+ // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
+ MCOperand DestReg = Inst.getOperand(0);
+ const MCExpr *Symbol = Inst.getOperand(1).getExpr();
+
+ MCContext &Ctx = getContext();
+
+ MCSymbol *TmpLabel = Ctx.createNamedTempSymbol("pcrel_hi");
+ Out.emitLabel(TmpLabel);
+
+ const RISCVMCExpr *SymbolHi =
+ RISCVMCExpr::create(Symbol, RISCVMCExpr::VK_RISCV_TLSDESC_HI, Ctx);
+ emitToStreamer(
+ Out, MCInstBuilder(RISCV::AUIPC).addOperand(DestReg).addExpr(SymbolHi));
+
+ const MCExpr *RefToLinkTmpLabel =
+ RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx),
+ RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO, Ctx);
+
+ emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
+ .addOperand(DestReg)
+ .addOperand(DestReg)
+ .addExpr(RefToLinkTmpLabel));
+
+ emitToStreamer(
+ Out,
+ MCInstBuilder(RISCV::JALR).addReg(RISCV::X5).addReg(RISCV::X5).addImm(0));
+}
+
void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
SMLoc IDLoc, MCStreamer &Out,
bool HasTmpReg) {
@@ -3246,6 +3310,18 @@ bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst,
return false;
}
+bool RISCVAsmParser::checkPseudoTLSDESCCall(MCInst &Inst,
+ OperandVector &Operands) {
+ assert(Inst.getOpcode() == RISCV::PseudoTLSDESCCall && "Invalid instruction");
+ assert(Inst.getOperand(0).isReg() && "Unexpected operand kind");
+ if (Inst.getOperand(0).getReg() != RISCV::X5) {
+ SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc();
+ return Error(ErrorLoc, "the output operand must be t0/x5 when using "
+ "%tlsdesc_call modifier");
+ }
+
+ return false;
+}
std::unique_ptr<RISCVOperand> RISCVAsmParser::defaultMaskRegOp() const {
return RISCVOperand::createReg(RISCV::NoRegister, llvm::SMLoc(),
@@ -3443,6 +3519,9 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
case RISCV::PseudoLA_TLS_GD:
emitLoadTLSGDAddress(Inst, IDLoc, Out);
return false;
+ case RISCV::PseudoLA_TLSDESC:
+ emitLoadTLSDescAddress(Inst, IDLoc, Out);
+ return false;
case RISCV::PseudoLB:
emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
return false;
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
index ca5aeb943c3be75..0b070e72c3ecb3d 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
@@ -80,6 +80,11 @@ RISCVAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"fixup_riscv_call_plt", 0, 64, MCFixupKindInfo::FKF_IsPCRel},
{"fixup_riscv_relax", 0, 0, 0},
{"fixup_riscv_align", 0, 0, 0},
+
+ {"fixup_riscv_tlsdesc_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget},
+ {"fixup_riscv_tlsdesc_load_lo12", 20, 12, 0},
+ {"fixup_riscv_tlsdesc_add_lo12", 20, 12, 0},
+ {"fixup_riscv_tlsdesc_call", 0, 0, 0},
};
static_assert((std::size(Infos)) == RISCV::NumTargetFixupKinds,
"Not all fixup kinds added to Infos array");
@@ -118,6 +123,7 @@ bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
case RISCV::fixup_riscv_got_hi20:
case RISCV::fixup_riscv_tls_got_hi20:
case RISCV::fixup_riscv_tls_gd_hi20:
+ case RISCV::fixup_riscv_tlsdesc_hi20:
return true;
}
@@ -390,6 +396,7 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
case RISCV::fixup_riscv_got_hi20:
case RISCV::fixup_riscv_tls_got_hi20:
case RISCV::fixup_riscv_tls_gd_hi20:
+ case RISCV::fixup_riscv_tlsdesc_hi20:
llvm_unreachable("Relocation should be unconditionally forced\n");
case FK_Data_1:
case FK_Data_2:
@@ -399,6 +406,7 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
case RISCV::fixup_riscv_lo12_i:
case RISCV::fixup_riscv_pcrel_lo12_i:
case RISCV::fixup_riscv_tprel_lo12_i:
+ case RISCV::fixup_riscv_tlsdesc_load_lo12:
return Value & 0xfff;
case RISCV::fixup_riscv_12_i:
if (!isInt<12>(Value)) {
@@ -502,6 +510,7 @@ bool RISCVAsmBackend::evaluateTargetFixup(
switch (Fixup.getTargetKind()) {
default:
llvm_unreachable("Unexpected fixup kind!");
+ case RISCV::fixup_riscv_tlsdesc_hi20:
case RISCV::fixup_riscv_pcrel_hi20:
AUIPCFixup = &Fixup;
AUIPCDF = DF;
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 20ff26a39dc3b30..244d2e56c9fa2e7 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -256,11 +256,15 @@ enum {
MO_TPREL_ADD = 10,
MO_TLS_GOT_HI = 11,
MO_TLS_GD_HI = 12,
+ MO_TLSDESC_HI = 13,
+ MO_TLSDESC_LOAD_LO = 14,
+ MO_TLSDESC_ADD_LO = 15,
+ MO_TLSDESC_CALL = 16,
// Used to differentiate between target-specific "direct" flags and "bitmask"
// flags. A machine operand can only have one "direct" flag, but can have
// multiple "bitmask" flags.
- MO_DIRECT_FLAG_MASK = 15
+ MO_DIRECT_FLAG_MASK = 31
};
} // namespace RISCVII
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
index 0799267eaf7c769..bf73b82eaea880c 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
@@ -77,6 +77,14 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
return ELF::R_RISCV_TLS_GOT_HI20;
case RISCV::fixup_riscv_tls_gd_hi20:
return ELF::R_RISCV_TLS_GD_HI20;
+ case RISCV::fixup_riscv_tlsdesc_hi20:
+ return ELF::R_RISCV_TLSDESC_HI20;
+ case RISCV::fixup_riscv_tlsdesc_load_lo12:
+ return ELF::R_RISCV_TLSDESC_LOAD_LO12;
+ case RISCV::fixup_riscv_tlsdesc_add_lo12:
+ return ELF::R_RISCV_TLSDESC_ADD_LO12;
+ case RISCV::fixup_riscv_tlsdesc_call:
+ return ELF::R_RISCV_TLSDESC_CALL;
case RISCV::fixup_riscv_jal:
return ELF::R_RISCV_JAL;
case RISCV::fixup_riscv_branch:
@@ -96,6 +104,13 @@ unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
default:
Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
return ELF::R_RISCV_NONE;
+ case RISCV::fixup_riscv_tlsdesc_load_lo12:
+ return ELF::R_RISCV_TLSDESC_LOAD_LO12;
+ case RISCV::fixup_riscv_tlsdesc_add_lo12:
+ return ELF::R_RISCV_TLSDESC_ADD_LO12;
+ case RISCV::fixup_riscv_tlsdesc_call:
+ return ELF::R_RISCV_TLSDESC_CALL;
+
case FK_Data_1:
Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
return ELF::R_RISCV_NONE;
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
index f3d0841eb6bca64..3e8239ac08458b8 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
@@ -71,6 +71,18 @@ enum Fixups {
// Used to generate an R_RISCV_ALIGN relocation, which indicates the linker
// should fixup the alignment after linker relaxation.
fixup_riscv_align,
+ // 20-bit fixup corresponding to %tlsdesc_hi(foo) for instructions like
+ // auipc
+ fixup_riscv_tlsdesc_hi20,
+ // 12-bit fixup corresponding to %tlsdesc_load_lo(foo) for instructions like
+ // addi
+ fixup_riscv_tlsdesc_load_lo12,
+ // 12-bit fixup correspon...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/66916
More information about the llvm-commits
mailing list