llvm.org GIT mirror llvm / dfc6383
[AsmPrinter][TLOF] 32-bit MachO support for replacing GOT equivalents Add MachO 32-bit (i.e. arm and x86) support for replacing global GOT equivalent symbol accesses. Unlike 64-bit targets, there's no GOTPCREL relocation, and access through a non_lazy_symbol_pointers section is used instead. -- before _extgotequiv: .long _extfoo _delta: .long _extgotequiv-_delta -- after _delta: .long L_extfoo$non_lazy_ptr-_delta .section __IMPORT,__pointers,non_lazy_symbol_pointers L_extfoo$non_lazy_ptr: .indirect_symbol _extfoo .long 0 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231475 91177308-0d34-0410-b5e6-96231b3b80d8 Bruno Cardoso Lopes 5 years ago
9 changed file(s) with 177 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
8787 class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile {
8888 public:
8989 virtual ~TargetLoweringObjectFileMachO() {}
90 TargetLoweringObjectFileMachO();
9091
9192 /// Extract the dependent library name from a linker option string. Returns
9293 /// StringRef() if the option does not specify a library.
121122 MCSymbol *getCFIPersonalitySymbol(const GlobalValue *GV, Mangler &Mang,
122123 const TargetMachine &TM,
123124 MachineModuleInfo *MMI) const override;
125
126 /// Get MachO PC relative GOT entry relocation
127 const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym,
128 const MCValue &MV, int64_t Offset,
129 MachineModuleInfo *MMI,
130 MCStreamer &Streamer) const override;
124131 };
125132
126133
2828 class MCSymbol;
2929 class MCSymbolRefExpr;
3030 class MCStreamer;
31 class MCValue;
3132 class ConstantExpr;
3233 class GlobalValue;
3334 class TargetMachine;
3435
3536 class TargetLoweringObjectFile : public MCObjectFileInfo {
3637 MCContext *Ctx;
37 const DataLayout *DL;
3838
3939 TargetLoweringObjectFile(
4040 const TargetLoweringObjectFile&) = delete;
4141 void operator=(const TargetLoweringObjectFile&) = delete;
4242
4343 protected:
44 const DataLayout *DL;
4445 bool SupportIndirectSymViaGOTPCRel;
4546 bool SupportGOTPCRelWithOffset;
4647
177178
178179 /// \brief Get the target specific PC relative GOT entry relocation
179180 virtual const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym,
181 const MCValue &MV,
180182 int64_t Offset,
183 MachineModuleInfo *MMI,
181184 MCStreamer &Streamer) const {
182185 return nullptr;
183186 }
20832083 //
20842084 // gotpcrelcst := +
20852085 //
2086 // Only encode if the target supports it.
2086 // If gotpcrelcst is positive it means that we can safely fold the pc rel
2087 // displacement into the GOTPCREL. We can also can have an extra offset
2088 // if the target knows how to encode it.
20872089 //
20882090 int64_t GOTPCRelCst = Offset + MV.getConstant();
20892091 if (GOTPCRelCst < 0)
21122114 unsigned NumUses = Result.second;
21132115 const GlobalValue *FinalGV = dyn_cast(GV->getOperand(0));
21142116 const MCSymbol *FinalSym = AP.getSymbol(FinalGV);
2115 *ME = AP.getObjFileLowering().getIndirectSymViaGOTPCRel(FinalSym,
2116 GOTPCRelCst,
2117 AP.OutStreamer);
2117 *ME = AP.getObjFileLowering().getIndirectSymViaGOTPCRel(
2118 FinalSym, MV, Offset, AP.MMI, AP.OutStreamer);
21182119
21192120 // Update GOT equivalent usage information
21202121 --NumUses;
3030 #include "llvm/MC/MCSectionMachO.h"
3131 #include "llvm/MC/MCStreamer.h"
3232 #include "llvm/MC/MCSymbol.h"
33 #include "llvm/MC/MCValue.h"
3334 #include "llvm/Support/Dwarf.h"
3435 #include "llvm/Support/ELF.h"
3536 #include "llvm/Support/ErrorHandling.h"
430431 // MachO
431432 //===----------------------------------------------------------------------===//
432433
434 TargetLoweringObjectFileMachO::TargetLoweringObjectFileMachO()
435 : TargetLoweringObjectFile() {
436 SupportIndirectSymViaGOTPCRel = true;
437 }
438
433439 /// getDepLibFromLinkerOpt - Extract the dependent library name from a linker
434440 /// option string. Returns StringRef() if the option does not specify a library.
435441 StringRef TargetLoweringObjectFileMachO::
702708 }
703709
704710 return SSym;
711 }
712
713 const MCExpr *TargetLoweringObjectFileMachO::getIndirectSymViaGOTPCRel(
714 const MCSymbol *Sym, const MCValue &MV, int64_t Offset,
715 MachineModuleInfo *MMI, MCStreamer &Streamer) const {
716 // Although MachO 32-bit targets do not explictly have a GOTPCREL relocation
717 // as 64-bit do, we replace the GOT equivalent by accessing the final symbol
718 // through a non_lazy_ptr stub instead. One advantage is that it allows the
719 // computation of deltas to final external symbols. Example:
720 //
721 // _extgotequiv:
722 // .long _extfoo
723 //
724 // _delta:
725 // .long _extgotequiv-_delta
726 //
727 // is transformed to:
728 //
729 // _delta:
730 // .long L_extfoo$non_lazy_ptr-(_delta+0)
731 //
732 // .section __IMPORT,__pointers,non_lazy_symbol_pointers
733 // L_extfoo$non_lazy_ptr:
734 // .indirect_symbol _extfoo
735 // .long 0
736 //
737 MachineModuleInfoMachO &MachOMMI =
738 MMI->getObjFileInfo();
739 MCContext &Ctx = getContext();
740
741 // The offset must consider the original displacement from the base symbol
742 // since 32-bit targets don't have a GOTPCREL to fold the PC displacement.
743 Offset = -MV.getConstant();
744 const MCSymbol *BaseSym = &MV.getSymB()->getSymbol();
745
746 // Access the final symbol via sym$non_lazy_ptr and generate the appropriated
747 // non_lazy_ptr stubs.
748 SmallString<128> Name;
749 StringRef Suffix = "$non_lazy_ptr";
750 Name += DL->getPrivateGlobalPrefix();
751 Name += Sym->getName();
752 Name += Suffix;
753 MCSymbol *Stub = Ctx.GetOrCreateSymbol(Name);
754
755 MachineModuleInfoImpl::StubValueTy &StubSym = MachOMMI.getGVStubEntry(Stub);
756 if (!StubSym.getPointer())
757 StubSym = MachineModuleInfoImpl::
758 StubValueTy(const_cast(Sym), true /* access indirectly */);
759
760 const MCExpr *BSymExpr =
761 MCSymbolRefExpr::Create(BaseSym, MCSymbolRefExpr::VK_None, Ctx);
762 const MCExpr *LHS =
763 MCSymbolRefExpr::Create(Stub, MCSymbolRefExpr::VK_None, Ctx);
764
765 if (!Offset)
766 return MCBinaryExpr::CreateSub(LHS, BSymExpr, Ctx);
767
768 const MCExpr *RHS =
769 MCBinaryExpr::CreateAdd(BSymExpr, MCConstantExpr::Create(Offset, Ctx), Ctx);
770 return MCBinaryExpr::CreateSub(LHS, RHS, Ctx);
705771 }
706772
707773 //===----------------------------------------------------------------------===//
1212 #include "llvm/MC/MCContext.h"
1313 #include "llvm/MC/MCExpr.h"
1414 #include "llvm/MC/MCStreamer.h"
15 #include "llvm/MC/MCValue.h"
1516 #include "llvm/Support/Dwarf.h"
1617 using namespace llvm;
1718 using namespace dwarf;
2425
2526 AArch64_MachoTargetObjectFile::AArch64_MachoTargetObjectFile()
2627 : TargetLoweringObjectFileMachO() {
27 SupportIndirectSymViaGOTPCRel = true;
2828 SupportGOTPCRelWithOffset = false;
2929 }
3030
5757 }
5858
5959 const MCExpr *AArch64_MachoTargetObjectFile::getIndirectSymViaGOTPCRel(
60 const MCSymbol *Sym, int64_t Offset, MCStreamer &Streamer) const {
60 const MCSymbol *Sym, const MCValue &MV, int64_t Offset,
61 MachineModuleInfo *MMI, MCStreamer &Streamer) const {
62 assert((Offset+MV.getConstant() == 0) &&
63 "Arch64 does not support GOT PC rel with extra offset");
6164 // On ARM64 Darwin, we can reference symbols with foo@GOT-., which
6265 // is an indirect pc-relative reference.
6366 const MCExpr *Res =
3535 const TargetMachine &TM,
3636 MachineModuleInfo *MMI) const override;
3737
38 const MCExpr *
39 getIndirectSymViaGOTPCRel(const MCSymbol *Sym, int64_t Offset,
40 MCStreamer &Streamer) const override;
38 const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym,
39 const MCValue &MV, int64_t Offset,
40 MachineModuleInfo *MMI,
41 MCStreamer &Streamer) const override;
4142 };
4243
4344 } // end namespace llvm
1414 #include "llvm/MC/MCExpr.h"
1515 #include "llvm/MC/MCSectionCOFF.h"
1616 #include "llvm/MC/MCSectionELF.h"
17 #include "llvm/MC/MCValue.h"
1718 #include "llvm/Support/Dwarf.h"
1819 #include "llvm/Target/TargetLowering.h"
1920
2021 using namespace llvm;
2122 using namespace dwarf;
22
23 X86_64MachoTargetObjectFile::X86_64MachoTargetObjectFile()
24 : TargetLoweringObjectFileMachO() {
25 SupportIndirectSymViaGOTPCRel = true;
26 }
2723
2824 const MCExpr *X86_64MachoTargetObjectFile::getTTypeGlobalReference(
2925 const GlobalValue *GV, unsigned Encoding, Mangler &Mang,
5147 }
5248
5349 const MCExpr *X86_64MachoTargetObjectFile::getIndirectSymViaGOTPCRel(
54 const MCSymbol *Sym, int64_t Offset, MCStreamer &Streamer) const {
50 const MCSymbol *Sym, const MCValue &MV, int64_t Offset,
51 MachineModuleInfo *MMI, MCStreamer &Streamer) const {
5552 // On Darwin/X86-64, we need to use foo@GOTPCREL+4 to access the got entry
5653 // from a data section. In case there's an additional offset, then use
5754 // foo@GOTPCREL+4+.
55 unsigned FinalOff = Offset+MV.getConstant()+4;
5856 const MCExpr *Res =
5957 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_GOTPCREL, getContext());
60 const MCExpr *Off = MCConstantExpr::Create(Offset+4, getContext());
58 const MCExpr *Off = MCConstantExpr::Create(FinalOff, getContext());
6159 return MCBinaryExpr::CreateAdd(Res, Off, getContext());
6260 }
6361
1818 /// x86-64.
1919 class X86_64MachoTargetObjectFile : public TargetLoweringObjectFileMachO {
2020 public:
21 X86_64MachoTargetObjectFile();
22
2321 const MCExpr *
2422 getTTypeGlobalReference(const GlobalValue *GV, unsigned Encoding,
2523 Mangler &Mang, const TargetMachine &TM,
3230 const TargetMachine &TM,
3331 MachineModuleInfo *MMI) const override;
3432
35 const MCExpr *
36 getIndirectSymViaGOTPCRel(const MCSymbol *Sym, int64_t Offset,
37 MCStreamer &Streamer) const override;
33 const MCExpr *getIndirectSymViaGOTPCRel(const MCSymbol *Sym,
34 const MCValue &MV, int64_t Offset,
35 MachineModuleInfo *MMI,
36 MCStreamer &Streamer) const override;
3837 };
3938
4039 /// \brief This implemenatation is used for X86 ELF targets that don't
0 ; RUN: llc -mtriple=i386-apple-darwin %s -o %t
1 ; RUN: FileCheck %s < %t
2 ; RUN: FileCheck %s -check-prefix=GOT-EQUIV < %t
3 ; RUN: llc -mtriple=arm-apple-darwin %s -o %t
4 ; RUN: FileCheck %s < %t
5 ; RUN: FileCheck %s -check-prefix=GOT-EQUIV < %t
6
7 ; GOT equivalent globals references can be replaced by the GOT entry of the
8 ; final symbol instead.
9
10 %struct.data = type { i32, %struct.anon }
11 %struct.anon = type { i32, i32 }
12
13 ; Check that these got equivalent symbols are never emitted or used
14 ; GOT-EQUIV-NOT: _localgotequiv
15 ; GOT-EQUIV-NOT: _extgotequiv
16 @localfoo = global i32 42
17 @localgotequiv = private unnamed_addr constant i32* @localfoo
18
19 @extfoo = external global i32
20 @extgotequiv = private unnamed_addr constant i32* @extfoo
21
22 ; Don't replace GOT equivalent usage within instructions and emit the GOT
23 ; equivalent since it can't be replaced by the GOT entry. @bargotequiv is
24 ; used by an instruction inside @t0.
25 ;
26 ; CHECK: l_bargotequiv:
27 ; CHECK-NEXT: .long _extbar
28 @extbar = external global i32
29 @bargotequiv = private unnamed_addr constant i32* @extbar
30
31 @table = global [4 x %struct.data] [
32 ; CHECK-LABEL: _table
33 %struct.data { i32 1, %struct.anon { i32 2, i32 3 } },
34 ; Test GOT equivalent usage inside nested constant arrays.
35 ; CHECK: .long 5
36 ; CHECK-NOT: l_localgotequiv-(_table+20)
37 ; CHECK-NEXT: L_localfoo$non_lazy_ptr-(_table+20)
38 %struct.data { i32 4, %struct.anon { i32 5,
39 i32 sub (i32 ptrtoint (i32** @localgotequiv to i32),
40 i32 ptrtoint (i32* getelementptr inbounds ([4 x %struct.data]* @table, i32 0, i32 1, i32 1, i32 1) to i32))}
41 },
42 ; CHECK: .long 5
43 ; CHECK-NOT: l_extgotequiv-(_table+32)
44 ; CHECK-NEXT: L_extfoo$non_lazy_ptr-(_table+32)
45 %struct.data { i32 4, %struct.anon { i32 5,
46 i32 sub (i32 ptrtoint (i32** @extgotequiv to i32),
47 i32 ptrtoint (i32* getelementptr inbounds ([4 x %struct.data]* @table, i32 0, i32 2, i32 1, i32 1) to i32))}
48 },
49 ; Test support for arbitrary constants into the GOTPCREL offset
50 ; CHECK: .long 5
51 ; CHECK-NOT: (l_extgotequiv-(_table+44))+24
52 ; CHECK-NEXT: L_extfoo$non_lazy_ptr-(_table+20)
53 %struct.data { i32 4, %struct.anon { i32 5,
54 i32 add (i32 sub (i32 ptrtoint (i32** @extgotequiv to i32),
55 i32 ptrtoint (i32* getelementptr inbounds ([4 x %struct.data]* @table, i32 0, i32 3, i32 1, i32 1) to i32)),
56 i32 24)}
57 }
58 ], align 16
59
60 ; Test multiple uses of GOT equivalents.
61 ; CHECK-LABEL: _delta
62 ; CHECK: .long L_extfoo$non_lazy_ptr-_delta
63 @delta = global i32 sub (i32 ptrtoint (i32** @extgotequiv to i32),
64 i32 ptrtoint (i32* @delta to i32))
65
66 ; CHECK-LABEL: _deltaplus:
67 ; CHECK: .long L_localfoo$non_lazy_ptr-(_deltaplus-55)
68 @deltaplus = global i32 add (i32 sub (i32 ptrtoint (i32** @localgotequiv to i32),
69 i32 ptrtoint (i32* @deltaplus to i32)),
70 i32 55)
71
72 define i32 @t0(i32 %a) {
73 %x = add i32 sub (i32 ptrtoint (i32** @bargotequiv to i32),
74 i32 ptrtoint (i32 (i32)* @t0 to i32)), %a
75 ret i32 %x
76 }