[llvm] [JITLink][AArch32] Add TableGen Backend for Instr Encodings (PR #76996)

Eymen Ünay via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 26 10:12:40 PST 2024


https://github.com/eymay updated https://github.com/llvm/llvm-project/pull/76996

>From 6d96b3f0a3fe80f7134f2076491a0784e49d8867 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eymen=20=C3=9Cnay?= <eymenunay at outlook.com>
Date: Fri, 22 Dec 2023 17:56:07 +0300
Subject: [PATCH 1/5] [JITLink][AArch32] Add TableGen Backend for Instr
 Encodings

This TableGen backend uses the Target info in lib/Target/ARM to
produce instruction encodings necessary for JITLink AArch32 backend.
Currently opcode, opcode mask, register mask and immediate mask are
generated. These were used to replace the `mov` related instruction
information in aarch32.h.
---
 .../llvm/ExecutionEngine/JITLink/aarch32.h    |  35 ----
 .../ExecutionEngine/JITLink/CMakeLists.txt    |   5 +
 llvm/lib/ExecutionEngine/JITLink/aarch32.cpp  |   2 +
 .../ExecutionEngine/JITLink/AArch32Tests.cpp  |   2 +
 .../JITLink/JITLinkAArch32.inc                |  58 ++++++
 llvm/utils/TableGen/CMakeLists.txt            |   5 +
 .../TableGen/JITLinkAArch32InstrInfo.cpp      | 196 ++++++++++++++++++
 7 files changed, 268 insertions(+), 35 deletions(-)
 create mode 100644 llvm/unittests/ExecutionEngine/JITLink/JITLinkAArch32.inc
 create mode 100644 llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp

diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
index eda6feb441e672..f81a071e7d773e 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
@@ -219,20 +219,6 @@ template <> struct FixupInfo<Arm_Call> : public FixupInfoArmBranch {
   static constexpr uint32_t BitBlx = 0x10000000;
 };
 
-struct FixupInfoArmMov : public FixupInfoArm {
-  static constexpr uint32_t OpcodeMask = 0x0ff00000;
-  static constexpr uint32_t ImmMask = 0x000f0fff;
-  static constexpr uint32_t RegMask = 0x0000f000;
-};
-
-template <> struct FixupInfo<Arm_MovtAbs> : public FixupInfoArmMov {
-  static constexpr uint32_t Opcode = 0x03400000;
-};
-
-template <> struct FixupInfo<Arm_MovwAbsNC> : public FixupInfoArmMov {
-  static constexpr uint32_t Opcode = 0x03000000;
-};
-
 template <> struct FixupInfo<Thumb_Jump24> : public FixupInfoThumb {
   static constexpr HalfWords Opcode{0xf000, 0x9000};
   static constexpr HalfWords OpcodeMask{0xf800, 0x9000};
@@ -247,27 +233,6 @@ template <> struct FixupInfo<Thumb_Call> : public FixupInfoThumb {
   static constexpr uint16_t LoBitNoBlx = 0x1000;
 };
 
-struct FixupInfoThumbMov : public FixupInfoThumb {
-  static constexpr HalfWords OpcodeMask{0xfbf0, 0x8000};
-  static constexpr HalfWords ImmMask{0x040f, 0x70ff};
-  static constexpr HalfWords RegMask{0x0000, 0x0f00};
-};
-
-template <> struct FixupInfo<Thumb_MovtAbs> : public FixupInfoThumbMov {
-  static constexpr HalfWords Opcode{0xf2c0, 0x0000};
-};
-
-template <> struct FixupInfo<Thumb_MovtPrel> : public FixupInfoThumbMov {
-  static constexpr HalfWords Opcode{0xf2c0, 0x0000};
-};
-
-template <> struct FixupInfo<Thumb_MovwAbsNC> : public FixupInfoThumbMov {
-  static constexpr HalfWords Opcode{0xf240, 0x0000};
-};
-
-template <> struct FixupInfo<Thumb_MovwPrelNC> : public FixupInfoThumbMov {
-  static constexpr HalfWords Opcode{0xf240, 0x0000};
-};
 
 /// Helper function to read the initial addend for Data-class relocations.
 Expected<int64_t> readAddendData(LinkGraph &G, Block &B, Edge::OffsetT Offset,
diff --git a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
index e5f5a99c39bc00..524bd9fad8e53e 100644
--- a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
@@ -1,5 +1,10 @@
 set(LLVM_TARGET_DEFINITIONS COFFOptions.td)
 tablegen(LLVM COFFOptions.inc -gen-opt-parser-defs)
+
+include_directories(${PROJECT_SOURCE_DIR}/lib/Target/ARM/)
+set(LLVM_TARGET_DEFINITIONS ${PROJECT_SOURCE_DIR}/lib/Target/ARM/ARM.td)
+tablegen(LLVM JITLinkAArch32.inc -gen-jitlink-aarch32-instr-info)
+
 add_public_tablegen_target(JITLinkTableGen)
 
 add_llvm_component_library(LLVMJITLink
diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
index 00be2f57d06640..0a705fcde89479 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
@@ -21,6 +21,8 @@
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/MathExtras.h"
 
+#include "JITLinkAArch32.inc"
+
 #define DEBUG_TYPE "jitlink"
 
 namespace llvm {
diff --git a/llvm/unittests/ExecutionEngine/JITLink/AArch32Tests.cpp b/llvm/unittests/ExecutionEngine/JITLink/AArch32Tests.cpp
index b1890d884d1735..46307db539b8d3 100644
--- a/llvm/unittests/ExecutionEngine/JITLink/AArch32Tests.cpp
+++ b/llvm/unittests/ExecutionEngine/JITLink/AArch32Tests.cpp
@@ -11,6 +11,8 @@
 
 #include "gtest/gtest.h"
 
+#include "JITLinkAArch32.inc"
+
 using namespace llvm;
 using namespace llvm::jitlink;
 using namespace llvm::jitlink::aarch32;
diff --git a/llvm/unittests/ExecutionEngine/JITLink/JITLinkAArch32.inc b/llvm/unittests/ExecutionEngine/JITLink/JITLinkAArch32.inc
new file mode 100644
index 00000000000000..42ef9795921e34
--- /dev/null
+++ b/llvm/unittests/ExecutionEngine/JITLink/JITLinkAArch32.inc
@@ -0,0 +1,58 @@
+/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
+|*                                                                            *|
+|* Skeleton data structures                                                   *|
+|*                                                                            *|
+|* Automatically generated file, do not edit!                                 *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+using namespace llvm::jitlink::aarch32;
+
+namespace llvm {
+namespace jitlink {
+namespace aarch32 {
+template <> struct FixupInfo<Arm_MovwAbsNC> : public FixupInfoArm {
+    static constexpr uint32_t Opcode = 0x3000000;
+    static constexpr uint32_t OpcodeMask = 0xff00000;
+    static constexpr uint32_t ImmMask = 0xf0fff;
+    static constexpr uint32_t RegMask = 0xf000;
+};
+
+template <> struct FixupInfo<Arm_MovtAbs> : public FixupInfoArm {
+    static constexpr uint32_t Opcode = 0x3400000;
+    static constexpr uint32_t OpcodeMask = 0xff00000;
+    static constexpr uint32_t ImmMask = 0xf0fff;
+    static constexpr uint32_t RegMask = 0xf000;
+};
+
+template <> struct FixupInfo<Thumb_MovwAbsNC> : public FixupInfoThumb {
+    static constexpr HalfWords Opcode {0xf240, 0x0};
+    static constexpr HalfWords OpcodeMask {0xfbf0, 0x8000};
+    static constexpr HalfWords ImmMask {0x40f, 0x70ff};
+    static constexpr HalfWords RegMask {0x0, 0xf00};
+};
+
+template <> struct FixupInfo<Thumb_MovtAbs> : public FixupInfoThumb {
+    static constexpr HalfWords Opcode {0xf2c0, 0x0};
+    static constexpr HalfWords OpcodeMask {0xfbf0, 0x8000};
+    static constexpr HalfWords ImmMask {0x40f, 0x70ff};
+    static constexpr HalfWords RegMask {0x0, 0xf00};
+};
+
+template <> struct FixupInfo<Thumb_MovwPrelNC> : public FixupInfoThumb {
+    static constexpr HalfWords Opcode {0xf240, 0x0};
+    static constexpr HalfWords OpcodeMask {0xfbf0, 0x8000};
+    static constexpr HalfWords ImmMask {0x40f, 0x70ff};
+    static constexpr HalfWords RegMask {0x0, 0xf00};
+};
+
+template <> struct FixupInfo<Thumb_MovtPrel> : public FixupInfoThumb {
+    static constexpr HalfWords Opcode {0xf2c0, 0x0};
+    static constexpr HalfWords OpcodeMask {0xfbf0, 0x8000};
+    static constexpr HalfWords ImmMask {0x40f, 0x70ff};
+    static constexpr HalfWords RegMask {0x0, 0xf00};
+};
+
+} //aarch32
+} //jitlink
+} //llvm
diff --git a/llvm/utils/TableGen/CMakeLists.txt b/llvm/utils/TableGen/CMakeLists.txt
index 0100bf345ec29e..0232003a7cd66a 100644
--- a/llvm/utils/TableGen/CMakeLists.txt
+++ b/llvm/utils/TableGen/CMakeLists.txt
@@ -66,6 +66,7 @@ add_tablegen(llvm-tblgen LLVM
   InfoByHwMode.cpp
   InstrInfoEmitter.cpp
   InstrDocsEmitter.cpp
+  JITLinkAArch32InstrInfo.cpp
   OptEmitter.cpp
   OptParserEmitter.cpp
   OptRSTEmitter.cpp
@@ -90,6 +91,10 @@ add_tablegen(llvm-tblgen LLVM
   WebAssemblyDisassemblerEmitter.cpp
   $<TARGET_OBJECTS:obj.LLVMTableGenCommon>
 
+  ADDITIONAL_HEADER_DIRS
+  ${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine/JITLink
+
+
   DEPENDS
   intrinsics_gen # via llvm-min-tablegen
   )
diff --git a/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp b/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp
new file mode 100644
index 00000000000000..6144764d482295
--- /dev/null
+++ b/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp
@@ -0,0 +1,196 @@
+//===- JITLinkAArch32InstrInfo.cpp - JITLink AArch32 TableGen backend -----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This Tablegen backend emits instruction encodings of AArch32 for JITLink.
+//
+//===----------------------------------------------------------------------===//
+#include "CodeGenDAGPatterns.h"
+#include "CodeGenInstruction.h"
+#include "CodeGenSchedule.h"
+#include "CodeGenTarget.h"
+#include "PredicateExpander.h"
+#include "SequenceToOffsetTable.h"
+#include "SubtargetFeatureInfo.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/JITLink/aarch32.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/TableGenBackend.h"
+
+#define DEBUG_TYPE "jitlink-aarch32-tblgen"
+
+namespace llvm {
+class RecordKeeper;
+class raw_ostream;
+} // namespace llvm
+
+using namespace llvm;
+using namespace llvm::jitlink;
+using namespace llvm::jitlink::aarch32;
+
+namespace {
+
+// Any helper data structures can be defined here. Some backends use
+// structs to collect information from the records.
+
+Twine getEdgeKindName(Edge::Kind K) {
+#define KIND_NAME_CASE(K)                                                      \
+  case K:                                                                      \
+    return #K;
+
+  switch (K) {
+    KIND_NAME_CASE(Data_Delta32)
+    KIND_NAME_CASE(Data_Pointer32)
+    KIND_NAME_CASE(Arm_Call)
+    KIND_NAME_CASE(Arm_Jump24)
+    KIND_NAME_CASE(Arm_MovwAbsNC)
+    KIND_NAME_CASE(Arm_MovtAbs)
+    KIND_NAME_CASE(Thumb_Call)
+    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 "";
+  }
+#undef KIND_NAME_CASE
+}
+
+static StringRef getInstrFromJITLinkEdgeKind(Edge::Kind Kind) {
+  /// Translate from JITLink-internal edge kind to TableGen instruction names.
+  switch (Kind) {
+  case Arm_Call:
+    return "";
+  case aarch32::Arm_Jump24:
+    return "";
+  case aarch32::Arm_MovwAbsNC:
+    return "MOVi16";
+  case aarch32::Arm_MovtAbs:
+    return "MOVTi16";
+  case aarch32::Thumb_Call:
+    return "";
+  case aarch32::Thumb_Jump24:
+    return "";
+  case aarch32::Thumb_MovwAbsNC:
+  case aarch32::Thumb_MovwPrelNC:
+    return "t2MOVi16";
+  case aarch32::Thumb_MovtAbs:
+  case aarch32::Thumb_MovtPrel:
+    return "t2MOVTi16";
+  default:
+    return "";
+  }
+}
+
+struct InstrInfo {
+  uint32_t Opcode = 0;
+  uint32_t OpcodeMask = 0;
+  uint32_t ImmMask = 0;
+  uint32_t RegMask = 0;
+};
+
+static void extractBits(BitsInit &InstBits, InstrInfo &II) {
+  for (unsigned i = 0; i < InstBits.getNumBits(); ++i) {
+    Init *Bit = InstBits.getBit(i);
+
+    if (auto *VarBit = dyn_cast<VarBitInit>(Bit)) {
+      // Check if the VarBit is for 'imm' or 'Rd'
+      std::string VarName = VarBit->getBitVar()->getAsUnquotedString();
+      if (VarName == "imm") {
+        II.ImmMask |= 1 << i;
+      } else if (VarName == "Rd") {
+        II.RegMask |= 1 << i;
+      }
+    } else if (auto *TheBit = dyn_cast<BitInit>(Bit)) {
+      II.OpcodeMask |= 1 << i;
+      if (TheBit->getValue()) {
+        II.Opcode |= 1 << i;
+      }
+    }
+  }
+
+  assert((II.OpcodeMask & II.ImmMask & II.RegMask) == 0 &&
+         "Masks have intersecting bits");
+}
+
+static void writeArmElement(raw_ostream &OS, Twine InfoName, uint32_t Value,
+                            int Indentation = 4) {
+  OS.indent(Indentation) << "static constexpr uint32_t " + InfoName + " = 0x";
+  OS.write_hex(Value) << ";\n";
+}
+
+static void writeArmInfo(raw_ostream &OS, InstrInfo &II, Edge::Kind Kind) {
+  OS << "template <> struct FixupInfo<" + getEdgeKindName(Kind) +
+            "> : public FixupInfoArm {\n";
+  writeArmElement(OS, "Opcode", II.Opcode);
+  writeArmElement(OS, "OpcodeMask", II.OpcodeMask);
+  writeArmElement(OS, "ImmMask", II.ImmMask);
+  writeArmElement(OS, "RegMask", II.RegMask);
+  OS << "};\n\n";
+}
+
+static void writeThumbElement(raw_ostream &OS, Twine InfoName, uint32_t Value,
+                              int Indentation = 4) {
+  OS.indent(Indentation) << "static constexpr HalfWords " + InfoName + " {0x";
+  OS.write_hex(Value >> 16) << ", 0x";
+  OS.write_hex(Value & 0x0000FFFF) << "};\n";
+}
+
+static void writeThumbInfo(raw_ostream &OS, InstrInfo &II, Edge::Kind Kind) {
+  OS << "template <> struct FixupInfo<" + getEdgeKindName(Kind) +
+            "> : public FixupInfoThumb {\n";
+  writeThumbElement(OS, "Opcode", II.Opcode);
+  writeThumbElement(OS, "OpcodeMask", II.OpcodeMask);
+  writeThumbElement(OS, "ImmMask", II.ImmMask);
+  writeThumbElement(OS, "RegMask", II.RegMask);
+  OS << "};\n\n";
+}
+
+class JITLinkAArch32Emitter {
+private:
+  RecordKeeper &Records;
+
+public:
+  JITLinkAArch32Emitter(RecordKeeper &RK) : Records(RK) {}
+
+  void run(raw_ostream &OS);
+}; // emitter class
+
+} // anonymous namespace
+
+void JITLinkAArch32Emitter::run(raw_ostream &OS) {
+  emitSourceFileHeader("Skeleton data structures", OS);
+  OS << "using namespace llvm::jitlink::aarch32;\n\n";
+  OS << "namespace llvm {\n";
+  OS << "namespace jitlink {\n";
+  OS << "namespace aarch32 {\n";
+  // const auto &Instructions = Records.getAllDerivedDefinitions("Instruction");
+  for (Edge::Kind JITLinkEdgeKind = aarch32::FirstArmRelocation;
+       JITLinkEdgeKind <= aarch32::LastThumbRelocation; JITLinkEdgeKind += 1) {
+    auto InstName = getInstrFromJITLinkEdgeKind(JITLinkEdgeKind);
+    if (InstName.empty())
+      continue;
+    auto *InstRecord = Records.getDef(InstName);
+    auto *InstBits = InstRecord->getValueAsBitsInit("Inst");
+    InstrInfo II;
+    extractBits(*InstBits, II);
+    if (JITLinkEdgeKind > LastArmRelocation)
+      writeThumbInfo(OS, II, JITLinkEdgeKind);
+    else
+      writeArmInfo(OS, II, JITLinkEdgeKind);
+  }
+
+  OS << "} //aarch32\n";
+  OS << "} //jitlink\n";
+  OS << "} //llvm\n";
+}
+
+static TableGen::Emitter::OptClass<JITLinkAArch32Emitter>
+    X("gen-jitlink-aarch32-instr-info",
+      "Generate JITLink AArch32 Instruction Information");

>From 63e28a2987806a1259d412e1c65af17a9b4935aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eymen=20=C3=9Cnay?= <eymenunay at outlook.com>
Date: Thu, 4 Jan 2024 23:17:47 +0300
Subject: [PATCH 2/5] Reformat and indent by 2

---
 .../llvm/ExecutionEngine/JITLink/aarch32.h    |  1 -
 .../JITLink/JITLinkAArch32.inc                | 54 +++++++++----------
 .../TableGen/JITLinkAArch32InstrInfo.cpp      |  4 +-
 3 files changed, 29 insertions(+), 30 deletions(-)

diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
index f81a071e7d773e..2bd2d6023bea8f 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
@@ -233,7 +233,6 @@ template <> struct FixupInfo<Thumb_Call> : public FixupInfoThumb {
   static constexpr uint16_t LoBitNoBlx = 0x1000;
 };
 
-
 /// Helper function to read the initial addend for Data-class relocations.
 Expected<int64_t> readAddendData(LinkGraph &G, Block &B, Edge::OffsetT Offset,
                                  Edge::Kind Kind);
diff --git a/llvm/unittests/ExecutionEngine/JITLink/JITLinkAArch32.inc b/llvm/unittests/ExecutionEngine/JITLink/JITLinkAArch32.inc
index 42ef9795921e34..aaff38b8c5ad85 100644
--- a/llvm/unittests/ExecutionEngine/JITLink/JITLinkAArch32.inc
+++ b/llvm/unittests/ExecutionEngine/JITLink/JITLinkAArch32.inc
@@ -12,47 +12,47 @@ namespace llvm {
 namespace jitlink {
 namespace aarch32 {
 template <> struct FixupInfo<Arm_MovwAbsNC> : public FixupInfoArm {
-    static constexpr uint32_t Opcode = 0x3000000;
-    static constexpr uint32_t OpcodeMask = 0xff00000;
-    static constexpr uint32_t ImmMask = 0xf0fff;
-    static constexpr uint32_t RegMask = 0xf000;
+  static constexpr uint32_t Opcode = 0x3000000;
+  static constexpr uint32_t OpcodeMask = 0xff00000;
+  static constexpr uint32_t ImmMask = 0xf0fff;
+  static constexpr uint32_t RegMask = 0xf000;
 };
 
 template <> struct FixupInfo<Arm_MovtAbs> : public FixupInfoArm {
-    static constexpr uint32_t Opcode = 0x3400000;
-    static constexpr uint32_t OpcodeMask = 0xff00000;
-    static constexpr uint32_t ImmMask = 0xf0fff;
-    static constexpr uint32_t RegMask = 0xf000;
+  static constexpr uint32_t Opcode = 0x3400000;
+  static constexpr uint32_t OpcodeMask = 0xff00000;
+  static constexpr uint32_t ImmMask = 0xf0fff;
+  static constexpr uint32_t RegMask = 0xf000;
 };
 
 template <> struct FixupInfo<Thumb_MovwAbsNC> : public FixupInfoThumb {
-    static constexpr HalfWords Opcode {0xf240, 0x0};
-    static constexpr HalfWords OpcodeMask {0xfbf0, 0x8000};
-    static constexpr HalfWords ImmMask {0x40f, 0x70ff};
-    static constexpr HalfWords RegMask {0x0, 0xf00};
+  static constexpr HalfWords Opcode{0xf240, 0x0};
+  static constexpr HalfWords OpcodeMask{0xfbf0, 0x8000};
+  static constexpr HalfWords ImmMask{0x40f, 0x70ff};
+  static constexpr HalfWords RegMask{0x0, 0xf00};
 };
 
 template <> struct FixupInfo<Thumb_MovtAbs> : public FixupInfoThumb {
-    static constexpr HalfWords Opcode {0xf2c0, 0x0};
-    static constexpr HalfWords OpcodeMask {0xfbf0, 0x8000};
-    static constexpr HalfWords ImmMask {0x40f, 0x70ff};
-    static constexpr HalfWords RegMask {0x0, 0xf00};
+  static constexpr HalfWords Opcode{0xf2c0, 0x0};
+  static constexpr HalfWords OpcodeMask{0xfbf0, 0x8000};
+  static constexpr HalfWords ImmMask{0x40f, 0x70ff};
+  static constexpr HalfWords RegMask{0x0, 0xf00};
 };
 
 template <> struct FixupInfo<Thumb_MovwPrelNC> : public FixupInfoThumb {
-    static constexpr HalfWords Opcode {0xf240, 0x0};
-    static constexpr HalfWords OpcodeMask {0xfbf0, 0x8000};
-    static constexpr HalfWords ImmMask {0x40f, 0x70ff};
-    static constexpr HalfWords RegMask {0x0, 0xf00};
+  static constexpr HalfWords Opcode{0xf240, 0x0};
+  static constexpr HalfWords OpcodeMask{0xfbf0, 0x8000};
+  static constexpr HalfWords ImmMask{0x40f, 0x70ff};
+  static constexpr HalfWords RegMask{0x0, 0xf00};
 };
 
 template <> struct FixupInfo<Thumb_MovtPrel> : public FixupInfoThumb {
-    static constexpr HalfWords Opcode {0xf2c0, 0x0};
-    static constexpr HalfWords OpcodeMask {0xfbf0, 0x8000};
-    static constexpr HalfWords ImmMask {0x40f, 0x70ff};
-    static constexpr HalfWords RegMask {0x0, 0xf00};
+  static constexpr HalfWords Opcode{0xf2c0, 0x0};
+  static constexpr HalfWords OpcodeMask{0xfbf0, 0x8000};
+  static constexpr HalfWords ImmMask{0x40f, 0x70ff};
+  static constexpr HalfWords RegMask{0x0, 0xf00};
 };
 
-} //aarch32
-} //jitlink
-} //llvm
+} // namespace aarch32
+} // namespace jitlink
+} // namespace llvm
diff --git a/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp b/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp
index 6144764d482295..62468ed057d431 100644
--- a/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp
+++ b/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp
@@ -120,7 +120,7 @@ static void extractBits(BitsInit &InstBits, InstrInfo &II) {
 }
 
 static void writeArmElement(raw_ostream &OS, Twine InfoName, uint32_t Value,
-                            int Indentation = 4) {
+                            int Indentation = 2) {
   OS.indent(Indentation) << "static constexpr uint32_t " + InfoName + " = 0x";
   OS.write_hex(Value) << ";\n";
 }
@@ -136,7 +136,7 @@ static void writeArmInfo(raw_ostream &OS, InstrInfo &II, Edge::Kind Kind) {
 }
 
 static void writeThumbElement(raw_ostream &OS, Twine InfoName, uint32_t Value,
-                              int Indentation = 4) {
+                              int Indentation = 2) {
   OS.indent(Indentation) << "static constexpr HalfWords " + InfoName + " {0x";
   OS.write_hex(Value >> 16) << ", 0x";
   OS.write_hex(Value & 0x0000FFFF) << "};\n";

>From 7e63dd2cf2ccf49586a75bfe6c45acb360b5a082 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eymen=20=C3=9Cnay?= <eymenunay at outlook.com>
Date: Sat, 6 Jan 2024 14:09:35 +0300
Subject: [PATCH 3/5] Include the generated file in header

Generating an includable file in header requires the TableGen backend
to be independent of the headers, if not a cyclic dependency occurs.
A macro based generation is prioritised and its manipulation is done
in the header file by constexpr lookups.
---
 llvm/include/llvm/CMakeLists.txt              |   1 +
 .../llvm/ExecutionEngine/CMakeLists.txt       |   1 +
 .../ExecutionEngine/JITLink/CMakeLists.txt    |   3 +
 .../llvm/ExecutionEngine/JITLink/aarch32.h    | 103 +++++++++++-
 .../ExecutionEngine/JITLink/CMakeLists.txt    |   9 +-
 llvm/lib/ExecutionEngine/JITLink/aarch32.cpp  |   4 +-
 .../ExecutionEngine/JITLink/AArch32Tests.cpp  |   4 +-
 .../JITLink/JITLinkAArch32.inc                |  58 -------
 llvm/utils/TableGen/CMakeLists.txt            |   6 +-
 .../TableGen/JITLinkAArch32InstrInfo.cpp      | 149 +++---------------
 10 files changed, 135 insertions(+), 203 deletions(-)
 create mode 100644 llvm/include/llvm/ExecutionEngine/CMakeLists.txt
 create mode 100644 llvm/include/llvm/ExecutionEngine/JITLink/CMakeLists.txt
 delete mode 100644 llvm/unittests/ExecutionEngine/JITLink/JITLinkAArch32.inc

diff --git a/llvm/include/llvm/CMakeLists.txt b/llvm/include/llvm/CMakeLists.txt
index ac6b96a68ab92d..22b06c598280e0 100644
--- a/llvm/include/llvm/CMakeLists.txt
+++ b/llvm/include/llvm/CMakeLists.txt
@@ -3,6 +3,7 @@
 set(LLVM_TABLEGEN_PROJECT LLVM_HEADERS)
 
 add_subdirectory(CodeGen)
+add_subdirectory(ExecutionEngine)
 add_subdirectory(IR)
 add_subdirectory(Support)
 add_subdirectory(Frontend)
diff --git a/llvm/include/llvm/ExecutionEngine/CMakeLists.txt b/llvm/include/llvm/ExecutionEngine/CMakeLists.txt
new file mode 100644
index 00000000000000..4dff4573dae892
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(JITLink)
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/CMakeLists.txt b/llvm/include/llvm/ExecutionEngine/JITLink/CMakeLists.txt
new file mode 100644
index 00000000000000..b1eb84feac1256
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/CMakeLists.txt
@@ -0,0 +1,3 @@
+set(LLVM_TARGET_DEFINITIONS ${PROJECT_SOURCE_DIR}/lib/Target/ARM/ARM.td)
+tablegen(LLVM JITLinkAArch32.inc -gen-jitlink-aarch32-instr-info -I ${PROJECT_SOURCE_DIR}/lib/Target/ARM/)
+add_public_tablegen_target(JITLinkAArch32TableGen)
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
index 2bd2d6023bea8f..8ca1467635047b 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
@@ -171,17 +171,77 @@ struct HalfWords {
   const uint16_t Lo; // Second halfword
 };
 
+enum InstrName {
+
+#define GET_INSTR(name, opcode, opcode_mask, imm_mask, reg_mask) name,
+
+#include "llvm/ExecutionEngine/JITLink/JITLinkAArch32.inc"
+#undef GET_INSTR
+  INSTR_COUNT,
+  NONE = INSTR_COUNT,
+};
+
+constexpr InstrName getInstrFromJITLinkEdgeKind(Edge::Kind Kind) {
+  switch (Kind) {
+  case Arm_Call:
+    return InstrName::NONE;
+  case aarch32::Arm_Jump24:
+    return InstrName::NONE;
+  case aarch32::Arm_MovwAbsNC:
+    return InstrName::MOVi16;
+  case aarch32::Arm_MovtAbs:
+    return InstrName::MOVTi16;
+  case aarch32::Thumb_Call:
+    return InstrName::NONE;
+  case aarch32::Thumb_Jump24:
+    return InstrName::NONE;
+  case aarch32::Thumb_MovwAbsNC:
+  case aarch32::Thumb_MovwPrelNC:
+    return InstrName::t2MOVi16;
+  case aarch32::Thumb_MovtAbs:
+  case aarch32::Thumb_MovtPrel:
+    return InstrName::t2MOVTi16;
+  default:
+    return InstrName::NONE;
+  }
+}
+
+struct InstrInfo {
+  uint32_t Opcode;
+  uint32_t OpcodeMask;
+  uint32_t ImmMask;
+  uint32_t RegMask;
+};
+
+static constexpr InstrInfo InstrTable[INSTR_COUNT] = {
+#define GET_INSTR(name, opcode, opcode_mask, imm_mask, reg_mask)               \
+  {opcode, opcode_mask, imm_mask, reg_mask},
+#include "llvm/ExecutionEngine/JITLink/JITLinkAArch32.inc"
+#undef GET_INSTR
+};
+
 /// FixupInfo base class is required for dynamic lookups.
 struct FixupInfoBase {
   static const FixupInfoBase *getDynFixupInfo(Edge::Kind K);
   virtual ~FixupInfoBase() {}
 };
 
-/// FixupInfo checks for Arm edge kinds work on 32-bit words
-struct FixupInfoArm : public FixupInfoBase {
+struct FixupInfoArmBase : public FixupInfoBase {
   bool (*checkOpcode)(uint32_t Wd) = nullptr;
 };
 
+/// FixupInfo checks for Arm edge kinds work on 32-bit words
+template <EdgeKind_aarch32 Kind> struct FixupInfoArm : public FixupInfoArmBase {
+  static constexpr uint32_t Opcode =
+      InstrTable[getInstrFromJITLinkEdgeKind(Kind)].Opcode;
+  static constexpr uint32_t OpcodeMask =
+      InstrTable[getInstrFromJITLinkEdgeKind(Kind)].OpcodeMask;
+  static constexpr uint32_t ImmMask =
+      InstrTable[getInstrFromJITLinkEdgeKind(Kind)].ImmMask;
+  static constexpr uint32_t RegMask =
+      InstrTable[getInstrFromJITLinkEdgeKind(Kind)].RegMask;
+};
+
 /// FixupInfo check for Thumb32 edge kinds work on a pair of 16-bit halfwords
 struct FixupInfoThumb : public FixupInfoBase {
   bool (*checkOpcode)(uint16_t Hi, uint16_t Lo) = nullptr;
@@ -199,10 +259,10 @@ struct FixupInfoThumb : public FixupInfoBase {
 ///   RegMask     - Mask with all bits set that encode the register
 ///
 /// Specializations can add further custom fields without restrictions.
-///
+
 template <EdgeKind_aarch32 Kind> struct FixupInfo {};
 
-struct FixupInfoArmBranch : public FixupInfoArm {
+struct FixupInfoArmBranch : public FixupInfoArmBase {
   static constexpr uint32_t Opcode = 0x0a000000;
   static constexpr uint32_t ImmMask = 0x00ffffff;
 };
@@ -219,6 +279,19 @@ template <> struct FixupInfo<Arm_Call> : public FixupInfoArmBranch {
   static constexpr uint32_t BitBlx = 0x10000000;
 };
 
+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;
+};
+
+template <>
+struct FixupInfo<Arm_MovtAbs> : public FixupInfoArmMov<Arm_MovtAbs> {};
+
+template <>
+struct FixupInfo<Arm_MovwAbsNC> : public FixupInfoArmMov<Arm_MovwAbsNC> {};
+
 template <> struct FixupInfo<Thumb_Jump24> : public FixupInfoThumb {
   static constexpr HalfWords Opcode{0xf000, 0x9000};
   static constexpr HalfWords OpcodeMask{0xf800, 0x9000};
@@ -233,6 +306,28 @@ template <> struct FixupInfo<Thumb_Call> : public FixupInfoThumb {
   static constexpr uint16_t LoBitNoBlx = 0x1000;
 };
 
+struct FixupInfoThumbMov : public FixupInfoThumb {
+  static constexpr HalfWords OpcodeMask{0xfbf0, 0x8000};
+  static constexpr HalfWords ImmMask{0x040f, 0x70ff};
+  static constexpr HalfWords RegMask{0x0000, 0x0f00};
+};
+
+template <> struct FixupInfo<Thumb_MovtAbs> : public FixupInfoThumbMov {
+  static constexpr HalfWords Opcode{0xf2c0, 0x0000};
+};
+
+template <> struct FixupInfo<Thumb_MovtPrel> : public FixupInfoThumbMov {
+  static constexpr HalfWords Opcode{0xf2c0, 0x0000};
+};
+
+template <> struct FixupInfo<Thumb_MovwAbsNC> : public FixupInfoThumbMov {
+  static constexpr HalfWords Opcode{0xf240, 0x0000};
+};
+
+template <> struct FixupInfo<Thumb_MovwPrelNC> : public FixupInfoThumbMov {
+  static constexpr HalfWords Opcode{0xf240, 0x0000};
+};
+
 /// Helper function to read the initial addend for Data-class relocations.
 Expected<int64_t> readAddendData(LinkGraph &G, Block &B, Edge::OffsetT Offset,
                                  Edge::Kind Kind);
diff --git a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
index 524bd9fad8e53e..c5482bb2ec69b7 100644
--- a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
@@ -1,11 +1,7 @@
 set(LLVM_TARGET_DEFINITIONS COFFOptions.td)
 tablegen(LLVM COFFOptions.inc -gen-opt-parser-defs)
+add_public_tablegen_target(JITLinkCOFFTableGen)
 
-include_directories(${PROJECT_SOURCE_DIR}/lib/Target/ARM/)
-set(LLVM_TARGET_DEFINITIONS ${PROJECT_SOURCE_DIR}/lib/Target/ARM/ARM.td)
-tablegen(LLVM JITLinkAArch32.inc -gen-jitlink-aarch32-instr-info)
-
-add_public_tablegen_target(JITLinkTableGen)
 
 add_llvm_component_library(LLVMJITLink
   DWARFRecordSectionSplitter.cpp
@@ -53,7 +49,8 @@ add_llvm_component_library(LLVMJITLink
 
   DEPENDS
   intrinsics_gen
-  JITLinkTableGen
+  JITLinkCOFFTableGen
+  JITLinkAArch32TableGen
 
   LINK_COMPONENTS
   BinaryFormat
diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
index 0a705fcde89479..d0aa20be19f90b 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
@@ -21,8 +21,6 @@
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/MathExtras.h"
 
-#include "JITLinkAArch32.inc"
-
 #define DEBUG_TYPE "jitlink"
 
 namespace llvm {
@@ -319,7 +317,7 @@ static Error checkOpcode(LinkGraph &G, const ArmRelocation &R,
   assert(Kind >= FirstArmRelocation && Kind <= LastArmRelocation &&
          "Edge kind must be Arm relocation");
   const FixupInfoBase *Entry = DynFixupInfos->getEntry(Kind);
-  const FixupInfoArm &Info = *static_cast<const FixupInfoArm *>(Entry);
+  const FixupInfoArmBase &Info = *static_cast<const FixupInfoArmBase *>(Entry);
   assert(Info.checkOpcode && "Opcode check is mandatory for Arm edges");
   if (!Info.checkOpcode(R.Wd))
     return makeUnexpectedOpcodeError(G, R, Kind);
diff --git a/llvm/unittests/ExecutionEngine/JITLink/AArch32Tests.cpp b/llvm/unittests/ExecutionEngine/JITLink/AArch32Tests.cpp
index 46307db539b8d3..28045bfedb51e3 100644
--- a/llvm/unittests/ExecutionEngine/JITLink/AArch32Tests.cpp
+++ b/llvm/unittests/ExecutionEngine/JITLink/AArch32Tests.cpp
@@ -11,8 +11,6 @@
 
 #include "gtest/gtest.h"
 
-#include "JITLinkAArch32.inc"
-
 using namespace llvm;
 using namespace llvm::jitlink;
 using namespace llvm::jitlink::aarch32;
@@ -76,7 +74,7 @@ TEST(AArch32_ELF, DynFixupInfos) {
   for (Edge::Kind K = FirstArmRelocation; K < LastArmRelocation; K += 1) {
     const auto *Info = FixupInfoBase::getDynFixupInfo(K);
     EXPECT_NE(Info, nullptr);
-    const auto *InfoArm = static_cast<const FixupInfoArm *>(Info);
+    const auto *InfoArm = static_cast<const FixupInfoArmBase *>(Info);
     EXPECT_NE(InfoArm->checkOpcode, nullptr);
     EXPECT_FALSE(InfoArm->checkOpcode(0x00000000));
   }
diff --git a/llvm/unittests/ExecutionEngine/JITLink/JITLinkAArch32.inc b/llvm/unittests/ExecutionEngine/JITLink/JITLinkAArch32.inc
deleted file mode 100644
index aaff38b8c5ad85..00000000000000
--- a/llvm/unittests/ExecutionEngine/JITLink/JITLinkAArch32.inc
+++ /dev/null
@@ -1,58 +0,0 @@
-/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
-|*                                                                            *|
-|* Skeleton data structures                                                   *|
-|*                                                                            *|
-|* Automatically generated file, do not edit!                                 *|
-|*                                                                            *|
-\*===----------------------------------------------------------------------===*/
-
-using namespace llvm::jitlink::aarch32;
-
-namespace llvm {
-namespace jitlink {
-namespace aarch32 {
-template <> struct FixupInfo<Arm_MovwAbsNC> : public FixupInfoArm {
-  static constexpr uint32_t Opcode = 0x3000000;
-  static constexpr uint32_t OpcodeMask = 0xff00000;
-  static constexpr uint32_t ImmMask = 0xf0fff;
-  static constexpr uint32_t RegMask = 0xf000;
-};
-
-template <> struct FixupInfo<Arm_MovtAbs> : public FixupInfoArm {
-  static constexpr uint32_t Opcode = 0x3400000;
-  static constexpr uint32_t OpcodeMask = 0xff00000;
-  static constexpr uint32_t ImmMask = 0xf0fff;
-  static constexpr uint32_t RegMask = 0xf000;
-};
-
-template <> struct FixupInfo<Thumb_MovwAbsNC> : public FixupInfoThumb {
-  static constexpr HalfWords Opcode{0xf240, 0x0};
-  static constexpr HalfWords OpcodeMask{0xfbf0, 0x8000};
-  static constexpr HalfWords ImmMask{0x40f, 0x70ff};
-  static constexpr HalfWords RegMask{0x0, 0xf00};
-};
-
-template <> struct FixupInfo<Thumb_MovtAbs> : public FixupInfoThumb {
-  static constexpr HalfWords Opcode{0xf2c0, 0x0};
-  static constexpr HalfWords OpcodeMask{0xfbf0, 0x8000};
-  static constexpr HalfWords ImmMask{0x40f, 0x70ff};
-  static constexpr HalfWords RegMask{0x0, 0xf00};
-};
-
-template <> struct FixupInfo<Thumb_MovwPrelNC> : public FixupInfoThumb {
-  static constexpr HalfWords Opcode{0xf240, 0x0};
-  static constexpr HalfWords OpcodeMask{0xfbf0, 0x8000};
-  static constexpr HalfWords ImmMask{0x40f, 0x70ff};
-  static constexpr HalfWords RegMask{0x0, 0xf00};
-};
-
-template <> struct FixupInfo<Thumb_MovtPrel> : public FixupInfoThumb {
-  static constexpr HalfWords Opcode{0xf2c0, 0x0};
-  static constexpr HalfWords OpcodeMask{0xfbf0, 0x8000};
-  static constexpr HalfWords ImmMask{0x40f, 0x70ff};
-  static constexpr HalfWords RegMask{0x0, 0xf00};
-};
-
-} // namespace aarch32
-} // namespace jitlink
-} // namespace llvm
diff --git a/llvm/utils/TableGen/CMakeLists.txt b/llvm/utils/TableGen/CMakeLists.txt
index 0232003a7cd66a..13e102485a3b9f 100644
--- a/llvm/utils/TableGen/CMakeLists.txt
+++ b/llvm/utils/TableGen/CMakeLists.txt
@@ -5,6 +5,7 @@ add_llvm_library(LLVMTableGenCommon STATIC OBJECT EXCLUDE_FROM_ALL
   CodeGenIntrinsics.cpp
   DirectiveEmitter.cpp
   IntrinsicEmitter.cpp
+  JITLinkAArch32InstrInfo.cpp
   RISCVTargetDefEmitter.cpp
   SDNodeProperties.cpp
   VTEmitter.cpp
@@ -66,7 +67,6 @@ add_tablegen(llvm-tblgen LLVM
   InfoByHwMode.cpp
   InstrInfoEmitter.cpp
   InstrDocsEmitter.cpp
-  JITLinkAArch32InstrInfo.cpp
   OptEmitter.cpp
   OptParserEmitter.cpp
   OptRSTEmitter.cpp
@@ -91,10 +91,6 @@ add_tablegen(llvm-tblgen LLVM
   WebAssemblyDisassemblerEmitter.cpp
   $<TARGET_OBJECTS:obj.LLVMTableGenCommon>
 
-  ADDITIONAL_HEADER_DIRS
-  ${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine/JITLink
-
-
   DEPENDS
   intrinsics_gen # via llvm-min-tablegen
   )
diff --git a/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp b/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp
index 62468ed057d431..54d149187eb8a6 100644
--- a/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp
+++ b/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp
@@ -9,20 +9,11 @@
 // This Tablegen backend emits instruction encodings of AArch32 for JITLink.
 //
 //===----------------------------------------------------------------------===//
-#include "CodeGenDAGPatterns.h"
-#include "CodeGenInstruction.h"
-#include "CodeGenSchedule.h"
-#include "CodeGenTarget.h"
-#include "PredicateExpander.h"
-#include "SequenceToOffsetTable.h"
-#include "SubtargetFeatureInfo.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/ExecutionEngine/JITLink/aarch32.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
 #include "llvm/TableGen/TableGenBackend.h"
 
-#define DEBUG_TYPE "jitlink-aarch32-tblgen"
+#define DEBUG_TYPE "jitlink-instr-info"
 
 namespace llvm {
 class RecordKeeper;
@@ -30,64 +21,9 @@ class raw_ostream;
 } // namespace llvm
 
 using namespace llvm;
-using namespace llvm::jitlink;
-using namespace llvm::jitlink::aarch32;
 
 namespace {
 
-// Any helper data structures can be defined here. Some backends use
-// structs to collect information from the records.
-
-Twine getEdgeKindName(Edge::Kind K) {
-#define KIND_NAME_CASE(K)                                                      \
-  case K:                                                                      \
-    return #K;
-
-  switch (K) {
-    KIND_NAME_CASE(Data_Delta32)
-    KIND_NAME_CASE(Data_Pointer32)
-    KIND_NAME_CASE(Arm_Call)
-    KIND_NAME_CASE(Arm_Jump24)
-    KIND_NAME_CASE(Arm_MovwAbsNC)
-    KIND_NAME_CASE(Arm_MovtAbs)
-    KIND_NAME_CASE(Thumb_Call)
-    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 "";
-  }
-#undef KIND_NAME_CASE
-}
-
-static StringRef getInstrFromJITLinkEdgeKind(Edge::Kind Kind) {
-  /// Translate from JITLink-internal edge kind to TableGen instruction names.
-  switch (Kind) {
-  case Arm_Call:
-    return "";
-  case aarch32::Arm_Jump24:
-    return "";
-  case aarch32::Arm_MovwAbsNC:
-    return "MOVi16";
-  case aarch32::Arm_MovtAbs:
-    return "MOVTi16";
-  case aarch32::Thumb_Call:
-    return "";
-  case aarch32::Thumb_Jump24:
-    return "";
-  case aarch32::Thumb_MovwAbsNC:
-  case aarch32::Thumb_MovwPrelNC:
-    return "t2MOVi16";
-  case aarch32::Thumb_MovtAbs:
-  case aarch32::Thumb_MovtPrel:
-    return "t2MOVTi16";
-  default:
-    return "";
-  }
-}
-
 struct InstrInfo {
   uint32_t Opcode = 0;
   uint32_t OpcodeMask = 0;
@@ -119,78 +55,43 @@ static void extractBits(BitsInit &InstBits, InstrInfo &II) {
          "Masks have intersecting bits");
 }
 
-static void writeArmElement(raw_ostream &OS, Twine InfoName, uint32_t Value,
-                            int Indentation = 2) {
-  OS.indent(Indentation) << "static constexpr uint32_t " + InfoName + " = 0x";
-  OS.write_hex(Value) << ";\n";
-}
-
-static void writeArmInfo(raw_ostream &OS, InstrInfo &II, Edge::Kind Kind) {
-  OS << "template <> struct FixupInfo<" + getEdgeKindName(Kind) +
-            "> : public FixupInfoArm {\n";
-  writeArmElement(OS, "Opcode", II.Opcode);
-  writeArmElement(OS, "OpcodeMask", II.OpcodeMask);
-  writeArmElement(OS, "ImmMask", II.ImmMask);
-  writeArmElement(OS, "RegMask", II.RegMask);
-  OS << "};\n\n";
+static void writeInstrInfo(raw_ostream &OS, const InstrInfo &II,
+                           const std::string &InstName) {
+  OS << "GET_INSTR(" << InstName << ", 0x";
+  OS.write_hex(II.Opcode) << ", 0x";
+  OS.write_hex(II.OpcodeMask) << ", 0x";
+  OS.write_hex(II.ImmMask) << ", 0x";
+  OS.write_hex(II.RegMask) << ")\n";
 }
 
-static void writeThumbElement(raw_ostream &OS, Twine InfoName, uint32_t Value,
-                              int Indentation = 2) {
-  OS.indent(Indentation) << "static constexpr HalfWords " + InfoName + " {0x";
-  OS.write_hex(Value >> 16) << ", 0x";
-  OS.write_hex(Value & 0x0000FFFF) << "};\n";
-}
-
-static void writeThumbInfo(raw_ostream &OS, InstrInfo &II, Edge::Kind Kind) {
-  OS << "template <> struct FixupInfo<" + getEdgeKindName(Kind) +
-            "> : public FixupInfoThumb {\n";
-  writeThumbElement(OS, "Opcode", II.Opcode);
-  writeThumbElement(OS, "OpcodeMask", II.OpcodeMask);
-  writeThumbElement(OS, "ImmMask", II.ImmMask);
-  writeThumbElement(OS, "RegMask", II.RegMask);
-  OS << "};\n\n";
-}
-
-class JITLinkAArch32Emitter {
+class JITLinkEmitter {
 private:
   RecordKeeper &Records;
 
 public:
-  JITLinkAArch32Emitter(RecordKeeper &RK) : Records(RK) {}
+  JITLinkEmitter(RecordKeeper &RK) : Records(RK) {}
 
   void run(raw_ostream &OS);
-}; // emitter class
-
-} // anonymous namespace
-
-void JITLinkAArch32Emitter::run(raw_ostream &OS) {
-  emitSourceFileHeader("Skeleton data structures", OS);
-  OS << "using namespace llvm::jitlink::aarch32;\n\n";
-  OS << "namespace llvm {\n";
-  OS << "namespace jitlink {\n";
-  OS << "namespace aarch32 {\n";
-  // const auto &Instructions = Records.getAllDerivedDefinitions("Instruction");
-  for (Edge::Kind JITLinkEdgeKind = aarch32::FirstArmRelocation;
-       JITLinkEdgeKind <= aarch32::LastThumbRelocation; JITLinkEdgeKind += 1) {
-    auto InstName = getInstrFromJITLinkEdgeKind(JITLinkEdgeKind);
-    if (InstName.empty())
+};
+
+void JITLinkEmitter::run(raw_ostream &OS) {
+  emitSourceFileHeader("Instruction Encoding Information", OS);
+
+  OS << "#ifdef GET_INSTR // (Opc, Opc_Mask, Imm_Mask, Reg_Mask)\n";
+  auto RecordsList = Records.getAllDerivedDefinitions("Instruction");
+  for (auto *InstRecord : RecordsList) {
+    if (InstRecord->getValueAsBit("isPseudo"))
       continue;
-    auto *InstRecord = Records.getDef(InstName);
     auto *InstBits = InstRecord->getValueAsBitsInit("Inst");
     InstrInfo II;
     extractBits(*InstBits, II);
-    if (JITLinkEdgeKind > LastArmRelocation)
-      writeThumbInfo(OS, II, JITLinkEdgeKind);
-    else
-      writeArmInfo(OS, II, JITLinkEdgeKind);
+    writeInstrInfo(OS, II, InstRecord->getNameInitAsString());
   }
 
-  OS << "} //aarch32\n";
-  OS << "} //jitlink\n";
-  OS << "} //llvm\n";
+  OS << "#endif\n";
 }
 
-static TableGen::Emitter::OptClass<JITLinkAArch32Emitter>
+static TableGen::Emitter::OptClass<JITLinkEmitter>
     X("gen-jitlink-aarch32-instr-info",
-      "Generate JITLink AArch32 Instruction Information");
+      "Generate JITLink Instruction Information");
+} // namespace

>From f6b812d78ed98239986c37eac63b9406b92c6e1a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eymen=20=C3=9Cnay?= <eymenunay at outlook.com>
Date: Sun, 7 Jan 2024 16:18:08 +0300
Subject: [PATCH 4/5] Remove unused header

---
 llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp b/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp
index 54d149187eb8a6..151b5aaafa15b4 100644
--- a/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp
+++ b/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp
@@ -9,7 +9,6 @@
 // This Tablegen backend emits instruction encodings of AArch32 for JITLink.
 //
 //===----------------------------------------------------------------------===//
-#include "llvm/ADT/StringRef.h"
 #include "llvm/TableGen/Record.h"
 #include "llvm/TableGen/TableGenBackend.h"
 

>From ce1db9d8b03a52d872d0afeb66c81d5142079c3e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eymen=20=C3=9Cnay?= <eymenunay at outlook.com>
Date: Fri, 26 Jan 2024 21:09:53 +0300
Subject: [PATCH 5/5] Reduce generated instructions by selecting mov and branch
 only

---
 .../JITLink/JITLinkAArch32.inc.example        | 33 +++++++++++++++++++
 .../TableGen/JITLinkAArch32InstrInfo.cpp      | 25 +++++++++++---
 2 files changed, 53 insertions(+), 5 deletions(-)
 create mode 100644 llvm/include/llvm/ExecutionEngine/JITLink/JITLinkAArch32.inc.example

diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkAArch32.inc.example b/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkAArch32.inc.example
new file mode 100644
index 00000000000000..7541fbdc82ed02
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkAArch32.inc.example
@@ -0,0 +1,33 @@
+/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
+|*                                                                            *|
+|* Instruction Encoding Information                                           *|
+|*                                                                            *|
+|* Automatically generated file, do not edit!                                 *|
+|*                                                                            *|
+\*===----------------------------------------------------------------------===*/
+
+#ifdef GET_INSTR // (Opc, Opc_Mask, Imm_Mask, Reg_Mask)
+GET_INSTR(BL, 0xeb000000, 0xff000000, 0xffffff, 0x0)
+GET_INSTR(BLX, 0xe12fff30, 0xfffffff0, 0xf, 0x0)
+GET_INSTR(BLX_pred, 0x12fff30, 0xffffff0, 0xf, 0x0)
+GET_INSTR(BLXi, 0xfa000000, 0xfe000000, 0x0, 0x0)
+GET_INSTR(BL_pred, 0xb000000, 0xf000000, 0xffffff, 0x0)
+GET_INSTR(HVC, 0xe1400070, 0xfff000f0, 0xfff0f, 0x0)
+GET_INSTR(MOVTi16, 0x3400000, 0xff00000, 0xf0fff, 0xf000)
+GET_INSTR(MOVi, 0x3a00000, 0xfef0000, 0xfff, 0xf000)
+GET_INSTR(MOVi16, 0x3000000, 0xff00000, 0xf0fff, 0xf000)
+GET_INSTR(MVNi, 0x3e00000, 0xfef0000, 0xfff, 0xf000)
+GET_INSTR(SVC, 0xf000000, 0xf000000, 0x0, 0x0)
+GET_INSTR(t2HVC, 0xf7e08000, 0xfff0f000, 0x0, 0x0)
+GET_INSTR(t2MOVTi16, 0xf2c00000, 0xfbf08000, 0x40f70ff, 0xf00)
+GET_INSTR(t2MOVi, 0xf04f0000, 0xfbef8000, 0x40070ff, 0xf00)
+GET_INSTR(t2MOVi16, 0xf2400000, 0xfbf08000, 0x40f70ff, 0xf00)
+GET_INSTR(t2MVNi, 0xf06f0000, 0xfbef8000, 0x40070ff, 0xf00)
+GET_INSTR(t2SMC, 0xf7f08000, 0xfff0f000, 0x0, 0x0)
+GET_INSTR(tBL, 0xf000d000, 0xf800d000, 0x7ff2fff, 0x0)
+GET_INSTR(tBLXNSr, 0x4784, 0xffffff87, 0x78, 0x0)
+GET_INSTR(tBLXi, 0xf000c000, 0xf800d001, 0x7ff2ffe, 0x0)
+GET_INSTR(tBLXr, 0x4780, 0xffffff87, 0x78, 0x0)
+GET_INSTR(tMOVi8, 0x2000, 0xfffff800, 0x0, 0x700)
+GET_INSTR(tSVC, 0xdf00, 0xffffff00, 0xff, 0x0)
+#endif
diff --git a/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp b/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp
index 151b5aaafa15b4..5d283ac71386ac 100644
--- a/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp
+++ b/llvm/utils/TableGen/JITLinkAArch32InstrInfo.cpp
@@ -9,6 +9,7 @@
 // This Tablegen backend emits instruction encodings of AArch32 for JITLink.
 //
 //===----------------------------------------------------------------------===//
+#include "llvm/Support/Debug.h"
 #include "llvm/TableGen/Record.h"
 #include "llvm/TableGen/TableGenBackend.h"
 
@@ -37,7 +38,7 @@ static void extractBits(BitsInit &InstBits, InstrInfo &II) {
     if (auto *VarBit = dyn_cast<VarBitInit>(Bit)) {
       // Check if the VarBit is for 'imm' or 'Rd'
       std::string VarName = VarBit->getBitVar()->getAsUnquotedString();
-      if (VarName == "imm") {
+      if (VarName == "imm" || VarName == "func") {
         II.ImmMask |= 1 << i;
       } else if (VarName == "Rd") {
         II.RegMask |= 1 << i;
@@ -81,10 +82,24 @@ void JITLinkEmitter::run(raw_ostream &OS) {
   for (auto *InstRecord : RecordsList) {
     if (InstRecord->getValueAsBit("isPseudo"))
       continue;
-    auto *InstBits = InstRecord->getValueAsBitsInit("Inst");
-    InstrInfo II;
-    extractBits(*InstBits, II);
-    writeInstrInfo(OS, II, InstRecord->getNameInitAsString());
+    LLVM_DEBUG(dbgs() << "Processing " << InstRecord->getNameInitAsString()
+                      << "\n");
+    if (InstRecord->getValueAsBit("isMoveImm") ||
+        InstRecord->getValueAsBit("isCall") ||
+        // FIXME movt for ARM and Thumb2 do not have their isMovImm flags set
+        //       so we add these conditionals
+        InstRecord->getNameInitAsString() == "MOVTi16" ||
+        InstRecord->getNameInitAsString() == "t2MOVTi16") {
+      LLVM_DEBUG(for (const auto &Val
+                      : InstRecord->getValues()) {
+        dbgs() << "Field: " << Val.getNameInitAsString() << " = "
+               << Val.getValue()->getAsUnquotedString() << "\n";
+      });
+      auto *InstBits = InstRecord->getValueAsBitsInit("Inst");
+      InstrInfo II;
+      extractBits(*InstBits, II);
+      writeInstrInfo(OS, II, InstRecord->getNameInitAsString());
+    }
   }
 
   OS << "#endif\n";



More information about the llvm-commits mailing list