xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
1 //===--------- aarch32.cpp - Generic JITLink arm/thumb utilities ----------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Generic utilities for graphs representing arm/thumb objects.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/ExecutionEngine/JITLink/aarch32.h"
14 
15 #include "llvm/ADT/StringExtras.h"
16 #include "llvm/BinaryFormat/ELF.h"
17 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
18 #include "llvm/Object/ELFObjectFile.h"
19 #include "llvm/Support/Endian.h"
20 #include "llvm/Support/ManagedStatic.h"
21 #include "llvm/Support/MathExtras.h"
22 
23 #define DEBUG_TYPE "jitlink"
24 
25 namespace llvm {
26 namespace jitlink {
27 namespace aarch32 {
28 
29 /// Check whether the given target flags are set for this Symbol.
30 bool hasTargetFlags(Symbol &Sym, TargetFlagsType Flags) {
31   return static_cast<TargetFlagsType>(Sym.getTargetFlags()) & Flags;
32 }
33 
34 /// Encode 22-bit immediate value for branch instructions without J1J2 range
35 /// extension (formats B T4, BL T1 and BLX T2).
36 ///
37 ///   00000:Imm11H:Imm11L:0 -> [ 00000:Imm11H, 00000:Imm11L ]
38 ///                                            J1^ ^J2 will always be 1
39 ///
40 HalfWords encodeImmBT4BlT1BlxT2(int64_t Value) {
41   constexpr uint32_t J1J2 = 0x2800;
42   uint32_t Imm11H = (Value >> 12) & 0x07ff;
43   uint32_t Imm11L = (Value >> 1) & 0x07ff;
44   return HalfWords{Imm11H, Imm11L | J1J2};
45 }
46 
47 /// Decode 22-bit immediate value for branch instructions without J1J2 range
48 /// extension (formats B T4, BL T1 and BLX T2).
49 ///
50 ///   [ 00000:Imm11H, 00000:Imm11L ] -> 00000:Imm11H:Imm11L:0
51 ///                   J1^ ^J2 will always be 1
52 ///
53 int64_t decodeImmBT4BlT1BlxT2(uint32_t Hi, uint32_t Lo) {
54   uint32_t Imm11H = Hi & 0x07ff;
55   uint32_t Imm11L = Lo & 0x07ff;
56   return SignExtend64<22>(Imm11H << 12 | Imm11L << 1);
57 }
58 
59 /// Encode 25-bit immediate value for branch instructions with J1J2 range
60 /// extension (formats B T4, BL T1 and BLX T2).
61 ///
62 ///   S:I1:I2:Imm10:Imm11:0 -> [ 00000:S:Imm10, 00:J1:0:J2:Imm11 ]
63 ///
64 HalfWords encodeImmBT4BlT1BlxT2_J1J2(int64_t Value) {
65   uint32_t S = (Value >> 14) & 0x0400;
66   uint32_t J1 = (((~(Value >> 10)) ^ (Value >> 11)) & 0x2000);
67   uint32_t J2 = (((~(Value >> 11)) ^ (Value >> 13)) & 0x0800);
68   uint32_t Imm10 = (Value >> 12) & 0x03ff;
69   uint32_t Imm11 = (Value >> 1) & 0x07ff;
70   return HalfWords{S | Imm10, J1 | J2 | Imm11};
71 }
72 
73 /// Decode 25-bit immediate value for branch instructions with J1J2 range
74 /// extension (formats B T4, BL T1 and BLX T2).
75 ///
76 ///   [ 00000:S:Imm10, 00:J1:0:J2:Imm11] -> S:I1:I2:Imm10:Imm11:0
77 ///
78 int64_t decodeImmBT4BlT1BlxT2_J1J2(uint32_t Hi, uint32_t Lo) {
79   uint32_t S = Hi & 0x0400;
80   uint32_t I1 = ~((Lo ^ (Hi << 3)) << 10) & 0x00800000;
81   uint32_t I2 = ~((Lo ^ (Hi << 1)) << 11) & 0x00400000;
82   uint32_t Imm10 = Hi & 0x03ff;
83   uint32_t Imm11 = Lo & 0x07ff;
84   return SignExtend64<25>(S << 14 | I1 | I2 | Imm10 << 12 | Imm11 << 1);
85 }
86 
87 /// Encode 26-bit immediate value for branch instructions
88 /// (formats B A1, BL A1 and BLX A2).
89 ///
90 ///   Imm24:00 ->  00000000:Imm24
91 ///
92 uint32_t encodeImmBA1BlA1BlxA2(int64_t Value) {
93   return (Value >> 2) & 0x00ffffff;
94 }
95 
96 /// Decode 26-bit immediate value for branch instructions
97 /// (formats B A1, BL A1 and BLX A2).
98 ///
99 ///   00000000:Imm24 ->  Imm24:00
100 ///
101 int64_t decodeImmBA1BlA1BlxA2(int64_t Value) {
102   return SignExtend64<26>((Value & 0x00ffffff) << 2);
103 }
104 
105 /// Encode 16-bit immediate value for move instruction formats MOVT T1 and
106 /// MOVW T3.
107 ///
108 ///   Imm4:Imm1:Imm3:Imm8 -> [ 00000:i:000000:Imm4, 0:Imm3:0000:Imm8 ]
109 ///
110 HalfWords encodeImmMovtT1MovwT3(uint16_t Value) {
111   uint32_t Imm4 = (Value >> 12) & 0x0f;
112   uint32_t Imm1 = (Value >> 11) & 0x01;
113   uint32_t Imm3 = (Value >> 8) & 0x07;
114   uint32_t Imm8 = Value & 0xff;
115   return HalfWords{Imm1 << 10 | Imm4, Imm3 << 12 | Imm8};
116 }
117 
118 /// Decode 16-bit immediate value from move instruction formats MOVT T1 and
119 /// MOVW T3.
120 ///
121 ///   [ 00000:i:000000:Imm4, 0:Imm3:0000:Imm8 ] -> Imm4:Imm1:Imm3:Imm8
122 ///
123 uint16_t decodeImmMovtT1MovwT3(uint32_t Hi, uint32_t Lo) {
124   uint32_t Imm4 = Hi & 0x0f;
125   uint32_t Imm1 = (Hi >> 10) & 0x01;
126   uint32_t Imm3 = (Lo >> 12) & 0x07;
127   uint32_t Imm8 = Lo & 0xff;
128   uint32_t Imm16 = Imm4 << 12 | Imm1 << 11 | Imm3 << 8 | Imm8;
129   assert(Imm16 <= 0xffff && "Decoded value out-of-range");
130   return Imm16;
131 }
132 
133 /// Encode register ID for instruction formats MOVT T1 and MOVW T3.
134 ///
135 ///   Rd4 -> [0000000000000000, 0000:Rd4:00000000]
136 ///
137 HalfWords encodeRegMovtT1MovwT3(int64_t Value) {
138   uint32_t Rd4 = (Value & 0x0f) << 8;
139   return HalfWords{0, Rd4};
140 }
141 
142 /// Decode register ID from instruction formats MOVT T1 and MOVW T3.
143 ///
144 ///   [0000000000000000, 0000:Rd4:00000000] -> Rd4
145 ///
146 int64_t decodeRegMovtT1MovwT3(uint32_t Hi, uint32_t Lo) {
147   uint32_t Rd4 = (Lo >> 8) & 0x0f;
148   return Rd4;
149 }
150 
151 /// Encode 16-bit immediate value for move instruction formats MOVT A1 and
152 /// MOVW A2.
153 ///
154 ///   Imm4:Imm12 -> 000000000000:Imm4:0000:Imm12
155 ///
156 uint32_t encodeImmMovtA1MovwA2(uint16_t Value) {
157   uint32_t Imm4 = (Value >> 12) & 0x0f;
158   uint32_t Imm12 = Value & 0x0fff;
159   return (Imm4 << 16) | Imm12;
160 }
161 
162 /// Decode 16-bit immediate value for move instruction formats MOVT A1 and
163 /// MOVW A2.
164 ///
165 ///   000000000000:Imm4:0000:Imm12 -> Imm4:Imm12
166 ///
167 uint16_t decodeImmMovtA1MovwA2(uint64_t Value) {
168   uint32_t Imm4 = (Value >> 16) & 0x0f;
169   uint32_t Imm12 = Value & 0x0fff;
170   return (Imm4 << 12) | Imm12;
171 }
172 
173 /// Encode register ID for instruction formats MOVT A1 and
174 /// MOVW A2.
175 ///
176 ///   Rd4 -> 0000000000000000:Rd4:000000000000
177 ///
178 uint32_t encodeRegMovtA1MovwA2(int64_t Value) {
179   uint32_t Rd4 = (Value & 0x00000f) << 12;
180   return Rd4;
181 }
182 
183 /// Decode register ID for instruction formats MOVT A1 and
184 /// MOVW A2.
185 ///
186 ///   0000000000000000:Rd4:000000000000 -> Rd4
187 ///
188 int64_t decodeRegMovtA1MovwA2(uint64_t Value) {
189   uint32_t Rd4 = (Value >> 12) & 0x00000f;
190   return Rd4;
191 }
192 
193 namespace {
194 
195 /// 32-bit Thumb instructions are stored as two little-endian halfwords.
196 /// An instruction at address A encodes bytes A+1, A in the first halfword (Hi),
197 /// followed by bytes A+3, A+2 in the second halfword (Lo).
198 struct WritableThumbRelocation {
199   /// Create a writable reference to a Thumb32 fixup.
200   WritableThumbRelocation(char *FixupPtr)
201       : Hi{*reinterpret_cast<support::ulittle16_t *>(FixupPtr)},
202         Lo{*reinterpret_cast<support::ulittle16_t *>(FixupPtr + 2)} {}
203 
204   support::ulittle16_t &Hi; // First halfword
205   support::ulittle16_t &Lo; // Second halfword
206 };
207 
208 struct ThumbRelocation {
209   /// Create a read-only reference to a Thumb32 fixup.
210   ThumbRelocation(const char *FixupPtr)
211       : Hi{*reinterpret_cast<const support::ulittle16_t *>(FixupPtr)},
212         Lo{*reinterpret_cast<const support::ulittle16_t *>(FixupPtr + 2)} {}
213 
214   /// Create a read-only Thumb32 fixup from a writeable one.
215   ThumbRelocation(WritableThumbRelocation &Writable)
216       : Hi{Writable.Hi}, Lo(Writable.Lo) {}
217 
218   const support::ulittle16_t &Hi; // First halfword
219   const support::ulittle16_t &Lo; // Second halfword
220 };
221 
222 struct WritableArmRelocation {
223   WritableArmRelocation(char *FixupPtr)
224       : Wd{*reinterpret_cast<support::ulittle32_t *>(FixupPtr)} {}
225 
226   support::ulittle32_t &Wd;
227 };
228 
229 struct ArmRelocation {
230   ArmRelocation(const char *FixupPtr)
231       : Wd{*reinterpret_cast<const support::ulittle32_t *>(FixupPtr)} {}
232 
233   ArmRelocation(WritableArmRelocation &Writable) : Wd{Writable.Wd} {}
234 
235   const support::ulittle32_t &Wd;
236 };
237 
238 Error makeUnexpectedOpcodeError(const LinkGraph &G, const ThumbRelocation &R,
239                                 Edge::Kind Kind) {
240   return make_error<JITLinkError>(
241       formatv("Invalid opcode [ {0:x4}, {1:x4} ] for relocation: {2}",
242               static_cast<uint16_t>(R.Hi), static_cast<uint16_t>(R.Lo),
243               G.getEdgeKindName(Kind)));
244 }
245 
246 Error makeUnexpectedOpcodeError(const LinkGraph &G, const ArmRelocation &R,
247                                 Edge::Kind Kind) {
248   return make_error<JITLinkError>(
249       formatv("Invalid opcode {0:x8} for relocation: {1}",
250               static_cast<uint32_t>(R.Wd), G.getEdgeKindName(Kind)));
251 }
252 
253 template <EdgeKind_aarch32 K> constexpr bool isArm() {
254   return FirstArmRelocation <= K && K <= LastArmRelocation;
255 }
256 template <EdgeKind_aarch32 K> constexpr bool isThumb() {
257   return FirstThumbRelocation <= K && K <= LastThumbRelocation;
258 }
259 
260 template <EdgeKind_aarch32 K> static bool checkOpcodeArm(uint32_t Wd) {
261   return (Wd & FixupInfo<K>::OpcodeMask) == FixupInfo<K>::Opcode;
262 }
263 
264 template <EdgeKind_aarch32 K>
265 static bool checkOpcodeThumb(uint16_t Hi, uint16_t Lo) {
266   return (Hi & FixupInfo<K>::OpcodeMask.Hi) == FixupInfo<K>::Opcode.Hi &&
267          (Lo & FixupInfo<K>::OpcodeMask.Lo) == FixupInfo<K>::Opcode.Lo;
268 }
269 
270 class FixupInfoTable {
271   static constexpr size_t Items = LastRelocation + 1;
272 
273 public:
274   FixupInfoTable() {
275     populateEntries<FirstArmRelocation, LastArmRelocation>();
276     populateEntries<FirstThumbRelocation, LastThumbRelocation>();
277   }
278 
279   const FixupInfoBase *getEntry(Edge::Kind K) {
280     assert(K < Data.size() && "Index out of bounds");
281     return Data.at(K).get();
282   }
283 
284 private:
285   template <EdgeKind_aarch32 K, EdgeKind_aarch32 LastK> void populateEntries() {
286     assert(K < Data.size() && "Index out of range");
287     assert(Data.at(K) == nullptr && "Initialized entries are immutable");
288     Data[K] = initEntry<K>();
289     if constexpr (K < LastK) {
290       constexpr auto Next = static_cast<EdgeKind_aarch32>(K + 1);
291       populateEntries<Next, LastK>();
292     }
293   }
294 
295   template <EdgeKind_aarch32 K>
296   static std::unique_ptr<FixupInfoBase> initEntry() {
297     auto Entry = std::make_unique<FixupInfo<K>>();
298     static_assert(isArm<K>() != isThumb<K>(), "Classes are mutually exclusive");
299     if constexpr (isArm<K>())
300       Entry->checkOpcode = checkOpcodeArm<K>;
301     if constexpr (isThumb<K>())
302       Entry->checkOpcode = checkOpcodeThumb<K>;
303     return Entry;
304   }
305 
306 private:
307   std::array<std::unique_ptr<FixupInfoBase>, Items> Data;
308 };
309 
310 ManagedStatic<FixupInfoTable> DynFixupInfos;
311 
312 } // namespace
313 
314 static Error checkOpcode(LinkGraph &G, const ArmRelocation &R,
315                          Edge::Kind Kind) {
316   assert(Kind >= FirstArmRelocation && Kind <= LastArmRelocation &&
317          "Edge kind must be Arm relocation");
318   const FixupInfoBase *Entry = DynFixupInfos->getEntry(Kind);
319   const FixupInfoArm &Info = *static_cast<const FixupInfoArm *>(Entry);
320   assert(Info.checkOpcode && "Opcode check is mandatory for Arm edges");
321   if (!Info.checkOpcode(R.Wd))
322     return makeUnexpectedOpcodeError(G, R, Kind);
323 
324   return Error::success();
325 }
326 
327 static Error checkOpcode(LinkGraph &G, const ThumbRelocation &R,
328                          Edge::Kind Kind) {
329   assert(Kind >= FirstThumbRelocation && Kind <= LastThumbRelocation &&
330          "Edge kind must be Thumb relocation");
331   const FixupInfoBase *Entry = DynFixupInfos->getEntry(Kind);
332   const FixupInfoThumb &Info = *static_cast<const FixupInfoThumb *>(Entry);
333   assert(Info.checkOpcode && "Opcode check is mandatory for Thumb edges");
334   if (!Info.checkOpcode(R.Hi, R.Lo))
335     return makeUnexpectedOpcodeError(G, R, Kind);
336 
337   return Error::success();
338 }
339 
340 const FixupInfoBase *FixupInfoBase::getDynFixupInfo(Edge::Kind K) {
341   return DynFixupInfos->getEntry(K);
342 }
343 
344 template <EdgeKind_aarch32 Kind>
345 bool checkRegister(const ThumbRelocation &R, HalfWords Reg) {
346   uint16_t Hi = R.Hi & FixupInfo<Kind>::RegMask.Hi;
347   uint16_t Lo = R.Lo & FixupInfo<Kind>::RegMask.Lo;
348   return Hi == Reg.Hi && Lo == Reg.Lo;
349 }
350 
351 template <EdgeKind_aarch32 Kind>
352 bool checkRegister(const ArmRelocation &R, uint32_t Reg) {
353   uint32_t Wd = R.Wd & FixupInfo<Kind>::RegMask;
354   return Wd == Reg;
355 }
356 
357 template <EdgeKind_aarch32 Kind>
358 void writeRegister(WritableThumbRelocation &R, HalfWords Reg) {
359   static constexpr HalfWords Mask = FixupInfo<Kind>::RegMask;
360   assert((Mask.Hi & Reg.Hi) == Reg.Hi && (Mask.Lo & Reg.Lo) == Reg.Lo &&
361          "Value bits exceed bit range of given mask");
362   R.Hi = (R.Hi & ~Mask.Hi) | Reg.Hi;
363   R.Lo = (R.Lo & ~Mask.Lo) | Reg.Lo;
364 }
365 
366 template <EdgeKind_aarch32 Kind>
367 void writeRegister(WritableArmRelocation &R, uint32_t Reg) {
368   static constexpr uint32_t Mask = FixupInfo<Kind>::RegMask;
369   assert((Mask & Reg) == Reg && "Value bits exceed bit range of given mask");
370   R.Wd = (R.Wd & ~Mask) | Reg;
371 }
372 
373 template <EdgeKind_aarch32 Kind>
374 void writeImmediate(WritableThumbRelocation &R, HalfWords Imm) {
375   static constexpr HalfWords Mask = FixupInfo<Kind>::ImmMask;
376   assert((Mask.Hi & Imm.Hi) == Imm.Hi && (Mask.Lo & Imm.Lo) == Imm.Lo &&
377          "Value bits exceed bit range of given mask");
378   R.Hi = (R.Hi & ~Mask.Hi) | Imm.Hi;
379   R.Lo = (R.Lo & ~Mask.Lo) | Imm.Lo;
380 }
381 
382 template <EdgeKind_aarch32 Kind>
383 void writeImmediate(WritableArmRelocation &R, uint32_t Imm) {
384   static constexpr uint32_t Mask = FixupInfo<Kind>::ImmMask;
385   assert((Mask & Imm) == Imm && "Value bits exceed bit range of given mask");
386   R.Wd = (R.Wd & ~Mask) | Imm;
387 }
388 
389 Expected<int64_t> readAddendData(LinkGraph &G, Block &B, Edge::OffsetT Offset,
390                                  Edge::Kind Kind) {
391   endianness Endian = G.getEndianness();
392   const char *BlockWorkingMem = B.getContent().data();
393   const char *FixupPtr = BlockWorkingMem + Offset;
394 
395   switch (Kind) {
396   case Data_Delta32:
397   case Data_Pointer32:
398     return SignExtend64<32>(support::endian::read32(FixupPtr, Endian));
399   default:
400     return make_error<JITLinkError>(
401         "In graph " + G.getName() + ", section " + B.getSection().getName() +
402         " can not read implicit addend for aarch32 edge kind " +
403         G.getEdgeKindName(Kind));
404   }
405 }
406 
407 Expected<int64_t> readAddendArm(LinkGraph &G, Block &B, Edge::OffsetT Offset,
408                                 Edge::Kind Kind) {
409   ArmRelocation R(B.getContent().data() + Offset);
410   if (Error Err = checkOpcode(G, R, Kind))
411     return std::move(Err);
412 
413   switch (Kind) {
414   case Arm_Call:
415   case Arm_Jump24:
416     return decodeImmBA1BlA1BlxA2(R.Wd);
417 
418   case Arm_MovtAbs:
419   case Arm_MovwAbsNC:
420     return decodeImmMovtA1MovwA2(R.Wd);
421 
422   default:
423     return make_error<JITLinkError>(
424         "In graph " + G.getName() + ", section " + B.getSection().getName() +
425         " can not read implicit addend for aarch32 edge kind " +
426         G.getEdgeKindName(Kind));
427   }
428 }
429 
430 Expected<int64_t> readAddendThumb(LinkGraph &G, Block &B, Edge::OffsetT Offset,
431                                   Edge::Kind Kind, const ArmConfig &ArmCfg) {
432   ThumbRelocation R(B.getContent().data() + Offset);
433   if (Error Err = checkOpcode(G, R, Kind))
434     return std::move(Err);
435 
436   switch (Kind) {
437   case Thumb_Call:
438   case Thumb_Jump24:
439     return LLVM_LIKELY(ArmCfg.J1J2BranchEncoding)
440                ? decodeImmBT4BlT1BlxT2_J1J2(R.Hi, R.Lo)
441                : decodeImmBT4BlT1BlxT2(R.Hi, R.Lo);
442 
443   case Thumb_MovwAbsNC:
444   case Thumb_MovwPrelNC:
445     // Initial addend is interpreted as a signed value
446     return SignExtend64<16>(decodeImmMovtT1MovwT3(R.Hi, R.Lo));
447 
448   case Thumb_MovtAbs:
449   case Thumb_MovtPrel:
450     // Initial addend is interpreted as a signed value
451     return SignExtend64<16>(decodeImmMovtT1MovwT3(R.Hi, R.Lo));
452 
453   default:
454     return make_error<JITLinkError>(
455         "In graph " + G.getName() + ", section " + B.getSection().getName() +
456         " can not read implicit addend for aarch32 edge kind " +
457         G.getEdgeKindName(Kind));
458   }
459 }
460 
461 Error applyFixupData(LinkGraph &G, Block &B, const Edge &E) {
462   using namespace support;
463 
464   char *BlockWorkingMem = B.getAlreadyMutableContent().data();
465   char *FixupPtr = BlockWorkingMem + E.getOffset();
466 
467   auto Write32 = [FixupPtr, Endian = G.getEndianness()](int64_t Value) {
468     assert(isInt<32>(Value) && "Must be in signed 32-bit range");
469     uint32_t Imm = static_cast<int32_t>(Value);
470     if (LLVM_LIKELY(Endian == endianness::little))
471       endian::write32<endianness::little>(FixupPtr, Imm);
472     else
473       endian::write32<endianness::big>(FixupPtr, Imm);
474   };
475 
476   Edge::Kind Kind = E.getKind();
477   uint64_t FixupAddress = (B.getAddress() + E.getOffset()).getValue();
478   int64_t Addend = E.getAddend();
479   Symbol &TargetSymbol = E.getTarget();
480   uint64_t TargetAddress = TargetSymbol.getAddress().getValue();
481 
482   // Regular data relocations have size 4, alignment 1 and write the full 32-bit
483   // result to the place; no need for overflow checking. There are three
484   // exceptions: R_ARM_ABS8, R_ARM_ABS16, R_ARM_PREL31
485   switch (Kind) {
486   case Data_Delta32: {
487     int64_t Value = TargetAddress - FixupAddress + Addend;
488     if (!isInt<32>(Value))
489       return makeTargetOutOfRangeError(G, B, E);
490     Write32(Value);
491     return Error::success();
492   }
493   case Data_Pointer32: {
494     int64_t Value = TargetAddress + Addend;
495     if (!isInt<32>(Value))
496       return makeTargetOutOfRangeError(G, B, E);
497     Write32(Value);
498     return Error::success();
499   }
500   default:
501     return make_error<JITLinkError>(
502         "In graph " + G.getName() + ", section " + B.getSection().getName() +
503         " encountered unfixable aarch32 edge kind " +
504         G.getEdgeKindName(E.getKind()));
505   }
506 }
507 
508 Error applyFixupArm(LinkGraph &G, Block &B, const Edge &E) {
509   WritableArmRelocation R(B.getAlreadyMutableContent().data() + E.getOffset());
510   Edge::Kind Kind = E.getKind();
511   if (Error Err = checkOpcode(G, R, Kind))
512     return Err;
513 
514   uint64_t FixupAddress = (B.getAddress() + E.getOffset()).getValue();
515   int64_t Addend = E.getAddend();
516   Symbol &TargetSymbol = E.getTarget();
517   uint64_t TargetAddress = TargetSymbol.getAddress().getValue();
518 
519   switch (Kind) {
520   case Arm_Jump24: {
521     if (hasTargetFlags(TargetSymbol, ThumbSymbol))
522       return make_error<JITLinkError>("Branch relocation needs interworking "
523                                       "stub when bridging to Thumb: " +
524                                       StringRef(G.getEdgeKindName(Kind)));
525 
526     int64_t Value = TargetAddress - FixupAddress + Addend;
527 
528     if (!isInt<26>(Value))
529       return makeTargetOutOfRangeError(G, B, E);
530     writeImmediate<Arm_Jump24>(R, encodeImmBA1BlA1BlxA2(Value));
531 
532     return Error::success();
533   }
534   case Arm_Call: {
535     if ((R.Wd & FixupInfo<Arm_Call>::CondMask) !=
536         FixupInfo<Arm_Call>::Unconditional)
537       return make_error<JITLinkError>("Relocation expects an unconditional "
538                                       "BL/BLX branch instruction: " +
539                                       StringRef(G.getEdgeKindName(Kind)));
540 
541     int64_t Value = TargetAddress - FixupAddress + Addend;
542 
543     // The call instruction itself is Arm. The call destination can either be
544     // Thumb or Arm. We use BL to stay in Arm and BLX to change to Thumb.
545     bool TargetIsThumb = hasTargetFlags(TargetSymbol, ThumbSymbol);
546     bool InstrIsBlx = (~R.Wd & FixupInfo<Arm_Call>::BitBlx) == 0;
547     if (TargetIsThumb != InstrIsBlx) {
548       if (LLVM_LIKELY(TargetIsThumb)) {
549         // Change opcode BL -> BLX
550         R.Wd = R.Wd | FixupInfo<Arm_Call>::BitBlx;
551         R.Wd = R.Wd & ~FixupInfo<Arm_Call>::BitH;
552       } else {
553         // Change opcode BLX -> BL
554         R.Wd = R.Wd & ~FixupInfo<Arm_Call>::BitBlx;
555       }
556     }
557 
558     if (!isInt<26>(Value))
559       return makeTargetOutOfRangeError(G, B, E);
560     writeImmediate<Arm_Call>(R, encodeImmBA1BlA1BlxA2(Value));
561 
562     return Error::success();
563   }
564   case Arm_MovwAbsNC: {
565     uint16_t Value = (TargetAddress + Addend) & 0xffff;
566     writeImmediate<Arm_MovwAbsNC>(R, encodeImmMovtA1MovwA2(Value));
567     return Error::success();
568   }
569   case Arm_MovtAbs: {
570     uint16_t Value = ((TargetAddress + Addend) >> 16) & 0xffff;
571     writeImmediate<Arm_MovtAbs>(R, encodeImmMovtA1MovwA2(Value));
572     return Error::success();
573   }
574   default:
575     return make_error<JITLinkError>(
576         "In graph " + G.getName() + ", section " + B.getSection().getName() +
577         " encountered unfixable aarch32 edge kind " +
578         G.getEdgeKindName(E.getKind()));
579   }
580 }
581 
582 Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E,
583                       const ArmConfig &ArmCfg) {
584   WritableThumbRelocation R(B.getAlreadyMutableContent().data() +
585                             E.getOffset());
586   Edge::Kind Kind = E.getKind();
587   if (Error Err = checkOpcode(G, R, Kind))
588     return Err;
589 
590   uint64_t FixupAddress = (B.getAddress() + E.getOffset()).getValue();
591   int64_t Addend = E.getAddend();
592   Symbol &TargetSymbol = E.getTarget();
593   uint64_t TargetAddress = TargetSymbol.getAddress().getValue();
594 
595   switch (Kind) {
596   case Thumb_Jump24: {
597     if (!hasTargetFlags(TargetSymbol, ThumbSymbol))
598       return make_error<JITLinkError>("Branch relocation needs interworking "
599                                       "stub when bridging to ARM: " +
600                                       StringRef(G.getEdgeKindName(Kind)));
601 
602     int64_t Value = TargetAddress - FixupAddress + Addend;
603     if (LLVM_LIKELY(ArmCfg.J1J2BranchEncoding)) {
604       if (!isInt<25>(Value))
605         return makeTargetOutOfRangeError(G, B, E);
606       writeImmediate<Thumb_Jump24>(R, encodeImmBT4BlT1BlxT2_J1J2(Value));
607     } else {
608       if (!isInt<22>(Value))
609         return makeTargetOutOfRangeError(G, B, E);
610       writeImmediate<Thumb_Jump24>(R, encodeImmBT4BlT1BlxT2(Value));
611     }
612 
613     return Error::success();
614   }
615 
616   case Thumb_Call: {
617     int64_t Value = TargetAddress - FixupAddress + Addend;
618 
619     // The call instruction itself is Thumb. The call destination can either be
620     // Thumb or Arm. We use BL to stay in Thumb and BLX to change to Arm.
621     bool TargetIsArm = !hasTargetFlags(TargetSymbol, ThumbSymbol);
622     bool InstrIsBlx = (R.Lo & FixupInfo<Thumb_Call>::LoBitNoBlx) == 0;
623     if (TargetIsArm != InstrIsBlx) {
624       if (LLVM_LIKELY(TargetIsArm)) {
625         // Change opcode BL -> BLX and fix range value: account for 4-byte
626         // aligned destination while instruction may only be 2-byte aligned
627         R.Lo = R.Lo & ~FixupInfo<Thumb_Call>::LoBitNoBlx;
628         R.Lo = R.Lo & ~FixupInfo<Thumb_Call>::LoBitH;
629         Value = alignTo(Value, 4);
630       } else {
631         // Change opcode BLX -> BL
632         R.Lo = R.Lo & ~FixupInfo<Thumb_Call>::LoBitNoBlx;
633       }
634     }
635 
636     if (LLVM_LIKELY(ArmCfg.J1J2BranchEncoding)) {
637       if (!isInt<25>(Value))
638         return makeTargetOutOfRangeError(G, B, E);
639       writeImmediate<Thumb_Call>(R, encodeImmBT4BlT1BlxT2_J1J2(Value));
640     } else {
641       if (!isInt<22>(Value))
642         return makeTargetOutOfRangeError(G, B, E);
643       writeImmediate<Thumb_Call>(R, encodeImmBT4BlT1BlxT2(Value));
644     }
645 
646     assert(((R.Lo & FixupInfo<Thumb_Call>::LoBitNoBlx) ||
647             (R.Lo & FixupInfo<Thumb_Call>::LoBitH) == 0) &&
648            "Opcode BLX implies H bit is clear (avoid UB in BLX T2)");
649     return Error::success();
650   }
651 
652   case Thumb_MovwAbsNC: {
653     uint16_t Value = (TargetAddress + Addend) & 0xffff;
654     writeImmediate<Thumb_MovwAbsNC>(R, encodeImmMovtT1MovwT3(Value));
655     return Error::success();
656   }
657   case Thumb_MovtAbs: {
658     uint16_t Value = ((TargetAddress + Addend) >> 16) & 0xffff;
659     writeImmediate<Thumb_MovtAbs>(R, encodeImmMovtT1MovwT3(Value));
660     return Error::success();
661   }
662   case Thumb_MovwPrelNC: {
663     uint16_t Value = ((TargetAddress + Addend - FixupAddress) & 0xffff);
664     writeImmediate<Thumb_MovwPrelNC>(R, encodeImmMovtT1MovwT3(Value));
665     return Error::success();
666   }
667   case Thumb_MovtPrel: {
668     uint16_t Value = (((TargetAddress + Addend - FixupAddress) >> 16) & 0xffff);
669     writeImmediate<Thumb_MovtPrel>(R, encodeImmMovtT1MovwT3(Value));
670     return Error::success();
671   }
672 
673   default:
674     return make_error<JITLinkError>(
675         "In graph " + G.getName() + ", section " + B.getSection().getName() +
676         " encountered unfixable aarch32 edge kind " +
677         G.getEdgeKindName(E.getKind()));
678   }
679 }
680 
681 const uint8_t Thumbv7ABS[] = {
682     0x40, 0xf2, 0x00, 0x0c, // movw r12, #0x0000    ; lower 16-bit
683     0xc0, 0xf2, 0x00, 0x0c, // movt r12, #0x0000    ; upper 16-bit
684     0x60, 0x47              // bx   r12
685 };
686 
687 template <>
688 Symbol &StubsManager<Thumbv7>::createEntry(LinkGraph &G, Symbol &Target) {
689   constexpr uint64_t Alignment = 4;
690   Block &B = addStub(G, Thumbv7ABS, Alignment);
691   LLVM_DEBUG({
692     const char *StubPtr = B.getContent().data();
693     HalfWords Reg12 = encodeRegMovtT1MovwT3(12);
694     assert(checkRegister<Thumb_MovwAbsNC>(StubPtr, Reg12) &&
695            checkRegister<Thumb_MovtAbs>(StubPtr + 4, Reg12) &&
696            "Linker generated stubs may only corrupt register r12 (IP)");
697   });
698   B.addEdge(Thumb_MovwAbsNC, 0, Target, 0);
699   B.addEdge(Thumb_MovtAbs, 4, Target, 0);
700   Symbol &Stub = G.addAnonymousSymbol(B, 0, B.getSize(), true, false);
701   Stub.setTargetFlags(ThumbSymbol);
702   return Stub;
703 }
704 
705 const char *getEdgeKindName(Edge::Kind K) {
706 #define KIND_NAME_CASE(K)                                                      \
707   case K:                                                                      \
708     return #K;
709 
710   switch (K) {
711     KIND_NAME_CASE(Data_Delta32)
712     KIND_NAME_CASE(Data_Pointer32)
713     KIND_NAME_CASE(Arm_Call)
714     KIND_NAME_CASE(Arm_Jump24)
715     KIND_NAME_CASE(Arm_MovwAbsNC)
716     KIND_NAME_CASE(Arm_MovtAbs)
717     KIND_NAME_CASE(Thumb_Call)
718     KIND_NAME_CASE(Thumb_Jump24)
719     KIND_NAME_CASE(Thumb_MovwAbsNC)
720     KIND_NAME_CASE(Thumb_MovtAbs)
721     KIND_NAME_CASE(Thumb_MovwPrelNC)
722     KIND_NAME_CASE(Thumb_MovtPrel)
723   default:
724     return getGenericEdgeKindName(K);
725   }
726 #undef KIND_NAME_CASE
727 }
728 
729 const char *getCPUArchName(ARMBuildAttrs::CPUArch K) {
730 #define CPUARCH_NAME_CASE(K)                                                   \
731   case K:                                                                      \
732     return #K;
733 
734   using namespace ARMBuildAttrs;
735   switch (K) {
736     CPUARCH_NAME_CASE(Pre_v4)
737     CPUARCH_NAME_CASE(v4)
738     CPUARCH_NAME_CASE(v4T)
739     CPUARCH_NAME_CASE(v5T)
740     CPUARCH_NAME_CASE(v5TE)
741     CPUARCH_NAME_CASE(v5TEJ)
742     CPUARCH_NAME_CASE(v6)
743     CPUARCH_NAME_CASE(v6KZ)
744     CPUARCH_NAME_CASE(v6T2)
745     CPUARCH_NAME_CASE(v6K)
746     CPUARCH_NAME_CASE(v7)
747     CPUARCH_NAME_CASE(v6_M)
748     CPUARCH_NAME_CASE(v6S_M)
749     CPUARCH_NAME_CASE(v7E_M)
750     CPUARCH_NAME_CASE(v8_A)
751     CPUARCH_NAME_CASE(v8_R)
752     CPUARCH_NAME_CASE(v8_M_Base)
753     CPUARCH_NAME_CASE(v8_M_Main)
754     CPUARCH_NAME_CASE(v8_1_M_Main)
755     CPUARCH_NAME_CASE(v9_A)
756   }
757   llvm_unreachable("Missing CPUArch in switch?");
758 #undef CPUARCH_NAME_CASE
759 }
760 
761 } // namespace aarch32
762 } // namespace jitlink
763 } // namespace llvm
764