diff --git a/llvm/lib/Target/X86/X86TargetObjectFile.cpp b/llvm/lib/Target/X86/X86TargetObjectFile.cpp index b88ad5a478f39..53c692060f08c 100644 --- a/llvm/lib/Target/X86/X86TargetObjectFile.cpp +++ b/llvm/lib/Target/X86/X86TargetObjectFile.cpp @@ -56,3 +56,13 @@ const MCExpr *X86ELFTargetObjectFile::getDebugThreadLocalSymbol( const MCSymbol *Sym) const { return MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_DTPOFF, getContext()); } + +const MCExpr *X86ELFTargetObjectFile::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()); +} diff --git a/llvm/lib/Target/X86/X86TargetObjectFile.h b/llvm/lib/Target/X86/X86TargetObjectFile.h index f4bf52c83771f..ed9390d1fad1a 100644 --- a/llvm/lib/Target/X86/X86TargetObjectFile.h +++ b/llvm/lib/Target/X86/X86TargetObjectFile.h @@ -42,9 +42,16 @@ namespace llvm { public: X86ELFTargetObjectFile() { PLTRelativeVariantKind = MCSymbolRefExpr::VK_PLT; + SupportIndirectSymViaGOTPCRel = true; } /// Describe a TLS variable address within debug info. const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const override; + + 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 new file mode 100644 index 0000000000000..c58bb5b77c6c5 --- /dev/null +++ b/llvm/test/MC/ELF/rtti-proxy-gotpcrel.ll @@ -0,0 +1,27 @@ +; RUN: llc %s -mtriple=x86_64-unknown-fuchsia -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 +@vtable_with_negative_offset = dso_local unnamed_addr constant [2 x i32] [ + i32 trunc ( + i64 sub ( + i64 ptrtoint (ptr @rtti.proxy to i64), + i64 ptrtoint (ptr getelementptr inbounds ([2 x i32], ptr @vtable_with_negative_offset, i32 0, i32 1) to i64) + ) + to i32), + i32 0 +], align 4 +@rtti = external global i8, align 8 +@rtti.proxy = linkonce_odr hidden unnamed_addr constant ptr @rtti + +; CHECK-NOT: rtti.proxy +; CHECK-LABEL: vtable: +; CHECK-NEXT: .{{word|long}} rtti@GOTPCREL+0{{$}} + +; CHECK-LABEL: vtable_with_offset: +; CHECK-NEXT: .{{word|long}} 0 +; CHECK-NEXT: .{{word|long}} rtti@GOTPCREL+4{{$}} + +; CHECK-LABEL: vtable_with_negative_offset: +; CHECK-NEXT: .{{word|long}} rtti@GOTPCREL-4{{$}} +; CHECK-NEXT: .{{word|long}} 0