diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp index 7ed934cfabc0d..e5c6b6d60d068 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.cpp @@ -25,6 +25,16 @@ void AArch64_ELFTargetObjectFile::Initialize(MCContext &Ctx, SupportDebugThreadLocalLocation = false; } +const MCExpr *AArch64_ELFTargetObjectFile::getIndirectSymViaGOTPCRel( + const GlobalValue *GV, const MCSymbol *Sym, const MCValue &MV, + int64_t Offset, MachineModuleInfo *MMI, MCStreamer &Streamer) const { + int64_t FinalOffset = Offset + MV.getConstant(); + const MCExpr *Res = + MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTPCREL, getContext()); + const MCExpr *Off = MCConstantExpr::create(FinalOffset, getContext()); + return MCBinaryExpr::createAdd(Res, Off, getContext()); +} + AArch64_MachoTargetObjectFile::AArch64_MachoTargetObjectFile() { SupportGOTPCRelWithOffset = false; } diff --git a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h index 9f098230bbd78..7cd56fc9a189d 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h +++ b/llvm/lib/Target/AArch64/AArch64TargetObjectFile.h @@ -21,7 +21,14 @@ class AArch64_ELFTargetObjectFile : public TargetLoweringObjectFileELF { public: AArch64_ELFTargetObjectFile() { PLTRelativeVariantKind = MCSymbolRefExpr::VK_PLT; + SupportIndirectSymViaGOTPCRel = true; } + + const MCExpr *getIndirectSymViaGOTPCRel(const GlobalValue *GV, + const MCSymbol *Sym, + const MCValue &MV, int64_t Offset, + MachineModuleInfo *MMI, + MCStreamer &Streamer) const override; }; /// AArch64_MachoTargetObjectFile - This TLOF implementation is used for Darwin. diff --git a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp index 7c9e57e6eef3c..1535149b919b5 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.cpp @@ -12,6 +12,7 @@ #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCValue.h" using namespace llvm; @@ -25,6 +26,7 @@ void RISCVELFTargetObjectFile::Initialize(MCContext &Ctx, TargetLoweringObjectFileELF::Initialize(Ctx, TM); PLTRelativeVariantKind = MCSymbolRefExpr::VK_PLT; + SupportIndirectSymViaGOTPCRel = true; SmallDataSection = getContext().getELFSection( ".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); @@ -32,6 +34,16 @@ void RISCVELFTargetObjectFile::Initialize(MCContext &Ctx, ELF::SHF_WRITE | ELF::SHF_ALLOC); } +const MCExpr *RISCVELFTargetObjectFile::getIndirectSymViaGOTPCRel( + const GlobalValue *GV, const MCSymbol *Sym, const MCValue &MV, + int64_t Offset, MachineModuleInfo *MMI, MCStreamer &Streamer) const { + int64_t FinalOffset = Offset + MV.getConstant(); + const MCExpr *Res = + MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTPCREL, getContext()); + const MCExpr *Off = MCConstantExpr::create(FinalOffset, getContext()); + return MCBinaryExpr::createAdd(Res, Off, getContext()); +} + // A address must be loaded from a small section if its size is less than the // small section size threshold. Data in this section could be addressed by // using gp_rel operator. diff --git a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h index 890effd07320a..0910fbd3d9504 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h +++ b/llvm/lib/Target/RISCV/RISCVTargetObjectFile.h @@ -42,6 +42,12 @@ class RISCVELFTargetObjectFile : public TargetLoweringObjectFileELF { void getModuleMetadata(Module &M) override; bool isInSmallSection(uint64_t Size) const; + + const MCExpr *getIndirectSymViaGOTPCRel(const GlobalValue *GV, + const MCSymbol *Sym, + const MCValue &MV, int64_t Offset, + MachineModuleInfo *MMI, + MCStreamer &Streamer) const override; }; } // end namespace llvm diff --git a/llvm/test/MC/ELF/rtti-proxy-gotpcrel.ll b/llvm/test/MC/ELF/rtti-proxy-gotpcrel.ll index c58bb5b77c6c5..9f47469ff5e7e 100644 --- a/llvm/test/MC/ELF/rtti-proxy-gotpcrel.ll +++ b/llvm/test/MC/ELF/rtti-proxy-gotpcrel.ll @@ -1,4 +1,7 @@ -; RUN: llc %s -mtriple=x86_64-unknown-fuchsia -o - | FileCheck %s +; REQUIRES: x86-registered-target && aarch64-registered-target && riscv-registered-target +; RUN: llc %s -mtriple=x86_64 -o - | FileCheck %s +; RUN: llc %s -mtriple=aarch64 -o - | FileCheck %s +; RUN: llc %s -mtriple=riscv64 -o - | FileCheck %s @vtable = dso_local unnamed_addr constant i32 trunc (i64 sub (i64 ptrtoint (ptr @rtti.proxy to i64), i64 ptrtoint (ptr @vtable to i64)) to i32), align 4 @vtable_with_offset = dso_local unnamed_addr constant [2 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint (ptr @rtti.proxy to i64), i64 ptrtoint (ptr @vtable_with_offset to i64)) to i32)], align 4