mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-08 06:32:24 +00:00
[AsmPrinter][TLOF] ARM64 MachO support for replacing GOT equivalents
Follow up r230264 and add ARM64 support for replacing global GOT equivalent symbol accesses by references to the GOT entry for the final symbol instead, example: -- before .globl _foo _foo: .long 42 .globl _gotequivalent _gotequivalent: .quad _foo .globl _delta _delta: .long _gotequivalent-_delta -- after .globl _foo _foo: .long 42 .globl _delta Ltmp3: .long _foo@GOT-Ltmp3 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231474 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a52da9a180
commit
66aa390799
@ -43,12 +43,14 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool SupportIndirectSymViaGOTPCRel;
|
bool SupportIndirectSymViaGOTPCRel;
|
||||||
|
bool SupportGOTPCRelWithOffset;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MCContext &getContext() const { return *Ctx; }
|
MCContext &getContext() const { return *Ctx; }
|
||||||
|
|
||||||
TargetLoweringObjectFile() : MCObjectFileInfo(), Ctx(nullptr), DL(nullptr),
|
TargetLoweringObjectFile() : MCObjectFileInfo(), Ctx(nullptr), DL(nullptr),
|
||||||
SupportIndirectSymViaGOTPCRel(false) {}
|
SupportIndirectSymViaGOTPCRel(false),
|
||||||
|
SupportGOTPCRelWithOffset(true) {}
|
||||||
|
|
||||||
virtual ~TargetLoweringObjectFile();
|
virtual ~TargetLoweringObjectFile();
|
||||||
|
|
||||||
@ -168,9 +170,16 @@ public:
|
|||||||
return SupportIndirectSymViaGOTPCRel;
|
return SupportIndirectSymViaGOTPCRel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Target GOT "PC"-relative relocation supports encoding an additional
|
||||||
|
/// binary expression with an offset?
|
||||||
|
bool supportGOTPCRelWithOffset() const {
|
||||||
|
return SupportGOTPCRelWithOffset;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Get the target specific PC relative GOT entry relocation
|
/// \brief Get the target specific PC relative GOT entry relocation
|
||||||
virtual const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym,
|
virtual const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym,
|
||||||
int64_t Offset) const {
|
int64_t Offset,
|
||||||
|
MCStreamer &Streamer) const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2084,9 +2084,13 @@ static void handleIndirectSymViaGOTPCRel(AsmPrinter &AP, const MCExpr **ME,
|
|||||||
//
|
//
|
||||||
// gotpcrelcst := <offset from @foo base> + <cst>
|
// gotpcrelcst := <offset from @foo base> + <cst>
|
||||||
//
|
//
|
||||||
|
// Only encode <cst> if the target supports it.
|
||||||
|
//
|
||||||
int64_t GOTPCRelCst = Offset + MV.getConstant();
|
int64_t GOTPCRelCst = Offset + MV.getConstant();
|
||||||
if (GOTPCRelCst < 0)
|
if (GOTPCRelCst < 0)
|
||||||
return;
|
return;
|
||||||
|
if (!AP.getObjFileLowering().supportGOTPCRelWithOffset() && GOTPCRelCst != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
// Emit the GOT PC relative to replace the got equivalent global, i.e.:
|
// Emit the GOT PC relative to replace the got equivalent global, i.e.:
|
||||||
//
|
//
|
||||||
@ -2110,7 +2114,8 @@ static void handleIndirectSymViaGOTPCRel(AsmPrinter &AP, const MCExpr **ME,
|
|||||||
const GlobalValue *FinalGV = dyn_cast<GlobalValue>(GV->getOperand(0));
|
const GlobalValue *FinalGV = dyn_cast<GlobalValue>(GV->getOperand(0));
|
||||||
const MCSymbol *FinalSym = AP.getSymbol(FinalGV);
|
const MCSymbol *FinalSym = AP.getSymbol(FinalGV);
|
||||||
*ME = AP.getObjFileLowering().getIndirectSymViaGOTPCRel(FinalSym,
|
*ME = AP.getObjFileLowering().getIndirectSymViaGOTPCRel(FinalSym,
|
||||||
GOTPCRelCst);
|
GOTPCRelCst,
|
||||||
|
AP.OutStreamer);
|
||||||
|
|
||||||
// Update GOT equivalent usage information
|
// Update GOT equivalent usage information
|
||||||
--NumUses;
|
--NumUses;
|
||||||
|
@ -23,6 +23,12 @@ void AArch64_ELFTargetObjectFile::Initialize(MCContext &Ctx,
|
|||||||
InitializeELF(TM.Options.UseInitArray);
|
InitializeELF(TM.Options.UseInitArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AArch64_MachoTargetObjectFile::AArch64_MachoTargetObjectFile()
|
||||||
|
: TargetLoweringObjectFileMachO() {
|
||||||
|
SupportIndirectSymViaGOTPCRel = true;
|
||||||
|
SupportGOTPCRelWithOffset = false;
|
||||||
|
}
|
||||||
|
|
||||||
const MCExpr *AArch64_MachoTargetObjectFile::getTTypeGlobalReference(
|
const MCExpr *AArch64_MachoTargetObjectFile::getTTypeGlobalReference(
|
||||||
const GlobalValue *GV, unsigned Encoding, Mangler &Mang,
|
const GlobalValue *GV, unsigned Encoding, Mangler &Mang,
|
||||||
const TargetMachine &TM, MachineModuleInfo *MMI,
|
const TargetMachine &TM, MachineModuleInfo *MMI,
|
||||||
@ -50,3 +56,15 @@ MCSymbol *AArch64_MachoTargetObjectFile::getCFIPersonalitySymbol(
|
|||||||
MachineModuleInfo *MMI) const {
|
MachineModuleInfo *MMI) const {
|
||||||
return TM.getSymbol(GV, Mang);
|
return TM.getSymbol(GV, Mang);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MCExpr *AArch64_MachoTargetObjectFile::getIndirectSymViaGOTPCRel(
|
||||||
|
const MCSymbol *Sym, int64_t Offset, MCStreamer &Streamer) const {
|
||||||
|
// On ARM64 Darwin, we can reference symbols with foo@GOT-., which
|
||||||
|
// is an indirect pc-relative reference.
|
||||||
|
const MCExpr *Res =
|
||||||
|
MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOT, getContext());
|
||||||
|
MCSymbol *PCSym = getContext().CreateTempSymbol();
|
||||||
|
Streamer.EmitLabel(PCSym);
|
||||||
|
const MCExpr *PC = MCSymbolRefExpr::Create(PCSym, getContext());
|
||||||
|
return MCBinaryExpr::CreateSub(Res, PC, getContext());
|
||||||
|
}
|
||||||
|
@ -24,6 +24,8 @@ class AArch64_ELFTargetObjectFile : public TargetLoweringObjectFileELF {
|
|||||||
/// AArch64_MachoTargetObjectFile - This TLOF implementation is used for Darwin.
|
/// AArch64_MachoTargetObjectFile - This TLOF implementation is used for Darwin.
|
||||||
class AArch64_MachoTargetObjectFile : public TargetLoweringObjectFileMachO {
|
class AArch64_MachoTargetObjectFile : public TargetLoweringObjectFileMachO {
|
||||||
public:
|
public:
|
||||||
|
AArch64_MachoTargetObjectFile();
|
||||||
|
|
||||||
const MCExpr *getTTypeGlobalReference(const GlobalValue *GV,
|
const MCExpr *getTTypeGlobalReference(const GlobalValue *GV,
|
||||||
unsigned Encoding, Mangler &Mang,
|
unsigned Encoding, Mangler &Mang,
|
||||||
const TargetMachine &TM,
|
const TargetMachine &TM,
|
||||||
@ -33,6 +35,10 @@ public:
|
|||||||
MCSymbol *getCFIPersonalitySymbol(const GlobalValue *GV, Mangler &Mang,
|
MCSymbol *getCFIPersonalitySymbol(const GlobalValue *GV, Mangler &Mang,
|
||||||
const TargetMachine &TM,
|
const TargetMachine &TM,
|
||||||
MachineModuleInfo *MMI) const override;
|
MachineModuleInfo *MMI) const override;
|
||||||
|
|
||||||
|
const MCExpr *
|
||||||
|
getIndirectSymViaGOTPCRel(const MCSymbol *Sym, int64_t Offset,
|
||||||
|
MCStreamer &Streamer) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@ -52,7 +52,7 @@ MCSymbol *X86_64MachoTargetObjectFile::getCFIPersonalitySymbol(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const MCExpr *X86_64MachoTargetObjectFile::getIndirectSymViaGOTPCRel(
|
const MCExpr *X86_64MachoTargetObjectFile::getIndirectSymViaGOTPCRel(
|
||||||
const MCSymbol *Sym, int64_t Offset) const {
|
const MCSymbol *Sym, int64_t Offset, MCStreamer &Streamer) const {
|
||||||
// On Darwin/X86-64, we need to use foo@GOTPCREL+4 to access the got entry
|
// On Darwin/X86-64, we need to use foo@GOTPCREL+4 to access the got entry
|
||||||
// from a data section. In case there's an additional offset, then use
|
// from a data section. In case there's an additional offset, then use
|
||||||
// foo@GOTPCREL+4+<offset>.
|
// foo@GOTPCREL+4+<offset>.
|
||||||
|
@ -34,8 +34,8 @@ namespace llvm {
|
|||||||
MachineModuleInfo *MMI) const override;
|
MachineModuleInfo *MMI) const override;
|
||||||
|
|
||||||
const MCExpr *
|
const MCExpr *
|
||||||
getIndirectSymViaGOTPCRel(const MCSymbol *Sym,
|
getIndirectSymViaGOTPCRel(const MCSymbol *Sym, int64_t Offset,
|
||||||
int64_t Offset) const override;
|
MCStreamer &Streamer) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief This implemenatation is used for X86 ELF targets that don't
|
/// \brief This implemenatation is used for X86 ELF targets that don't
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
; RUN: llc -mtriple=x86_64-apple-darwin %s -o %t
|
; RUN: llc -mtriple=x86_64-apple-darwin %s -o %t
|
||||||
; RUN: FileCheck %s < %t
|
; RUN: FileCheck %s -check-prefix=X86 < %t
|
||||||
; RUN: FileCheck %s -check-prefix=GOT-EQUIV < %t
|
; RUN: FileCheck %s -check-prefix=X86-GOT-EQUIV < %t
|
||||||
|
; RUN: llc -mtriple=arm64-apple-darwin %s -o %t
|
||||||
|
; RUN: FileCheck %s -check-prefix=ARM < %t
|
||||||
|
; RUN: FileCheck %s -check-prefix=ARM-GOT-EQUIV < %t
|
||||||
|
|
||||||
; GOT equivalent globals references can be replaced by the GOT entry of the
|
; GOT equivalent globals references can be replaced by the GOT entry of the
|
||||||
; final symbol instead.
|
; final symbol instead.
|
||||||
@ -8,9 +11,15 @@
|
|||||||
%struct.data = type { i32, %struct.anon }
|
%struct.data = type { i32, %struct.anon }
|
||||||
%struct.anon = type { i32, i32 }
|
%struct.anon = type { i32, i32 }
|
||||||
|
|
||||||
; Check that these got equivalent symbols are never emitted or used
|
; Check that these got equivalent symbols are never emitted on x86-64 and
|
||||||
; GOT-EQUIV-NOT: _localgotequiv
|
; emitted on ARM64. Since ARM64 does not support encoding an extra offset with
|
||||||
; GOT-EQUIV-NOT: _extgotequiv
|
; @GOT, we still need to emit the equivalents for use by such IR constructs.
|
||||||
|
|
||||||
|
; X86-GOT-EQUIV-NOT: L_localgotequiv
|
||||||
|
; X86-GOT-EQUIV-NOT: l_extgotequiv
|
||||||
|
|
||||||
|
; ARM-GOT-EQUIV-LABEL: l_extgotequiv:
|
||||||
|
; ARM-GOT-EQUIV-LABEL: l_localgotequiv:
|
||||||
@localfoo = global i32 42
|
@localfoo = global i32 42
|
||||||
@localgotequiv = private unnamed_addr constant i32* @localfoo
|
@localgotequiv = private unnamed_addr constant i32* @localfoo
|
||||||
|
|
||||||
@ -21,35 +30,54 @@
|
|||||||
; equivalent since it can't be replaced by the GOT entry. @bargotequiv is
|
; equivalent since it can't be replaced by the GOT entry. @bargotequiv is
|
||||||
; used by an instruction inside @t0.
|
; used by an instruction inside @t0.
|
||||||
;
|
;
|
||||||
; CHECK: l_bargotequiv:
|
; X86: l_bargotequiv:
|
||||||
; CHECK-NEXT: .quad _extbar
|
; X86-NEXT: .quad _extbar
|
||||||
|
; ARM: l_bargotequiv:
|
||||||
|
; ARM-NEXT: .quad _extbar
|
||||||
@extbar = external global i32
|
@extbar = external global i32
|
||||||
@bargotequiv = private unnamed_addr constant i32* @extbar
|
@bargotequiv = private unnamed_addr constant i32* @extbar
|
||||||
|
|
||||||
@table = global [4 x %struct.data] [
|
@table = global [4 x %struct.data] [
|
||||||
; CHECK-LABEL: _table
|
; X86-LABEL: _table
|
||||||
|
; ARM-LABEL: _table
|
||||||
%struct.data { i32 1, %struct.anon { i32 2, i32 3 } },
|
%struct.data { i32 1, %struct.anon { i32 2, i32 3 } },
|
||||||
; Test GOT equivalent usage inside nested constant arrays.
|
; Test GOT equivalent usage inside nested constant arrays.
|
||||||
; CHECK: .long 5
|
|
||||||
; CHECK-NOT: .long _localgotequiv-(_table+20)
|
; X86: .long 5
|
||||||
; CHECK-NEXT: .long _localfoo@GOTPCREL+4
|
; X86-NOT: .long _localgotequiv-(_table+20)
|
||||||
|
; X86-NEXT: .long _localfoo@GOTPCREL+4
|
||||||
|
|
||||||
|
; ARM: .long 5
|
||||||
|
; ARM-NOT: .long _localgotequiv-(_table+20)
|
||||||
|
; ARM-NEXT: Ltmp1:
|
||||||
|
; ARM-NEXT: .long _localfoo@GOT-Ltmp1
|
||||||
%struct.data { i32 4, %struct.anon { i32 5,
|
%struct.data { i32 4, %struct.anon { i32 5,
|
||||||
i32 trunc (i64 sub (i64 ptrtoint (i32** @localgotequiv to i64),
|
i32 trunc (i64 sub (i64 ptrtoint (i32** @localgotequiv to i64),
|
||||||
i64 ptrtoint (i32* getelementptr inbounds ([4 x %struct.data]* @table, i32 0, i64 1, i32 1, i32 1) to i64))
|
i64 ptrtoint (i32* getelementptr inbounds ([4 x %struct.data]* @table, i32 0, i64 1, i32 1, i32 1) to i64))
|
||||||
to i32)}
|
to i32)}
|
||||||
},
|
},
|
||||||
; CHECK: .long 5
|
; X86: .long 5
|
||||||
; CHECK-NOT: _extgotequiv-(_table+32)
|
; X86-NOT: _extgotequiv-(_table+32)
|
||||||
; CHECK-NEXT: .long _extfoo@GOTPCREL+4
|
; X86-NEXT: .long _extfoo@GOTPCREL+4
|
||||||
|
|
||||||
|
; ARM: .long 5
|
||||||
|
; ARM-NOT: _extgotequiv-(_table+32)
|
||||||
|
; ARM-NEXT: Ltmp2:
|
||||||
|
; ARM-NEXT: _extfoo@GOT-Ltmp2
|
||||||
%struct.data { i32 4, %struct.anon { i32 5,
|
%struct.data { i32 4, %struct.anon { i32 5,
|
||||||
i32 trunc (i64 sub (i64 ptrtoint (i32** @extgotequiv to i64),
|
i32 trunc (i64 sub (i64 ptrtoint (i32** @extgotequiv to i64),
|
||||||
i64 ptrtoint (i32* getelementptr inbounds ([4 x %struct.data]* @table, i32 0, i64 2, i32 1, i32 1) to i64))
|
i64 ptrtoint (i32* getelementptr inbounds ([4 x %struct.data]* @table, i32 0, i64 2, i32 1, i32 1) to i64))
|
||||||
to i32)}
|
to i32)}
|
||||||
},
|
},
|
||||||
; Test support for arbitrary constants into the GOTPCREL offset
|
; Test support for arbitrary constants into the GOTPCREL offset, which is
|
||||||
; CHECK: .long 5
|
; supported on x86-64 but not on ARM64
|
||||||
; CHECK-NOT: _extgotequiv-(_table+44)
|
|
||||||
; CHECK-NEXT: .long _extfoo@GOTPCREL+28
|
; X86: .long 5
|
||||||
|
; X86-NOT: _extgotequiv-(_table+44)
|
||||||
|
; X86-NEXT: .long _extfoo@GOTPCREL+28
|
||||||
|
|
||||||
|
; ARM: .long 5
|
||||||
|
; ARM-NEXT: .long (l_extgotequiv-(_table+44))+24
|
||||||
%struct.data { i32 4, %struct.anon { i32 5,
|
%struct.data { i32 4, %struct.anon { i32 5,
|
||||||
i32 add (i32 trunc (i64 sub (i64 ptrtoint (i32** @extgotequiv to i64),
|
i32 add (i32 trunc (i64 sub (i64 ptrtoint (i32** @extgotequiv to i64),
|
||||||
i64 ptrtoint (i32* getelementptr inbounds ([4 x %struct.data]* @table, i32 0, i64 3, i32 1, i32 1) to i64))
|
i64 ptrtoint (i32* getelementptr inbounds ([4 x %struct.data]* @table, i32 0, i64 3, i32 1, i32 1) to i64))
|
||||||
@ -58,14 +86,22 @@
|
|||||||
], align 16
|
], align 16
|
||||||
|
|
||||||
; Test multiple uses of GOT equivalents.
|
; Test multiple uses of GOT equivalents.
|
||||||
; CHECK-LABEL: _delta
|
|
||||||
; CHECK: .long _extfoo@GOTPCREL+4
|
; X86-LABEL: _delta
|
||||||
|
; X86: .long _extfoo@GOTPCREL+4
|
||||||
|
|
||||||
|
; ARM-LABEL: _delta
|
||||||
|
; ARM: Ltmp3:
|
||||||
|
; ARM-NEXT: .long _extfoo@GOT-Ltmp3
|
||||||
@delta = global i32 trunc (i64 sub (i64 ptrtoint (i32** @extgotequiv to i64),
|
@delta = global i32 trunc (i64 sub (i64 ptrtoint (i32** @extgotequiv to i64),
|
||||||
i64 ptrtoint (i32* @delta to i64))
|
i64 ptrtoint (i32* @delta to i64))
|
||||||
to i32)
|
to i32)
|
||||||
|
|
||||||
; CHECK-LABEL: _deltaplus:
|
; X86-LABEL: _deltaplus:
|
||||||
; CHECK: .long _localfoo@GOTPCREL+59
|
; X86: .long _localfoo@GOTPCREL+59
|
||||||
|
|
||||||
|
; ARM-LABEL: _deltaplus:
|
||||||
|
; ARM: .long (l_localgotequiv-_deltaplus)+55
|
||||||
@deltaplus = global i32 add (i32 trunc (i64 sub (i64 ptrtoint (i32** @localgotequiv to i64),
|
@deltaplus = global i32 add (i32 trunc (i64 sub (i64 ptrtoint (i32** @localgotequiv to i64),
|
||||||
i64 ptrtoint (i32* @deltaplus to i64))
|
i64 ptrtoint (i32* @deltaplus to i64))
|
||||||
to i32), i32 55)
|
to i32), i32 55)
|
Loading…
x
Reference in New Issue
Block a user