[llvm] [JITLink][AArch32] Add TableGen Backend for Instr Encodings (PR #76996)
Eymen Ünay via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 4 12:12:55 PST 2024
https://github.com/eymay created https://github.com/llvm/llvm-project/pull/76996
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`.
>From becbe3a324aa8b484a539cb5e07ea1caf6db5e11 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] [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 f346cfb2a93112..a0c25b56770f5a 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h
@@ -212,20 +212,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};
@@ -240,27 +226,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 671ee1a8125252..e603b0bb19fd73 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
@@ -20,6 +20,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 26c773b8dc3a71..4536cad755e13d 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 071ea3bc07054b..1e629deca93a83 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
@@ -89,6 +90,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");
More information about the llvm-commits
mailing list