xref: /aosp_15_r20/external/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MachObjectWriter.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- AArch64MachObjectWriter.cpp - ARM Mach Object Writer --------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/AArch64FixupKinds.h"
11*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/AArch64MCTargetDesc.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Twine.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmInfo.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmLayout.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAssembler.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCFixup.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCMachObjectWriter.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSectionMachO.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCValue.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MachO.h"
24*9880d681SAndroid Build Coastguard Worker using namespace llvm;
25*9880d681SAndroid Build Coastguard Worker 
26*9880d681SAndroid Build Coastguard Worker namespace {
27*9880d681SAndroid Build Coastguard Worker class AArch64MachObjectWriter : public MCMachObjectTargetWriter {
28*9880d681SAndroid Build Coastguard Worker   bool getAArch64FixupKindMachOInfo(const MCFixup &Fixup, unsigned &RelocType,
29*9880d681SAndroid Build Coastguard Worker                                   const MCSymbolRefExpr *Sym,
30*9880d681SAndroid Build Coastguard Worker                                   unsigned &Log2Size, const MCAssembler &Asm);
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker public:
AArch64MachObjectWriter(uint32_t CPUType,uint32_t CPUSubtype)33*9880d681SAndroid Build Coastguard Worker   AArch64MachObjectWriter(uint32_t CPUType, uint32_t CPUSubtype)
34*9880d681SAndroid Build Coastguard Worker       : MCMachObjectTargetWriter(true /* is64Bit */, CPUType, CPUSubtype) {}
35*9880d681SAndroid Build Coastguard Worker 
36*9880d681SAndroid Build Coastguard Worker   void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
37*9880d681SAndroid Build Coastguard Worker                         const MCAsmLayout &Layout, const MCFragment *Fragment,
38*9880d681SAndroid Build Coastguard Worker                         const MCFixup &Fixup, MCValue Target,
39*9880d681SAndroid Build Coastguard Worker                         uint64_t &FixedValue) override;
40*9880d681SAndroid Build Coastguard Worker };
41*9880d681SAndroid Build Coastguard Worker }
42*9880d681SAndroid Build Coastguard Worker 
getAArch64FixupKindMachOInfo(const MCFixup & Fixup,unsigned & RelocType,const MCSymbolRefExpr * Sym,unsigned & Log2Size,const MCAssembler & Asm)43*9880d681SAndroid Build Coastguard Worker bool AArch64MachObjectWriter::getAArch64FixupKindMachOInfo(
44*9880d681SAndroid Build Coastguard Worker     const MCFixup &Fixup, unsigned &RelocType, const MCSymbolRefExpr *Sym,
45*9880d681SAndroid Build Coastguard Worker     unsigned &Log2Size, const MCAssembler &Asm) {
46*9880d681SAndroid Build Coastguard Worker   RelocType = unsigned(MachO::ARM64_RELOC_UNSIGNED);
47*9880d681SAndroid Build Coastguard Worker   Log2Size = ~0U;
48*9880d681SAndroid Build Coastguard Worker 
49*9880d681SAndroid Build Coastguard Worker   switch ((unsigned)Fixup.getKind()) {
50*9880d681SAndroid Build Coastguard Worker   default:
51*9880d681SAndroid Build Coastguard Worker     return false;
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker   case FK_Data_1:
54*9880d681SAndroid Build Coastguard Worker     Log2Size = llvm::Log2_32(1);
55*9880d681SAndroid Build Coastguard Worker     return true;
56*9880d681SAndroid Build Coastguard Worker   case FK_Data_2:
57*9880d681SAndroid Build Coastguard Worker     Log2Size = llvm::Log2_32(2);
58*9880d681SAndroid Build Coastguard Worker     return true;
59*9880d681SAndroid Build Coastguard Worker   case FK_Data_4:
60*9880d681SAndroid Build Coastguard Worker     Log2Size = llvm::Log2_32(4);
61*9880d681SAndroid Build Coastguard Worker     if (Sym->getKind() == MCSymbolRefExpr::VK_GOT)
62*9880d681SAndroid Build Coastguard Worker       RelocType = unsigned(MachO::ARM64_RELOC_POINTER_TO_GOT);
63*9880d681SAndroid Build Coastguard Worker     return true;
64*9880d681SAndroid Build Coastguard Worker   case FK_Data_8:
65*9880d681SAndroid Build Coastguard Worker     Log2Size = llvm::Log2_32(8);
66*9880d681SAndroid Build Coastguard Worker     if (Sym->getKind() == MCSymbolRefExpr::VK_GOT)
67*9880d681SAndroid Build Coastguard Worker       RelocType = unsigned(MachO::ARM64_RELOC_POINTER_TO_GOT);
68*9880d681SAndroid Build Coastguard Worker     return true;
69*9880d681SAndroid Build Coastguard Worker   case AArch64::fixup_aarch64_add_imm12:
70*9880d681SAndroid Build Coastguard Worker   case AArch64::fixup_aarch64_ldst_imm12_scale1:
71*9880d681SAndroid Build Coastguard Worker   case AArch64::fixup_aarch64_ldst_imm12_scale2:
72*9880d681SAndroid Build Coastguard Worker   case AArch64::fixup_aarch64_ldst_imm12_scale4:
73*9880d681SAndroid Build Coastguard Worker   case AArch64::fixup_aarch64_ldst_imm12_scale8:
74*9880d681SAndroid Build Coastguard Worker   case AArch64::fixup_aarch64_ldst_imm12_scale16:
75*9880d681SAndroid Build Coastguard Worker     Log2Size = llvm::Log2_32(4);
76*9880d681SAndroid Build Coastguard Worker     switch (Sym->getKind()) {
77*9880d681SAndroid Build Coastguard Worker     default:
78*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Unexpected symbol reference variant kind!");
79*9880d681SAndroid Build Coastguard Worker     case MCSymbolRefExpr::VK_PAGEOFF:
80*9880d681SAndroid Build Coastguard Worker       RelocType = unsigned(MachO::ARM64_RELOC_PAGEOFF12);
81*9880d681SAndroid Build Coastguard Worker       return true;
82*9880d681SAndroid Build Coastguard Worker     case MCSymbolRefExpr::VK_GOTPAGEOFF:
83*9880d681SAndroid Build Coastguard Worker       RelocType = unsigned(MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12);
84*9880d681SAndroid Build Coastguard Worker       return true;
85*9880d681SAndroid Build Coastguard Worker     case MCSymbolRefExpr::VK_TLVPPAGEOFF:
86*9880d681SAndroid Build Coastguard Worker       RelocType = unsigned(MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12);
87*9880d681SAndroid Build Coastguard Worker       return true;
88*9880d681SAndroid Build Coastguard Worker     }
89*9880d681SAndroid Build Coastguard Worker   case AArch64::fixup_aarch64_pcrel_adrp_imm21:
90*9880d681SAndroid Build Coastguard Worker     Log2Size = llvm::Log2_32(4);
91*9880d681SAndroid Build Coastguard Worker     // This encompasses the relocation for the whole 21-bit value.
92*9880d681SAndroid Build Coastguard Worker     switch (Sym->getKind()) {
93*9880d681SAndroid Build Coastguard Worker     default: {
94*9880d681SAndroid Build Coastguard Worker       Asm.getContext().reportError(Fixup.getLoc(),
95*9880d681SAndroid Build Coastguard Worker                                    "ADR/ADRP relocations must be GOT relative");
96*9880d681SAndroid Build Coastguard Worker       return false;
97*9880d681SAndroid Build Coastguard Worker     }
98*9880d681SAndroid Build Coastguard Worker     case MCSymbolRefExpr::VK_PAGE:
99*9880d681SAndroid Build Coastguard Worker       RelocType = unsigned(MachO::ARM64_RELOC_PAGE21);
100*9880d681SAndroid Build Coastguard Worker       return true;
101*9880d681SAndroid Build Coastguard Worker     case MCSymbolRefExpr::VK_GOTPAGE:
102*9880d681SAndroid Build Coastguard Worker       RelocType = unsigned(MachO::ARM64_RELOC_GOT_LOAD_PAGE21);
103*9880d681SAndroid Build Coastguard Worker       return true;
104*9880d681SAndroid Build Coastguard Worker     case MCSymbolRefExpr::VK_TLVPPAGE:
105*9880d681SAndroid Build Coastguard Worker       RelocType = unsigned(MachO::ARM64_RELOC_TLVP_LOAD_PAGE21);
106*9880d681SAndroid Build Coastguard Worker       return true;
107*9880d681SAndroid Build Coastguard Worker     }
108*9880d681SAndroid Build Coastguard Worker     return true;
109*9880d681SAndroid Build Coastguard Worker   case AArch64::fixup_aarch64_pcrel_branch26:
110*9880d681SAndroid Build Coastguard Worker   case AArch64::fixup_aarch64_pcrel_call26:
111*9880d681SAndroid Build Coastguard Worker     Log2Size = llvm::Log2_32(4);
112*9880d681SAndroid Build Coastguard Worker     RelocType = unsigned(MachO::ARM64_RELOC_BRANCH26);
113*9880d681SAndroid Build Coastguard Worker     return true;
114*9880d681SAndroid Build Coastguard Worker   }
115*9880d681SAndroid Build Coastguard Worker }
116*9880d681SAndroid Build Coastguard Worker 
canUseLocalRelocation(const MCSectionMachO & Section,const MCSymbol & Symbol,unsigned Log2Size)117*9880d681SAndroid Build Coastguard Worker static bool canUseLocalRelocation(const MCSectionMachO &Section,
118*9880d681SAndroid Build Coastguard Worker                                   const MCSymbol &Symbol, unsigned Log2Size) {
119*9880d681SAndroid Build Coastguard Worker   // Debug info sections can use local relocations.
120*9880d681SAndroid Build Coastguard Worker   if (Section.hasAttribute(MachO::S_ATTR_DEBUG))
121*9880d681SAndroid Build Coastguard Worker     return true;
122*9880d681SAndroid Build Coastguard Worker 
123*9880d681SAndroid Build Coastguard Worker   // Otherwise, only pointer sized relocations are supported.
124*9880d681SAndroid Build Coastguard Worker   if (Log2Size != 3)
125*9880d681SAndroid Build Coastguard Worker     return false;
126*9880d681SAndroid Build Coastguard Worker 
127*9880d681SAndroid Build Coastguard Worker   // But only if they don't point to a few forbidden sections.
128*9880d681SAndroid Build Coastguard Worker   if (!Symbol.isInSection())
129*9880d681SAndroid Build Coastguard Worker     return true;
130*9880d681SAndroid Build Coastguard Worker   const MCSectionMachO &RefSec = cast<MCSectionMachO>(Symbol.getSection());
131*9880d681SAndroid Build Coastguard Worker   if (RefSec.getType() == MachO::S_CSTRING_LITERALS)
132*9880d681SAndroid Build Coastguard Worker     return false;
133*9880d681SAndroid Build Coastguard Worker 
134*9880d681SAndroid Build Coastguard Worker   if (RefSec.getSegmentName() == "__DATA" &&
135*9880d681SAndroid Build Coastguard Worker       RefSec.getSectionName() == "__objc_classrefs")
136*9880d681SAndroid Build Coastguard Worker     return false;
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker   // FIXME: ld64 currently handles internal pointer-sized relocations
139*9880d681SAndroid Build Coastguard Worker   // incorrectly (applying the addend twice). We should be able to return true
140*9880d681SAndroid Build Coastguard Worker   // unconditionally by this point when that's fixed.
141*9880d681SAndroid Build Coastguard Worker   return false;
142*9880d681SAndroid Build Coastguard Worker }
143*9880d681SAndroid Build Coastguard Worker 
recordRelocation(MachObjectWriter * Writer,MCAssembler & Asm,const MCAsmLayout & Layout,const MCFragment * Fragment,const MCFixup & Fixup,MCValue Target,uint64_t & FixedValue)144*9880d681SAndroid Build Coastguard Worker void AArch64MachObjectWriter::recordRelocation(
145*9880d681SAndroid Build Coastguard Worker     MachObjectWriter *Writer, MCAssembler &Asm, const MCAsmLayout &Layout,
146*9880d681SAndroid Build Coastguard Worker     const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
147*9880d681SAndroid Build Coastguard Worker     uint64_t &FixedValue) {
148*9880d681SAndroid Build Coastguard Worker   unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind());
149*9880d681SAndroid Build Coastguard Worker 
150*9880d681SAndroid Build Coastguard Worker   // See <reloc.h>.
151*9880d681SAndroid Build Coastguard Worker   uint32_t FixupOffset = Layout.getFragmentOffset(Fragment);
152*9880d681SAndroid Build Coastguard Worker   unsigned Log2Size = 0;
153*9880d681SAndroid Build Coastguard Worker   int64_t Value = 0;
154*9880d681SAndroid Build Coastguard Worker   unsigned Index = 0;
155*9880d681SAndroid Build Coastguard Worker   unsigned Type = 0;
156*9880d681SAndroid Build Coastguard Worker   unsigned Kind = Fixup.getKind();
157*9880d681SAndroid Build Coastguard Worker   const MCSymbol *RelSymbol = nullptr;
158*9880d681SAndroid Build Coastguard Worker 
159*9880d681SAndroid Build Coastguard Worker   FixupOffset += Fixup.getOffset();
160*9880d681SAndroid Build Coastguard Worker 
161*9880d681SAndroid Build Coastguard Worker   // AArch64 pcrel relocation addends do not include the section offset.
162*9880d681SAndroid Build Coastguard Worker   if (IsPCRel)
163*9880d681SAndroid Build Coastguard Worker     FixedValue += FixupOffset;
164*9880d681SAndroid Build Coastguard Worker 
165*9880d681SAndroid Build Coastguard Worker   // ADRP fixups use relocations for the whole symbol value and only
166*9880d681SAndroid Build Coastguard Worker   // put the addend in the instruction itself. Clear out any value the
167*9880d681SAndroid Build Coastguard Worker   // generic code figured out from the sybmol definition.
168*9880d681SAndroid Build Coastguard Worker   if (Kind == AArch64::fixup_aarch64_pcrel_adrp_imm21)
169*9880d681SAndroid Build Coastguard Worker     FixedValue = 0;
170*9880d681SAndroid Build Coastguard Worker 
171*9880d681SAndroid Build Coastguard Worker   // imm19 relocations are for conditional branches, which require
172*9880d681SAndroid Build Coastguard Worker   // assembler local symbols. If we got here, that's not what we have,
173*9880d681SAndroid Build Coastguard Worker   // so complain loudly.
174*9880d681SAndroid Build Coastguard Worker   if (Kind == AArch64::fixup_aarch64_pcrel_branch19) {
175*9880d681SAndroid Build Coastguard Worker     Asm.getContext().reportError(Fixup.getLoc(),
176*9880d681SAndroid Build Coastguard Worker                                  "conditional branch requires assembler-local"
177*9880d681SAndroid Build Coastguard Worker                                  " label. '" +
178*9880d681SAndroid Build Coastguard Worker                                      Target.getSymA()->getSymbol().getName() +
179*9880d681SAndroid Build Coastguard Worker                                      "' is external.");
180*9880d681SAndroid Build Coastguard Worker     return;
181*9880d681SAndroid Build Coastguard Worker   }
182*9880d681SAndroid Build Coastguard Worker 
183*9880d681SAndroid Build Coastguard Worker   // 14-bit branch relocations should only target internal labels, and so
184*9880d681SAndroid Build Coastguard Worker   // should never get here.
185*9880d681SAndroid Build Coastguard Worker   if (Kind == AArch64::fixup_aarch64_pcrel_branch14) {
186*9880d681SAndroid Build Coastguard Worker     Asm.getContext().reportError(Fixup.getLoc(),
187*9880d681SAndroid Build Coastguard Worker                                  "Invalid relocation on conditional branch!");
188*9880d681SAndroid Build Coastguard Worker     return;
189*9880d681SAndroid Build Coastguard Worker   }
190*9880d681SAndroid Build Coastguard Worker 
191*9880d681SAndroid Build Coastguard Worker   if (!getAArch64FixupKindMachOInfo(Fixup, Type, Target.getSymA(), Log2Size,
192*9880d681SAndroid Build Coastguard Worker                                     Asm)) {
193*9880d681SAndroid Build Coastguard Worker     Asm.getContext().reportError(Fixup.getLoc(), "unknown AArch64 fixup kind!");
194*9880d681SAndroid Build Coastguard Worker     return;
195*9880d681SAndroid Build Coastguard Worker   }
196*9880d681SAndroid Build Coastguard Worker 
197*9880d681SAndroid Build Coastguard Worker   Value = Target.getConstant();
198*9880d681SAndroid Build Coastguard Worker 
199*9880d681SAndroid Build Coastguard Worker   if (Target.isAbsolute()) { // constant
200*9880d681SAndroid Build Coastguard Worker     // FIXME: Should this always be extern?
201*9880d681SAndroid Build Coastguard Worker     // SymbolNum of 0 indicates the absolute section.
202*9880d681SAndroid Build Coastguard Worker     Type = MachO::ARM64_RELOC_UNSIGNED;
203*9880d681SAndroid Build Coastguard Worker 
204*9880d681SAndroid Build Coastguard Worker     if (IsPCRel) {
205*9880d681SAndroid Build Coastguard Worker       Asm.getContext().reportError(Fixup.getLoc(),
206*9880d681SAndroid Build Coastguard Worker                                    "PC relative absolute relocation!");
207*9880d681SAndroid Build Coastguard Worker       return;
208*9880d681SAndroid Build Coastguard Worker 
209*9880d681SAndroid Build Coastguard Worker       // FIXME: x86_64 sets the type to a branch reloc here. Should we do
210*9880d681SAndroid Build Coastguard Worker       // something similar?
211*9880d681SAndroid Build Coastguard Worker     }
212*9880d681SAndroid Build Coastguard Worker   } else if (Target.getSymB()) { // A - B + constant
213*9880d681SAndroid Build Coastguard Worker     const MCSymbol *A = &Target.getSymA()->getSymbol();
214*9880d681SAndroid Build Coastguard Worker     const MCSymbol *A_Base = Asm.getAtom(*A);
215*9880d681SAndroid Build Coastguard Worker 
216*9880d681SAndroid Build Coastguard Worker     const MCSymbol *B = &Target.getSymB()->getSymbol();
217*9880d681SAndroid Build Coastguard Worker     const MCSymbol *B_Base = Asm.getAtom(*B);
218*9880d681SAndroid Build Coastguard Worker 
219*9880d681SAndroid Build Coastguard Worker     // Check for "_foo@got - .", which comes through here as:
220*9880d681SAndroid Build Coastguard Worker     // Ltmp0:
221*9880d681SAndroid Build Coastguard Worker     //    ... _foo@got - Ltmp0
222*9880d681SAndroid Build Coastguard Worker     if (Target.getSymA()->getKind() == MCSymbolRefExpr::VK_GOT &&
223*9880d681SAndroid Build Coastguard Worker         Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None &&
224*9880d681SAndroid Build Coastguard Worker         Layout.getSymbolOffset(*B) ==
225*9880d681SAndroid Build Coastguard Worker             Layout.getFragmentOffset(Fragment) + Fixup.getOffset()) {
226*9880d681SAndroid Build Coastguard Worker       // SymB is the PC, so use a PC-rel pointer-to-GOT relocation.
227*9880d681SAndroid Build Coastguard Worker       Type = MachO::ARM64_RELOC_POINTER_TO_GOT;
228*9880d681SAndroid Build Coastguard Worker       IsPCRel = 1;
229*9880d681SAndroid Build Coastguard Worker       MachO::any_relocation_info MRE;
230*9880d681SAndroid Build Coastguard Worker       MRE.r_word0 = FixupOffset;
231*9880d681SAndroid Build Coastguard Worker       MRE.r_word1 = (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
232*9880d681SAndroid Build Coastguard Worker       Writer->addRelocation(A_Base, Fragment->getParent(), MRE);
233*9880d681SAndroid Build Coastguard Worker       return;
234*9880d681SAndroid Build Coastguard Worker     } else if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
235*9880d681SAndroid Build Coastguard Worker                Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None) {
236*9880d681SAndroid Build Coastguard Worker       // Otherwise, neither symbol can be modified.
237*9880d681SAndroid Build Coastguard Worker       Asm.getContext().reportError(Fixup.getLoc(),
238*9880d681SAndroid Build Coastguard Worker                                    "unsupported relocation of modified symbol");
239*9880d681SAndroid Build Coastguard Worker       return;
240*9880d681SAndroid Build Coastguard Worker     }
241*9880d681SAndroid Build Coastguard Worker 
242*9880d681SAndroid Build Coastguard Worker     // We don't support PCrel relocations of differences.
243*9880d681SAndroid Build Coastguard Worker     if (IsPCRel) {
244*9880d681SAndroid Build Coastguard Worker       Asm.getContext().reportError(Fixup.getLoc(),
245*9880d681SAndroid Build Coastguard Worker                                    "unsupported pc-relative relocation of "
246*9880d681SAndroid Build Coastguard Worker                                    "difference");
247*9880d681SAndroid Build Coastguard Worker       return;
248*9880d681SAndroid Build Coastguard Worker     }
249*9880d681SAndroid Build Coastguard Worker 
250*9880d681SAndroid Build Coastguard Worker     // AArch64 always uses external relocations. If there is no symbol to use as
251*9880d681SAndroid Build Coastguard Worker     // a base address (a local symbol with no preceding non-local symbol),
252*9880d681SAndroid Build Coastguard Worker     // error out.
253*9880d681SAndroid Build Coastguard Worker     //
254*9880d681SAndroid Build Coastguard Worker     // FIXME: We should probably just synthesize an external symbol and use
255*9880d681SAndroid Build Coastguard Worker     // that.
256*9880d681SAndroid Build Coastguard Worker     if (!A_Base) {
257*9880d681SAndroid Build Coastguard Worker       Asm.getContext().reportError(
258*9880d681SAndroid Build Coastguard Worker           Fixup.getLoc(),
259*9880d681SAndroid Build Coastguard Worker           "unsupported relocation of local symbol '" + A->getName() +
260*9880d681SAndroid Build Coastguard Worker               "'. Must have non-local symbol earlier in section.");
261*9880d681SAndroid Build Coastguard Worker       return;
262*9880d681SAndroid Build Coastguard Worker     }
263*9880d681SAndroid Build Coastguard Worker     if (!B_Base) {
264*9880d681SAndroid Build Coastguard Worker       Asm.getContext().reportError(
265*9880d681SAndroid Build Coastguard Worker           Fixup.getLoc(),
266*9880d681SAndroid Build Coastguard Worker           "unsupported relocation of local symbol '" + B->getName() +
267*9880d681SAndroid Build Coastguard Worker               "'. Must have non-local symbol earlier in section.");
268*9880d681SAndroid Build Coastguard Worker       return;
269*9880d681SAndroid Build Coastguard Worker     }
270*9880d681SAndroid Build Coastguard Worker 
271*9880d681SAndroid Build Coastguard Worker     if (A_Base == B_Base && A_Base) {
272*9880d681SAndroid Build Coastguard Worker       Asm.getContext().reportError(
273*9880d681SAndroid Build Coastguard Worker           Fixup.getLoc(), "unsupported relocation with identical base");
274*9880d681SAndroid Build Coastguard Worker       return;
275*9880d681SAndroid Build Coastguard Worker     }
276*9880d681SAndroid Build Coastguard Worker 
277*9880d681SAndroid Build Coastguard Worker     Value += (!A->getFragment() ? 0 : Writer->getSymbolAddress(*A, Layout)) -
278*9880d681SAndroid Build Coastguard Worker              (!A_Base || !A_Base->getFragment() ? 0 : Writer->getSymbolAddress(
279*9880d681SAndroid Build Coastguard Worker                                                           *A_Base, Layout));
280*9880d681SAndroid Build Coastguard Worker     Value -= (!B->getFragment() ? 0 : Writer->getSymbolAddress(*B, Layout)) -
281*9880d681SAndroid Build Coastguard Worker              (!B_Base || !B_Base->getFragment() ? 0 : Writer->getSymbolAddress(
282*9880d681SAndroid Build Coastguard Worker                                                           *B_Base, Layout));
283*9880d681SAndroid Build Coastguard Worker 
284*9880d681SAndroid Build Coastguard Worker     Type = MachO::ARM64_RELOC_UNSIGNED;
285*9880d681SAndroid Build Coastguard Worker 
286*9880d681SAndroid Build Coastguard Worker     MachO::any_relocation_info MRE;
287*9880d681SAndroid Build Coastguard Worker     MRE.r_word0 = FixupOffset;
288*9880d681SAndroid Build Coastguard Worker     MRE.r_word1 = (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
289*9880d681SAndroid Build Coastguard Worker     Writer->addRelocation(A_Base, Fragment->getParent(), MRE);
290*9880d681SAndroid Build Coastguard Worker 
291*9880d681SAndroid Build Coastguard Worker     RelSymbol = B_Base;
292*9880d681SAndroid Build Coastguard Worker     Type = MachO::ARM64_RELOC_SUBTRACTOR;
293*9880d681SAndroid Build Coastguard Worker   } else { // A + constant
294*9880d681SAndroid Build Coastguard Worker     const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
295*9880d681SAndroid Build Coastguard Worker     const MCSectionMachO &Section =
296*9880d681SAndroid Build Coastguard Worker         static_cast<const MCSectionMachO &>(*Fragment->getParent());
297*9880d681SAndroid Build Coastguard Worker 
298*9880d681SAndroid Build Coastguard Worker     bool CanUseLocalRelocation =
299*9880d681SAndroid Build Coastguard Worker         canUseLocalRelocation(Section, *Symbol, Log2Size);
300*9880d681SAndroid Build Coastguard Worker     if (Symbol->isTemporary() && (Value || !CanUseLocalRelocation)) {
301*9880d681SAndroid Build Coastguard Worker       const MCSection &Sec = Symbol->getSection();
302*9880d681SAndroid Build Coastguard Worker       if (!Asm.getContext().getAsmInfo()->isSectionAtomizableBySymbols(Sec))
303*9880d681SAndroid Build Coastguard Worker         Symbol->setUsedInReloc();
304*9880d681SAndroid Build Coastguard Worker     }
305*9880d681SAndroid Build Coastguard Worker 
306*9880d681SAndroid Build Coastguard Worker     const MCSymbol *Base = Asm.getAtom(*Symbol);
307*9880d681SAndroid Build Coastguard Worker 
308*9880d681SAndroid Build Coastguard Worker     // If the symbol is a variable and we weren't able to get a Base for it
309*9880d681SAndroid Build Coastguard Worker     // (i.e., it's not in the symbol table associated with a section) resolve
310*9880d681SAndroid Build Coastguard Worker     // the relocation based its expansion instead.
311*9880d681SAndroid Build Coastguard Worker     if (Symbol->isVariable() && !Base) {
312*9880d681SAndroid Build Coastguard Worker       // If the evaluation is an absolute value, just use that directly
313*9880d681SAndroid Build Coastguard Worker       // to keep things easy.
314*9880d681SAndroid Build Coastguard Worker       int64_t Res;
315*9880d681SAndroid Build Coastguard Worker       if (Symbol->getVariableValue()->evaluateAsAbsolute(
316*9880d681SAndroid Build Coastguard Worker               Res, Layout, Writer->getSectionAddressMap())) {
317*9880d681SAndroid Build Coastguard Worker         FixedValue = Res;
318*9880d681SAndroid Build Coastguard Worker         return;
319*9880d681SAndroid Build Coastguard Worker       }
320*9880d681SAndroid Build Coastguard Worker 
321*9880d681SAndroid Build Coastguard Worker       // FIXME: Will the Target we already have ever have any data in it
322*9880d681SAndroid Build Coastguard Worker       // we need to preserve and merge with the new Target? How about
323*9880d681SAndroid Build Coastguard Worker       // the FixedValue?
324*9880d681SAndroid Build Coastguard Worker       if (!Symbol->getVariableValue()->evaluateAsRelocatable(Target, &Layout,
325*9880d681SAndroid Build Coastguard Worker                                                              &Fixup)) {
326*9880d681SAndroid Build Coastguard Worker         Asm.getContext().reportError(Fixup.getLoc(),
327*9880d681SAndroid Build Coastguard Worker                                      "unable to resolve variable '" +
328*9880d681SAndroid Build Coastguard Worker                                          Symbol->getName() + "'");
329*9880d681SAndroid Build Coastguard Worker         return;
330*9880d681SAndroid Build Coastguard Worker       }
331*9880d681SAndroid Build Coastguard Worker       return recordRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
332*9880d681SAndroid Build Coastguard Worker                               FixedValue);
333*9880d681SAndroid Build Coastguard Worker     }
334*9880d681SAndroid Build Coastguard Worker 
335*9880d681SAndroid Build Coastguard Worker     // Relocations inside debug sections always use local relocations when
336*9880d681SAndroid Build Coastguard Worker     // possible. This seems to be done because the debugger doesn't fully
337*9880d681SAndroid Build Coastguard Worker     // understand relocation entries and expects to find values that
338*9880d681SAndroid Build Coastguard Worker     // have already been fixed up.
339*9880d681SAndroid Build Coastguard Worker     if (Symbol->isInSection()) {
340*9880d681SAndroid Build Coastguard Worker       if (Section.hasAttribute(MachO::S_ATTR_DEBUG))
341*9880d681SAndroid Build Coastguard Worker         Base = nullptr;
342*9880d681SAndroid Build Coastguard Worker     }
343*9880d681SAndroid Build Coastguard Worker 
344*9880d681SAndroid Build Coastguard Worker     // AArch64 uses external relocations as much as possible. For debug
345*9880d681SAndroid Build Coastguard Worker     // sections, and for pointer-sized relocations (.quad), we allow section
346*9880d681SAndroid Build Coastguard Worker     // relocations.  It's code sections that run into trouble.
347*9880d681SAndroid Build Coastguard Worker     if (Base) {
348*9880d681SAndroid Build Coastguard Worker       RelSymbol = Base;
349*9880d681SAndroid Build Coastguard Worker 
350*9880d681SAndroid Build Coastguard Worker       // Add the local offset, if needed.
351*9880d681SAndroid Build Coastguard Worker       if (Base != Symbol)
352*9880d681SAndroid Build Coastguard Worker         Value +=
353*9880d681SAndroid Build Coastguard Worker             Layout.getSymbolOffset(*Symbol) - Layout.getSymbolOffset(*Base);
354*9880d681SAndroid Build Coastguard Worker     } else if (Symbol->isInSection()) {
355*9880d681SAndroid Build Coastguard Worker       if (!CanUseLocalRelocation) {
356*9880d681SAndroid Build Coastguard Worker         Asm.getContext().reportError(
357*9880d681SAndroid Build Coastguard Worker             Fixup.getLoc(),
358*9880d681SAndroid Build Coastguard Worker             "unsupported relocation of local symbol '" + Symbol->getName() +
359*9880d681SAndroid Build Coastguard Worker                 "'. Must have non-local symbol earlier in section.");
360*9880d681SAndroid Build Coastguard Worker         return;
361*9880d681SAndroid Build Coastguard Worker       }
362*9880d681SAndroid Build Coastguard Worker       // Adjust the relocation to be section-relative.
363*9880d681SAndroid Build Coastguard Worker       // The index is the section ordinal (1-based).
364*9880d681SAndroid Build Coastguard Worker       const MCSection &Sec = Symbol->getSection();
365*9880d681SAndroid Build Coastguard Worker       Index = Sec.getOrdinal() + 1;
366*9880d681SAndroid Build Coastguard Worker       Value += Writer->getSymbolAddress(*Symbol, Layout);
367*9880d681SAndroid Build Coastguard Worker 
368*9880d681SAndroid Build Coastguard Worker       if (IsPCRel)
369*9880d681SAndroid Build Coastguard Worker         Value -= Writer->getFragmentAddress(Fragment, Layout) +
370*9880d681SAndroid Build Coastguard Worker                  Fixup.getOffset() + (1ULL << Log2Size);
371*9880d681SAndroid Build Coastguard Worker     } else {
372*9880d681SAndroid Build Coastguard Worker       // Resolve constant variables.
373*9880d681SAndroid Build Coastguard Worker       if (Symbol->isVariable()) {
374*9880d681SAndroid Build Coastguard Worker         int64_t Res;
375*9880d681SAndroid Build Coastguard Worker         if (Symbol->getVariableValue()->evaluateAsAbsolute(
376*9880d681SAndroid Build Coastguard Worker                 Res, Layout, Writer->getSectionAddressMap())) {
377*9880d681SAndroid Build Coastguard Worker           FixedValue = Res;
378*9880d681SAndroid Build Coastguard Worker           return;
379*9880d681SAndroid Build Coastguard Worker         }
380*9880d681SAndroid Build Coastguard Worker       }
381*9880d681SAndroid Build Coastguard Worker       Asm.getContext().reportError(Fixup.getLoc(),
382*9880d681SAndroid Build Coastguard Worker                                   "unsupported relocation of variable '" +
383*9880d681SAndroid Build Coastguard Worker                                       Symbol->getName() + "'");
384*9880d681SAndroid Build Coastguard Worker       return;
385*9880d681SAndroid Build Coastguard Worker     }
386*9880d681SAndroid Build Coastguard Worker   }
387*9880d681SAndroid Build Coastguard Worker 
388*9880d681SAndroid Build Coastguard Worker   // If the relocation kind is Branch26, Page21, or Pageoff12, any addend
389*9880d681SAndroid Build Coastguard Worker   // is represented via an Addend relocation, not encoded directly into
390*9880d681SAndroid Build Coastguard Worker   // the instruction.
391*9880d681SAndroid Build Coastguard Worker   if ((Type == MachO::ARM64_RELOC_BRANCH26 ||
392*9880d681SAndroid Build Coastguard Worker        Type == MachO::ARM64_RELOC_PAGE21 ||
393*9880d681SAndroid Build Coastguard Worker        Type == MachO::ARM64_RELOC_PAGEOFF12) &&
394*9880d681SAndroid Build Coastguard Worker       Value) {
395*9880d681SAndroid Build Coastguard Worker     assert((Value & 0xff000000) == 0 && "Added relocation out of range!");
396*9880d681SAndroid Build Coastguard Worker 
397*9880d681SAndroid Build Coastguard Worker     MachO::any_relocation_info MRE;
398*9880d681SAndroid Build Coastguard Worker     MRE.r_word0 = FixupOffset;
399*9880d681SAndroid Build Coastguard Worker     MRE.r_word1 =
400*9880d681SAndroid Build Coastguard Worker         (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
401*9880d681SAndroid Build Coastguard Worker     Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
402*9880d681SAndroid Build Coastguard Worker 
403*9880d681SAndroid Build Coastguard Worker     // Now set up the Addend relocation.
404*9880d681SAndroid Build Coastguard Worker     Type = MachO::ARM64_RELOC_ADDEND;
405*9880d681SAndroid Build Coastguard Worker     Index = Value;
406*9880d681SAndroid Build Coastguard Worker     RelSymbol = nullptr;
407*9880d681SAndroid Build Coastguard Worker     IsPCRel = 0;
408*9880d681SAndroid Build Coastguard Worker     Log2Size = 2;
409*9880d681SAndroid Build Coastguard Worker 
410*9880d681SAndroid Build Coastguard Worker     // Put zero into the instruction itself. The addend is in the relocation.
411*9880d681SAndroid Build Coastguard Worker     Value = 0;
412*9880d681SAndroid Build Coastguard Worker   }
413*9880d681SAndroid Build Coastguard Worker 
414*9880d681SAndroid Build Coastguard Worker   // If there's any addend left to handle, encode it in the instruction.
415*9880d681SAndroid Build Coastguard Worker   FixedValue = Value;
416*9880d681SAndroid Build Coastguard Worker 
417*9880d681SAndroid Build Coastguard Worker   // struct relocation_info (8 bytes)
418*9880d681SAndroid Build Coastguard Worker   MachO::any_relocation_info MRE;
419*9880d681SAndroid Build Coastguard Worker   MRE.r_word0 = FixupOffset;
420*9880d681SAndroid Build Coastguard Worker   MRE.r_word1 =
421*9880d681SAndroid Build Coastguard Worker       (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28);
422*9880d681SAndroid Build Coastguard Worker   Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
423*9880d681SAndroid Build Coastguard Worker }
424*9880d681SAndroid Build Coastguard Worker 
createAArch64MachObjectWriter(raw_pwrite_stream & OS,uint32_t CPUType,uint32_t CPUSubtype)425*9880d681SAndroid Build Coastguard Worker MCObjectWriter *llvm::createAArch64MachObjectWriter(raw_pwrite_stream &OS,
426*9880d681SAndroid Build Coastguard Worker                                                     uint32_t CPUType,
427*9880d681SAndroid Build Coastguard Worker                                                     uint32_t CPUSubtype) {
428*9880d681SAndroid Build Coastguard Worker   return createMachObjectWriter(
429*9880d681SAndroid Build Coastguard Worker       new AArch64MachObjectWriter(CPUType, CPUSubtype), OS,
430*9880d681SAndroid Build Coastguard Worker       /*IsLittleEndian=*/true);
431*9880d681SAndroid Build Coastguard Worker }
432