clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ARMAsmBackend.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/Target/ARM/MCTargetDesc -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/Target/ARM/MCTargetDesc -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/Target/ARM/MCTargetDesc -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/Target/ARM -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/Target/ARM -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/include -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/include -D NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/Target/ARM/MCTargetDesc -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e=. -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2021-09-04-040900-46481-1 -x c++ /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #include "MCTargetDesc/ARMAsmBackend.h" |
10 | #include "MCTargetDesc/ARMAddressingModes.h" |
11 | #include "MCTargetDesc/ARMAsmBackendDarwin.h" |
12 | #include "MCTargetDesc/ARMAsmBackendELF.h" |
13 | #include "MCTargetDesc/ARMAsmBackendWinCOFF.h" |
14 | #include "MCTargetDesc/ARMFixupKinds.h" |
15 | #include "MCTargetDesc/ARMMCTargetDesc.h" |
16 | #include "llvm/ADT/StringSwitch.h" |
17 | #include "llvm/BinaryFormat/ELF.h" |
18 | #include "llvm/BinaryFormat/MachO.h" |
19 | #include "llvm/MC/MCAsmBackend.h" |
20 | #include "llvm/MC/MCAssembler.h" |
21 | #include "llvm/MC/MCContext.h" |
22 | #include "llvm/MC/MCDirectives.h" |
23 | #include "llvm/MC/MCELFObjectWriter.h" |
24 | #include "llvm/MC/MCExpr.h" |
25 | #include "llvm/MC/MCFixupKindInfo.h" |
26 | #include "llvm/MC/MCObjectWriter.h" |
27 | #include "llvm/MC/MCRegisterInfo.h" |
28 | #include "llvm/MC/MCSectionELF.h" |
29 | #include "llvm/MC/MCSectionMachO.h" |
30 | #include "llvm/MC/MCSubtargetInfo.h" |
31 | #include "llvm/MC/MCValue.h" |
32 | #include "llvm/MC/MCAsmLayout.h" |
33 | #include "llvm/Support/Debug.h" |
34 | #include "llvm/Support/EndianStream.h" |
35 | #include "llvm/Support/ErrorHandling.h" |
36 | #include "llvm/Support/Format.h" |
37 | #include "llvm/Support/TargetParser.h" |
38 | #include "llvm/Support/raw_ostream.h" |
39 | using namespace llvm; |
40 | |
41 | namespace { |
42 | class ARMELFObjectWriter : public MCELFObjectTargetWriter { |
43 | public: |
44 | ARMELFObjectWriter(uint8_t OSABI) |
45 | : MCELFObjectTargetWriter( false, OSABI, ELF::EM_ARM, |
46 | false) {} |
47 | }; |
48 | } |
49 | |
50 | Optional<MCFixupKind> ARMAsmBackend::getFixupKind(StringRef Name) const { |
51 | if (!STI.getTargetTriple().isOSBinFormatELF()) |
52 | return None; |
53 | |
54 | unsigned Type = llvm::StringSwitch<unsigned>(Name) |
55 | #define ELF_RELOC(X, Y) .Case(#X, Y) |
56 | #include "llvm/BinaryFormat/ELFRelocs/ARM.def" |
57 | #undef ELF_RELOC |
58 | .Case("BFD_RELOC_NONE", ELF::R_ARM_NONE) |
59 | .Case("BFD_RELOC_8", ELF::R_ARM_ABS8) |
60 | .Case("BFD_RELOC_16", ELF::R_ARM_ABS16) |
61 | .Case("BFD_RELOC_32", ELF::R_ARM_ABS32) |
62 | .Default(-1u); |
63 | if (Type == -1u) |
64 | return None; |
65 | return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type); |
66 | } |
67 | |
68 | const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { |
69 | unsigned IsPCRelConstant = |
70 | MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_Constant; |
71 | const static MCFixupKindInfo InfosLE[ARM::NumTargetFixupKinds] = { |
72 | |
73 | |
74 | |
75 | |
76 | {"fixup_arm_ldst_pcrel_12", 0, 32, IsPCRelConstant}, |
77 | {"fixup_t2_ldst_pcrel_12", 0, 32, |
78 | IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
79 | {"fixup_arm_pcrel_10_unscaled", 0, 32, IsPCRelConstant}, |
80 | {"fixup_arm_pcrel_10", 0, 32, IsPCRelConstant}, |
81 | {"fixup_t2_pcrel_10", 0, 32, |
82 | MCFixupKindInfo::FKF_IsPCRel | |
83 | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
84 | {"fixup_arm_pcrel_9", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
85 | {"fixup_t2_pcrel_9", 0, 32, |
86 | IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
87 | {"fixup_arm_ldst_abs_12", 0, 32, 0}, |
88 | {"fixup_thumb_adr_pcrel_10", 0, 8, |
89 | IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
90 | {"fixup_arm_adr_pcrel_12", 0, 32, IsPCRelConstant}, |
91 | {"fixup_t2_adr_pcrel_12", 0, 32, |
92 | IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
93 | {"fixup_arm_condbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel}, |
94 | {"fixup_arm_uncondbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel}, |
95 | {"fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
96 | {"fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
97 | {"fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel}, |
98 | {"fixup_arm_uncondbl", 0, 24, MCFixupKindInfo::FKF_IsPCRel}, |
99 | {"fixup_arm_condbl", 0, 24, MCFixupKindInfo::FKF_IsPCRel}, |
100 | {"fixup_arm_blx", 0, 24, MCFixupKindInfo::FKF_IsPCRel}, |
101 | {"fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
102 | {"fixup_arm_thumb_blx", 0, 32, |
103 | MCFixupKindInfo::FKF_IsPCRel | |
104 | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
105 | {"fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel}, |
106 | {"fixup_arm_thumb_cp", 0, 8, |
107 | MCFixupKindInfo::FKF_IsPCRel | |
108 | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
109 | {"fixup_arm_thumb_bcc", 0, 8, MCFixupKindInfo::FKF_IsPCRel}, |
110 | |
111 | |
112 | {"fixup_arm_movt_hi16", 0, 20, 0}, |
113 | {"fixup_arm_movw_lo16", 0, 20, 0}, |
114 | {"fixup_t2_movt_hi16", 0, 20, 0}, |
115 | {"fixup_t2_movw_lo16", 0, 20, 0}, |
116 | {"fixup_arm_mod_imm", 0, 12, 0}, |
117 | {"fixup_t2_so_imm", 0, 26, 0}, |
118 | {"fixup_bf_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
119 | {"fixup_bf_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
120 | {"fixup_bfl_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
121 | {"fixup_bfc_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
122 | {"fixup_bfcsel_else_target", 0, 32, 0}, |
123 | {"fixup_wls", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
124 | {"fixup_le", 0, 32, MCFixupKindInfo::FKF_IsPCRel}}; |
125 | const static MCFixupKindInfo InfosBE[ARM::NumTargetFixupKinds] = { |
126 | |
127 | |
128 | |
129 | |
130 | {"fixup_arm_ldst_pcrel_12", 0, 32, IsPCRelConstant}, |
131 | {"fixup_t2_ldst_pcrel_12", 0, 32, |
132 | IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
133 | {"fixup_arm_pcrel_10_unscaled", 0, 32, IsPCRelConstant}, |
134 | {"fixup_arm_pcrel_10", 0, 32, IsPCRelConstant}, |
135 | {"fixup_t2_pcrel_10", 0, 32, |
136 | MCFixupKindInfo::FKF_IsPCRel | |
137 | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
138 | {"fixup_arm_pcrel_9", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
139 | {"fixup_t2_pcrel_9", 0, 32, |
140 | IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
141 | {"fixup_arm_ldst_abs_12", 0, 32, 0}, |
142 | {"fixup_thumb_adr_pcrel_10", 8, 8, |
143 | IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
144 | {"fixup_arm_adr_pcrel_12", 0, 32, IsPCRelConstant}, |
145 | {"fixup_t2_adr_pcrel_12", 0, 32, |
146 | IsPCRelConstant | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
147 | {"fixup_arm_condbranch", 8, 24, MCFixupKindInfo::FKF_IsPCRel}, |
148 | {"fixup_arm_uncondbranch", 8, 24, MCFixupKindInfo::FKF_IsPCRel}, |
149 | {"fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
150 | {"fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
151 | {"fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel}, |
152 | {"fixup_arm_uncondbl", 8, 24, MCFixupKindInfo::FKF_IsPCRel}, |
153 | {"fixup_arm_condbl", 8, 24, MCFixupKindInfo::FKF_IsPCRel}, |
154 | {"fixup_arm_blx", 8, 24, MCFixupKindInfo::FKF_IsPCRel}, |
155 | {"fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
156 | {"fixup_arm_thumb_blx", 0, 32, |
157 | MCFixupKindInfo::FKF_IsPCRel | |
158 | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
159 | {"fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel}, |
160 | {"fixup_arm_thumb_cp", 8, 8, |
161 | MCFixupKindInfo::FKF_IsPCRel | |
162 | MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}, |
163 | {"fixup_arm_thumb_bcc", 8, 8, MCFixupKindInfo::FKF_IsPCRel}, |
164 | |
165 | |
166 | {"fixup_arm_movt_hi16", 12, 20, 0}, |
167 | {"fixup_arm_movw_lo16", 12, 20, 0}, |
168 | {"fixup_t2_movt_hi16", 12, 20, 0}, |
169 | {"fixup_t2_movw_lo16", 12, 20, 0}, |
170 | {"fixup_arm_mod_imm", 20, 12, 0}, |
171 | {"fixup_t2_so_imm", 26, 6, 0}, |
172 | {"fixup_bf_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
173 | {"fixup_bf_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
174 | {"fixup_bfl_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
175 | {"fixup_bfc_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
176 | {"fixup_bfcsel_else_target", 0, 32, 0}, |
177 | {"fixup_wls", 0, 32, MCFixupKindInfo::FKF_IsPCRel}, |
178 | {"fixup_le", 0, 32, MCFixupKindInfo::FKF_IsPCRel}}; |
179 | |
180 | |
181 | |
182 | if (Kind >= FirstLiteralRelocationKind) |
183 | return MCAsmBackend::getFixupKindInfo(FK_NONE); |
184 | |
185 | if (Kind < FirstTargetFixupKind) |
186 | return MCAsmBackend::getFixupKindInfo(Kind); |
187 | |
188 | assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && |
189 | "Invalid kind!"); |
190 | return (Endian == support::little ? InfosLE |
191 | : InfosBE)[Kind - FirstTargetFixupKind]; |
192 | } |
193 | |
194 | void ARMAsmBackend::handleAssemblerFlag(MCAssemblerFlag Flag) { |
195 | switch (Flag) { |
196 | default: |
197 | break; |
198 | case MCAF_Code16: |
199 | setIsThumb(true); |
200 | break; |
201 | case MCAF_Code32: |
202 | setIsThumb(false); |
203 | break; |
204 | } |
205 | } |
206 | |
207 | unsigned ARMAsmBackend::getRelaxedOpcode(unsigned Op, |
208 | const MCSubtargetInfo &STI) const { |
209 | bool HasThumb2 = STI.getFeatureBits()[ARM::FeatureThumb2]; |
210 | bool HasV8MBaselineOps = STI.getFeatureBits()[ARM::HasV8MBaselineOps]; |
211 | |
212 | switch (Op) { |
213 | default: |
214 | return Op; |
215 | case ARM::tBcc: |
216 | return HasThumb2 ? (unsigned)ARM::t2Bcc : Op; |
217 | case ARM::tLDRpci: |
218 | return HasThumb2 ? (unsigned)ARM::t2LDRpci : Op; |
219 | case ARM::tADR: |
220 | return HasThumb2 ? (unsigned)ARM::t2ADR : Op; |
221 | case ARM::tB: |
222 | return HasV8MBaselineOps ? (unsigned)ARM::t2B : Op; |
223 | case ARM::tCBZ: |
224 | return ARM::tHINT; |
225 | case ARM::tCBNZ: |
226 | return ARM::tHINT; |
227 | } |
228 | } |
229 | |
230 | bool ARMAsmBackend::mayNeedRelaxation(const MCInst &Inst, |
231 | const MCSubtargetInfo &STI) const { |
232 | if (getRelaxedOpcode(Inst.getOpcode(), STI) != Inst.getOpcode()) |
233 | return true; |
234 | return false; |
235 | } |
236 | |
237 | static const char *checkPCRelOffset(uint64_t Value, int64_t Min, int64_t Max) { |
238 | int64_t Offset = int64_t(Value) - 4; |
239 | if (Offset < Min || Offset > Max) |
240 | return "out of range pc-relative fixup value"; |
241 | return nullptr; |
242 | } |
243 | |
244 | const char *ARMAsmBackend::reasonForFixupRelaxation(const MCFixup &Fixup, |
245 | uint64_t Value) const { |
246 | switch (Fixup.getTargetKind()) { |
247 | case ARM::fixup_arm_thumb_br: { |
248 | |
249 | |
250 | |
251 | |
252 | |
253 | |
254 | int64_t Offset = int64_t(Value) - 4; |
255 | if (Offset > 2046 || Offset < -2048) |
256 | return "out of range pc-relative fixup value"; |
257 | break; |
258 | } |
259 | case ARM::fixup_arm_thumb_bcc: { |
260 | |
261 | |
262 | |
263 | |
264 | |
265 | |
266 | int64_t Offset = int64_t(Value) - 4; |
267 | if (Offset > 254 || Offset < -256) |
268 | return "out of range pc-relative fixup value"; |
269 | break; |
270 | } |
271 | case ARM::fixup_thumb_adr_pcrel_10: |
272 | case ARM::fixup_arm_thumb_cp: { |
273 | |
274 | |
275 | int64_t Offset = int64_t(Value) - 4; |
276 | if (Offset & 3) |
277 | return "misaligned pc-relative fixup value"; |
278 | else if (Offset > 1020 || Offset < 0) |
279 | return "out of range pc-relative fixup value"; |
280 | break; |
281 | } |
282 | case ARM::fixup_arm_thumb_cb: { |
283 | |
284 | |
285 | |
286 | int64_t Offset = (Value & ~1); |
287 | if (Offset == 2) |
288 | return "will be converted to nop"; |
289 | break; |
290 | } |
291 | case ARM::fixup_bf_branch: |
292 | return checkPCRelOffset(Value, 0, 30); |
293 | case ARM::fixup_bf_target: |
294 | return checkPCRelOffset(Value, -0x10000, +0xfffe); |
295 | case ARM::fixup_bfl_target: |
296 | return checkPCRelOffset(Value, -0x40000, +0x3fffe); |
297 | case ARM::fixup_bfc_target: |
298 | return checkPCRelOffset(Value, -0x1000, +0xffe); |
299 | case ARM::fixup_wls: |
300 | return checkPCRelOffset(Value, 0, +0xffe); |
301 | case ARM::fixup_le: |
302 | |
303 | |
304 | |
305 | |
306 | |
307 | |
308 | |
309 | |
310 | return checkPCRelOffset(Value, -0xffe, 0); |
311 | case ARM::fixup_bfcsel_else_target: { |
312 | if (Value != 2 && Value != 4) |
313 | return "out of range label-relative fixup value"; |
314 | break; |
315 | } |
316 | |
317 | default: |
318 | llvm_unreachable("Unexpected fixup kind in reasonForFixupRelaxation()!"); |
319 | } |
320 | return nullptr; |
321 | } |
322 | |
323 | bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, |
324 | const MCRelaxableFragment *DF, |
325 | const MCAsmLayout &Layout) const { |
326 | return reasonForFixupRelaxation(Fixup, Value); |
327 | } |
328 | |
329 | void ARMAsmBackend::relaxInstruction(MCInst &Inst, |
330 | const MCSubtargetInfo &STI) const { |
331 | unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode(), STI); |
332 | |
333 | |
334 | if (RelaxedOp == Inst.getOpcode()) { |
335 | SmallString<256> Tmp; |
336 | raw_svector_ostream OS(Tmp); |
337 | Inst.dump_pretty(OS); |
338 | OS << "\n"; |
339 | report_fatal_error("unexpected instruction to relax: " + OS.str()); |
340 | } |
341 | |
342 | |
343 | |
344 | if ((Inst.getOpcode() == ARM::tCBZ || Inst.getOpcode() == ARM::tCBNZ) && |
345 | RelaxedOp == ARM::tHINT) { |
346 | MCInst Res; |
347 | Res.setOpcode(RelaxedOp); |
348 | Res.addOperand(MCOperand::createImm(0)); |
349 | Res.addOperand(MCOperand::createImm(14)); |
350 | Res.addOperand(MCOperand::createReg(0)); |
351 | Inst = std::move(Res); |
352 | return; |
353 | } |
354 | |
355 | |
356 | |
357 | Inst.setOpcode(RelaxedOp); |
358 | } |
359 | |
360 | bool ARMAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { |
361 | const uint16_t Thumb1_16bitNopEncoding = 0x46c0; |
362 | const uint16_t Thumb2_16bitNopEncoding = 0xbf00; |
363 | const uint32_t ARMv4_NopEncoding = 0xe1a00000; |
364 | const uint32_t ARMv6T2_NopEncoding = 0xe320f000; |
365 | if (isThumb()) { |
366 | const uint16_t nopEncoding = |
367 | hasNOP() ? Thumb2_16bitNopEncoding : Thumb1_16bitNopEncoding; |
368 | uint64_t NumNops = Count / 2; |
369 | for (uint64_t i = 0; i != NumNops; ++i) |
370 | support::endian::write(OS, nopEncoding, Endian); |
371 | if (Count & 1) |
372 | OS << '\0'; |
373 | return true; |
374 | } |
375 | |
376 | const uint32_t nopEncoding = |
377 | hasNOP() ? ARMv6T2_NopEncoding : ARMv4_NopEncoding; |
378 | uint64_t NumNops = Count / 4; |
379 | for (uint64_t i = 0; i != NumNops; ++i) |
380 | support::endian::write(OS, nopEncoding, Endian); |
381 | |
382 | |
383 | switch (Count % 4) { |
384 | default: |
385 | break; |
386 | case 1: |
387 | OS << '\0'; |
388 | break; |
389 | case 2: |
390 | OS.write("\0\0", 2); |
391 | break; |
392 | case 3: |
393 | OS.write("\0\0\xa0", 3); |
394 | break; |
395 | } |
396 | |
397 | return true; |
398 | } |
399 | |
400 | static uint32_t swapHalfWords(uint32_t Value, bool IsLittleEndian) { |
401 | if (IsLittleEndian) { |
402 | |
403 | |
404 | uint32_t Swapped = (Value & 0xFFFF0000) >> 16; |
405 | Swapped |= (Value & 0x0000FFFF) << 16; |
406 | return Swapped; |
407 | } else |
408 | return Value; |
409 | } |
410 | |
411 | static uint32_t joinHalfWords(uint32_t FirstHalf, uint32_t SecondHalf, |
412 | bool IsLittleEndian) { |
413 | uint32_t Value; |
414 | |
415 | if (IsLittleEndian) { |
416 | Value = (SecondHalf & 0xFFFF) << 16; |
417 | Value |= (FirstHalf & 0xFFFF); |
418 | } else { |
419 | Value = (SecondHalf & 0xFFFF); |
420 | Value |= (FirstHalf & 0xFFFF) << 16; |
421 | } |
422 | |
423 | return Value; |
424 | } |
425 | |
426 | unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm, |
427 | const MCFixup &Fixup, |
428 | const MCValue &Target, uint64_t Value, |
429 | bool IsResolved, MCContext &Ctx, |
430 | const MCSubtargetInfo* STI) const { |
431 | unsigned Kind = Fixup.getKind(); |
432 | |
433 | |
434 | |
435 | |
436 | |
437 | |
438 | if (const MCSymbolRefExpr *A = Target.getSymA()) { |
439 | if (A->hasSubsectionsViaSymbols() && Asm.isThumbFunc(&A->getSymbol()) && |
440 | A->getSymbol().isExternal() && |
441 | (Kind == FK_Data_4 || Kind == ARM::fixup_arm_movw_lo16 || |
442 | Kind == ARM::fixup_arm_movt_hi16 || Kind == ARM::fixup_t2_movw_lo16 || |
443 | Kind == ARM::fixup_t2_movt_hi16)) |
444 | Value |= 1; |
445 | } |
446 | |
447 | switch (Kind) { |
448 | default: |
449 | Ctx.reportError(Fixup.getLoc(), "bad relocation fixup type"); |
450 | return 0; |
451 | case FK_Data_1: |
452 | case FK_Data_2: |
453 | case FK_Data_4: |
454 | return Value; |
455 | case FK_SecRel_2: |
456 | return Value; |
457 | case FK_SecRel_4: |
458 | return Value; |
459 | case ARM::fixup_arm_movt_hi16: |
460 | assert(STI != nullptr); |
461 | if (IsResolved || !STI->getTargetTriple().isOSBinFormatELF()) |
462 | Value >>= 16; |
463 | LLVM_FALLTHROUGH; |
464 | case ARM::fixup_arm_movw_lo16: { |
465 | unsigned Hi4 = (Value & 0xF000) >> 12; |
466 | unsigned Lo12 = Value & 0x0FFF; |
467 | |
468 | |
469 | Value = (Hi4 << 16) | (Lo12); |
470 | return Value; |
471 | } |
472 | case ARM::fixup_t2_movt_hi16: |
473 | assert(STI != nullptr); |
474 | if (IsResolved || !STI->getTargetTriple().isOSBinFormatELF()) |
475 | Value >>= 16; |
476 | LLVM_FALLTHROUGH; |
477 | case ARM::fixup_t2_movw_lo16: { |
478 | unsigned Hi4 = (Value & 0xF000) >> 12; |
479 | unsigned i = (Value & 0x800) >> 11; |
480 | unsigned Mid3 = (Value & 0x700) >> 8; |
481 | unsigned Lo8 = Value & 0x0FF; |
482 | |
483 | |
484 | |
485 | |
486 | Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8); |
487 | return swapHalfWords(Value, Endian == support::little); |
488 | } |
489 | case ARM::fixup_arm_ldst_pcrel_12: |
490 | |
491 | Value -= 4; |
492 | LLVM_FALLTHROUGH; |
493 | case ARM::fixup_t2_ldst_pcrel_12: |
494 | |
495 | Value -= 4; |
496 | LLVM_FALLTHROUGH; |
497 | case ARM::fixup_arm_ldst_abs_12: { |
498 | bool isAdd = true; |
499 | if ((int64_t)Value < 0) { |
500 | Value = -Value; |
501 | isAdd = false; |
502 | } |
503 | if (Value >= 4096) { |
504 | Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value"); |
505 | return 0; |
506 | } |
507 | Value |= isAdd << 23; |
508 | |
509 | |
510 | |
511 | if (Kind == ARM::fixup_t2_ldst_pcrel_12) |
512 | return swapHalfWords(Value, Endian == support::little); |
513 | |
514 | return Value; |
515 | } |
516 | case ARM::fixup_arm_adr_pcrel_12: { |
517 | |
518 | Value -= 8; |
519 | unsigned opc = 4; |
520 | if ((int64_t)Value < 0) { |
521 | Value = -Value; |
522 | opc = 2; |
523 | } |
524 | if (ARM_AM::getSOImmVal(Value) == -1) { |
525 | Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value"); |
526 | return 0; |
527 | } |
528 | |
529 | return ARM_AM::getSOImmVal(Value) | (opc << 21); |
530 | } |
531 | |
532 | case ARM::fixup_t2_adr_pcrel_12: { |
533 | Value -= 4; |
534 | unsigned opc = 0; |
535 | if ((int64_t)Value < 0) { |
536 | Value = -Value; |
537 | opc = 5; |
538 | } |
539 | |
540 | uint32_t out = (opc << 21); |
541 | out |= (Value & 0x800) << 15; |
542 | out |= (Value & 0x700) << 4; |
543 | out |= (Value & 0x0FF); |
544 | |
545 | return swapHalfWords(out, Endian == support::little); |
546 | } |
547 | |
548 | case ARM::fixup_arm_condbranch: |
549 | case ARM::fixup_arm_uncondbranch: |
550 | case ARM::fixup_arm_uncondbl: |
551 | case ARM::fixup_arm_condbl: |
552 | case ARM::fixup_arm_blx: |
553 | |
554 | |
555 | if (const MCSymbolRefExpr *SRE = |
556 | dyn_cast<MCSymbolRefExpr>(Fixup.getValue())) |
557 | if (SRE->getKind() == MCSymbolRefExpr::VK_TLSCALL) |
558 | return 0; |
559 | return 0xffffff & ((Value - 8) >> 2); |
560 | case ARM::fixup_t2_uncondbranch: { |
561 | Value = Value - 4; |
562 | if (!isInt<25>(Value)) { |
563 | Ctx.reportError(Fixup.getLoc(), "Relocation out of range"); |
564 | return 0; |
565 | } |
566 | |
567 | Value >>= 1; |
568 | |
569 | uint32_t out = 0; |
570 | bool I = Value & 0x800000; |
571 | bool J1 = Value & 0x400000; |
572 | bool J2 = Value & 0x200000; |
573 | J1 ^= I; |
574 | J2 ^= I; |
575 | |
576 | out |= I << 26; |
577 | out |= !J1 << 13; |
578 | out |= !J2 << 11; |
579 | out |= (Value & 0x1FF800) << 5; |
580 | out |= (Value & 0x0007FF); |
581 | |
582 | return swapHalfWords(out, Endian == support::little); |
583 | } |
584 | case ARM::fixup_t2_condbranch: { |
585 | Value = Value - 4; |
586 | if (!isInt<21>(Value)) { |
587 | Ctx.reportError(Fixup.getLoc(), "Relocation out of range"); |
588 | return 0; |
589 | } |
590 | |
591 | Value >>= 1; |
592 | |
593 | uint64_t out = 0; |
594 | out |= (Value & 0x80000) << 7; |
595 | out |= (Value & 0x40000) >> 7; |
596 | out |= (Value & 0x20000) >> 4; |
597 | out |= (Value & 0x1F800) << 5; |
598 | out |= (Value & 0x007FF); |
599 | |
600 | return swapHalfWords(out, Endian == support::little); |
601 | } |
602 | case ARM::fixup_arm_thumb_bl: { |
603 | if (!isInt<25>(Value - 4) || |
604 | (!STI->getFeatureBits()[ARM::FeatureThumb2] && |
605 | !STI->getFeatureBits()[ARM::HasV8MBaselineOps] && |
606 | !STI->getFeatureBits()[ARM::HasV6MOps] && |
607 | !isInt<23>(Value - 4))) { |
608 | Ctx.reportError(Fixup.getLoc(), "Relocation out of range"); |
609 | return 0; |
610 | } |
611 | |
612 | |
613 | |
614 | |
615 | |
616 | |
617 | |
618 | |
619 | |
620 | |
621 | |
622 | |
623 | |
624 | uint32_t offset = (Value - 4) >> 1; |
625 | uint32_t signBit = (offset & 0x800000) >> 23; |
626 | uint32_t I1Bit = (offset & 0x400000) >> 22; |
627 | uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit; |
628 | uint32_t I2Bit = (offset & 0x200000) >> 21; |
629 | uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit; |
630 | uint32_t imm10Bits = (offset & 0x1FF800) >> 11; |
631 | uint32_t imm11Bits = (offset & 0x000007FF); |
632 | |
633 | uint32_t FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10Bits); |
634 | uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | |
635 | (uint16_t)imm11Bits); |
636 | return joinHalfWords(FirstHalf, SecondHalf, Endian == support::little); |
637 | } |
638 | case ARM::fixup_arm_thumb_blx: { |
639 | |
640 | |
641 | |
642 | |
643 | |
644 | |
645 | |
646 | |
647 | |
648 | |
649 | |
650 | |
651 | if (Value % 4 != 0) { |
652 | Ctx.reportError(Fixup.getLoc(), "misaligned ARM call destination"); |
653 | return 0; |
654 | } |
655 | |
656 | uint32_t offset = (Value - 4) >> 2; |
657 | if (const MCSymbolRefExpr *SRE = |
658 | dyn_cast<MCSymbolRefExpr>(Fixup.getValue())) |
659 | if (SRE->getKind() == MCSymbolRefExpr::VK_TLSCALL) |
660 | offset = 0; |
661 | uint32_t signBit = (offset & 0x400000) >> 22; |
662 | uint32_t I1Bit = (offset & 0x200000) >> 21; |
663 | uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit; |
664 | uint32_t I2Bit = (offset & 0x100000) >> 20; |
665 | uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit; |
666 | uint32_t imm10HBits = (offset & 0xFFC00) >> 10; |
667 | uint32_t imm10LBits = (offset & 0x3FF); |
668 | |
669 | uint32_t FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10HBits); |
670 | uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | |
671 | ((uint16_t)imm10LBits) << 1); |
672 | return joinHalfWords(FirstHalf, SecondHalf, Endian == support::little); |
673 | } |
674 | case ARM::fixup_thumb_adr_pcrel_10: |
675 | case ARM::fixup_arm_thumb_cp: |
676 | |
677 | |
678 | assert(STI != nullptr); |
679 | if (!STI->getFeatureBits()[ARM::FeatureThumb2] && IsResolved) { |
680 | const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value); |
681 | if (FixupDiagnostic) { |
682 | Ctx.reportError(Fixup.getLoc(), FixupDiagnostic); |
683 | return 0; |
684 | } |
685 | } |
686 | |
687 | return ((Value - 4) >> 2) & 0xff; |
688 | case ARM::fixup_arm_thumb_cb: { |
689 | |
690 | |
691 | |
692 | if ((int64_t)Value < 2 || Value > 0x82 || Value & 1) { |
693 | Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value"); |
694 | return 0; |
695 | } |
696 | |
697 | |
698 | uint32_t Binary = (Value - 4) >> 1; |
699 | return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3); |
700 | } |
701 | case ARM::fixup_arm_thumb_br: |
702 | |
703 | assert(STI != nullptr); |
704 | if (!STI->getFeatureBits()[ARM::FeatureThumb2] && |
705 | !STI->getFeatureBits()[ARM::HasV8MBaselineOps]) { |
706 | const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value); |
707 | if (FixupDiagnostic) { |
708 | Ctx.reportError(Fixup.getLoc(), FixupDiagnostic); |
709 | return 0; |
710 | } |
711 | } |
712 | return ((Value - 4) >> 1) & 0x7ff; |
713 | case ARM::fixup_arm_thumb_bcc: |
714 | |
715 | assert(STI != nullptr); |
716 | if (!STI->getFeatureBits()[ARM::FeatureThumb2]) { |
717 | const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value); |
718 | if (FixupDiagnostic) { |
719 | Ctx.reportError(Fixup.getLoc(), FixupDiagnostic); |
720 | return 0; |
721 | } |
722 | } |
723 | return ((Value - 4) >> 1) & 0xff; |
724 | case ARM::fixup_arm_pcrel_10_unscaled: { |
725 | Value = Value - 8; |
726 | |
727 | bool isAdd = true; |
728 | if ((int64_t)Value < 0) { |
729 | Value = -Value; |
730 | isAdd = false; |
731 | } |
732 | |
733 | if (Value >= 256) { |
734 | Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value"); |
735 | return 0; |
736 | } |
737 | Value = (Value & 0xf) | ((Value & 0xf0) << 4); |
738 | return Value | (isAdd << 23); |
739 | } |
740 | case ARM::fixup_arm_pcrel_10: |
741 | Value = Value - 4; |
742 | |
743 | LLVM_FALLTHROUGH; |
744 | case ARM::fixup_t2_pcrel_10: { |
745 | |
746 | Value = Value - 4; |
747 | bool isAdd = true; |
748 | if ((int64_t)Value < 0) { |
749 | Value = -Value; |
750 | isAdd = false; |
751 | } |
752 | |
753 | Value >>= 2; |
754 | if (Value >= 256) { |
755 | Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value"); |
756 | return 0; |
757 | } |
758 | Value |= isAdd << 23; |
759 | |
760 | |
761 | |
762 | if (Kind == ARM::fixup_t2_pcrel_10) |
763 | return swapHalfWords(Value, Endian == support::little); |
764 | |
765 | return Value; |
766 | } |
767 | case ARM::fixup_arm_pcrel_9: |
768 | Value = Value - 4; |
769 | |
770 | LLVM_FALLTHROUGH; |
771 | case ARM::fixup_t2_pcrel_9: { |
772 | |
773 | Value = Value - 4; |
774 | bool isAdd = true; |
775 | if ((int64_t)Value < 0) { |
776 | Value = -Value; |
777 | isAdd = false; |
778 | } |
779 | |
780 | if (Value & 1) { |
781 | Ctx.reportError(Fixup.getLoc(), "invalid value for this fixup"); |
782 | return 0; |
783 | } |
784 | Value >>= 1; |
785 | if (Value >= 256) { |
786 | Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value"); |
787 | return 0; |
788 | } |
789 | Value |= isAdd << 23; |
790 | |
791 | |
792 | |
793 | if (Kind == ARM::fixup_t2_pcrel_9) |
794 | return swapHalfWords(Value, Endian == support::little); |
795 | |
796 | return Value; |
797 | } |
798 | case ARM::fixup_arm_mod_imm: |
799 | Value = ARM_AM::getSOImmVal(Value); |
800 | if (Value >> 12) { |
801 | Ctx.reportError(Fixup.getLoc(), "out of range immediate fixup value"); |
802 | return 0; |
803 | } |
804 | return Value; |
805 | case ARM::fixup_t2_so_imm: { |
806 | Value = ARM_AM::getT2SOImmVal(Value); |
807 | if ((int64_t)Value < 0) { |
808 | Ctx.reportError(Fixup.getLoc(), "out of range immediate fixup value"); |
809 | return 0; |
810 | } |
811 | |
812 | |
813 | |
814 | |
815 | |
816 | uint64_t EncValue = 0; |
817 | EncValue |= (Value & 0x800) << 15; |
818 | EncValue |= (Value & 0x700) << 4; |
819 | EncValue |= (Value & 0xff); |
820 | return swapHalfWords(EncValue, Endian == support::little); |
821 | } |
822 | case ARM::fixup_bf_branch: { |
823 | const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value); |
824 | if (FixupDiagnostic) { |
825 | Ctx.reportError(Fixup.getLoc(), FixupDiagnostic); |
826 | return 0; |
827 | } |
828 | uint32_t out = (((Value - 4) >> 1) & 0xf) << 23; |
829 | return swapHalfWords(out, Endian == support::little); |
830 | } |
831 | case ARM::fixup_bf_target: |
832 | case ARM::fixup_bfl_target: |
833 | case ARM::fixup_bfc_target: { |
834 | const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value); |
835 | if (FixupDiagnostic) { |
836 | Ctx.reportError(Fixup.getLoc(), FixupDiagnostic); |
837 | return 0; |
838 | } |
839 | uint32_t out = 0; |
840 | uint32_t HighBitMask = (Kind == ARM::fixup_bf_target ? 0xf800 : |
841 | Kind == ARM::fixup_bfl_target ? 0x3f800 : 0x800); |
842 | out |= (((Value - 4) >> 1) & 0x1) << 11; |
843 | out |= (((Value - 4) >> 1) & 0x7fe); |
844 | out |= (((Value - 4) >> 1) & HighBitMask) << 5; |
845 | return swapHalfWords(out, Endian == support::little); |
846 | } |
847 | case ARM::fixup_bfcsel_else_target: { |
848 | |
849 | |
850 | |
851 | Value = Target.getConstant(); |
852 | |
853 | const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value); |
854 | if (FixupDiagnostic) { |
855 | Ctx.reportError(Fixup.getLoc(), FixupDiagnostic); |
856 | return 0; |
857 | } |
858 | uint32_t out = ((Value >> 2) & 1) << 17; |
859 | return swapHalfWords(out, Endian == support::little); |
860 | } |
861 | case ARM::fixup_wls: |
862 | case ARM::fixup_le: { |
863 | const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value); |
864 | if (FixupDiagnostic) { |
865 | Ctx.reportError(Fixup.getLoc(), FixupDiagnostic); |
866 | return 0; |
867 | } |
868 | uint64_t real_value = Value - 4; |
869 | uint32_t out = 0; |
870 | if (Kind == ARM::fixup_le) |
871 | real_value = -real_value; |
872 | out |= ((real_value >> 1) & 0x1) << 11; |
873 | out |= ((real_value >> 1) & 0x7fe); |
874 | return swapHalfWords(out, Endian == support::little); |
875 | } |
876 | } |
877 | } |
878 | |
879 | bool ARMAsmBackend::shouldForceRelocation(const MCAssembler &Asm, |
880 | const MCFixup &Fixup, |
881 | const MCValue &Target) { |
882 | const MCSymbolRefExpr *A = Target.getSymA(); |
883 | const MCSymbol *Sym = A ? &A->getSymbol() : nullptr; |
| |
| |
| 3 | | 'Sym' initialized to a null pointer value | |
|
884 | const unsigned FixupKind = Fixup.getKind(); |
885 | if (FixupKind >= FirstLiteralRelocationKind) |
| 4 | | Assuming 'FixupKind' is < FirstLiteralRelocationKind | |
|
| |
886 | return true; |
887 | if (FixupKind == ARM::fixup_arm_thumb_bl) { |
| 6 | | Assuming 'FixupKind' is equal to fixup_arm_thumb_bl | |
|
| |
888 | assert(Sym && "How did we resolve this?"); |
889 | |
890 | |
891 | |
892 | |
893 | |
894 | |
895 | if (Sym->isExternal()) |
| 8 | | Called C++ object pointer is null |
|
896 | return true; |
897 | } |
898 | |
899 | |
900 | if (Sym && Sym->isELF()) { |
901 | unsigned Type = cast<MCSymbolELF>(Sym)->getType(); |
902 | if ((Type == ELF::STT_FUNC || Type == ELF::STT_GNU_IFUNC)) { |
903 | if (Asm.isThumbFunc(Sym) && (FixupKind == ARM::fixup_arm_uncondbranch)) |
904 | return true; |
905 | if (!Asm.isThumbFunc(Sym) && (FixupKind == ARM::fixup_arm_thumb_br || |
906 | FixupKind == ARM::fixup_arm_thumb_bl || |
907 | FixupKind == ARM::fixup_t2_condbranch || |
908 | FixupKind == ARM::fixup_t2_uncondbranch)) |
909 | return true; |
910 | } |
911 | } |
912 | |
913 | |
914 | |
915 | if (A && (FixupKind == ARM::fixup_arm_thumb_blx || |
916 | FixupKind == ARM::fixup_arm_blx || |
917 | FixupKind == ARM::fixup_arm_uncondbl || |
918 | FixupKind == ARM::fixup_arm_condbl)) |
919 | return true; |
920 | return false; |
921 | } |
922 | |
923 | |
924 | static unsigned getFixupKindNumBytes(unsigned Kind) { |
925 | switch (Kind) { |
926 | default: |
927 | llvm_unreachable("Unknown fixup kind!"); |
928 | |
929 | case FK_Data_1: |
930 | case ARM::fixup_arm_thumb_bcc: |
931 | case ARM::fixup_arm_thumb_cp: |
932 | case ARM::fixup_thumb_adr_pcrel_10: |
933 | return 1; |
934 | |
935 | case FK_Data_2: |
936 | case ARM::fixup_arm_thumb_br: |
937 | case ARM::fixup_arm_thumb_cb: |
938 | case ARM::fixup_arm_mod_imm: |
939 | return 2; |
940 | |
941 | case ARM::fixup_arm_pcrel_10_unscaled: |
942 | case ARM::fixup_arm_ldst_pcrel_12: |
943 | case ARM::fixup_arm_pcrel_10: |
944 | case ARM::fixup_arm_pcrel_9: |
945 | case ARM::fixup_arm_ldst_abs_12: |
946 | case ARM::fixup_arm_adr_pcrel_12: |
947 | case ARM::fixup_arm_uncondbl: |
948 | case ARM::fixup_arm_condbl: |
949 | case ARM::fixup_arm_blx: |
950 | case ARM::fixup_arm_condbranch: |
951 | case ARM::fixup_arm_uncondbranch: |
952 | return 3; |
953 | |
954 | case FK_Data_4: |
955 | case ARM::fixup_t2_ldst_pcrel_12: |
956 | case ARM::fixup_t2_condbranch: |
957 | case ARM::fixup_t2_uncondbranch: |
958 | case ARM::fixup_t2_pcrel_10: |
959 | case ARM::fixup_t2_pcrel_9: |
960 | case ARM::fixup_t2_adr_pcrel_12: |
961 | case ARM::fixup_arm_thumb_bl: |
962 | case ARM::fixup_arm_thumb_blx: |
963 | case ARM::fixup_arm_movt_hi16: |
964 | case ARM::fixup_arm_movw_lo16: |
965 | case ARM::fixup_t2_movt_hi16: |
966 | case ARM::fixup_t2_movw_lo16: |
967 | case ARM::fixup_t2_so_imm: |
968 | case ARM::fixup_bf_branch: |
969 | case ARM::fixup_bf_target: |
970 | case ARM::fixup_bfl_target: |
971 | case ARM::fixup_bfc_target: |
972 | case ARM::fixup_bfcsel_else_target: |
973 | case ARM::fixup_wls: |
974 | case ARM::fixup_le: |
975 | return 4; |
976 | |
977 | case FK_SecRel_2: |
978 | return 2; |
979 | case FK_SecRel_4: |
980 | return 4; |
981 | } |
982 | } |
983 | |
984 | |
985 | |
986 | static unsigned getFixupKindContainerSizeBytes(unsigned Kind) { |
987 | switch (Kind) { |
988 | default: |
989 | llvm_unreachable("Unknown fixup kind!"); |
990 | |
991 | case FK_Data_1: |
992 | return 1; |
993 | case FK_Data_2: |
994 | return 2; |
995 | case FK_Data_4: |
996 | return 4; |
997 | |
998 | case ARM::fixup_arm_thumb_bcc: |
999 | case ARM::fixup_arm_thumb_cp: |
1000 | case ARM::fixup_thumb_adr_pcrel_10: |
1001 | case ARM::fixup_arm_thumb_br: |
1002 | case ARM::fixup_arm_thumb_cb: |
1003 | |
1004 | return 2; |
1005 | |
1006 | case ARM::fixup_arm_pcrel_10_unscaled: |
1007 | case ARM::fixup_arm_ldst_pcrel_12: |
1008 | case ARM::fixup_arm_pcrel_10: |
1009 | case ARM::fixup_arm_pcrel_9: |
1010 | case ARM::fixup_arm_adr_pcrel_12: |
1011 | case ARM::fixup_arm_uncondbl: |
1012 | case ARM::fixup_arm_condbl: |
1013 | case ARM::fixup_arm_blx: |
1014 | case ARM::fixup_arm_condbranch: |
1015 | case ARM::fixup_arm_uncondbranch: |
1016 | case ARM::fixup_t2_ldst_pcrel_12: |
1017 | case ARM::fixup_t2_condbranch: |
1018 | case ARM::fixup_t2_uncondbranch: |
1019 | case ARM::fixup_t2_pcrel_10: |
1020 | case ARM::fixup_t2_pcrel_9: |
1021 | case ARM::fixup_t2_adr_pcrel_12: |
1022 | case ARM::fixup_arm_thumb_bl: |
1023 | case ARM::fixup_arm_thumb_blx: |
1024 | case ARM::fixup_arm_movt_hi16: |
1025 | case ARM::fixup_arm_movw_lo16: |
1026 | case ARM::fixup_t2_movt_hi16: |
1027 | case ARM::fixup_t2_movw_lo16: |
1028 | case ARM::fixup_arm_mod_imm: |
1029 | case ARM::fixup_t2_so_imm: |
1030 | case ARM::fixup_bf_branch: |
1031 | case ARM::fixup_bf_target: |
1032 | case ARM::fixup_bfl_target: |
1033 | case ARM::fixup_bfc_target: |
1034 | case ARM::fixup_bfcsel_else_target: |
1035 | case ARM::fixup_wls: |
1036 | case ARM::fixup_le: |
1037 | |
1038 | return 4; |
1039 | } |
1040 | } |
1041 | |
1042 | void ARMAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, |
1043 | const MCValue &Target, |
1044 | MutableArrayRef<char> Data, uint64_t Value, |
1045 | bool IsResolved, |
1046 | const MCSubtargetInfo* STI) const { |
1047 | unsigned Kind = Fixup.getKind(); |
1048 | if (Kind >= FirstLiteralRelocationKind) |
1049 | return; |
1050 | unsigned NumBytes = getFixupKindNumBytes(Kind); |
1051 | MCContext &Ctx = Asm.getContext(); |
1052 | Value = adjustFixupValue(Asm, Fixup, Target, Value, IsResolved, Ctx, STI); |
1053 | if (!Value) |
1054 | return; |
1055 | |
1056 | unsigned Offset = Fixup.getOffset(); |
1057 | assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!"); |
1058 | |
1059 | |
1060 | unsigned FullSizeBytes; |
1061 | if (Endian == support::big) { |
1062 | FullSizeBytes = getFixupKindContainerSizeBytes(Kind); |
1063 | assert((Offset + FullSizeBytes) <= Data.size() && "Invalid fixup size!"); |
1064 | assert(NumBytes <= FullSizeBytes && "Invalid fixup size!"); |
1065 | } |
1066 | |
1067 | |
1068 | |
1069 | |
1070 | for (unsigned i = 0; i != NumBytes; ++i) { |
1071 | unsigned Idx = Endian == support::little ? i : (FullSizeBytes - 1 - i); |
1072 | Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff); |
1073 | } |
1074 | } |
1075 | |
1076 | namespace CU { |
1077 | |
1078 | |
1079 | enum CompactUnwindEncodings { |
1080 | UNWIND_ARM_MODE_MASK = 0x0F000000, |
1081 | UNWIND_ARM_MODE_FRAME = 0x01000000, |
1082 | UNWIND_ARM_MODE_FRAME_D = 0x02000000, |
1083 | UNWIND_ARM_MODE_DWARF = 0x04000000, |
1084 | |
1085 | UNWIND_ARM_FRAME_STACK_ADJUST_MASK = 0x00C00000, |
1086 | |
1087 | UNWIND_ARM_FRAME_FIRST_PUSH_R4 = 0x00000001, |
1088 | UNWIND_ARM_FRAME_FIRST_PUSH_R5 = 0x00000002, |
1089 | UNWIND_ARM_FRAME_FIRST_PUSH_R6 = 0x00000004, |
1090 | |
1091 | UNWIND_ARM_FRAME_SECOND_PUSH_R8 = 0x00000008, |
1092 | UNWIND_ARM_FRAME_SECOND_PUSH_R9 = 0x00000010, |
1093 | UNWIND_ARM_FRAME_SECOND_PUSH_R10 = 0x00000020, |
1094 | UNWIND_ARM_FRAME_SECOND_PUSH_R11 = 0x00000040, |
1095 | UNWIND_ARM_FRAME_SECOND_PUSH_R12 = 0x00000080, |
1096 | |
1097 | UNWIND_ARM_FRAME_D_REG_COUNT_MASK = 0x00000F00, |
1098 | |
1099 | UNWIND_ARM_DWARF_SECTION_OFFSET = 0x00FFFFFF |
1100 | }; |
1101 | |
1102 | } |
1103 | |
1104 | |
1105 | |
1106 | |
1107 | |
1108 | uint32_t ARMAsmBackendDarwin::generateCompactUnwindEncoding( |
1109 | ArrayRef<MCCFIInstruction> Instrs) const { |
1110 | DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs() << "generateCU()\n"); |
1111 | |
1112 | if (Subtype != MachO::CPU_SUBTYPE_ARM_V7K) |
1113 | return 0; |
1114 | |
1115 | if (Instrs.empty()) |
1116 | return 0; |
1117 | |
1118 | unsigned CFARegister = ARM::SP; |
1119 | int CFARegisterOffset = 0; |
1120 | |
1121 | DenseMap<unsigned, int> RegOffsets; |
1122 | int FloatRegCount = 0; |
1123 | |
1124 | for (size_t i = 0, e = Instrs.size(); i != e; ++i) { |
1125 | unsigned Reg; |
1126 | const MCCFIInstruction &Inst = Instrs[i]; |
1127 | switch (Inst.getOperation()) { |
1128 | case MCCFIInstruction::OpDefCfa: |
1129 | CFARegisterOffset = Inst.getOffset(); |
1130 | CFARegister = *MRI.getLLVMRegNum(Inst.getRegister(), true); |
1131 | break; |
1132 | case MCCFIInstruction::OpDefCfaOffset: |
1133 | CFARegisterOffset = Inst.getOffset(); |
1134 | break; |
1135 | case MCCFIInstruction::OpDefCfaRegister: |
1136 | CFARegister = *MRI.getLLVMRegNum(Inst.getRegister(), true); |
1137 | break; |
1138 | case MCCFIInstruction::OpOffset: |
1139 | Reg = *MRI.getLLVMRegNum(Inst.getRegister(), true); |
1140 | if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg)) |
1141 | RegOffsets[Reg] = Inst.getOffset(); |
1142 | else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) { |
1143 | RegOffsets[Reg] = Inst.getOffset(); |
1144 | ++FloatRegCount; |
1145 | } else { |
1146 | DEBUG_WITH_TYPE("compact-unwind", |
1147 | llvm::dbgs() << ".cfi_offset on unknown register=" |
1148 | << Inst.getRegister() << "\n"); |
1149 | return CU::UNWIND_ARM_MODE_DWARF; |
1150 | } |
1151 | break; |
1152 | case MCCFIInstruction::OpRelOffset: |
1153 | |
1154 | break; |
1155 | default: |
1156 | |
1157 | DEBUG_WITH_TYPE("compact-unwind", |
1158 | llvm::dbgs() |
1159 | << "CFI directive not compatiable with comact " |
1160 | "unwind encoding, opcode=" << Inst.getOperation() |
1161 | << "\n"); |
1162 | return CU::UNWIND_ARM_MODE_DWARF; |
1163 | break; |
1164 | } |
1165 | } |
1166 | |
1167 | |
1168 | if ((CFARegister == ARM::SP) && (CFARegisterOffset == 0)) |
1169 | return 0; |
1170 | |
1171 | |
1172 | if (CFARegister != ARM::R7) { |
1173 | DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs() << "frame register is " |
1174 | << CFARegister |
1175 | << " instead of r7\n"); |
1176 | return CU::UNWIND_ARM_MODE_DWARF; |
1177 | } |
1178 | int StackAdjust = CFARegisterOffset - 8; |
1179 | if (RegOffsets.lookup(ARM::LR) != (-4 - StackAdjust)) { |
1180 | DEBUG_WITH_TYPE("compact-unwind", |
1181 | llvm::dbgs() |
1182 | << "LR not saved as standard frame, StackAdjust=" |
1183 | << StackAdjust |
1184 | << ", CFARegisterOffset=" << CFARegisterOffset |
1185 | << ", lr save at offset=" << RegOffsets[14] << "\n"); |
1186 | return CU::UNWIND_ARM_MODE_DWARF; |
1187 | } |
1188 | if (RegOffsets.lookup(ARM::R7) != (-8 - StackAdjust)) { |
1189 | DEBUG_WITH_TYPE("compact-unwind", |
1190 | llvm::dbgs() << "r7 not saved as standard frame\n"); |
1191 | return CU::UNWIND_ARM_MODE_DWARF; |
1192 | } |
1193 | uint32_t CompactUnwindEncoding = CU::UNWIND_ARM_MODE_FRAME; |
1194 | |
1195 | |
1196 | switch (StackAdjust) { |
1197 | case 0: |
1198 | break; |
1199 | case 4: |
1200 | CompactUnwindEncoding |= 0x00400000; |
1201 | break; |
1202 | case 8: |
1203 | CompactUnwindEncoding |= 0x00800000; |
1204 | break; |
1205 | case 12: |
1206 | CompactUnwindEncoding |= 0x00C00000; |
1207 | break; |
1208 | default: |
1209 | DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs() |
1210 | << ".cfi_def_cfa stack adjust (" |
1211 | << StackAdjust << ") out of range\n"); |
1212 | return CU::UNWIND_ARM_MODE_DWARF; |
1213 | } |
1214 | |
1215 | |
1216 | static struct { |
1217 | unsigned Reg; |
1218 | unsigned Encoding; |
1219 | } GPRCSRegs[] = {{ARM::R6, CU::UNWIND_ARM_FRAME_FIRST_PUSH_R6}, |
1220 | {ARM::R5, CU::UNWIND_ARM_FRAME_FIRST_PUSH_R5}, |
1221 | {ARM::R4, CU::UNWIND_ARM_FRAME_FIRST_PUSH_R4}, |
1222 | {ARM::R12, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R12}, |
1223 | {ARM::R11, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R11}, |
1224 | {ARM::R10, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R10}, |
1225 | {ARM::R9, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R9}, |
1226 | {ARM::R8, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R8}}; |
1227 | |
1228 | int CurOffset = -8 - StackAdjust; |
1229 | for (auto CSReg : GPRCSRegs) { |
1230 | auto Offset = RegOffsets.find(CSReg.Reg); |
1231 | if (Offset == RegOffsets.end()) |
1232 | continue; |
1233 | |
1234 | int RegOffset = Offset->second; |
1235 | if (RegOffset != CurOffset - 4) { |
1236 | DEBUG_WITH_TYPE("compact-unwind", |
1237 | llvm::dbgs() << MRI.getName(CSReg.Reg) << " saved at " |
1238 | << RegOffset << " but only supported at " |
1239 | << CurOffset << "\n"); |
1240 | return CU::UNWIND_ARM_MODE_DWARF; |
1241 | } |
1242 | CompactUnwindEncoding |= CSReg.Encoding; |
1243 | CurOffset -= 4; |
1244 | } |
1245 | |
1246 | |
1247 | if (FloatRegCount == 0) |
1248 | return CompactUnwindEncoding; |
1249 | |
1250 | |
1251 | CompactUnwindEncoding &= ~CU::UNWIND_ARM_MODE_MASK; |
1252 | CompactUnwindEncoding |= CU::UNWIND_ARM_MODE_FRAME_D; |
1253 | |
1254 | |
1255 | |
1256 | if (FloatRegCount > 4) { |
1257 | DEBUG_WITH_TYPE("compact-unwind", |
1258 | llvm::dbgs() << "unsupported number of D registers saved (" |
1259 | << FloatRegCount << ")\n"); |
1260 | return CU::UNWIND_ARM_MODE_DWARF; |
1261 | } |
1262 | |
1263 | |
1264 | |
1265 | |
1266 | static unsigned FPRCSRegs[] = { ARM::D8, ARM::D10, ARM::D12, ARM::D14 }; |
1267 | for (int Idx = FloatRegCount - 1; Idx >= 0; --Idx) { |
1268 | auto Offset = RegOffsets.find(FPRCSRegs[Idx]); |
1269 | if (Offset == RegOffsets.end()) { |
1270 | DEBUG_WITH_TYPE("compact-unwind", |
1271 | llvm::dbgs() << FloatRegCount << " D-regs saved, but " |
1272 | << MRI.getName(FPRCSRegs[Idx]) |
1273 | << " not saved\n"); |
1274 | return CU::UNWIND_ARM_MODE_DWARF; |
1275 | } else if (Offset->second != CurOffset - 8) { |
1276 | DEBUG_WITH_TYPE("compact-unwind", |
1277 | llvm::dbgs() << FloatRegCount << " D-regs saved, but " |
1278 | << MRI.getName(FPRCSRegs[Idx]) |
1279 | << " saved at " << Offset->second |
1280 | << ", expected at " << CurOffset - 8 |
1281 | << "\n"); |
1282 | return CU::UNWIND_ARM_MODE_DWARF; |
1283 | } |
1284 | CurOffset -= 8; |
1285 | } |
1286 | |
1287 | return CompactUnwindEncoding | ((FloatRegCount - 1) << 8); |
1288 | } |
1289 | |
1290 | static MCAsmBackend *createARMAsmBackend(const Target &T, |
1291 | const MCSubtargetInfo &STI, |
1292 | const MCRegisterInfo &MRI, |
1293 | const MCTargetOptions &Options, |
1294 | support::endianness Endian) { |
1295 | const Triple &TheTriple = STI.getTargetTriple(); |
1296 | switch (TheTriple.getObjectFormat()) { |
1297 | default: |
1298 | llvm_unreachable("unsupported object format"); |
1299 | case Triple::MachO: |
1300 | return new ARMAsmBackendDarwin(T, STI, MRI); |
1301 | case Triple::COFF: |
1302 | assert(TheTriple.isOSWindows() && "non-Windows ARM COFF is not supported"); |
1303 | return new ARMAsmBackendWinCOFF(T, STI); |
1304 | case Triple::ELF: |
1305 | assert(TheTriple.isOSBinFormatELF() && "using ELF for non-ELF target"); |
1306 | uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); |
1307 | return new ARMAsmBackendELF(T, STI, OSABI, Endian); |
1308 | } |
1309 | } |
1310 | |
1311 | MCAsmBackend *llvm::createARMLEAsmBackend(const Target &T, |
1312 | const MCSubtargetInfo &STI, |
1313 | const MCRegisterInfo &MRI, |
1314 | const MCTargetOptions &Options) { |
1315 | return createARMAsmBackend(T, STI, MRI, Options, support::little); |
1316 | } |
1317 | |
1318 | MCAsmBackend *llvm::createARMBEAsmBackend(const Target &T, |
1319 | const MCSubtargetInfo &STI, |
1320 | const MCRegisterInfo &MRI, |
1321 | const MCTargetOptions &Options) { |
1322 | return createARMAsmBackend(T, STI, MRI, Options, support::big); |
1323 | } |