[compiler-rt] [llvm] [JITLink][Mips] Add ELF backend (PR #224578)

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 27 17:28:36 PDT 2026


================
@@ -0,0 +1,1161 @@
+//===-- ELF_mips.cpp - JIT linker implementation for ELF/MIPS ------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/JITLink/ELF_mips.h"
+
+#include "EHFrameSupportImpl.h"
+#include "ELFLinkGraphBuilder.h"
+#include "JITLinkGeneric.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
+#include "llvm/ExecutionEngine/JITLink/mips.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MipsABIFlags.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <tuple>
+
+#define DEBUG_TYPE "jitlink"
+
+using namespace llvm;
+using namespace llvm::jitlink;
+using namespace llvm::jitlink::mips;
+
+namespace {
+
+constexpr StringRef GOTSectionName = "$__GOT";
+constexpr StringRef StubsSectionName = "$__STUBS";
+constexpr StringRef TLSInfoSectionName = "$__TLSINFO";
+constexpr StringRef TLSBaseName = "__jitlink_mips_tls_base";
+constexpr StringRef GOTSymbolName = "_GLOBAL_OFFSET_TABLE_";
+constexpr StringRef GPName = "_gp";
+constexpr StringRef GPDispName = "_gp_disp";
+constexpr StringRef LocalGPName = "__gnu_local_gp";
+constexpr unsigned InstructionSize = sizeof(uint32_t);
+constexpr unsigned RelocationTypeBits = 8;
+constexpr unsigned MaxRelocationOperations = 3;
+constexpr unsigned GOTPageBits = 16;
+constexpr uint64_t GOTPageSize = UINT64_C(1) << GOTPageBits;
+constexpr uint64_t GOTPageMask = GOTPageSize - 1;
+constexpr uint64_t GOTPageBias = GOTPageSize / 2;
+constexpr unsigned JumpRegionBits = 28;
+constexpr uint64_t JumpRegionMask = ~maskTrailingOnes<uint64_t>(JumpRegionBits);
+constexpr int64_t CompactBranchPCBias = InstructionSize;
+// The MIPS psABI defines $gp as 0x7ff0 bytes past the GOT base.
+constexpr uint64_t GPAnchorOffset = 0x7ff0;
+
+enum class MipsABI { O32, N32, N64 };
+
+static uint16_t getLo16(uint64_t Value) { return static_cast<uint16_t>(Value); }
+
+static uint16_t getHi16(uint64_t Value) {
+  return static_cast<uint16_t>((Value + GOTPageBias) >> 16);
+}
+
+static uint16_t getHigher16(uint64_t Value) {
+  constexpr uint64_t Bias = GOTPageBias | (GOTPageBias << 16);
+  return static_cast<uint16_t>((Value + Bias) >> 32);
+}
+
+static uint16_t getHighest16(uint64_t Value) {
+  constexpr uint64_t Bias =
+      GOTPageBias | (GOTPageBias << 16) | (GOTPageBias << 32);
+  return static_cast<uint16_t>((Value + Bias) >> 48);
+}
+
+static uint64_t getGOTPage(uint64_t Value) {
+  return (Value + GOTPageBias) & ~GOTPageMask;
+}
+
+static Edge::Kind getPagePointerEdgeKind(const LinkGraph &G) {
+  return G.getPointerSize() == 8 ? PagePointer64 : PagePointer32;
+}
+
+struct PCRelEncoding {
+  unsigned Bits;
+  unsigned Shift;
+  unsigned PCAlignment;
+};
+
+static PCRelEncoding getPCRelEncoding(Edge::Kind Kind) {
+  switch (Kind) {
+  case PC16:
+    return {16, 2, 1};
+  case PC18S3:
+    return {18, 3, 8};
+  case PC19S2:
+    return {19, 2, 4};
+  case PC21S2:
+    return {21, 2, 1};
+  case PC26S2:
+    return {26, 2, 1};
+  default:
+    llvm_unreachable("not a MIPS immediate branch edge");
+  }
+}
+
+template <unsigned Bits, unsigned Shift>
+static int64_t decodeInstructionImmediate(uint32_t Instruction) {
+  static_assert(Bits + Shift <= 32);
+  uint32_t Value = (Instruction & maskTrailingOnes<uint32_t>(Bits)) << Shift;
+  return SignExtend64<Bits + Shift>(Value);
+}
+
+static uint8_t getPackedRelocationField(uint32_t Packed, unsigned Index) {
+  return static_cast<uint8_t>((Packed >> (Index * RelocationTypeBits)) &
+                              maskTrailingOnes<uint32_t>(RelocationTypeBits));
+}
+
+static std::string getRelocationChainName(ArrayRef<uint8_t> Types) {
+  std::string Result;
+  raw_string_ostream OS(Result);
+  for (auto [Index, Type] : llvm::enumerate(Types)) {
+    if (Index)
+      OS << '/';
+    OS << object::getELFRelocationTypeName(ELF::EM_MIPS, Type);
+  }
+  return Result;
+}
+
+static bool needsGP(Edge::Kind K) {
+  switch (K) {
+  case GPRel16:
+  case GPRel32:
+  case GPRel64:
+  case GOTOffset16:
+  case GOTOffsetHi16:
+  case GOTOffsetLo16:
+  case GPDispHi16:
+  case GPDispLo16:
+  case NegGPRelHi16:
+  case NegGPRelLo16:
+    return true;
+  default:
+    return false;
+  }
+}
+
+static unsigned getFixupSize(Edge::Kind K) {
+  switch (K) {
+  case Abs16:
+    return sizeof(uint16_t);
+  case Pointer64:
+  case PagePointer64:
+  case Delta64:
+  case GPRel64:
+  case DTPRel64:
+    return sizeof(uint64_t);
+  case Pointer32:
+  case PagePointer32:
+  case Delta32:
+  case NegDelta32:
+  case Hi16:
+  case Lo16:
+  case Higher16:
+  case Highest16:
+  case Jump26:
+  case PC16:
+  case PC32:
+  case PC18S3:
+  case PC19S2:
+  case PC21S2:
+  case PC26S2:
+  case PCHi16:
+  case PCLo16:
+  case GPDispHi16:
+  case GPDispLo16:
+  case GPRel16:
+  case GPRel32:
+  case GOTOffset16:
+  case GOTOffsetHi16:
+  case GOTOffsetLo16:
+  case GOTPageOffset16:
+  case DTPRelHi16:
+  case DTPRelLo16:
+  case DTPRel32:
+  case NegGPRelHi16:
+  case NegGPRelLo16:
+  case RequestGOTAndTransformToOffset16:
+  case RequestGOTPageAndTransformToOffset16:
+  case RequestGOTAndTransformToOffsetHi16:
+  case RequestGOTAndTransformToOffsetLo16:
+  case RequestTLSGDAndTransformToOffset16:
+  case RequestTLSLDMAndTransformToOffset16:
+    return sizeof(uint32_t);
+  default:
+    llvm_unreachable("not a MIPS relocation edge");
+  }
+}
+
+class ELFJITLinker_mips : public JITLinker<ELFJITLinker_mips> {
+  friend class JITLinker<ELFJITLinker_mips>;
+
+public:
+  ELFJITLinker_mips(std::unique_ptr<JITLinkContext> Ctx,
+                    std::unique_ptr<LinkGraph> G, PassConfiguration PassConfig)
+      : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
+
+private:
+  Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
----------------
lhames wrote:

Can this be moved into `mips.h` for consistency with the other backends?

(I don't know if there's a COFF_mips backend in the works, but if nothing else this helps to support the convention that edge-kinds are expressed per-architecture, rather than per-backend).

https://github.com/llvm/llvm-project/pull/224578


More information about the llvm-commits mailing list