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