[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