File indexing completed on 2026-05-10 08:43:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_EXECUTIONENGINE_JITLINK_AARCH32
0014 #define LLVM_EXECUTIONENGINE_JITLINK_AARCH32
0015
0016 #include "TableManager.h"
0017 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
0018 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
0019 #include "llvm/Support/ARMBuildAttributes.h"
0020 #include "llvm/Support/Error.h"
0021
0022 namespace llvm {
0023 namespace jitlink {
0024 namespace aarch32 {
0025
0026
0027 bool hasTargetFlags(Symbol &Sym, TargetFlagsType Flags);
0028
0029
0030 enum EdgeKind_aarch32 : Edge::Kind {
0031
0032
0033
0034
0035
0036 FirstDataRelocation = Edge::FirstRelocation,
0037
0038
0039 Data_Delta32 = FirstDataRelocation,
0040
0041
0042 Data_Pointer32,
0043
0044
0045 Data_PRel31,
0046
0047
0048 Data_RequestGOTAndTransformToDelta32,
0049
0050 LastDataRelocation = Data_RequestGOTAndTransformToDelta32,
0051
0052
0053
0054
0055 FirstArmRelocation,
0056
0057
0058
0059
0060
0061 Arm_Call = FirstArmRelocation,
0062
0063
0064
0065
0066 Arm_Jump24,
0067
0068
0069 Arm_MovwAbsNC,
0070
0071
0072 Arm_MovtAbs,
0073
0074 LastArmRelocation = Arm_MovtAbs,
0075
0076
0077
0078
0079 FirstThumbRelocation,
0080
0081
0082
0083
0084
0085 Thumb_Call = FirstThumbRelocation,
0086
0087
0088
0089
0090 Thumb_Jump24,
0091
0092
0093 Thumb_MovwAbsNC,
0094
0095
0096 Thumb_MovtAbs,
0097
0098
0099
0100 Thumb_MovwPrelNC,
0101
0102
0103
0104 Thumb_MovtPrel,
0105
0106 LastThumbRelocation = Thumb_MovtPrel,
0107
0108
0109 None,
0110
0111 LastRelocation = None,
0112 };
0113
0114
0115 enum TargetFlags_aarch32 : TargetFlagsType {
0116 ThumbSymbol = 1 << 0,
0117 };
0118
0119
0120 const char *getCPUArchName(ARMBuildAttrs::CPUArch K);
0121
0122
0123 const char *getEdgeKindName(Edge::Kind K);
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 enum class StubsFlavor {
0137 Undefined = 0,
0138 pre_v7,
0139 v7,
0140 };
0141
0142
0143 struct ArmConfig {
0144 bool J1J2BranchEncoding = false;
0145 StubsFlavor Stubs = StubsFlavor::Undefined;
0146
0147 bool Target1Rel = false;
0148 };
0149
0150
0151 inline ArmConfig getArmConfigForCPUArch(ARMBuildAttrs::CPUArch CPUArch) {
0152 ArmConfig ArmCfg;
0153 if (CPUArch == ARMBuildAttrs::v7 || CPUArch >= ARMBuildAttrs::v7E_M) {
0154 ArmCfg.J1J2BranchEncoding = true;
0155 ArmCfg.Stubs = StubsFlavor::v7;
0156 } else {
0157 ArmCfg.J1J2BranchEncoding = false;
0158 ArmCfg.Stubs = StubsFlavor::pre_v7;
0159 }
0160 return ArmCfg;
0161 }
0162
0163
0164 struct HalfWords {
0165 constexpr HalfWords() : Hi(0), Lo(0) {}
0166 constexpr HalfWords(uint32_t Hi, uint32_t Lo) : Hi(Hi), Lo(Lo) {
0167 assert(isUInt<16>(Hi) && "Overflow in first half-word");
0168 assert(isUInt<16>(Lo) && "Overflow in second half-word");
0169 }
0170 const uint16_t Hi;
0171 const uint16_t Lo;
0172 };
0173
0174
0175 struct FixupInfoBase {
0176 static const FixupInfoBase *getDynFixupInfo(Edge::Kind K);
0177 virtual ~FixupInfoBase() {}
0178 };
0179
0180
0181 struct FixupInfoArm : public FixupInfoBase {
0182 bool (*checkOpcode)(uint32_t Wd) = nullptr;
0183 };
0184
0185
0186 struct FixupInfoThumb : public FixupInfoBase {
0187 bool (*checkOpcode)(uint16_t Hi, uint16_t Lo) = nullptr;
0188 };
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203 template <EdgeKind_aarch32 Kind> struct FixupInfo {};
0204
0205 struct FixupInfoArmBranch : public FixupInfoArm {
0206 static constexpr uint32_t Opcode = 0x0a000000;
0207 static constexpr uint32_t ImmMask = 0x00ffffff;
0208 };
0209
0210 template <> struct FixupInfo<Arm_Jump24> : public FixupInfoArmBranch {
0211 static constexpr uint32_t OpcodeMask = 0x0f000000;
0212 };
0213
0214 template <> struct FixupInfo<Arm_Call> : public FixupInfoArmBranch {
0215 static constexpr uint32_t OpcodeMask = 0x0e000000;
0216 static constexpr uint32_t CondMask = 0xe0000000;
0217 static constexpr uint32_t Unconditional = 0xe0000000;
0218 static constexpr uint32_t BitH = 0x01000000;
0219 static constexpr uint32_t BitBlx = 0x10000000;
0220 };
0221
0222 struct FixupInfoArmMov : public FixupInfoArm {
0223 static constexpr uint32_t OpcodeMask = 0x0ff00000;
0224 static constexpr uint32_t ImmMask = 0x000f0fff;
0225 static constexpr uint32_t RegMask = 0x0000f000;
0226 };
0227
0228 template <> struct FixupInfo<Arm_MovtAbs> : public FixupInfoArmMov {
0229 static constexpr uint32_t Opcode = 0x03400000;
0230 };
0231
0232 template <> struct FixupInfo<Arm_MovwAbsNC> : public FixupInfoArmMov {
0233 static constexpr uint32_t Opcode = 0x03000000;
0234 };
0235
0236 template <> struct FixupInfo<Thumb_Jump24> : public FixupInfoThumb {
0237 static constexpr HalfWords Opcode{0xf000, 0x9000};
0238 static constexpr HalfWords OpcodeMask{0xf800, 0x9000};
0239 static constexpr HalfWords ImmMask{0x07ff, 0x2fff};
0240 };
0241
0242 template <> struct FixupInfo<Thumb_Call> : public FixupInfoThumb {
0243 static constexpr HalfWords Opcode{0xf000, 0xc000};
0244 static constexpr HalfWords OpcodeMask{0xf800, 0xc000};
0245 static constexpr HalfWords ImmMask{0x07ff, 0x2fff};
0246 static constexpr uint16_t LoBitH = 0x0001;
0247 static constexpr uint16_t LoBitNoBlx = 0x1000;
0248 };
0249
0250 struct FixupInfoThumbMov : public FixupInfoThumb {
0251 static constexpr HalfWords OpcodeMask{0xfbf0, 0x8000};
0252 static constexpr HalfWords ImmMask{0x040f, 0x70ff};
0253 static constexpr HalfWords RegMask{0x0000, 0x0f00};
0254 };
0255
0256 template <> struct FixupInfo<Thumb_MovtAbs> : public FixupInfoThumbMov {
0257 static constexpr HalfWords Opcode{0xf2c0, 0x0000};
0258 };
0259
0260 template <> struct FixupInfo<Thumb_MovtPrel> : public FixupInfoThumbMov {
0261 static constexpr HalfWords Opcode{0xf2c0, 0x0000};
0262 };
0263
0264 template <> struct FixupInfo<Thumb_MovwAbsNC> : public FixupInfoThumbMov {
0265 static constexpr HalfWords Opcode{0xf240, 0x0000};
0266 };
0267
0268 template <> struct FixupInfo<Thumb_MovwPrelNC> : public FixupInfoThumbMov {
0269 static constexpr HalfWords Opcode{0xf240, 0x0000};
0270 };
0271
0272
0273 Expected<int64_t> readAddendData(LinkGraph &G, Block &B, Edge::OffsetT Offset,
0274 Edge::Kind Kind);
0275
0276
0277 Expected<int64_t> readAddendArm(LinkGraph &G, Block &B, Edge::OffsetT Offset,
0278 Edge::Kind Kind);
0279
0280
0281 Expected<int64_t> readAddendThumb(LinkGraph &G, Block &B, Edge::OffsetT Offset,
0282 Edge::Kind Kind, const ArmConfig &ArmCfg);
0283
0284
0285
0286 inline Expected<int64_t> readAddend(LinkGraph &G, Block &B,
0287 Edge::OffsetT Offset, Edge::Kind Kind,
0288 const ArmConfig &ArmCfg) {
0289 if (Kind <= LastDataRelocation)
0290 return readAddendData(G, B, Offset, Kind);
0291
0292 if (Kind <= LastArmRelocation)
0293 return readAddendArm(G, B, Offset, Kind);
0294
0295 if (Kind <= LastThumbRelocation)
0296 return readAddendThumb(G, B, Offset, Kind, ArmCfg);
0297
0298 assert(Kind == None && "Not associated with a relocation class");
0299 return 0;
0300 }
0301
0302
0303 Error applyFixupData(LinkGraph &G, Block &B, const Edge &E);
0304
0305
0306 Error applyFixupArm(LinkGraph &G, Block &B, const Edge &E);
0307
0308
0309 Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E,
0310 const ArmConfig &ArmCfg);
0311
0312
0313 inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
0314 const ArmConfig &ArmCfg) {
0315 Edge::Kind Kind = E.getKind();
0316
0317 if (Kind <= LastDataRelocation)
0318 return applyFixupData(G, B, E);
0319
0320 if (Kind <= LastArmRelocation)
0321 return applyFixupArm(G, B, E);
0322
0323 if (Kind <= LastThumbRelocation)
0324 return applyFixupThumb(G, B, E, ArmCfg);
0325
0326 assert(Kind == None && "Not associated with a relocation class");
0327 return Error::success();
0328 }
0329
0330
0331 class GOTBuilder : public TableManager<GOTBuilder> {
0332 public:
0333 static StringRef getSectionName() { return "$__GOT"; }
0334
0335 bool visitEdge(LinkGraph &G, Block *B, Edge &E);
0336 Symbol &createEntry(LinkGraph &G, Symbol &Target);
0337
0338 private:
0339 Section *GOTSection = nullptr;
0340 };
0341
0342
0343
0344
0345
0346 class StubsManager_prev7 {
0347 public:
0348 StubsManager_prev7() = default;
0349
0350
0351 static StringRef getSectionName() {
0352 return "__llvm_jitlink_aarch32_STUBS_prev7";
0353 }
0354
0355
0356 bool visitEdge(LinkGraph &G, Block *B, Edge &E);
0357
0358 private:
0359
0360
0361 struct StubMapEntry {
0362 Block *B = nullptr;
0363 Symbol *ArmEntry = nullptr;
0364 Symbol *ThumbEntry = nullptr;
0365 };
0366
0367 std::pair<StubMapEntry *, bool> getStubMapSlot(StringRef Name) {
0368 auto &&[Stubs, NewStub] = StubMap.try_emplace(Name);
0369 return std::make_pair(&Stubs->second, NewStub);
0370 }
0371
0372 Symbol *getOrCreateSlotEntrypoint(LinkGraph &G, StubMapEntry &Slot,
0373 bool Thumb);
0374
0375 DenseMap<StringRef, StubMapEntry> StubMap;
0376 Section *StubsSection = nullptr;
0377 };
0378
0379
0380 class StubsManager_v7 {
0381 public:
0382 StubsManager_v7() = default;
0383
0384
0385 static StringRef getSectionName() {
0386 return "__llvm_jitlink_aarch32_STUBS_v7";
0387 }
0388
0389
0390 bool visitEdge(LinkGraph &G, Block *B, Edge &E);
0391
0392 private:
0393
0394 using StubMapEntry = std::tuple<Symbol *, Symbol *>;
0395
0396 Symbol *&getStubSymbolSlot(StringRef Name, bool Thumb) {
0397 StubMapEntry &Stubs = StubMap[Name];
0398 if (Thumb)
0399 return std::get<1>(Stubs);
0400 return std::get<0>(Stubs);
0401 }
0402
0403 DenseMap<StringRef, StubMapEntry> StubMap;
0404 Section *StubsSection = nullptr;
0405 };
0406
0407 }
0408 }
0409 }
0410
0411 #endif