[llvm] [JITLink][AArch32] Add dynamic lookup for relocation fixup infos (PR #71649)

Stefan Gränitz via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 8 02:21:00 PST 2023


https://github.com/weliveindetail created https://github.com/llvm/llvm-project/pull/71649

Specifying relocation fixup constants with name and type facilitates readability and compile-time checks. The `FixupInfo<EdgeKind>` facade organizes the information into entries per relocation type and provides uniform access across Arm and Thumb relocations. Since it uses template specializations, it doesn't limit potential entries. We cannot access the entries dynamically though, because `EdgeKind` must be given as a compile-time constant. It's a drawback that this patch aims to compensate for.

>From 7458391ec700bf50601cc49b2b2950267407201f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eymen=20=C3=9Cnay?= <eymenunay at outlook.com>
Date: Thu, 26 Oct 2023 18:26:50 +0300
Subject: [PATCH 1/2] [JITLink][AArch32] Add support for
 ELF::R_ARM_THM_MOV{W_PREL_NC,T_ABS}

Support for ELF::R_ARM_THM_MOVW_PREL_NC and ELF::R_ARM_THM_MOVW_PREL_NC
is added. Move instructions with PC-relative immediates can be handled
in Thumb mode with this addition.
---
 .../llvm/ExecutionEngine/JITLink/aarch32.h    | 10 +++++-
 .../ExecutionEngine/JITLink/ELF_aarch32.cpp   |  8 +++++
 llvm/lib/ExecutionEngine/JITLink/aarch32.cpp  | 18 +++++++++++
 .../JITLink/AArch32/ELF_static_thumb_reloc.s  | 31 ++++++++++++++++++-
 4 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
index 3f36b53d6684a79..97999a61dfe7334 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
@@ -89,7 +89,15 @@ enum EdgeKind_aarch32 : Edge::Kind {
   /// Write immediate value to the top halfword of the destination register
   Thumb_MovtAbs,
 
-  LastThumbRelocation = Thumb_MovtAbs,
+  /// Write PC-relative immediate value to the lower halfword of the destination
+  /// register
+  Thumb_MovwPrelNC,
+
+  /// Write PC-relative immediate value to the top halfword of the destination
+  /// register
+  Thumb_MovtPrel,
+
+  LastThumbRelocation = Thumb_MovtPrel,
 };
 
 /// Flags enum for AArch32-specific symbol properties
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp
index 6359ceb4c51749c..b6b63691d8408ea 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp
@@ -53,6 +53,10 @@ Expected<aarch32::EdgeKind_aarch32> getJITLinkEdgeKind(uint32_t ELFType) {
     return aarch32::Thumb_MovwAbsNC;
   case ELF::R_ARM_THM_MOVT_ABS:
     return aarch32::Thumb_MovtAbs;
+  case ELF::R_ARM_THM_MOVW_PREL_NC:
+    return aarch32::Thumb_MovwPrelNC;
+  case ELF::R_ARM_THM_MOVT_PREL:
+    return aarch32::Thumb_MovtPrel;
   }
 
   return make_error<JITLinkError>(
@@ -83,6 +87,10 @@ Expected<uint32_t> getELFRelocationType(Edge::Kind Kind) {
     return ELF::R_ARM_THM_MOVW_ABS_NC;
   case aarch32::Thumb_MovtAbs:
     return ELF::R_ARM_THM_MOVT_ABS;
+  case aarch32::Thumb_MovwPrelNC:
+    return ELF::R_ARM_THM_MOVW_PREL_NC;
+  case aarch32::Thumb_MovtPrel:
+    return ELF::R_ARM_THM_MOVT_PREL;
   }
 
   return make_error<JITLinkError>(formatv("Invalid aarch32 edge {0:d}: ",
diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
index 4aed64966654420..c3823f985ce182d 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
@@ -377,12 +377,14 @@ Expected<int64_t> readAddendThumb(LinkGraph &G, Block &B, const Edge &E,
                   : decodeImmBT4BlT1BlxT2(R.Hi, R.Lo);
 
   case Thumb_MovwAbsNC:
+  case Thumb_MovwPrelNC:
     if (!checkOpcode<Thumb_MovwAbsNC>(R))
       return makeUnexpectedOpcodeError(G, R, Kind);
     // Initial addend is interpreted as a signed value
     return SignExtend64<16>(decodeImmMovtT1MovwT3(R.Hi, R.Lo));
 
   case Thumb_MovtAbs:
+  case Thumb_MovtPrel:
     if (!checkOpcode<Thumb_MovtAbs>(R))
       return makeUnexpectedOpcodeError(G, R, Kind);
     // Initial addend is interpreted as a signed value
@@ -610,6 +612,20 @@ Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E,
     writeImmediate<Thumb_MovtAbs>(R, encodeImmMovtT1MovwT3(Value));
     return Error::success();
   }
+  case Thumb_MovwPrelNC: {
+    if (!checkOpcode<Thumb_MovwAbsNC>(R))
+      return makeUnexpectedOpcodeError(G, R, Kind);
+    uint16_t Value = ((TargetAddress + Addend - FixupAddress) & 0xffff);
+    writeImmediate<Thumb_MovwAbsNC>(R, encodeImmMovtT1MovwT3(Value));
+    return Error::success();
+  }
+  case Thumb_MovtPrel: {
+    if (!checkOpcode<Thumb_MovtAbs>(R))
+      return makeUnexpectedOpcodeError(G, R, Kind);
+    uint16_t Value = (((TargetAddress + Addend - FixupAddress) >> 16) & 0xffff);
+    writeImmediate<Thumb_MovtAbs>(R, encodeImmMovtT1MovwT3(Value));
+    return Error::success();
+  }
 
   default:
     return make_error<JITLinkError>(
@@ -659,6 +675,8 @@ const char *getEdgeKindName(Edge::Kind K) {
     KIND_NAME_CASE(Thumb_Jump24)
     KIND_NAME_CASE(Thumb_MovwAbsNC)
     KIND_NAME_CASE(Thumb_MovtAbs)
+    KIND_NAME_CASE(Thumb_MovwPrelNC)
+    KIND_NAME_CASE(Thumb_MovtPrel)
   default:
     return getGenericEdgeKindName(K);
   }
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_static_thumb_reloc.s b/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_static_thumb_reloc.s
index c694a65ae1061aa..a523ada96ed32a6 100644
--- a/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_static_thumb_reloc.s
+++ b/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_static_thumb_reloc.s
@@ -2,7 +2,8 @@
 # RUN: llvm-objdump -r %t.o | FileCheck --check-prefix=CHECK-TYPE %s
 # RUN: llvm-objdump --disassemble %t.o | FileCheck --check-prefix=CHECK-INSTR %s
 # RUN: llvm-jitlink -noexec -slab-address 0x76ff0000 -slab-allocate 10Kb \
-# RUN:              -slab-page-size 4096 -show-entry-es -check %s %t.o
+# RUN:              -slab-page-size 4096 -abs external_func=0x76bbe880 \
+# RUN:              -check %s %t.o
 
 
 	.text
@@ -95,6 +96,34 @@ data_symbol:
 
 	.text
 
+# CHECK-TYPE: {{[0-9a-f]+}} R_ARM_THM_MOVW_PREL_NC external_func
+# CHECK-INSTR: 	00000014 <movw_prel>:
+# CHECK-INSTR: 	      14: f240 0000     movw    r0, #0x0
+# jitlink-check: decode_operand(movw_prel, 1) = \
+# jitlink-check:              ((external_func - next_pc(movw_prel) + 4)&0x0000ffff)
+.globl	movw_prel
+.type	movw_prel,%function
+.p2align	1
+.code	16
+.thumb_func
+movw_prel:
+	movw r0, :lower16:external_func - .
+	.size	movw_prel,	.-movw_prel
+
+# CHECK-TYPE: {{[0-9a-f]+}} R_ARM_THM_MOVT_PREL external_func 
+# CHECK-INSTR: 	00000018 <movt_prel>:
+# CHECK-INSTR: 	      18: f2c0 0000    movt    r0, #0x0
+# jitlink-check: decode_operand(movt_prel, 2) = \
+# jitlink-check:               ((external_func - next_pc(movt_prel) + 4)&0xffff0000>>16)
+.globl	movt_prel
+.type	movt_prel,%function
+.p2align	1
+.code	16
+.thumb_func
+movt_prel:
+	movt r0, :upper16:external_func - .
+	.size	movt_prel,	.-movt_prel
+
 # Empty main function for jitlink to be happy
 	.globl	main
 	.type	main,%function

>From f94662f6412e2ba3debd33aa04f2b63b277d5dbc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Tue, 7 Nov 2023 18:50:35 +0100
Subject: [PATCH 2/2] [JITLink][AArch32] Add dynamic lookup for relocation
 fixup infos

---
 .../llvm/ExecutionEngine/JITLink/aarch32.h    |  94 ++++++++++++---
 .../ExecutionEngine/JITLink/ELF_aarch32.cpp   |   2 +
 llvm/lib/ExecutionEngine/JITLink/aarch32.cpp  | 114 +++++++++---------
 3 files changed, 136 insertions(+), 74 deletions(-)

diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
index 97999a61dfe7334..95782e9bc6f1228 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
@@ -163,49 +163,83 @@ struct HalfWords {
   const uint16_t Lo; // Second halfword
 };
 
-/// Collection of named constants per fixup kind. It may contain but is not
-/// limited to the following entries:
+struct FixupInfoBaseArm {
+  virtual ~FixupInfoBaseArm() {}
+  virtual bool checkOpcode(uint32_t Wd) const = 0;
+};
+
+struct FixupInfoBaseThumb {
+  virtual ~FixupInfoBaseThumb() {}
+  virtual bool checkOpcode(uint16_t Hi, uint16_t Lo) const = 0;
+};
+
+template <EdgeKind_aarch32 Kind> struct FixupInfoArm : public FixupInfoBaseArm {
+  bool checkOpcode(uint32_t Wd) const override;
+};
+
+template <EdgeKind_aarch32 Kind> struct FixupInfoThumb : public FixupInfoBaseThumb {
+  bool checkOpcode(uint16_t Hi, uint16_t Lo) const override;
+};
+
+/// Collection of named constants per fixup kind
 ///
+/// Mandatory entries:
 ///   Opcode      - Values of the op-code bits in the instruction, with
 ///                 unaffected bits nulled
 ///   OpcodeMask  - Mask with all bits set that encode the op-code
+///
+/// Other common entries:
 ///   ImmMask     - Mask with all bits set that encode the immediate value
 ///   RegMask     - Mask with all bits set that encode the register
 ///
+/// Specializations can add further custom fields without restrictions.
+///
 template <EdgeKind_aarch32 Kind> struct FixupInfo {};
 
-template <> struct FixupInfo<Arm_Jump24> {
+namespace {
+template <EdgeKind_aarch32 Kind>
+struct FixupInfoArmBranch : public FixupInfoArm<Kind> {
   static constexpr uint32_t Opcode = 0x0a000000;
-  static constexpr uint32_t OpcodeMask = 0x0f000000;
   static constexpr uint32_t ImmMask = 0x00ffffff;
-  static constexpr uint32_t Unconditional = 0xe0000000;
-  static constexpr uint32_t CondMask = 0xe0000000; // excluding BLX bit
+};
+} // namespace
+
+template <> struct FixupInfo<Arm_Jump24> : public FixupInfoArmBranch<Arm_Jump24> {
+  static constexpr uint32_t OpcodeMask = 0x0f000000;
 };
 
-template <> struct FixupInfo<Arm_Call> : public FixupInfo<Arm_Jump24> {
+template <> struct FixupInfo<Arm_Call> : public FixupInfoArmBranch<Arm_Call> {
   static constexpr uint32_t OpcodeMask = 0x0e000000;
+  static constexpr uint32_t CondMask = 0xe0000000; // excluding BLX bit
+  static constexpr uint32_t Unconditional = 0xe0000000;
   static constexpr uint32_t BitH = 0x01000000;
   static constexpr uint32_t BitBlx = 0x10000000;
 };
 
-template <> struct FixupInfo<Arm_MovtAbs> {
-  static constexpr uint32_t Opcode = 0x03400000;
+namespace {
+template <EdgeKind_aarch32 Kind>
+struct FixupInfoArmMov : public FixupInfoArm<Kind> {
   static constexpr uint32_t OpcodeMask = 0x0ff00000;
   static constexpr uint32_t ImmMask = 0x000f0fff;
   static constexpr uint32_t RegMask = 0x0000f000;
 };
+} // namespace
+
+template <> struct FixupInfo<Arm_MovtAbs> : public FixupInfoArmMov<Arm_MovtAbs> {
+  static constexpr uint32_t Opcode = 0x03400000;
+};
 
-template <> struct FixupInfo<Arm_MovwAbsNC> : public FixupInfo<Arm_MovtAbs> {
+template <> struct FixupInfo<Arm_MovwAbsNC> : public FixupInfoArmMov<Arm_MovwAbsNC> {
   static constexpr uint32_t Opcode = 0x03000000;
 };
 
-template <> struct FixupInfo<Thumb_Jump24> {
+template <> struct FixupInfo<Thumb_Jump24> : public FixupInfoThumb<Thumb_Jump24> {
   static constexpr HalfWords Opcode{0xf000, 0x8000};
   static constexpr HalfWords OpcodeMask{0xf800, 0x8000};
   static constexpr HalfWords ImmMask{0x07ff, 0x2fff};
 };
 
-template <> struct FixupInfo<Thumb_Call> {
+template <> struct FixupInfo<Thumb_Call> : public FixupInfoThumb<Thumb_Call> {
   static constexpr HalfWords Opcode{0xf000, 0xc000};
   static constexpr HalfWords OpcodeMask{0xf800, 0xc000};
   static constexpr HalfWords ImmMask{0x07ff, 0x2fff};
@@ -213,18 +247,48 @@ template <> struct FixupInfo<Thumb_Call> {
   static constexpr uint16_t LoBitNoBlx = 0x1000;
 };
 
-template <> struct FixupInfo<Thumb_MovtAbs> {
-  static constexpr HalfWords Opcode{0xf2c0, 0x0000};
+namespace {
+template <EdgeKind_aarch32 Kind>
+struct FixupInfoThumbMov : public FixupInfoThumb<Kind> {
   static constexpr HalfWords OpcodeMask{0xfbf0, 0x8000};
   static constexpr HalfWords ImmMask{0x040f, 0x70ff};
   static constexpr HalfWords RegMask{0x0000, 0x0f00};
 };
+} // namespace
+
+template <>
+struct FixupInfo<Thumb_MovtAbs> : public FixupInfoThumbMov<Thumb_MovtAbs> {
+  static constexpr HalfWords Opcode{0xf2c0, 0x0000};
+};
+
+template <>
+struct FixupInfo<Thumb_MovtPrel> : public FixupInfoThumbMov<Thumb_MovtPrel> {
+  static constexpr HalfWords Opcode{0xf2c0, 0x0000};
+};
+
+template <>
+struct FixupInfo<Thumb_MovwAbsNC> : public FixupInfoThumbMov<Thumb_MovwAbsNC> {
+  static constexpr HalfWords Opcode{0xf240, 0x0000};
+};
 
 template <>
-struct FixupInfo<Thumb_MovwAbsNC> : public FixupInfo<Thumb_MovtAbs> {
+struct FixupInfo<Thumb_MovwPrelNC> : public FixupInfoThumbMov<Thumb_MovwPrelNC> {
   static constexpr HalfWords Opcode{0xf240, 0x0000};
 };
 
+template <EdgeKind_aarch32 Kind>
+bool FixupInfoArm<Kind>::checkOpcode(uint32_t Wd) const {
+  return (Wd & FixupInfo<Kind>::OpcodeMask) == FixupInfo<Kind>::Opcode;
+}
+
+template <EdgeKind_aarch32 Kind>
+bool FixupInfoThumb<Kind>::checkOpcode(uint16_t Hi, uint16_t Lo) const {
+  return (Hi & FixupInfo<Kind>::OpcodeMask.Hi) == FixupInfo<Kind>::Opcode.Hi &&
+         (Lo & FixupInfo<Kind>::OpcodeMask.Lo) == FixupInfo<Kind>::Opcode.Lo;
+}
+
+void populateFixupInfos();
+
 /// Helper function to read the initial addend for Data-class relocations.
 Expected<int64_t> readAddendData(LinkGraph &G, Block &B, const Edge &E);
 
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp
index b6b63691d8408ea..f5d24817595dd7d 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp
@@ -233,6 +233,8 @@ createLinkGraphFromELFObject_aarch32(MemoryBufferRef ObjectBuffer) {
            << ObjectBuffer.getBufferIdentifier() << "...\n";
   });
 
+  aarch32::populateFixupInfos();
+
   auto ELFObj = ObjectFile::createELFObjectFile(ObjectBuffer);
   if (!ELFObj)
     return ELFObj.takeError();
diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
index c3823f985ce182d..303dac19da2b99f 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
@@ -224,7 +224,6 @@ struct WritableArmRelocation {
 };
 
 struct ArmRelocation {
-
   ArmRelocation(const char *FixupPtr)
       : Wd{*reinterpret_cast<const support::ulittle32_t *>(FixupPtr)} {}
 
@@ -248,15 +247,49 @@ Error makeUnexpectedOpcodeError(const LinkGraph &G, const ArmRelocation &R,
               static_cast<uint32_t>(R.Wd), G.getEdgeKindName(Kind)));
 }
 
-template <EdgeKind_aarch32 Kind> bool checkOpcode(const ThumbRelocation &R) {
-  uint16_t Hi = R.Hi & FixupInfo<Kind>::OpcodeMask.Hi;
-  uint16_t Lo = R.Lo & FixupInfo<Kind>::OpcodeMask.Lo;
-  return Hi == FixupInfo<Kind>::Opcode.Hi && Lo == FixupInfo<Kind>::Opcode.Lo;
+static auto &getFixupInfoTableArm() {
+  static constexpr size_t Items = LastArmRelocation - FirstArmRelocation + 1;
+  static std::array<std::unique_ptr<FixupInfoBaseArm>, Items> FixupInfoTableArm;
+  return FixupInfoTableArm;
+}
+
+static auto &getFixupInfoTableThumb() {
+  static constexpr size_t Items = LastThumbRelocation - FirstThumbRelocation + 1;
+  static std::array<std::unique_ptr<FixupInfoBaseThumb>, Items> FixupInfoTableThumb;
+  return FixupInfoTableThumb;
 }
 
-template <EdgeKind_aarch32 Kind> bool checkOpcode(const ArmRelocation &R) {
-  uint32_t Wd = R.Wd & FixupInfo<Kind>::OpcodeMask;
-  return Wd == FixupInfo<Kind>::Opcode;
+template <EdgeKind_aarch32 It, EdgeKind_aarch32 Last, typename TableT>
+void populateFixupInfos(TableT &Table, size_t Idx = 0) {
+  Table[Idx] = std::make_unique<FixupInfo<It>>();
+  if constexpr (It < Last) {
+    constexpr auto Next = EdgeKind_aarch32((Edge::Kind)It + 1);
+    populateFixupInfos<Next, Last>(Table, Idx + 1);
+  }
+}
+
+void populateFixupInfos() {
+  static std::once_flag Flag;
+  std::call_once(Flag, []() {
+    populateFixupInfos<FirstArmRelocation, LastArmRelocation>(getFixupInfoTableArm());
+    populateFixupInfos<FirstThumbRelocation, LastThumbRelocation>(getFixupInfoTableThumb());
+  });
+}
+
+static bool checkOpcode(const ArmRelocation &R, Edge::Kind Kind) {
+  assert(Kind >= FirstArmRelocation && Kind <= LastArmRelocation &&
+         "Edge kind is no Arm relocation");
+  assert(getFixupInfoTableArm().at(Kind - FirstArmRelocation) != nullptr &&
+         "Call populateFixupInfos() before dynamic access");
+  return getFixupInfoTableArm()[Kind - FirstArmRelocation]->checkOpcode(R.Wd);
+}
+
+static bool checkOpcode(const ThumbRelocation &R, Edge::Kind Kind) {
+  assert(Kind >= FirstThumbRelocation && Kind <= LastThumbRelocation &&
+         "Edge kind is no Thumb relocation");
+  assert(getFixupInfoTableThumb().at(Kind - FirstThumbRelocation) != nullptr &&
+         "Call populateFixupInfos() before dynamic access");
+  return getFixupInfoTableThumb()[Kind - FirstThumbRelocation]->checkOpcode(R.Hi, R.Lo);
 }
 
 template <EdgeKind_aarch32 Kind>
@@ -326,26 +359,16 @@ Expected<int64_t> readAddendData(LinkGraph &G, Block &B, const Edge &E) {
 Expected<int64_t> readAddendArm(LinkGraph &G, Block &B, const Edge &E) {
   ArmRelocation R(B.getContent().data() + E.getOffset());
   Edge::Kind Kind = E.getKind();
+  if (!checkOpcode(R, Kind))
+      return makeUnexpectedOpcodeError(G, R, Kind);
 
   switch (Kind) {
   case Arm_Call:
-    if (!checkOpcode<Arm_Call>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
-    return decodeImmBA1BlA1BlxA2(R.Wd);
-
   case Arm_Jump24:
-    if (!checkOpcode<Arm_Jump24>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
     return decodeImmBA1BlA1BlxA2(R.Wd);
 
-  case Arm_MovwAbsNC:
-    if (!checkOpcode<Arm_MovwAbsNC>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
-    return decodeImmMovtA1MovwA2(R.Wd);
-
   case Arm_MovtAbs:
-    if (!checkOpcode<Arm_MovtAbs>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
+  case Arm_MovwAbsNC:
     return decodeImmMovtA1MovwA2(R.Wd);
 
   default:
@@ -360,33 +383,23 @@ Expected<int64_t> readAddendThumb(LinkGraph &G, Block &B, const Edge &E,
                                   const ArmConfig &ArmCfg) {
   ThumbRelocation R(B.getContent().data() + E.getOffset());
   Edge::Kind Kind = E.getKind();
+  if (!checkOpcode(R, Kind))
+      return makeUnexpectedOpcodeError(G, R, Kind);
 
   switch (Kind) {
   case Thumb_Call:
-    if (!checkOpcode<Thumb_Call>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
+  case Thumb_Jump24:
     return LLVM_LIKELY(ArmCfg.J1J2BranchEncoding)
                ? decodeImmBT4BlT1BlxT2_J1J2(R.Hi, R.Lo)
                : decodeImmBT4BlT1BlxT2(R.Hi, R.Lo);
 
-  case Thumb_Jump24:
-    if (!checkOpcode<Thumb_Jump24>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
-    return LLVM_LIKELY(ArmCfg.J1J2BranchEncoding)
-                  ? decodeImmBT4BlT1BlxT2_J1J2(R.Hi, R.Lo)
-                  : decodeImmBT4BlT1BlxT2(R.Hi, R.Lo);
-
   case Thumb_MovwAbsNC:
   case Thumb_MovwPrelNC:
-    if (!checkOpcode<Thumb_MovwAbsNC>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
     // Initial addend is interpreted as a signed value
     return SignExtend64<16>(decodeImmMovtT1MovwT3(R.Hi, R.Lo));
 
   case Thumb_MovtAbs:
   case Thumb_MovtPrel:
-    if (!checkOpcode<Thumb_MovtAbs>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
     // Initial addend is interpreted as a signed value
     return SignExtend64<16>(decodeImmMovtT1MovwT3(R.Hi, R.Lo));
 
@@ -448,6 +461,9 @@ Error applyFixupData(LinkGraph &G, Block &B, const Edge &E) {
 Error applyFixupArm(LinkGraph &G, Block &B, const Edge &E) {
   WritableArmRelocation R(B.getAlreadyMutableContent().data() + E.getOffset());
   Edge::Kind Kind = E.getKind();
+  if (!checkOpcode(R, Kind))
+      return makeUnexpectedOpcodeError(G, R, Kind);
+
   uint64_t FixupAddress = (B.getAddress() + E.getOffset()).getValue();
   int64_t Addend = E.getAddend();
   Symbol &TargetSymbol = E.getTarget();
@@ -455,8 +471,6 @@ Error applyFixupArm(LinkGraph &G, Block &B, const Edge &E) {
 
   switch (Kind) {
   case Arm_Jump24: {
-    if (!checkOpcode<Arm_Jump24>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
     if (hasTargetFlags(TargetSymbol, ThumbSymbol))
       return make_error<JITLinkError>("Branch relocation needs interworking "
                                       "stub when bridging to Thumb: " +
@@ -471,8 +485,6 @@ Error applyFixupArm(LinkGraph &G, Block &B, const Edge &E) {
     return Error::success();
   }
   case Arm_Call: {
-    if (!checkOpcode<Arm_Call>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
     if ((R.Wd & FixupInfo<Arm_Call>::CondMask) !=
         FixupInfo<Arm_Call>::Unconditional)
       return make_error<JITLinkError>("Relocation expects an unconditional "
@@ -503,15 +515,11 @@ Error applyFixupArm(LinkGraph &G, Block &B, const Edge &E) {
     return Error::success();
   }
   case Arm_MovwAbsNC: {
-    if (!checkOpcode<Arm_MovwAbsNC>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
     uint16_t Value = (TargetAddress + Addend) & 0xffff;
     writeImmediate<Arm_MovwAbsNC>(R, encodeImmMovtA1MovwA2(Value));
     return Error::success();
   }
   case Arm_MovtAbs: {
-    if (!checkOpcode<Arm_MovtAbs>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
     uint16_t Value = ((TargetAddress + Addend) >> 16) & 0xffff;
     writeImmediate<Arm_MovtAbs>(R, encodeImmMovtA1MovwA2(Value));
     return Error::success();
@@ -528,8 +536,10 @@ Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E,
                       const ArmConfig &ArmCfg) {
   WritableThumbRelocation R(B.getAlreadyMutableContent().data() +
                             E.getOffset());
-
   Edge::Kind Kind = E.getKind();
+  if (!checkOpcode(R, Kind))
+      return makeUnexpectedOpcodeError(G, R, Kind);
+
   uint64_t FixupAddress = (B.getAddress() + E.getOffset()).getValue();
   int64_t Addend = E.getAddend();
   Symbol &TargetSymbol = E.getTarget();
@@ -537,8 +547,6 @@ Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E,
 
   switch (Kind) {
   case Thumb_Jump24: {
-    if (!checkOpcode<Thumb_Jump24>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
     if (!hasTargetFlags(TargetSymbol, ThumbSymbol))
       return make_error<JITLinkError>("Branch relocation needs interworking "
                                       "stub when bridging to ARM: " +
@@ -559,9 +567,6 @@ Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E,
   }
 
   case Thumb_Call: {
-    if (!checkOpcode<Thumb_Call>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
-
     int64_t Value = TargetAddress - FixupAddress + Addend;
 
     // The call instruction itself is Thumb. The call destination can either be
@@ -598,32 +603,23 @@ Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E,
   }
 
   case Thumb_MovwAbsNC: {
-    if (!checkOpcode<Thumb_MovwAbsNC>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
     uint16_t Value = (TargetAddress + Addend) & 0xffff;
     writeImmediate<Thumb_MovwAbsNC>(R, encodeImmMovtT1MovwT3(Value));
     return Error::success();
   }
-
   case Thumb_MovtAbs: {
-    if (!checkOpcode<Thumb_MovtAbs>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
     uint16_t Value = ((TargetAddress + Addend) >> 16) & 0xffff;
     writeImmediate<Thumb_MovtAbs>(R, encodeImmMovtT1MovwT3(Value));
     return Error::success();
   }
   case Thumb_MovwPrelNC: {
-    if (!checkOpcode<Thumb_MovwAbsNC>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
     uint16_t Value = ((TargetAddress + Addend - FixupAddress) & 0xffff);
-    writeImmediate<Thumb_MovwAbsNC>(R, encodeImmMovtT1MovwT3(Value));
+    writeImmediate<Thumb_MovwPrelNC>(R, encodeImmMovtT1MovwT3(Value));
     return Error::success();
   }
   case Thumb_MovtPrel: {
-    if (!checkOpcode<Thumb_MovtAbs>(R))
-      return makeUnexpectedOpcodeError(G, R, Kind);
     uint16_t Value = (((TargetAddress + Addend - FixupAddress) >> 16) & 0xffff);
-    writeImmediate<Thumb_MovtAbs>(R, encodeImmMovtT1MovwT3(Value));
+    writeImmediate<Thumb_MovtPrel>(R, encodeImmMovtT1MovwT3(Value));
     return Error::success();
   }
 



More information about the llvm-commits mailing list