[llvm] JITLink: Add initial SystemZ Support. (PR #144528)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 5 12:03:56 PST 2025
https://github.com/anoopkg6 updated https://github.com/llvm/llvm-project/pull/144528
>From e4a4547a394266c1b0c8e464b12ccc0b1cbaf091 Mon Sep 17 00:00:00 2001
From: anoopkg6 <anoopkg6 at github.com>
Date: Tue, 17 Jun 2025 15:00:13 +0200
Subject: [PATCH 1/7] Add initial llvm-jitlink support for SystemZ.
---
.../ExecutionEngine/JITLink/ELF_systemz.h | 39 +
.../llvm/ExecutionEngine/JITLink/systemz.h | 1089 +++++++++++++++++
.../ExecutionEngine/JITLink/CMakeLists.txt | 2 +
llvm/lib/ExecutionEngine/JITLink/ELF.cpp | 6 +
.../ExecutionEngine/JITLink/ELF_systemz.cpp | 437 +++++++
llvm/lib/ExecutionEngine/JITLink/JITLink.cpp | 6 +
llvm/lib/ExecutionEngine/JITLink/systemz.cpp | 121 ++
.../JITLink/systemz/ELF_systemz_ehframe.s | 58 +
.../JITLink/systemz/ELF_systemz_got.s | 78 ++
.../JITLink/systemz/ELF_systemz_reloc_abs16.s | 35 +
.../JITLink/systemz/ELF_systemz_reloc_abs32.s | 32 +
.../JITLink/systemz/ELF_systemz_reloc_abs64.s | 28 +
.../JITLink/systemz/ELF_systemz_reloc_abs8.s | 38 +
.../systemz/ELF_systemz_reloc_call_pic.s | 82 ++
.../systemz/ELF_systemz_reloc_disp12.s | 28 +
.../systemz/ELF_systemz_reloc_disp20.s | 31 +
.../JITLink/systemz/ELF_systemz_reloc_got.s | 244 ++++
.../systemz/ELF_systemz_reloc_gotrel.s | 68 +
.../JITLink/systemz/ELF_systemz_reloc_pc.s | 20 +
.../JITLink/systemz/ELF_systemz_reloc_pc16.s | 40 +
.../JITLink/systemz/ELF_systemz_reloc_pc32.s | 40 +
.../JITLink/systemz/ELF_systemz_reloc_pc64.s | 34 +
.../JITLink/systemz/ELF_systemz_reloc_pcdbl.s | 84 ++
.../JITLink/systemz/ELF_systemz_reloc_plt.s | 71 ++
.../systemz/ELF_systemz_reloc_pltdbl.s | 51 +
.../JITLink/systemz/lit.local.cfg | 2 +
llvm/test/ExecutionEngine/lit.local.cfg | 2 +-
27 files changed, 2765 insertions(+), 1 deletion(-)
create mode 100644 llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h
create mode 100644 llvm/include/llvm/ExecutionEngine/JITLink/systemz.h
create mode 100644 llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp
create mode 100644 llvm/lib/ExecutionEngine/JITLink/systemz.cpp
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_ehframe.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_got.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs64.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_got.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_gotrel.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc16.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc32.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc64.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pcdbl.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_plt.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pltdbl.s
create mode 100644 llvm/test/ExecutionEngine/JITLink/systemz/lit.local.cfg
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h
new file mode 100644
index 0000000000000..c78bc7cc1f499
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h
@@ -0,0 +1,39 @@
+//===--- ELF_systemz.h - JIT link functions for ELF/systemz --*- C++ -*----===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+//===----------------------------------------------------------------------===//
+//
+// jit-link functions for ELF/systemz.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITLINK_ELF_SYSTEMZ_H
+#define LLVM_EXECUTIONENGINE_JITLINK_ELF_SYSTEMZ_H
+
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+
+namespace llvm {
+namespace jitlink {
+
+/// Create a LinkGraph from an ELF/systemz relocatable object
+///
+/// Note: The graph does not take ownership of the underlying buffer, nor copy
+/// its contents. The caller is responsible for ensuring that the object buffer
+/// outlives the graph.
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromELFObject_systemz(MemoryBufferRef ObjectBuffer);
+
+/// jit-link the given object buffer, which must be a ELF systemz relocatable
+/// object file.
+void link_ELF_systemz(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx);
+
+} // end namespace jitlink
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_JITLINK_ELF_SYSTEMZ_H
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h
new file mode 100644
index 0000000000000..e1498ff820fe6
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h
@@ -0,0 +1,1089 @@
+//=== systemz.h - Generic JITLink systemz edge kinds, utilities -*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic utilities for graphs representing systemz objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITLINK_SYSTEMZ_H
+#define LLVM_EXECUTIONENGINE_JITLINK_SYSTEMZ_H
+
+#include "TableManager.h"
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+
+using namespace llvm::support::endian;
+
+namespace llvm {
+namespace jitlink {
+namespace systemz {
+
+/// Represents systemz fixups and other systemz-specific edge kinds.
+enum EdgeKind_systemz : Edge::Kind {
+
+ /// A plain 64-bit pointer value relocation.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target + Addend : uint64
+ ///
+ Pointer64 = Edge::FirstRelocation,
+
+ /// A plain 32-bit pointer value relocation.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target + Addend : uint32
+ ///
+ /// Errors:
+ /// - The target must reside in the low 32-bits of the address space,
+ /// otherwise an out-of-range error will be returned.
+ ///
+ Pointer32,
+
+ /// A plain 20-bit pointer value relocation.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target + Addend : uint20
+ ///
+ /// Errors:
+ /// - The target must reside in the mid 20-bits of the address space,
+ /// otherwise an out-of-range error will be returned.
+ ///
+ Pointer20,
+
+ /// A plain 16-bit pointer value relocation.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target + Addend : uint16
+ ///
+ /// Errors:
+ /// - The target must reside in the low 16-bits of the address space,
+ /// otherwise an out-of-range error will be returned.
+ ///
+ Pointer16,
+
+ /// A plain 12-bit pointer value relocation.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target + Addend : uint12
+ ///
+ /// Errors:
+ /// - The target must reside in the low 12-bits of the address space,
+ /// otherwise an out-of-range error will be returned.
+ ///
+ Pointer12,
+
+ /// A plain 8-bit pointer value relocation.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target + Addend : uint8
+ ///
+ /// Errors:
+ /// - The target must reside in the low 8-bits of the address space,
+ /// otherwise an out-of-range error will be returned.
+ ///
+ Pointer8,
+
+ /// A 64-bit delta.
+ ///
+ /// Delta from the fixup to the target.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - Fixup + Addend : int64
+ ///
+ Delta64,
+
+ /// A 32-bit delta.
+ ///
+ /// Delta from the fixup to the target.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - Fixup + Addend : int32
+ ///
+ /// Errors:
+ /// - The result of the fixup expression must fit into an int32, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ Delta32,
+
+ /// A 16-bit delta.
+ ///
+ /// Delta from the fixup to the target.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - Fixup + Addend : int16
+ ///
+ /// Errors:
+ /// - The result of the fixup expression must fit into an int16, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ Delta16,
+
+ /// A 32-bit delta.
+ ///
+ /// Delta from the fixup to the target.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend : int32) >> 1
+ ///
+ /// Errors:
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// fit into an int33, otherwise an out-of-range error will be returned.
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// be multiple of 2, otherwise an alignment error will be returned.
+ ///
+ Delta32dbl,
+
+ /// A 24-bit delta.
+ ///
+ /// Delta from the fixup to the target.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend : int24) >> 1
+ ///
+ /// Errors:
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// fit into an int25, otherwise an out-of-range error will be returned.
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// be multiple of 2, otherwise an alignment error will be returned.
+ ///
+ Delta24dbl,
+
+ /// A 16-bit delta.
+ ///
+ /// Delta from the fixup to the target.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend : int16) >> 1
+ ///
+ /// Errors:
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// fit into an int17, otherwise an out-of-range error will be returned.
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// be multiple of 2, otherwise an alignment error will be returned.
+ ///
+ Delta16dbl,
+
+ /// A 12-bit delta.
+ ///
+ /// Delta from the fixup to the target.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend : int12) >> 1
+ ///
+ /// Errors:
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// fit into an int13, otherwise an out-of-range error will be returned.
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// be multiple of 2, otherwise an alignment error will be returned.
+ ///
+ Delta12dbl,
+
+ /// A 64-bit negative delta.
+ ///
+ /// Delta from target back to the fixup.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Fixup - Target + Addend : int64
+ ///
+ NegDelta64,
+
+ /// A 32-bit negative delta.
+ ///
+ /// Delta from the target back to the fixup.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Fixup - Target + Addend : int32
+ ///
+ /// Errors:
+ /// - The result of the fixup expression must fit into an int32, otherwise
+ /// an out-of-range error will be returned.
+ NegDelta32,
+
+ /// A 64-bit GOT delta.
+ ///
+ /// Delta from the global offset table to the target
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTSymbol + Addend : int64
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ Delta64FromGOT,
+
+ /// A 32-bit GOT delta.
+ ///
+ /// Delta from the global offset table to the target
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTSymbol + Addend : int32
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ /// - The result of the fixup expression must fit into an int32, otherwise
+ /// an out-of-range error will be returned.
+ Delta32FromGOT,
+
+ /// A 16-bit GOT delta.
+ ///
+ /// Delta from the global offset table to the target
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTSymbol + Addend : int16
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ /// - The result of the fixup expression must fit into an int16, otherwise
+ /// an out-of-range error will be returned.
+ Delta16FromGOT,
+
+ /// A 32-bit PC-relative branch.
+ ///
+ /// Represents a PC-relative call or branch to a target. This can be used to
+ /// identify, record, and/or patch call sites.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend) >> 1 : int32
+ ///
+ /// Errors:
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// fit into an int33, otherwise an out-of-range error will be returned.
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// be multiple of 2, otherwise an alignment error will be returned.
+ ///
+ BranchPCRelPLT32dbl,
+
+ /// A 24-bit PC-relative branch.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend) >> 1 : int24
+ ///
+ /// Errors:
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// fit into an int25, otherwise an out-of-range error will be returned.
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// be multiple of 2, otherwise an alignment error will be returned.
+ ///
+ BranchPCRelPLT24dbl,
+
+ /// A 16-bit PC-relative branch.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend) >> 1 : int16
+ ///
+ /// Errors:
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// fit into an int17, otherwise an out-of-range error will be returned.
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// be multiple of 2, otherwise an alignment error will be returned.
+ ///
+ BranchPCRelPLT16dbl,
+
+ /// A 12-bit PC-relative branch.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend) >> 1 : int12
+ ///
+ /// Errors:
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// fit into an int13, otherwise an out-of-range error will be returned.
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// be multiple of 2, otherwise an alignment error will be returned.
+ ///
+ BranchPCRelPLT12dbl,
+
+ /// A 64-bit PC-relative PLT address.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - Fixup + Addend : int64
+ ///
+ BranchPCRelPLT64,
+
+ /// A 32-bit PC-relative PLT address.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - Fixup + Addend : int32
+ ///
+ /// Errors:
+ /// - The result of the fixup expression must fit into an int32, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ BranchPCRelPLT32,
+
+ /// A 32-bit PC-relative branch to a pointer jump stub.
+ /// Create a jump stub block that jumps via the pointer at the given symbol.
+ ///
+ /// Stub Content:
+ /// larl %r1, ptr
+ /// lg %r1, 0(%r1)
+ /// j %r1
+ ///
+ /// Fixup expression at offset 2 of branch Instruction:
+ /// Fixup <- (Target - Fixup + Addend) >> 1 : int32
+ ///
+ /// Errors:
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// fit into an int33, otherwise an out-of-range error will be returned.
+ /// an out-of-range error will be returned.
+ ///
+ Branch32dblToStub,
+
+ /// A 64-bit offset from GOT to PLT.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTBase + Addend : int64
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ ///
+ DeltaPLT64FromGOT,
+
+ /// A 32-bit offset from GOT to PLT.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTBase + Addend : int32
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ /// - The result of the fixup expression must fit into an int32, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ DeltaPLT32FromGOT,
+
+ /// A 16-bit offset from GOT to PLT.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTBase + Addend : int16
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ /// - The result of the fixup expression must fit into an int16, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ DeltaPLT16FromGOT,
+
+ /// A 64-bit GOT offset.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTBase + Addend : int64
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ ///
+ Delta64GOT,
+
+ /// A 32-bit GOT offset.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTBase + Addend : int32
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ /// - The result of the fixup expression must fit into an int32, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ Delta32GOT,
+
+ /// A 20-bit GOT offset.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTBase + Addend : int20
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ /// - The result of the fixup expression must fit into an int20, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ Delta20GOT,
+
+ /// A 16-bit GOT offset.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTBase + Addend : int16
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ /// - The result of the fixup expression must fit into an int16, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ Delta16GOT,
+
+ /// A 12-bit GOT offset.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTBase + Addend : int12
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ /// - The result of the fixup expression must fit into an int12, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ Delta12GOT,
+
+ /// A 32-bit PC rel. offset to GOT.
+ ///
+ /// Fixup expression:
+ /// Fixup <- GOTBase - Fixup + Addend : int32
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ /// - The result of the fixup expression must fit into an int32, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ DeltaPCRelGOT,
+
+ /// A 32-bit PC rel. offset to GOT shifted by 1.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (GOTBase - Fixup + Addend) >> 1 : int32
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// fit into an int33, otherwise an out-of-range error will be returned.
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// be multiple of 2, otherwise an alignment error will be returned.
+ ///
+ DeltaPCRelGOTdbl,
+
+ /// A 64-bit offset to Jump Slot.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTBase + Addend : int64
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ ///
+ Delta64JumpSlot,
+
+ /// A 32-bit offset to Jump Slot.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTBase + Addend : int32
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ /// - The result of the fixup expression must fit into an int32, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ Delta32JumpSlot,
+
+ /// A 20-bit offset to Jump Slot.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTBase + Addend : int20
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ /// - The result of the fixup expression must fit into an int20, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ Delta20JumpSlot,
+
+ /// A 16-bit offset to Jump Slot.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTBase + Addend : int16
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ /// - The result of the fixup expression must fit into an int16, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ Delta16JumpSlot,
+
+ /// A 12-bit offset to Jump Slot.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTBase + Addend : int12
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ /// - The result of the fixup expression must fit into an int12, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ Delta12JumpSlot,
+
+ /// A 32-bit PC rel. offset to Jump Slot.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend) >> 1 : int32
+ ///
+ /// Errors:
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// fit into an int33, otherwise an out-of-range error will be returned.
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// be multiple of 2, otherwise an alignment error will be returned.
+ ///
+ PCRel32JumpSlot,
+
+ /// A 32-bit PC rel. to GOT entry >> 1.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend) >> 1 : int32
+ ///
+ /// Errors:
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// fit into an int33, otherwise an out-of-range error will be returned.
+ /// - The result of the fixup expression before shifting right by 1 must
+ /// be multiple of 2, otherwise an alignment error will be returned.
+ ///
+ PCRel32GOTEntry,
+
+};
+
+/// Returns a string name for the given systemz edge. For debugging purposes
+/// only
+const char *getEdgeKindName(Edge::Kind K);
+
+/// Apply fixup expression for edge to block content.
+inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
+ const Symbol *GOTSymbol) {
+ using namespace support;
+
+ char *BlockWorkingMem = B.getAlreadyMutableContent().data();
+ char *FixupPtr = BlockWorkingMem + E.getOffset();
+ orc::ExecutorAddr FixupAddress = B.getAddress() + E.getOffset();
+ int64_t S = E.getTarget().getAddress().getValue();
+ int64_t A = E.getAddend();
+ int64_t P = FixupAddress.getValue();
+ int64_t GOTBase = GOTSymbol ? GOTSymbol->getAddress().getValue() : 0;
+ Edge::Kind K = E.getKind();
+
+ DEBUG_WITH_TYPE("jitlink", {
+ dbgs() << " Applying fixup on " << G.getEdgeKindName(K)
+ << " edge, (S, A, P, .GOT.) = (" << formatv("{0:x}", S) << ", "
+ << formatv("{0:x}", A) << ", " << formatv("{0:x}", P) << ", "
+ << formatv("{0:x}", GOTBase) << ")\n";
+ });
+
+ const auto isAlignmentCorrect = [](uint64_t Value, int N) {
+ return (Value & (N - 1)) ? false : true;
+ };
+
+ switch (K) {
+ case Pointer64: {
+ uint64_t Value = S + A;
+ write64be(FixupPtr, Value);
+ break;
+ }
+ case Pointer32: {
+ uint64_t Value = S + A;
+ if (!LLVM_UNLIKELY(isUInt<32>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(ubig32_t *)FixupPtr = Value;
+ break;
+ }
+ case Pointer20: {
+ uint64_t Value = S + A;
+ if (!LLVM_UNLIKELY(isInt<20>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ write32be(FixupPtr, (read32be(FixupPtr) & 0xF00000FF) |
+ ((Value & 0xFFF) << 16) | ((Value & 0xFF000) >> 4));
+ break;
+ }
+ case Pointer16: {
+ uint64_t Value = S + A;
+ if (!LLVM_UNLIKELY(isUInt<16>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(ubig16_t *)FixupPtr = Value;
+ break;
+ }
+ case Pointer12: {
+ uint64_t Value = S + A;
+ if (!LLVM_UNLIKELY(isUInt<12>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ write16be(FixupPtr, (read16be(FixupPtr) & 0xF000) | Value);
+ break;
+ }
+ case Pointer8: {
+ uint64_t Value = S + A;
+ if (!LLVM_UNLIKELY(isUInt<8>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(uint8_t *)FixupPtr = Value;
+ break;
+ }
+ case Delta64: {
+ int64_t Value = S + A - P;
+ *(big64_t *)FixupPtr = Value;
+ break;
+ }
+ case Delta32: {
+ int64_t Value = S + A - P;
+ if (!LLVM_UNLIKELY(isInt<32>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(big32_t *)FixupPtr = Value;
+ break;
+ }
+ case Delta16: {
+ int64_t Value = S + A - P;
+ if (!LLVM_UNLIKELY(isInt<16>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(big16_t *)FixupPtr = Value;
+ break;
+ }
+ case NegDelta32: {
+ int64_t Value = P + A - S;
+ if (!LLVM_UNLIKELY(isInt<32>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(big32_t *)FixupPtr = Value;
+ break;
+ }
+ case Delta32dbl: {
+ int64_t Value = (S + A - P);
+ if (!LLVM_UNLIKELY(isInt<33>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2)))
+ return makeAlignmentError(FixupAddress, Value, 2, E);
+ write32be(FixupPtr, Value >> 1);
+ break;
+ }
+ case Delta24dbl: {
+ int64_t Value = (S + A - P);
+ if (!LLVM_UNLIKELY(isInt<25>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2)))
+ return makeAlignmentError(FixupAddress, Value, 2, E);
+ FixupPtr[0] = Value >> 17;
+ FixupPtr[1] = Value >> 9;
+ FixupPtr[2] = Value >> 1;
+ break;
+ }
+ case Delta16dbl: {
+ int64_t Value = (S + A - P);
+ if (!LLVM_UNLIKELY(isInt<17>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2)))
+ return makeAlignmentError(FixupAddress, Value, 2, E);
+ write16be(FixupPtr, Value >> 1);
+ break;
+ }
+ case Delta12dbl: {
+ int64_t Value = (S + A - P);
+ if (!LLVM_UNLIKELY(isInt<13>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2)))
+ return makeAlignmentError(FixupAddress, Value, 2, E);
+ write16be(FixupPtr,
+ (read16be(FixupPtr) & 0xF000) | ((Value >> 1) & 0x0FFF));
+ break;
+ }
+ case Delta64FromGOT: {
+ assert(GOTSymbol && "No GOT section symbol");
+ int64_t Value = S - GOTBase + A;
+ *(big64_t *)FixupPtr = Value;
+ break;
+ }
+ case Delta32FromGOT: {
+ assert(GOTSymbol && "No GOT section symbol");
+ int64_t Value = S - GOTBase + A;
+ if (!LLVM_UNLIKELY(isInt<32>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(big32_t *)FixupPtr = Value;
+ break;
+ }
+ case Delta16FromGOT: {
+ assert(GOTSymbol && "No GOT section symbol");
+ int64_t Value = S - GOTBase + A;
+ if (!LLVM_UNLIKELY(isInt<16>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(big16_t *)FixupPtr = Value;
+ break;
+ }
+ case DeltaPCRelGOT: {
+ assert(GOTSymbol && "No GOT section symbol");
+ int64_t Value = GOTBase + A - P;
+ *(big32_t *)FixupPtr = Value;
+ break;
+ }
+ case DeltaPCRelGOTdbl: {
+ assert(GOTSymbol && "No GOT section symbol");
+ int64_t Value = (GOTBase + A - P);
+ if (!LLVM_UNLIKELY(isInt<33>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2)))
+ return makeAlignmentError(FixupAddress, Value, 2, E);
+ write32be(FixupPtr, Value >> 1);
+ break;
+ }
+ case BranchPCRelPLT32dbl: {
+ int64_t Value = (S + A - P);
+ if (!LLVM_UNLIKELY(isInt<33>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2)))
+ return makeAlignmentError(FixupAddress, Value, 2, E);
+ write32be(FixupPtr, Value >> 1);
+ break;
+ }
+ case BranchPCRelPLT24dbl: {
+ int64_t Value = (S + A - P);
+ if (!LLVM_UNLIKELY(isInt<25>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ FixupPtr[0] = Value >> 17;
+ FixupPtr[1] = Value >> 9;
+ FixupPtr[2] = Value >> 1;
+ break;
+ }
+ case BranchPCRelPLT16dbl: {
+ int64_t Value = (S + A - P);
+ if (!LLVM_UNLIKELY(isInt<17>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2)))
+ return makeAlignmentError(FixupAddress, Value, 2, E);
+ write16be(FixupPtr, Value >> 1);
+ break;
+ }
+ case BranchPCRelPLT12dbl: {
+ int64_t Value = (S + A - P);
+ if (!LLVM_UNLIKELY(isInt<13>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2)))
+ return makeAlignmentError(FixupAddress, Value, 2, E);
+ write16be(FixupPtr,
+ (read16be(FixupPtr) & 0xF000) | ((Value >> 1) & 0x0FFF));
+ break;
+ }
+ case BranchPCRelPLT64: {
+ int64_t Value = (S + A - P);
+ *(big64_t *)FixupPtr = Value;
+ break;
+ }
+ case BranchPCRelPLT32: {
+ int64_t Value = (S + A - P);
+ if (!LLVM_UNLIKELY(isInt<32>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(big32_t *)FixupPtr = Value;
+ break;
+ }
+ case DeltaPLT64FromGOT: {
+ assert(GOTSymbol && "No GOT section symbol");
+ int64_t Value = (S + A - GOTBase);
+ *(big64_t *)FixupPtr = Value;
+ break;
+ }
+ case DeltaPLT32FromGOT: {
+ assert(GOTSymbol && "No GOT section symbol");
+ int64_t Value = (S + A - GOTBase);
+ if (!LLVM_UNLIKELY(isInt<32>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(big32_t *)FixupPtr = Value;
+ break;
+ }
+ case DeltaPLT16FromGOT: {
+ assert(GOTSymbol && "No GOT section symbol");
+ int64_t Value = (S + A - GOTBase);
+ if (!LLVM_UNLIKELY(isInt<16>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(big16_t *)FixupPtr = Value;
+ break;
+ }
+ case Branch32dblToStub: {
+ int64_t Value = (S + A - P);
+ if (!LLVM_UNLIKELY(isInt<33>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ char *AddrToPatch = FixupPtr + 2;
+ *(big32_t *)AddrToPatch = (Value >> 1);
+ break;
+ }
+ case PCRel32GOTEntry: {
+ int64_t Value = (S + A - P);
+ if (!LLVM_UNLIKELY(isInt<33>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2)))
+ return makeAlignmentError(FixupAddress, Value, 2, E);
+ write32be(FixupPtr, Value >> 1);
+ break;
+ }
+ case Delta64GOT: {
+ assert(GOTSymbol && "No GOT section symbol");
+ int64_t Value = S - GOTBase + A;
+ *(big64_t *)FixupPtr = Value;
+ break;
+ }
+ case Delta32GOT: {
+ assert(GOTSymbol && "No GOT section symbol");
+ uint64_t Value = S - GOTBase + A;
+ if (!LLVM_UNLIKELY(isUInt<32>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(big32_t *)FixupPtr = Value;
+ break;
+ }
+ case Delta20GOT: {
+ assert(GOTSymbol && "No GOT section symbol");
+ uint64_t Value = S - GOTBase + A;
+ if (!LLVM_UNLIKELY(isInt<20>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ write32be(FixupPtr, (read32be(FixupPtr) & 0xF00000FF) |
+ ((Value & 0xFFF) << 16) | ((Value & 0xFF000) >> 4));
+ break;
+ }
+ case Delta16GOT: {
+ assert(GOTSymbol && "No GOT section symbol");
+ uint64_t Value = S - GOTBase + A;
+ if (!LLVM_UNLIKELY(isUInt<16>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(big16_t *)FixupPtr = Value;
+ break;
+ }
+ case Delta12GOT: {
+ assert(GOTSymbol && "No GOT section symbol");
+ uint64_t Value = S - GOTBase + A;
+ if (!LLVM_UNLIKELY(isUInt<12>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ write16be(FixupPtr, (read16be(FixupPtr) & 0xF000) | Value);
+ break;
+ }
+ case Delta64JumpSlot: {
+ assert(GOTSymbol && "No GOT section symbol");
+ uint64_t Value = S - GOTBase + A;
+ *(big64_t *)FixupPtr = Value;
+ break;
+ }
+ case Delta32JumpSlot: {
+ assert(GOTSymbol && "No GOT section symbol");
+ uint64_t Value = S - GOTBase + A;
+ if (!LLVM_UNLIKELY(isUInt<32>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(big32_t *)FixupPtr = Value;
+ break;
+ }
+ case Delta20JumpSlot: {
+ assert(GOTSymbol && "No GOT section symbol");
+ int64_t Value = S - GOTBase + A;
+ if (!LLVM_UNLIKELY(isInt<20>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ write32be(FixupPtr, (read32be(FixupPtr) & 0xF00000FF) |
+ ((Value & 0xFFF) << 16) | ((Value & 0xFF000) >> 4));
+ break;
+ }
+ case Delta16JumpSlot: {
+ assert(GOTSymbol && "No GOT section symbol");
+ uint64_t Value = S - GOTBase + A;
+ if (!LLVM_UNLIKELY(isUInt<16>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ *(big16_t *)FixupPtr = Value;
+ break;
+ }
+ case Delta12JumpSlot: {
+ assert(GOTSymbol && "No GOT section symbol");
+ uint64_t Value = S - GOTBase + A;
+ if (!LLVM_UNLIKELY(isUInt<13>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ write16be(FixupPtr, (read16be(FixupPtr) & 0xF000) | Value);
+ break;
+ }
+ case PCRel32JumpSlot: {
+ int64_t Value = S + A - P;
+ if (!LLVM_UNLIKELY(isInt<33>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2)))
+ return makeAlignmentError(FixupAddress, Value, 2, E);
+ write32be(FixupPtr, Value >> 1);
+ break;
+ }
+ default:
+ return make_error<JITLinkError>(
+ "In graph " + G.getName() + ", section " + B.getSection().getName() +
+ " unsupported edge kind " + getEdgeKindName(E.getKind()));
+ }
+
+ return Error::success();
+}
+
+/// SystemZ null pointer content.
+extern const char NullPointerContent[8];
+inline ArrayRef<char> getGOTEntryBlockContent(LinkGraph &G) {
+ return {reinterpret_cast<const char *>(NullPointerContent),
+ G.getPointerSize()};
+}
+
+/// SystemZ pointer jump stub content.
+///
+/// Contains the instruction sequence for an indirect jump via an in-memory
+/// pointer:
+/// larl %r1, ptr
+/// lg %r1, 0(%r1)
+/// j %r1
+constexpr size_t StubEntrySize = 14;
+extern const char Pointer64JumpStubContent[StubEntrySize];
+inline ArrayRef<char> getStubBlockContent(LinkGraph &G) {
+ auto StubContent = Pointer64JumpStubContent;
+ return {reinterpret_cast<const char *>(StubContent), StubEntrySize};
+}
+
+/// Creates a new pointer block in the given section and returns an
+/// Anonymous symbol pointing to it.
+///
+/// If InitialTarget is given then an Pointer64 relocation will be added to the
+/// block pointing at InitialTarget.
+inline Symbol &createAnonymousPointer(LinkGraph &G, Section &PointerSection,
+ Symbol *InitialTarget = nullptr,
+ uint64_t InitialAddend = 0) {
+ auto &B = G.createContentBlock(PointerSection, getGOTEntryBlockContent(G),
+ orc::ExecutorAddr(), G.getPointerSize(), 0);
+ if (InitialTarget)
+ B.addEdge(Pointer64, 0, *InitialTarget, InitialAddend);
+ return G.addAnonymousSymbol(B, 0, G.getPointerSize(), false, false);
+}
+
+/// Create a jump stub block that jumps via the pointer at the given symbol.
+///
+/// The stub block will have the following default values:
+/// alignment: 8-bit
+/// alignment-offset: 0
+inline Block &createPointerJumpStubBlock(LinkGraph &G, Section &StubSection,
+ Symbol &PointerSymbol) {
+ auto &B = G.createContentBlock(StubSection, getStubBlockContent(G),
+ orc::ExecutorAddr(), 8, 0);
+ B.addEdge(Branch32dblToStub, 0, PointerSymbol, 0);
+ return B;
+}
+
+/// Create a jump stub that jumps via the pointer at the given symbol and
+/// an anonymous symbol pointing to it. Return the anonymous symbol.
+///
+/// The stub block will be created by createPointerJumpStubBlock.
+inline Symbol &createAnonymousPointerJumpStub(LinkGraph &G,
+ Section &StubSection,
+ Symbol &PointerSymbol) {
+ return G.addAnonymousSymbol(
+ createPointerJumpStubBlock(G, StubSection, PointerSymbol), 0,
+ StubEntrySize, true, false);
+}
+
+/// Global Offset Table Builder.
+class GOTTableManager : public TableManager<GOTTableManager> {
+public:
+ static StringRef getSectionName() { return "$__GOT"; }
+
+ bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
+ if (E.getTarget().isDefined())
+ return false;
+ Edge::Kind KindToSet = Edge::Invalid;
+ switch (E.getKind()) {
+ case systemz::Delta12GOT:
+ case systemz::Delta16GOT:
+ case systemz::Delta20GOT:
+ case systemz::Delta32GOT:
+ case systemz::Delta64GOT:
+ case systemz::Delta16FromGOT:
+ case systemz::Delta32FromGOT:
+ case systemz::Delta64FromGOT:
+ case systemz::Delta12JumpSlot:
+ case systemz::Delta16JumpSlot:
+ case systemz::Delta32JumpSlot:
+ case systemz::Delta64JumpSlot:
+ case systemz::Delta20JumpSlot: {
+ case systemz::DeltaPCRelGOT:
+ case systemz::DeltaPCRelGOTdbl:
+ case systemz::PCRel32GOTEntry:
+ case systemz::PCRel32JumpSlot:
+ KindToSet = E.getKind();
+ break;
+ }
+ default:
+ return false;
+ }
+ assert(KindToSet != Edge::Invalid &&
+ "Fell through switch, but no new kind to set");
+ DEBUG_WITH_TYPE("jitlink", {
+ dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
+ << B->getFixupAddress(E) << " (" << B->getAddress() << " + "
+ << formatv("{0:x}", E.getOffset()) << ")\n";
+ });
+ E.setTarget(getEntryForTarget(G, E.getTarget()));
+ return true;
+ }
+
+ Symbol &createEntry(LinkGraph &G, Symbol &Target) {
+ return createAnonymousPointer(G, getGOTSection(G), &Target);
+ }
+
+private:
+ Section &getGOTSection(LinkGraph &G) {
+ if (!GOTSection)
+ GOTSection = &G.createSection(getSectionName(),
+ orc::MemProt::Read | orc::MemProt::Exec);
+ return *GOTSection;
+ }
+
+ Section *GOTSection = nullptr;
+};
+
+/// Procedure Linkage Table Builder.
+class PLTTableManager : public TableManager<PLTTableManager> {
+public:
+ PLTTableManager(GOTTableManager &GOT) : GOT(GOT) {}
+
+ static StringRef getSectionName() { return "$__STUBS"; }
+
+ bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
+ if (E.getTarget().isDefined())
+ return false;
+
+ switch (E.getKind()) {
+ case systemz::BranchPCRelPLT32:
+ case systemz::BranchPCRelPLT64:
+ case systemz::BranchPCRelPLT12dbl:
+ case systemz::BranchPCRelPLT16dbl:
+ case systemz::BranchPCRelPLT24dbl:
+ case systemz::BranchPCRelPLT32dbl:
+ case systemz::DeltaPLT16FromGOT:
+ case systemz::DeltaPLT32FromGOT:
+ case systemz::DeltaPLT64FromGOT:
+ break;
+ default:
+ return false;
+ }
+ DEBUG_WITH_TYPE("jitlink", {
+ dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
+ << B->getFixupAddress(E) << " (" << B->getAddress() << " + "
+ << formatv("{0:x}", E.getOffset()) << ")\n";
+ });
+ E.setTarget(getEntryForTarget(G, E.getTarget()));
+ return true;
+ }
+
+ Symbol &createEntry(LinkGraph &G, Symbol &Target) {
+ return createAnonymousPointerJumpStub(G, getStubsSection(G),
+ GOT.getEntryForTarget(G, Target));
+ }
+
+public:
+ Section &getStubsSection(LinkGraph &G) {
+ if (!StubsSection)
+ StubsSection = &G.createSection(getSectionName(),
+ orc::MemProt::Read | orc::MemProt::Exec);
+ return *StubsSection;
+ }
+
+ GOTTableManager &GOT;
+ Section *StubsSection = nullptr;
+};
+
+} // namespace systemz
+} // namespace jitlink
+} // namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_JITLINK_SYSTEMZ_H
diff --git a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
index e5f5a99c39bc0..bd78150407830 100644
--- a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
@@ -26,6 +26,7 @@ add_llvm_component_library(LLVMJITLink
ELF_loongarch.cpp
ELF_ppc64.cpp
ELF_riscv.cpp
+ ELF_systemz.cpp
ELF_x86_64.cpp
# COFF
@@ -41,6 +42,7 @@ add_llvm_component_library(LLVMJITLink
loongarch.cpp
ppc64.cpp
riscv.cpp
+ systemz.cpp
x86_64.cpp
ADDITIONAL_HEADER_DIRS
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp
index fdcce20cd2d10..374982d9e2b1d 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF.cpp
@@ -19,6 +19,7 @@
#include "llvm/ExecutionEngine/JITLink/ELF_loongarch.h"
#include "llvm/ExecutionEngine/JITLink/ELF_ppc64.h"
#include "llvm/ExecutionEngine/JITLink/ELF_riscv.h"
+#include "llvm/ExecutionEngine/JITLink/ELF_systemz.h"
#include "llvm/ExecutionEngine/JITLink/ELF_x86_64.h"
#include "llvm/Object/ELF.h"
#include "llvm/Support/Format.h"
@@ -99,6 +100,8 @@ createLinkGraphFromELFObject(MemoryBufferRef ObjectBuffer) {
}
case ELF::EM_RISCV:
return createLinkGraphFromELFObject_riscv(ObjectBuffer);
+ case ELF::EM_S390:
+ return createLinkGraphFromELFObject_systemz(ObjectBuffer);
case ELF::EM_X86_64:
return createLinkGraphFromELFObject_x86_64(ObjectBuffer);
case ELF::EM_386:
@@ -136,6 +139,9 @@ void link_ELF(std::unique_ptr<LinkGraph> G,
case Triple::riscv64:
link_ELF_riscv(std::move(G), std::move(Ctx));
return;
+ case Triple::systemz:
+ link_ELF_systemz(std::move(G), std::move(Ctx));
+ return;
case Triple::x86_64:
link_ELF_x86_64(std::move(G), std::move(Ctx));
return;
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp
new file mode 100644
index 0000000000000..6d598d62b1fc2
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp
@@ -0,0 +1,437 @@
+//===----- ELF_systemz.cpp - JIT linker implementation for ELF/systemz ----===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// ELF/systemz jit-link implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
+#include "llvm/ExecutionEngine/JITLink/systemz.h"
+#include "llvm/Object/ELFObjectFile.h"
+
+#include "DefineExternalSectionStartAndEndSymbols.h"
+#include "EHFrameSupportImpl.h"
+#include "ELFLinkGraphBuilder.h"
+#include "JITLinkGeneric.h"
+
+#define DEBUG_TYPE "jitlink"
+
+using namespace llvm;
+using namespace llvm::jitlink;
+
+namespace {
+
+constexpr StringRef ELFGOTSymbolName = "_GLOBAL_OFFSET_TABLE_";
+
+Error buildTables_ELF_systemz(LinkGraph &G) {
+ LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
+ systemz::GOTTableManager GOT;
+ systemz::PLTTableManager PLT(GOT);
+ visitExistingEdges(G, GOT, PLT);
+ return Error::success();
+}
+
+} // namespace
+
+namespace llvm {
+namespace jitlink {
+class ELFJITLinker_systemz : public JITLinker<ELFJITLinker_systemz> {
+ friend class JITLinker<ELFJITLinker_systemz>;
+
+public:
+ ELFJITLinker_systemz(std::unique_ptr<JITLinkContext> Ctx,
+ std::unique_ptr<LinkGraph> G,
+ PassConfiguration PassConfig)
+ : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {
+ if (shouldAddDefaultTargetPasses(getGraph().getTargetTriple()))
+ getPassConfig().PostAllocationPasses.push_back(
+ [this](LinkGraph &G) { return getOrCreateGOTSymbol(G); });
+ }
+
+private:
+ Symbol *GOTSymbol = nullptr;
+
+ Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
+ return systemz::applyFixup(G, B, E, GOTSymbol);
+ }
+
+ Error getOrCreateGOTSymbol(LinkGraph &G) {
+ auto DefineExternalGOTSymbolIfPresent =
+ createDefineExternalSectionStartAndEndSymbolsPass(
+ [&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc {
+ if (Sym.getName() == ELFGOTSymbolName)
+ if (auto *GOTSection = G.findSectionByName(
+ systemz::GOTTableManager::getSectionName())) {
+ GOTSymbol = &Sym;
+ return {*GOTSection, true};
+ }
+ return {};
+ });
+
+ // Try to attach _GLOBAL_OFFSET_TABLE_ to the GOT if it's defined as an
+ // external.
+ if (auto Err = DefineExternalGOTSymbolIfPresent(G))
+ return Err;
+
+ // If we succeeded then we're done.
+ if (GOTSymbol)
+ return Error::success();
+
+ // Otherwise look for a GOT section: If it already has a start symbol we'll
+ // record it, otherwise we'll create our own.
+ // If there's a GOT section but we didn't find an external GOT symbol...
+ if (auto *GOTSection =
+ G.findSectionByName(systemz::GOTTableManager::getSectionName())) {
+
+ // Check for an existing defined symbol.
+ for (auto *Sym : GOTSection->symbols())
+ if (Sym->getName() == ELFGOTSymbolName) {
+ GOTSymbol = Sym;
+ return Error::success();
+ }
+
+ // If there's no defined symbol then create one.
+ SectionRange SR(*GOTSection);
+ if (SR.empty())
+ GOTSymbol =
+ &G.addAbsoluteSymbol(ELFGOTSymbolName, orc::ExecutorAddr(), 0,
+ Linkage::Strong, Scope::Local, true);
+ else
+ GOTSymbol =
+ &G.addDefinedSymbol(*SR.getFirstBlock(), 0, ELFGOTSymbolName, 0,
+ Linkage::Strong, Scope::Local, false, true);
+ }
+
+ // If we still haven't found a GOT symbol then double check the externals.
+ // We may have a GOT-relative reference but no GOT section, in which case
+ // we just need to point the GOT symbol at some address in this graph.
+ if (!GOTSymbol) {
+ for (auto *Sym : G.external_symbols()) {
+ if (Sym->getName() == ELFGOTSymbolName) {
+ auto Blocks = G.blocks();
+ if (!Blocks.empty()) {
+ G.makeAbsolute(*Sym, (*Blocks.begin())->getAddress());
+ GOTSymbol = Sym;
+ break;
+ }
+ }
+ }
+ }
+
+ return Error::success();
+ }
+};
+
+class ELFLinkGraphBuilder_systemz
+ : public ELFLinkGraphBuilder<object::ELF64BE> {
+private:
+ using ELFT = object::ELF64BE;
+ using Base = ELFLinkGraphBuilder<ELFT>;
+ using Base::G; // Use LinkGraph pointer from base class.
+
+ Error addRelocations() override {
+ LLVM_DEBUG(dbgs() << "Processing relocations:\n");
+
+ using Base = ELFLinkGraphBuilder<ELFT>;
+ using Self = ELFLinkGraphBuilder_systemz;
+ for (const auto &RelSect : Base::Sections) {
+ if (RelSect.sh_type == ELF::SHT_REL)
+ // Validate the section to read relocation entries from.
+ return make_error<StringError>("No SHT_REL in valid " +
+ G->getTargetTriple().getArchName() +
+ " ELF object files",
+ inconvertibleErrorCode());
+
+ if (Error Err = Base::forEachRelaRelocation(RelSect, this,
+ &Self::addSingleRelocation))
+ return Err;
+ }
+
+ return Error::success();
+ }
+
+ Error addSingleRelocation(const typename ELFT::Rela &Rel,
+ const typename ELFT::Shdr &FixupSect,
+ Block &BlockToFix) {
+ using support::big32_t;
+ using Base = ELFLinkGraphBuilder<ELFT>;
+ auto ELFReloc = Rel.getType(false);
+
+ // No reloc.
+ if (LLVM_UNLIKELY(ELFReloc == ELF::R_390_NONE))
+ return Error::success();
+
+ uint32_t SymbolIndex = Rel.getSymbol(false);
+ auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
+ if (!ObjSymbol)
+ return ObjSymbol.takeError();
+
+ Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
+ if (!GraphSymbol)
+ return make_error<StringError>(
+ formatv("Could not find symbol at given index, did you add it to "
+ "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
+ SymbolIndex, (*ObjSymbol)->st_shndx,
+ Base::GraphSymbols.size()),
+ inconvertibleErrorCode());
+
+ // Validate the relocation kind.
+ int64_t Addend = Rel.r_addend;
+ Edge::Kind Kind = Edge::Invalid;
+
+ switch (ELFReloc) {
+ case ELF::R_390_PC64: {
+ Kind = systemz::Delta64;
+ break;
+ }
+ case ELF::R_390_PC32: {
+ Kind = systemz::Delta32;
+ break;
+ }
+ case ELF::R_390_PC16: {
+ Kind = systemz::Delta16;
+ break;
+ }
+ case ELF::R_390_PC32DBL: {
+ Kind = systemz::Delta32dbl;
+ break;
+ }
+ case ELF::R_390_PC24DBL: {
+ Kind = systemz::Delta24dbl;
+ break;
+ }
+ case ELF::R_390_PC16DBL: {
+ Kind = systemz::Delta16dbl;
+ break;
+ }
+ case ELF::R_390_PC12DBL: {
+ Kind = systemz::Delta12dbl;
+ break;
+ }
+ case ELF::R_390_64: {
+ Kind = systemz::Pointer64;
+ break;
+ }
+ case ELF::R_390_32: {
+ Kind = systemz::Pointer32;
+ break;
+ }
+ case ELF::R_390_20: {
+ Kind = systemz::Pointer20;
+ break;
+ }
+ case ELF::R_390_16: {
+ Kind = systemz::Pointer16;
+ break;
+ }
+ case ELF::R_390_12: {
+ Kind = systemz::Pointer12;
+ break;
+ }
+ case ELF::R_390_8: {
+ Kind = systemz::Pointer8;
+ break;
+ }
+ // Relocations targeting the PLT associated with the symbol.
+ case ELF::R_390_PLT64: {
+ Kind = systemz::BranchPCRelPLT64;
+ break;
+ }
+ case ELF::R_390_PLT32: {
+ Kind = systemz::BranchPCRelPLT32;
+ break;
+ }
+ case ELF::R_390_PLT32DBL: {
+ Kind = systemz::BranchPCRelPLT32dbl;
+ break;
+ }
+ case ELF::R_390_PLT24DBL: {
+ Kind = systemz::BranchPCRelPLT24dbl;
+ break;
+ }
+ case ELF::R_390_PLT16DBL: {
+ Kind = systemz::BranchPCRelPLT16dbl;
+ break;
+ }
+ case ELF::R_390_PLT12DBL: {
+ Kind = systemz::BranchPCRelPLT12dbl;
+ break;
+ }
+ case ELF::R_390_PLTOFF64: {
+ Kind = systemz::DeltaPLT64FromGOT;
+ break;
+ }
+ case ELF::R_390_PLTOFF32: {
+ Kind = systemz::DeltaPLT32FromGOT;
+ break;
+ }
+ case ELF::R_390_PLTOFF16: {
+ Kind = systemz::DeltaPLT16FromGOT;
+ break;
+ }
+ // Relocations targeting the GOT entry associated with the symbol.
+ case ELF::R_390_GOTOFF64: {
+ Kind = systemz::Delta64FromGOT;
+ break;
+ }
+ // Seems loke ‘R_390_GOTOFF32’.
+ case ELF::R_390_GOTOFF: {
+ Kind = systemz::Delta32FromGOT;
+ break;
+ }
+ case ELF::R_390_GOTOFF16: {
+ Kind = systemz::Delta16FromGOT;
+ break;
+ }
+ case ELF::R_390_GOT64: {
+ Kind = systemz::Delta64GOT;
+ break;
+ }
+ case ELF::R_390_GOT32: {
+ Kind = systemz::Delta32GOT;
+ break;
+ }
+ case ELF::R_390_GOT20: {
+ Kind = systemz::Delta20GOT;
+ break;
+ }
+ case ELF::R_390_GOT16: {
+ Kind = systemz::Delta16GOT;
+ break;
+ }
+ case ELF::R_390_GOT12: {
+ Kind = systemz::Delta12GOT;
+ break;
+ }
+ case ELF::R_390_GOTPC: {
+ Kind = systemz::DeltaPCRelGOT;
+ break;
+ }
+ case ELF::R_390_GOTPCDBL: {
+ Kind = systemz::DeltaPCRelGOTdbl;
+ break;
+ }
+ case ELF::R_390_GOTPLT64: {
+ Kind = systemz::Delta64JumpSlot;
+ break;
+ }
+ case ELF::R_390_GOTPLT32: {
+ Kind = systemz::Delta32JumpSlot;
+ break;
+ }
+ case ELF::R_390_GOTPLT20: {
+ Kind = systemz::Delta20JumpSlot;
+ break;
+ }
+ case ELF::R_390_GOTPLT16: {
+ Kind = systemz::Delta16JumpSlot;
+ break;
+ }
+ case ELF::R_390_GOTPLT12: {
+ Kind = systemz::Delta12JumpSlot;
+ break;
+ }
+ case ELF::R_390_GOTPLTENT: {
+ Kind = systemz::PCRel32JumpSlot;
+ break;
+ }
+ case ELF::R_390_GOTENT: {
+ Kind = systemz::PCRel32GOTEntry;
+ break;
+ }
+ default:
+ return make_error<JITLinkError>(
+ "In " + G->getName() + ": Unsupported systemz relocation type " +
+ object::getELFRelocationTypeName(ELF::EM_S390, ELFReloc));
+ }
+ auto FixupAddress = orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;
+ Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
+ Edge GE(Kind, Offset, *GraphSymbol, Addend);
+ LLVM_DEBUG({
+ dbgs() << " ";
+ printEdge(dbgs(), BlockToFix, GE, systemz::getEdgeKindName(Kind));
+ dbgs() << "\n";
+ });
+
+ BlockToFix.addEdge(std::move(GE));
+
+ return Error::success();
+ }
+
+public:
+ ELFLinkGraphBuilder_systemz(StringRef FileName,
+ const object::ELFFile<ELFT> &Obj, Triple TT,
+ SubtargetFeatures Features)
+ : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features),
+ FileName, systemz::getEdgeKindName) {}
+};
+
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromELFObject_systemz(MemoryBufferRef ObjectBuffer) {
+ LLVM_DEBUG({
+ dbgs() << "Building jitlink graph for new input "
+ << ObjectBuffer.getBufferIdentifier() << "...\n";
+ });
+
+ auto ELFObj = object::ObjectFile::createELFObjectFile(ObjectBuffer);
+ if (!ELFObj)
+ return ELFObj.takeError();
+
+ auto Features = (*ELFObj)->getFeatures();
+ if (!Features)
+ return Features.takeError();
+
+ assert((*ELFObj)->getArch() == Triple::systemz &&
+ "Only SystemZ (big endian) is supported for now");
+
+ auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64BE>>(**ELFObj);
+ return ELFLinkGraphBuilder_systemz(
+ (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
+ (*ELFObj)->makeTriple(), std::move(*Features))
+ .buildGraph();
+}
+
+void link_ELF_systemz(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
+ PassConfiguration Config;
+ const Triple &TT = G->getTargetTriple();
+ if (Ctx->shouldAddDefaultTargetPasses(TT)) {
+ // Add eh-frame passes.
+ Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame"));
+ Config.PrePrunePasses.push_back(
+ EHFrameEdgeFixer(".eh_frame", G->getPointerSize(), systemz::Pointer32,
+ systemz::Pointer64, systemz::Delta32, systemz::Delta64,
+ systemz::NegDelta32));
+ Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame"));
+
+ // Add a mark-live pass.
+ if (auto MarkLive = Ctx->getMarkLivePass(TT))
+ Config.PrePrunePasses.push_back(std::move(MarkLive));
+ else
+ Config.PrePrunePasses.push_back(markAllSymbolsLive);
+
+ // Add an in-place GOT/Stubs build pass.
+ Config.PostPrunePasses.push_back(buildTables_ELF_systemz);
+
+ // Resolve any external section start / end symbols.
+ Config.PostAllocationPasses.push_back(
+ createDefineExternalSectionStartAndEndSymbolsPass(
+ identifyELFSectionStartAndEndSymbols));
+
+ // TODO: Add GOT/Stubs optimizer pass.
+ // Config.PreFixupPasses.push_back(systemz::optimizeGOTAndStubAccesses);
+ }
+
+ if (auto Err = Ctx->modifyPassConfig(*G, Config))
+ return Ctx->notifyFailed(std::move(Err));
+
+ ELFJITLinker_systemz::link(std::move(Ctx), std::move(G), std::move(Config));
+}
+
+} // namespace jitlink
+} // namespace llvm
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
index ef382c3ce695a..453c26cca8eae 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
@@ -16,6 +16,7 @@
#include "llvm/ExecutionEngine/JITLink/aarch64.h"
#include "llvm/ExecutionEngine/JITLink/i386.h"
#include "llvm/ExecutionEngine/JITLink/loongarch.h"
+#include "llvm/ExecutionEngine/JITLink/systemz.h"
#include "llvm/ExecutionEngine/JITLink/x86_64.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -459,6 +460,8 @@ AnonymousPointerCreator getAnonymousPointerCreator(const Triple &TT) {
case Triple::loongarch32:
case Triple::loongarch64:
return loongarch::createAnonymousPointer;
+ case Triple::systemz:
+ return systemz::createAnonymousPointer;
default:
return nullptr;
}
@@ -475,6 +478,8 @@ PointerJumpStubCreator getPointerJumpStubCreator(const Triple &TT) {
case Triple::loongarch32:
case Triple::loongarch64:
return loongarch::createAnonymousPointerJumpStub;
+ case Triple::systemz:
+ return systemz::createAnonymousPointerJumpStub;
default:
return nullptr;
}
@@ -503,6 +508,7 @@ std::unique_ptr<LinkGraph> absoluteSymbolsLinkGraph(const Triple &TT,
switch (TT.getArch()) {
case Triple::aarch64:
case llvm::Triple::riscv64:
+ case Triple::systemz:
case Triple::x86_64:
PointerSize = 8;
break;
diff --git a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp
new file mode 100644
index 0000000000000..36ba857d8f5c4
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp
@@ -0,0 +1,121 @@
+//===---- systemz.cpp - Generic JITLink systemz edge kinds, utilities -----===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic utilities for graphs representing systemz objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/JITLink/systemz.h"
+
+#define DEBUG_TYPE "jitlink"
+
+namespace llvm {
+namespace jitlink {
+namespace systemz {
+
+const char NullPointerContent[8] = {0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00};
+
+const char Pointer64JumpStubContent[14] = {
+ static_cast<char>(0xC0), 0x10, 0x00, 0x00, 0x00, 0x00, // larl r1
+ static_cast<char>(0xE3), 0x10, 0x10, 0x00, 0x00, 0x04, // LG 1, 0(1)
+ static_cast<char>(0x07), 0xF1, // BCR 15, 1
+};
+
+const char *getEdgeKindName(Edge::Kind R) {
+ switch (R) {
+ case Pointer64:
+ return "Pointer64";
+ case Pointer32:
+ return "Pointer32";
+ case Pointer20:
+ return "Pointer20";
+ case Pointer16:
+ return "Pointer16";
+ case Pointer12:
+ return "Pointer12";
+ case Pointer8:
+ return "Pointer8";
+ case Delta64:
+ return "Delta64";
+ case Delta32:
+ return "Delta32";
+ case Delta16:
+ return "Delta16";
+ case Delta32dbl:
+ return "Delta32dbl";
+ case Delta24dbl:
+ return "Delta24dbl";
+ case Delta16dbl:
+ return "Delta16dbl";
+ case Delta12dbl:
+ return "Delta12dbl";
+ case NegDelta64:
+ return "NegDelta64";
+ case NegDelta32:
+ return "NegDelta32";
+ case Delta64FromGOT:
+ return "Delta64FromGOT";
+ case Delta32FromGOT:
+ return "Delta32FromGOT";
+ case Delta16FromGOT:
+ return "Delta16FromGOT";
+ case BranchPCRelPLT32dbl:
+ return "BranchPCRelPLT32dbl";
+ case BranchPCRelPLT24dbl:
+ return "BranchPCRelPLT24dbl";
+ case BranchPCRelPLT16dbl:
+ return "BranchPCRelPLT16dbl";
+ case BranchPCRelPLT12dbl:
+ return "BranchPCRelPLT12dbl";
+ case PCRel32GOTEntry:
+ return "PCRel32GOTENTRY";
+ case BranchPCRelPLT64:
+ return "BranchPCRelPLT64";
+ case BranchPCRelPLT32:
+ return "BranchPCRelPLT32";
+ case DeltaPLT64FromGOT:
+ return "DeltaPLT64FromGOT";
+ case DeltaPLT32FromGOT:
+ return "DeltaPLT32FromGOT";
+ case DeltaPLT16FromGOT:
+ return "DeltaPLT16FromGOT";
+ case Delta64GOT:
+ return "Delta64GOT";
+ case Delta32GOT:
+ return "Delta32GOT";
+ case Delta20GOT:
+ return "Delta20GOT";
+ case Delta16GOT:
+ return "Delta16GOT";
+ case Delta12GOT:
+ return "Delta12GOT";
+ case DeltaPCRelGOT:
+ return "DeltaPCRelGOT";
+ case DeltaPCRelGOTdbl:
+ return "DeltaPCRelGOTdbl";
+ case Delta64JumpSlot:
+ return "Delta64JumpSlot";
+ case Delta32JumpSlot:
+ return "Delta32JumpSlot";
+ case Delta20JumpSlot:
+ return "Delta20JumpSlot";
+ case Delta16JumpSlot:
+ return "Delta16JumpSlot";
+ case Delta12JumpSlot:
+ return "Delta12JumpSlot";
+ case PCRel32JumpSlot:
+ return "PCRel32JumpSlot";
+ default:
+ return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
+ }
+}
+
+} // namespace systemz
+} // namespace jitlink
+} // namespace llvm
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_ehframe.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_ehframe.s
new file mode 100644
index 0000000000000..fca8345ff207c
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_ehframe.s
@@ -0,0 +1,58 @@
+# REQUIRES: asserts
+# REQUIRES: system-linux
+# RUN: llvm-mc -triple=systemz-unknown-linux-gnu -filetype=obj -o %t %s
+# RUN: llvm-jitlink -noexec -phony-externals -debug-only=jitlink %t 2>&1 | \
+# RUN: FileCheck %s
+#
+# Check that splitting of eh-frame sections works.
+#
+# CHECK: DWARFRecordSectionSplitter: Processing .eh_frame...
+# CHECK: Processing block at
+# CHECK: Processing CFI record at
+# CHECK: Processing CFI record at
+# CHECK: EHFrameEdgeFixer: Processing .eh_frame in "{{.*}}"...
+# CHECK: Processing block at
+# CHECK: Record is CIE
+# CHECK: Processing block at
+# CHECK: Record is FDE
+# CHECK: Adding edge at {{.*}} to CIE at: {{.*}}
+# CHECK: Processing PC-begin at
+# CHECK: Existing edge at {{.*}} to PC begin at {{.*}}
+# CHECK: Adding keep-alive edge from target at {{.*}} to FDE at {{.*}}
+
+ .text
+ .file "exceptions.cpp"
+ # Start of file scope inline assembly
+ .globl _ZSt21ios_base_library_initv
+
+ # End of file scope inline assembly
+ .globl main # -- Begin function main
+ .p2align 4
+ .type main, at function
+main: # @main
+ .cfi_startproc
+# %bb.0: # %entry
+ stmg %r11, %r15, 88(%r15)
+ .cfi_offset %r11, -72
+ .cfi_offset %r14, -48
+ .cfi_offset %r15, -40
+ aghi %r15, -168
+ .cfi_def_cfa_offset 328
+ lgr %r11, %r15
+ .cfi_def_cfa_register %r11
+ mvhi 164(%r11), 0
+ lghi %r2, 4
+ brasl %r14, __cxa_allocate_exception at PLT
+ mvhi 0(%r2), 1
+ lgrl %r3, _ZTIi at GOT
+ lghi %r4, 0
+ brasl %r14, __cxa_throw at PLT
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section ".note.GNU-stack","", at progbits
+ .addrsig
+ .addrsig_sym __cxa_allocate_exception
+ .addrsig_sym __cxa_throw
+ .addrsig_sym _ZTIi
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_got.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_got.s
new file mode 100644
index 0000000000000..00b111d5d59f1
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_got.s
@@ -0,0 +1,78 @@
+# REQUIRES: system-linux
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -filetype=obj -o %t/elf_reloc.o %s
+#
+# RUN: llvm-jitlink -noexec \
+# RUN: -slab-allocate 100Kb -slab-address 0x6ff00000 -slab-page-size 4096 \
+# RUN: -abs foo=0x6ff04040 \
+# RUN: -abs bar=0x6ff04048 \
+# RUN: %t/elf_reloc.o
+#
+# Check R_390_GOT* handling.
+
+ .text
+ .globl main
+ .type main, at function
+main:
+ larl %r12, _GLOBAL_OFFSET_TABLE_
+ .reloc .+2, R_390_GOTENT, foo+2
+ larl %r1, 0
+ .reloc .+2, R_390_GOTENT, bar+2
+ larl %r1, 0
+ .reloc .+2, R_390_GOTPLTENT, foo+2
+ larl %r1, 0
+ .reloc .+2, R_390_GOTPLTENT, bar+2
+ larl %r1, 0
+ .reloc .+2, R_390_GOT12, foo
+ l %r1, 0(%r12)
+ .reloc .+2, R_390_GOT12, bar
+ l %r1, 0(%r12)
+ .reloc .+2, R_390_GOTPLT12, foo
+ l %r1, 0(%r12)
+ .reloc .+2, R_390_GOTPLT12, bar
+ l %r1, 0(%r12)
+ .reloc .+2, R_390_GOT20, foo
+ lg %r1, 0(%r12)
+ .reloc .+2, R_390_GOT20, bar
+ lg %r1, 0(%r12)
+ .reloc .+2, R_390_GOTPLT20, foo
+ lg %r1, 0(%r12)
+ .reloc .+2, R_390_GOTPLT20, bar
+ lg %r1, 0(%r12)
+ br %r14
+ .size main, .-main
+
+ .data
+ .reloc ., R_390_GOT16, foo
+ .space 2
+ .reloc ., R_390_GOT16, bar
+ .space 2
+ .reloc ., R_390_GOTPLT16, foo
+ .space 2
+ .reloc ., R_390_GOTPLT16, bar
+ .space 2
+ .reloc ., R_390_GOT32, foo
+ .space 4
+ .reloc ., R_390_GOT32, bar
+ .space 4
+ .reloc ., R_390_GOTPLT32, foo
+ .space 4
+ .reloc ., R_390_GOTPLT32, bar
+ .space 4
+ .reloc ., R_390_GOT64, foo
+ .space 8
+ .reloc ., R_390_GOT64, bar
+ .space 8
+ .reloc ., R_390_GOTPLT64, foo
+ .space 8
+ .reloc ., R_390_GOTPLT64, bar
+ .space 8
+ .reloc ., R_390_GOTPC, foo
+ .space 4
+ .reloc ., R_390_GOTPC, bar
+ .space 4
+ .reloc ., R_390_GOTPCDBL, foo
+ .space 4
+ .reloc ., R_390_GOTPCDBL, bar
+ .space 4
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s
new file mode 100644
index 0000000000000..3d1484acaf9ae
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s
@@ -0,0 +1,35 @@
+# REQUIRES: system-linux
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -filetype=obj -o %t.o %s
+# RUN: llvm-jitlink -noexec -abs X=0xFFFF -check=%s %t.o
+
+# RUN: not llvm-jitlink -noexec -abs X=0x10000 %t.o 2>&1 | \
+# RUN: FileCheck -check-prefix=CHECK-ERROR %s
+#
+# Check success and failure cases of R_390_16 handling.
+
+# jitlink-check: *{8}P = X
+
+# CHECK-ERROR: relocation target "X" {{.*}} is out of range of Pointer16 fixup
+
+ .text
+ .section .text.main
+ .globl main
+ .p2align 4
+ .type main, at function
+main:
+ br %r14
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+
+ .type P, at object
+ .data
+ .globl P
+ .p2align 1
+P:
+ .short 0
+ .short 0
+ .short 0
+ .short X # Using byte here generates R_390_16.
+ .size P, 8
+
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s
new file mode 100644
index 0000000000000..2b3122b91ff5e
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s
@@ -0,0 +1,32 @@
+# REQUIRES: system-linux
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -filetype=obj -o %t.o %s
+# RUN: llvm-jitlink -noexec -abs X=0x12345678 -check=%s %t.o
+#
+# RUN: not llvm-jitlink -noexec -abs X=0x123456789 %t.o 2>&1 | \
+# RUN: FileCheck -check-prefix=CHECK-ERROR %s
+#
+# Check success and failure cases of R_390_32 handling.
+
+# jitlink-check: *{8}P = X
+
+# CHECK-ERROR: relocation target "X" {{.*}} is out of range of Pointer32 fixup
+
+ .text
+ .section .text.main
+ .globl main
+ .p2align 4
+ .type main, at function
+main:
+ br %r14
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+
+ .type P, at object
+ .data
+ .globl P
+ .p2align 2
+P:
+ .long 0
+ .long X # Using long here generates R_390_32.
+ .size P, 8
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs64.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs64.s
new file mode 100644
index 0000000000000..63d2a1a539aeb
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs64.s
@@ -0,0 +1,28 @@
+# REQUIRES: system-linux
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -filetype=obj -o %t.o %s
+# RUN: llvm-jitlink -noexec -abs X=0xffffffffffffffff -check=%s %t.o
+#
+# Check success and failure cases of R_390_64 handling.
+
+# jitlink-check: *{8}P = X
+
+# CHECK-ERROR: relocation target "X" {{.*}} is out of range of Pointer64 fixup
+
+ .text
+ .section .text.main
+ .globl main
+ .p2align 4
+ .type main, at function
+main:
+ br %r14
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+
+ .type P, at object
+ .data
+ .globl P
+ .p2align 4
+P:
+ .quad X # Using quad here generates R_390_64.
+ .size P, 8
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s
new file mode 100644
index 0000000000000..6b9d9503035f5
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s
@@ -0,0 +1,38 @@
+# REQUIRES: system-linux
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -filetype=obj -o %t.o %s
+# RUN: llvm-jitlink -noexec -abs X=0xFF -check=%s %t.o
+
+# RUN: not llvm-jitlink -noexec -abs X=0x100 %t.o 2>&1 | \
+# RUN: FileCheck -check-prefix=CHECK-ERROR %s
+#
+# Check success and failure cases of R_390_8 handling.
+
+# jitlink-check: *{8}P = X
+
+# CHECK-ERROR: relocation target "X" {{.*}} is out of range of Pointer8 fixup
+
+ .text
+ .section .text.main
+ .globl main
+ .p2align 4
+ .type main, at function
+main:
+ br %r14
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+
+ .type P, at object
+ .data
+ .globl P
+P:
+ .byte 0
+ .byte 0
+ .byte 0
+ .byte 0
+ .byte 0
+ .byte 0
+ .byte 0
+ .byte X # Using byte here generates R_390_8.
+ .size P, 8
+
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s
new file mode 100644
index 0000000000000..2b4c3d2102231
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_call_pic.s
@@ -0,0 +1,82 @@
+# REQUIRES: system-linux
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -filetype=obj -o %t/elf_pic_reloc.o %s
+#
+# RUN: llvm-jitlink -noexec \
+# RUN: -slab-allocate 100Kb -slab-address 0xfff00000 -slab-page-size 4096 \
+# RUN: -abs external_data=0x1 \
+# RUN: -abs extern_out_of_range32=0x7fff00000000 \
+# RUN: -abs extern_in_range32=0xffe00000 \
+# RUN: -check %s %t/elf_pic_reloc.o
+
+ .text
+ .section .text.main
+ .globl main
+ .p2align 4
+ .type main, at function
+main:
+ br %r14
+ .size main, .-main
+
+ .globl named_func
+ .p2align 4
+ .type named_func, at function
+named_func:
+ br %r14
+ .size named_func, .-named_func
+
+# Check R_390_PLT32DBL handling with a call to a local function in the text
+# section. This produces a Branch32 edge that is resolved like a regular
+# BranchPCRelPLT32dbl(no PLT entry created).
+#
+# jitlink-check: decode_operand(test_call_local, 1) = \
+# jitlink-check: named_func - test_call_local
+ .globl test_call_local
+ .p2align 4
+ .type test_call_local, at function
+test_call_local:
+ brasl %r14, named_func at PLT
+
+ .size test_call_local, .-test_call_local
+
+# Check R_390_PLT32dbl(BranchPCRelPLT32dbl) handling with a call to an
+# external via PLT. This produces a Branch32ToStub edge, because externals are
+# not defined locally. As the target is out-of-range from the callsite,
+# the edge keeps using its PLT entry.
+#
+# jitlink-check: decode_operand(test_call_extern_plt, 1) = \
+# jitlink-check: stub_addr(elf_pic_reloc.o, extern_out_of_range32) - \
+# jitlink-check: test_call_extern_plt
+# jitlink-check: *{8}(got_addr(elf_pic_reloc.o, extern_out_of_range32)) = \
+# jitlink-check: extern_out_of_range32
+ .globl test_call_extern_plt
+ .p2align 4
+ .type test_call_extern_plt, at function
+test_call_extern_plt:
+ brasl %r14, extern_out_of_range32 at plt
+
+ .size test_call_extern_plt, .-test_call_extern_plt
+
+# Check R_390_PLT32(BranchPCRelPLT32dbl) handling with a call to an external.
+# This produces a Branch32ToStub edge, because externals are not defined
+# locally. During resolution, the target turns out to be in-range from the
+# callsite.
+### TODO: edge can be relaxed in post-allocation optimization, it will then
+### require:
+### jitlink-check: decode_operand(test_call_extern, 1) = \
+### jitlink-check: extern_in_range32 - test_call_extern
+#
+# Same as test_call_extern_plt(no-optimization)
+# jitlink-check: decode_operand(test_call_extern, 1) = \
+# jitlink-check: stub_addr(elf_pic_reloc.o, extern_in_range32) - \
+# jitlink-check: test_call_extern
+# jitlink-check: *{8}(got_addr(elf_pic_reloc.o, extern_in_range32)) = \
+# jitlink-check: extern_in_range32
+ .globl test_call_extern
+ .p2align 4
+ .type test_call_extern, at function
+test_call_extern:
+ brasl %r14, extern_in_range32 at plt
+ .size test_call_extern, .-test_call_extern
+
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s
new file mode 100644
index 0000000000000..3a5ebf9f3ba70
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s
@@ -0,0 +1,28 @@
+# REQUIRES: system-linux
+
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -filetype=obj -o %t.o %s
+#
+# RUN: llvm-jitlink -noexec -abs DISP=0xFFF -check=%s %t.o
+
+# RUN: not llvm-jitlink -noexec -abs DISP=0x1000 %t.o 2>&1 | \
+# RUN: FileCheck -check-prefix=CHECK-ERROR %s
+#
+# Check success and failure cases of R_390_12 handling.
+
+# CHECK-ERROR: relocation target "DISP" {{.*}} is out of range of
+# CHECK-ERROR: Pointer12 fixup
+
+# jitlink-check: decode_operand(main, 2) = DISP
+ .text
+ .section .text.main
+ .globl main
+ .p2align 4
+ .type main, at function
+main:
+ .reloc .+2, R_390_12, DISP
+ l %r6, 0(%r7,%r8)
+ br %r14
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s
new file mode 100644
index 0000000000000..e6d22aff78f50
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s
@@ -0,0 +1,31 @@
+# REQUIRES: system-linux
+
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -filetype=obj -o %t.o %s
+#
+# RUN: llvm-jitlink -noexec -abs DISP=0x7FFFF -check=%s %t.o
+
+# RUN: not llvm-jitlink -noexec -abs DISP=0x80000 %t.o 2>&1 | \
+# RUN: FileCheck -check-prefix=CHECK-ERROR %s
+
+# RUN: not llvm-jitlink -noexec -abs DISP=0xFFFFF %t.o 2>&1 | \
+# RUN: FileCheck -check-prefix=CHECK-ERROR %s
+#
+# Check success and failure cases of R_390_20 handling.
+
+# CHECK-ERROR: relocation target "DISP" {{.*}} is out of range of
+# CHECK-ERROR: Pointer20 fixup
+
+# jitlink-check: decode_operand(main, 2) = DISP
+ .text
+ .section .text.main
+ .globl main
+ .p2align 4
+ .type main, at function
+main:
+ .reloc .+2, R_390_20, DISP
+ lg %r6, 0(%r7,%r8)
+ br %r14
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_got.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_got.s
new file mode 100644
index 0000000000000..7da48cfa704e2
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_got.s
@@ -0,0 +1,244 @@
+# REQUIRES: system-linux
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -filetype=obj -o %t/elf_reloc.o %s
+#
+# RUN: llvm-jitlink -noexec \
+# RUN: -slab-allocate 100Kb -slab-address 0x6ff00000 -slab-page-size 4096 \
+# RUN: -abs foo=0x6ff04040 \
+# RUN: -abs bar=0x6ff04048 \
+# RUN: %t/elf_reloc.o -check %s
+
+# Verifying GOT related relocations.
+
+ .text
+ .globl main
+ .type main, at function
+main:
+# jitlink-check: decode_operand(main, 1) = _GLOBAL_OFFSET_TABLE_ - main
+ larl %r12, _GLOBAL_OFFSET_TABLE_
+ .globl test_gotent_foo
+test_gotent_foo:
+# jitlink-check: decode_operand(test_gotent_foo, 1) = \
+# jitlink-check: (got_addr(elf_reloc.o, foo) - test_gotent_foo)
+ .reloc .+2, R_390_GOTENT, foo+2
+ larl %r1, 0
+ .size test_gotent_foo, .-test_gotent_foo
+
+ .globl test_gotent_bar
+test_gotent_bar:
+# jitlink-check: decode_operand(test_gotent_bar, 1) = \
+# jitlink-check: (got_addr(elf_reloc.o, bar) - test_gotent_bar)
+ .reloc .+2, R_390_GOTENT, bar+2
+ larl %r1, 0
+ .size test_gotent_bar, .-test_gotent_bar
+
+ .globl test_gotpltent_foo
+test_gotpltent_foo:
+# jitlink-check: decode_operand(test_gotpltent_foo, 1) = \
+# jitlink-check: (got_addr(elf_reloc.o, foo) - test_gotpltent_foo)
+ .reloc .+2, R_390_GOTPLTENT, foo+2
+ larl %r1, 0
+ .size test_gotpltent_foo, .-test_gotpltent_foo
+
+ .globl test_gotpltent_bar
+test_gotpltent_bar:
+# jitlink-check: decode_operand(test_gotpltent_bar, 1) = \
+# jitlink-check: (got_addr(elf_reloc.o, bar) - test_gotpltent_bar)
+ .reloc .+2, R_390_GOTPLTENT, bar+2
+ larl %r1, 0
+ .size test_gotpltent_bar, .-test_gotpltent_bar
+
+ .globl test_got12_foo
+test_got12_foo:
+# jitlink-check: decode_operand(test_got12_foo, 2) = \
+# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_)
+ .reloc .+2, R_390_GOT12, foo
+ l %r1, 0(%r12)
+ .size test_got12_foo, .-test_got12_foo
+
+ .globl test_got12_bar
+test_got12_bar:
+# jitlink-check: decode_operand(test_got12_bar, 2) = \
+# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_)
+ .reloc .+2, R_390_GOT12, bar
+ l %r1, 0(%r12)
+ .size test_got12_bar, .-test_got12_bar
+
+ .globl test_gotplt12_foo
+test_gotplt12_foo:
+# jitlink-check: decode_operand(test_gotplt12_foo, 2) = \
+# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_)
+ .reloc .+2, R_390_GOTPLT12, foo
+ l %r1, 0(%r12)
+ .size test_gotplt12_foo, .-test_gotplt12_foo
+
+ .globl test_gotplt12_bar
+test_gotplt12_bar:
+# jitlink-check: decode_operand(test_gotplt12_bar, 2) = \
+# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_)
+ .reloc .+2, R_390_GOTPLT12, bar
+ l %r1, 0(%r12)
+ .size test_gotplt12_bar, .-test_gotplt12_bar
+
+ .globl test_got20_foo
+test_got20_foo:
+# jitlink-check: decode_operand(test_got20_foo, 2) = \
+# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_)
+ .reloc .+2, R_390_GOT20, foo
+ lg %r1, 0(%r12)
+ .size test_got20_foo, .-test_got20_foo
+
+ .globl test_got20_bar
+test_got20_bar:
+# jitlink-check: decode_operand(test_got20_bar, 2) = \
+# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_)
+ .reloc .+2, R_390_GOT20, bar
+ lg %r1, 0(%r12)
+ .size test_got20_bar, .-test_got20_bar
+
+ .globl test_gotplt20_foo
+test_gotplt20_foo:
+# jitlink-check: decode_operand(test_gotplt20_foo, 2) = \
+# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_)
+ .reloc .+2, R_390_GOTPLT20, foo
+ lg %r1, 0(%r12)
+ .size test_gotplt20_foo, .-test_gotplt20_foo
+
+ .globl test_gotplt20_bar
+test_gotplt20_bar:
+# jitlink-check: decode_operand(test_gotplt20_bar, 2) = \
+# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_)
+ .reloc .+2, R_390_GOTPLT20, bar
+ lg %r1, 0(%r12)
+ .size test_gotplt20_bar, .-test_gotplt20_bar
+ br %r14
+ .size main, .-main
+
+ .data
+ .globl test_got16_foo
+# jitlink-check: *{2}test_got16_foo = \
+# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_)
+test_got16_foo:
+ .reloc ., R_390_GOT16, foo
+ .space 2
+ .size test_got16_foo, .-test_got16_foo
+
+ .globl test_got16_bar
+# jitlink-check: *{2}test_got16_bar = \
+# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_)
+test_got16_bar:
+ .reloc ., R_390_GOT16, bar
+ .space 2
+ .size test_got16_bar, .-test_got16_bar
+
+ .globl test_gotplt16_foo
+# jitlink-check: *{2}test_gotplt16_foo = \
+# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_)
+test_gotplt16_foo:
+ .reloc ., R_390_GOTPLT16, foo
+ .space 2
+ .size test_gotplt16_foo, .-test_gotplt16_foo
+
+ .globl test_gotplt16_bar
+# jitlink-check: *{2}test_gotplt16_bar = \
+# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_)
+test_gotplt16_bar:
+ .reloc ., R_390_GOTPLT16, bar
+ .space 2
+ .size test_gotplt16_bar, .-test_gotplt16_bar
+
+ .globl test_got32_foo
+# jitlink-check: *{4}test_got32_foo = \
+# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_)
+test_got32_foo:
+ .reloc ., R_390_GOT32, foo
+ .space 4
+ .size test_got32_foo, .-test_got32_foo
+
+ .globl test_got32_bar
+# jitlink-check: *{4}test_got32_bar = \
+# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_)
+test_got32_bar:
+ .reloc ., R_390_GOT32, bar
+ .space 4
+ .size test_got32_bar, .-test_got32_bar
+
+ .globl test_gotplt32_foo
+# jitlink-check: *{4}test_gotplt32_foo = \
+# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_)
+test_gotplt32_foo:
+ .reloc ., R_390_GOTPLT32, foo
+ .space 4
+ .size test_gotplt32_foo, .-test_gotplt32_foo
+
+ .globl test_gotplt32_bar
+# jitlink-check: *{4}test_gotplt32_bar = \
+# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_)
+test_gotplt32_bar:
+ .reloc ., R_390_GOTPLT32, bar
+ .space 4
+ .size test_gotplt32_bar, .-test_gotplt32_bar
+
+ .globl test_got64_foo
+# jitlink-check: *{8}test_got64_foo = \
+# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_)
+test_got64_foo:
+ .reloc ., R_390_GOT64, foo
+ .space 8
+ .size test_got64_foo, .-test_got64_foo
+
+ .globl test_got64_bar
+# jitlink-check: *{8}test_got64_bar = \
+# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_)
+test_got64_bar:
+ .reloc ., R_390_GOT64, bar
+ .space 8
+ .size test_got64_bar, .-test_got64_bar
+
+ .globl test_gotplt64_foo
+# jitlink-check: *{8}test_gotplt64_foo = \
+# jitlink-check: (got_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_)
+test_gotplt64_foo:
+ .reloc ., R_390_GOTPLT64, foo
+ .space 8
+ .size test_gotplt64_foo, .-test_gotplt64_foo
+
+ .globl test_gotplt64_bar
+# jitlink-check: *{8}test_gotplt64_bar = \
+# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_)
+test_gotplt64_bar:
+ .reloc ., R_390_GOTPLT64, bar
+ .space 8
+ .size test_gotplt64_bar, .-test_gotplt64_bar
+
+ .globl test_gotpc_foo
+# jitlink-check: *{4}test_gotpc_foo = _GLOBAL_OFFSET_TABLE_ - test_gotpc_foo
+test_gotpc_foo:
+ .reloc ., R_390_GOTPC, foo
+ .space 4
+ .size test_gotpc_foo, .-test_gotpc_foo
+
+ .globl test_gotpc_bar
+# jitlink-check: *{4}test_gotpc_bar = _GLOBAL_OFFSET_TABLE_ - test_gotpc_bar
+test_gotpc_bar:
+ .reloc ., R_390_GOTPC, bar
+ .space 4
+ .size test_gotpc_bar, .-test_gotpc_bar
+
+ .globl test_gotpcdbl_foo
+# jitlink-check: *{4}test_gotpcdbl_foo = \
+# jitlink-check: (_GLOBAL_OFFSET_TABLE_ - test_gotpcdbl_foo) >> 1
+test_gotpcdbl_foo:
+ .reloc ., R_390_GOTPCDBL, foo
+ .space 4
+ .size test_gotpcdbl_foo, .-test_gotpcdbl_foo
+
+ .globl test_gotpcdbl_bar
+# jitlink-check: *{4}test_gotpcdbl_bar = \
+# jitlink-check: (_GLOBAL_OFFSET_TABLE_ - test_gotpcdbl_bar) >> 1
+test_gotpcdbl_bar:
+ .reloc ., R_390_GOTPCDBL, bar
+ .space 4
+ .size test_gotpcdbl_bar, .-test_gotpcdbl_bar
+
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_gotrel.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_gotrel.s
new file mode 100644
index 0000000000000..bb1220d3780bb
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_gotrel.s
@@ -0,0 +1,68 @@
+# REQUIRES: system-linux
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -filetype=obj -o %t/elf_reloc.o %s
+#
+# RUN: llvm-jitlink -noexec \
+# RUN: -slab-allocate 100Kb -slab-address 0x6ff00000 -slab-page-size 4096 \
+# RUN: -abs foo=0x6ff04080 \
+# RUN: -abs bar=0x6ff04040 \
+# RUN: %t/elf_reloc.o -check %s
+
+ .text
+ .globl main
+ .type main, at function
+main:
+ br %r14
+ .size main, .-main
+
+ .data
+ .globl test_gotoff16_bar
+# jitlink-check: *{2}test_gotoff16_bar = \
+# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_)
+test_gotoff16_bar:
+ .reloc ., R_390_GOTOFF16, bar
+ .space 2
+ .size test_gotoff16_bar, .-test_gotoff16_bar
+
+ .globl test_pltoff16_foo
+# jitlink-check: *{2}test_pltoff16_foo = \
+# jitlink-check: (stub_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_)
+test_pltoff16_foo:
+ .reloc ., R_390_PLTOFF16, foo
+ .space 2
+ .size test_pltoff16_foo, .-test_pltoff16_foo
+
+
+ .globl test_gotoff32_bar
+# jitlink-check: *{4}test_gotoff32_bar = \
+# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_)
+test_gotoff32_bar:
+ .reloc ., R_390_GOTOFF, bar
+ .space 4
+ .size test_gotoff32_bar, .-test_gotoff32_bar
+
+ .globl test_pltoff32_foo
+# jitlink-check: *{4}test_pltoff32_foo = \
+# jitlink-check: (stub_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_)
+test_pltoff32_foo:
+ .reloc ., R_390_PLTOFF32, foo
+ .space 4
+ .size test_pltoff32_foo, .-test_pltoff32_foo
+
+ .globl test_gotoff64_bar
+# jitlink-check: *{8}test_gotoff64_bar = \
+# jitlink-check: (got_addr(elf_reloc.o, bar) - _GLOBAL_OFFSET_TABLE_)
+test_gotoff64_bar:
+ .reloc ., R_390_GOTOFF64, bar
+ .space 8
+ .size test_gotoff64_bar, .-test_gotoff64_bar
+
+ .globl test_pltoff64_foo
+# jitlink-check: *{8}test_pltoff64_foo = \
+# jitlink-check: (stub_addr(elf_reloc.o, foo) - _GLOBAL_OFFSET_TABLE_)
+test_pltoff64_foo:
+ .reloc ., R_390_PLTOFF64, foo
+ .space 8
+ .size test_pltoff64_foo, .-test_pltoff64_foo
+
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc.s
new file mode 100644
index 0000000000000..4b3a65e53ab93
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc.s
@@ -0,0 +1,20 @@
+# REQUIRES: system-linux
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -filetype=obj -o %t.o %s
+#
+# RUN: llvm-jitlink -noexec %t.o
+#
+# Check R_390_PC* handling.
+
+ .text
+ .globl main
+ .type main, at function
+main:
+ br %r14
+ .size main, .-main
+
+ .rodata
+ .short main-. # Generate R_390_PC16 relocation.
+ .long main-. # Generate R_390_PC32 relocation.
+ .quad main-. # Generate R_390_PC64 relocation.
+
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc16.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc16.s
new file mode 100644
index 0000000000000..47a7262902fd9
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc16.s
@@ -0,0 +1,40 @@
+# REQUIRES: system-linux
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -defsym OFFSET=0x8000 -filetype=obj -o %t.o %s
+# RUN: llvm-jitlink -noexec -abs OFFSET=0x8000 -check=%s %t.o
+#
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -defsym OFFSET=0xFFFF -filetype=obj -o %t.o %s
+# RUN: not llvm-jitlink -noexec -abs OFFSET=0xFFFF %t.o 2>&1 | \
+# RUN: FileCheck -check-prefix=CHECK-ERROR %s
+#
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -defsym OFFSET=0x8001 -filetype=obj -o %t.o %s
+# RUN: not llvm-jitlink -noexec -abs OFFSET=0x8001 %t.o 2>&1 | \
+# RUN: FileCheck -check-prefix=CHECK-ERROR %s
+#
+# jitlink-check: *{2}test_pc16 = OFFSET
+
+# CHECK-ERROR: {{.*}} is out of range of Delta16 fixup
+
+ .text
+ .section .text.main
+ .globl main
+ .p2align 4
+ .type main, at function
+main:
+ br %r14
+ .size main, .-main
+
+ .globl test_pc16
+test_pc16:
+ .reloc test_pc16, R_390_PC16, .-OFFSET
+ .space 2
+ .size test_pc16, .-test_pc16
+
+ .globl test_pc16dbl
+test_pc16dbl:
+ .reloc test_pc16dbl, R_390_PC16DBL, .-(OFFSET + OFFSET)
+ .space 2
+ .size test_pc16dbl, .-test_pc16dbl
+
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc32.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc32.s
new file mode 100644
index 0000000000000..cda90dbe5a316
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc32.s
@@ -0,0 +1,40 @@
+# REQUIRES: system-linux
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -defsym OFFSET=0x80000000 -filetype=obj -o %t.o %s
+# RUN: llvm-jitlink -noexec -abs OFFSET=0x80000000 -check=%s %t.o
+#
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -defsym OFFSET=0xFFFFFFFF -filetype=obj -o %t.o %s
+# RUN: not llvm-jitlink -noexec -abs OFFSET=0xFFFFFFFF %t.o 2>&1 | \
+# RUN: FileCheck -check-prefix=CHECK-ERROR %s
+#
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -defsym OFFSET=0x80000001 -filetype=obj -o %t.o %s
+# RUN: not llvm-jitlink -noexec -abs OFFSET=0x80000001 %t.o 2>&1 | \
+# RUN: FileCheck -check-prefix=CHECK-ERROR %s
+#
+# jitlink-check: *{4}test_pc32 = OFFSET
+
+# CHECK-ERROR: {{.*}} is out of range of Delta32 fixup
+
+ .text
+ .section .text.main
+ .globl main
+ .p2align 4
+ .type main, at function
+main:
+ br %r14
+ .size main, .-main
+
+ .globl test_pc32
+test_pc32:
+ .reloc test_pc32, R_390_PC32, .-OFFSET
+ .space 4
+ .size test_pc32, .-test_pc32
+
+ .globl test_pc32dbl
+test_pc32dbl:
+ .reloc test_pc32dbl, R_390_PC32DBL, .-(OFFSET + OFFSET)
+ .space 4
+ .size test_pc32dbl, .-test_pc32dbl
+
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc64.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc64.s
new file mode 100644
index 0000000000000..0d33ae2976de5
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pc64.s
@@ -0,0 +1,34 @@
+# REQUIRES: system-linux
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -filetype=obj -o %t/elf_reloc.o %s
+#
+# RUN: llvm-jitlink -noexec \
+# RUN: -slab-allocate 100Kb -slab-address 0xffff0000 -slab-page-size 4096 \
+# RUN: -abs external_data=0x1 \
+# RUN: -abs foo=0x6ff04040 \
+# RUN: -abs bar=0x6ff04048 \
+# RUN: -check %s %t/elf_reloc.o
+
+ .text
+ .section .text.main
+ .globl main
+ .p2align 4
+ .type main, at function
+main:
+ br %r14
+ .size main, .-main
+
+ .globl test_pc64_foo
+# jitlink-check: *{8}test_pc64_foo = foo - test_pc64_foo
+test_pc64_foo:
+ .reloc ., R_390_PC64, foo
+ .space 8
+ .size test_pc64_foo, .-test_pc64_foo
+
+ .globl test_pc64_bar
+# jitlink-check: *{8}test_pc64_bar = bar - test_pc64_bar
+test_pc64_bar:
+ .reloc ., R_390_PC64, bar
+ .space 8
+ .size test_pc64_bar, .-test_pc64_bar
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pcdbl.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pcdbl.s
new file mode 100644
index 0000000000000..efe8357e76bef
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pcdbl.s
@@ -0,0 +1,84 @@
+# REQUIRES: system-linux
+# RUN: llvm-mc -triple=systemz-unknown-linux -mcpu=z16 -position-independent \
+# RUN: -defsym OFF12=0xffe -defsym OFF16=4 -defsym OFF24=6 \
+# RUN: -defsym OFF32=6 -filetype=obj -o %t.o %s
+#
+# RUN: llvm-jitlink -noexec -abs OFF12=0xffe -abs OFF16=4 -abs OFF24=6 \
+# RUN: -abs OFF32=6 -check=%s %t.o
+#
+# RUN: llvm-mc -triple=systemz-unknown-linux -mcpu=z16 -position-independent \
+# RUN: -defsym OFF12=6 -defsym OFF16=0xfffe -defsym OFF24=6 \
+# RUN: -defsym OFF32=6 -filetype=obj -o %t.o %s
+#
+# RUN: llvm-jitlink -noexec -abs OFF12=6 -abs OFF16=0xfffe -abs OFF24=6 \
+# RUN: -abs OFF32=6 -check=%s %t.o
+#
+# RUN: llvm-mc -triple=systemz-unknown-linux -mcpu=z16 -position-independent \
+# RUN: -defsym OFF12=6 -defsym OFF16=4 -defsym OFF24=0xfffffe \
+# RUN: -defsym OFF32=6 -filetype=obj -o %t.o %s
+#
+# RUN: llvm-jitlink -noexec -abs OFF12=6 -abs OFF16=4 -abs OFF24=0xfffffe \
+# RUN: -abs OFF32=6 -check=%s %t.o
+#
+# RUN: llvm-mc -triple=systemz-unknown-linux -mcpu=z16 -position-independent \
+# RUN: -defsym OFF12=6 -defsym OFF16=4 -defsym OFF24=6 \
+# RUN: -defsym OFF32=0xffffffc8 -filetype=obj -o %t.o %s
+#
+# RUN: llvm-jitlink -noexec -abs OFF12=6 -abs OFF16=4 -abs OFF24=6 \
+# RUN: -abs OFF32=0xffffffc8 -check=%s %t.o
+
+# Check R_390_PC*dbl relocations.
+
+ .text
+ .section .text.main
+ .globl main
+ .p2align 4
+ .type main, at function
+main:
+ br %r14
+ .size main, .-main
+
+# R_390_PC16DBL
+# jitlink-check: *{2}(test_pc16dbl + 2) = (OFF16 >> 1)
+ .globl test_pc16dbl
+ .p2align 3
+test_pc16dbl:
+ je .Lpc16dbl
+ .space OFF16 - 4
+.Lpc16dbl:
+ jne test_pc16dbl
+ .size test_pc16dbl,.-test_pc16dbl
+
+# R_390_PC32DBL
+# jitlink-check: *{4}(test_pc32dbl + 2) = (OFF32 >> 1)
+ .globl test_pc32dbl
+ .p2align 3
+test_pc32dbl:
+ jge .Lpc32dbl
+ .space OFF32 - 6
+.Lpc32dbl:
+ jgne test_pc32dbl
+ .size test_pc32dbl,.-test_pc32dbl
+
+# R_390_PC12DBL
+# jitlink-check: ((*{2} (test_pc12dbl + 1)) & 0x0fff) = (OFF12 >> 1)
+ .globl test_pc12dbl
+ .p2align 4
+test_pc12dbl:
+ bprp 0, .Lpc12dbl, 0
+ .space OFF12 - 6
+.Lpc12dbl:
+ bprp 0, test_pc12dbl, 0
+ .size test_pc12dbl,.-test_pc12dbl
+
+# R_390_PC24DBL
+# jitlink-check: ((*{4} (test_pc24dbl + 2)) & 0x0ffffff) = (OFF24 >> 1)
+ .globl test_pc24dbl
+ .p2align 4
+test_pc24dbl:
+ bprp 0, 0, .Lpc24dbl
+ .space OFF24 - 6
+.Lpc24dbl:
+ bprp 0, 0, test_pc24dbl
+ .size test_pc24dbl,.-test_pc24dbl
+
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_plt.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_plt.s
new file mode 100644
index 0000000000000..47f064b45816a
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_plt.s
@@ -0,0 +1,71 @@
+# REQUIRES: system-linux
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -filetype=obj -o %t/elf_reloc.o %s
+#
+# RUN: llvm-jitlink -noexec \
+# RUN: -slab-allocate 100Kb -slab-address 0xffff0000 -slab-page-size 4096 \
+# RUN: -abs external_data=0x1 \
+# RUN: -abs foo=0x6ff04040 \
+# RUN: -abs bar=0x6ff04048 \
+# RUN: -check %s %t/elf_reloc.o
+
+# Check R_390_PLT32/64 relocations.
+
+ .text
+ .section .text.main
+ .globl main
+ .p2align 4
+ .type main, at function
+main:
+ br %r14
+ .size main, .-main
+
+ .globl test_plt32_foo
+# jitlink-check: *{4}test_plt32_foo = \
+# jitlink-check: stub_addr(elf_reloc.o, foo) - test_plt32_foo
+test_plt32_foo:
+ .reloc ., R_390_PLT32, foo
+ .space 4
+ .size test_plt32_foo, .-test_plt32_foo
+
+ .globl test_plt32_bar
+# jitlink-check: *{4}test_plt32_bar = \
+# jitlink-check: stub_addr(elf_reloc.o, bar) - test_plt32_bar
+test_plt32_bar:
+ .reloc ., R_390_PLT32, bar
+ .space 4
+ .size test_plt32_bar, .-test_plt32_bar
+
+ .globl test_plt64_foo
+# jitlink-check: *{8}test_plt64_foo = \
+# jitlink-check: stub_addr(elf_reloc.o, foo) - test_plt64_foo
+test_plt64_foo:
+ .reloc ., R_390_PLT64, foo
+ .space 8
+ .size test_plt64_foo, .-test_plt64_foo
+
+ .globl test_plt64_bar
+# jitlink-check: *{8}test_plt64_bar = \
+# jitlink-check: stub_addr(elf_reloc.o, bar) - test_plt64_bar
+test_plt64_bar:
+ .reloc ., R_390_PLT64, bar
+ .space 8
+ .size test_plt64_bar, .-test_plt64_bar
+
+ .globl test_plt32dbl_foo
+# jitlink-check: *{4}test_plt32dbl_foo = \
+# jitlink-check: (stub_addr(elf_reloc.o, foo) - test_plt32dbl_foo) >> 1
+test_plt32dbl_foo:
+ .reloc ., R_390_PLT32DBL, foo
+ .space 4
+ .size test_plt32dbl_foo, .-test_plt32dbl_foo
+
+ .globl test_plt32dbl_bar
+# jitlink-check: *{4}test_plt32dbl_bar = \
+# jitlink-check: (stub_addr(elf_reloc.o, bar) - test_plt32dbl_bar) >> 1
+test_plt32dbl_bar:
+ .reloc ., R_390_PLT32DBL, bar
+ .space 4
+ .size test_plt32dbl_bar, .-test_plt32dbl_bar
+
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pltdbl.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pltdbl.s
new file mode 100644
index 0000000000000..c36a77684008a
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_pltdbl.s
@@ -0,0 +1,51 @@
+# REQUIRES: system-linux
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: llvm-mc -triple=systemz-unknown-linux -position-independent \
+# RUN: -mcpu=z16 -filetype=obj -o %t/elf_reloc.o %s
+
+# RUN: llvm-jitlink -noexec \
+# RUN: -abs external_addr12=0xffe \
+# RUN: -abs external_addr16=0xfffe \
+# RUN: -abs external_addr24=0xffffe \
+# RUN: %t/elf_reloc.o -check %s
+
+
+ .text
+ .section .text.main
+ .globl main
+ .p2align 4
+ .type main, at function
+main:
+ br %r14
+ .size main, .-main
+
+# R_390_PLT16DBL
+# jitlink-check: *{2}(test_plt16dbl + 4) = \
+# jitlink-check: (stub_addr(elf_reloc.o, external_addr16) - \
+# jitlink-check: test_plt16dbl) >> 1
+ .globl test_plt16dbl
+ .p2align 4
+test_plt16dbl:
+ bpp 0, external_addr16 at plt, 0
+ .size test_plt16dbl,.-test_plt16dbl
+
+# R_390_PLT12DBL
+# jitlink-check: ((*{2}(test_plt12dbl + 1)) & 0x0fff) = \
+# jitlink-check: (stub_addr(elf_reloc.o, external_addr12) - \
+# jitlink-check: test_plt12dbl) >> 1
+ .globl test_plt12dbl
+ .p2align 4
+test_plt12dbl:
+ bprp 0, external_addr12 at plt, 0
+ .size test_plt12dbl,.-test_plt12dbl
+
+# R_390_PLT24DBL
+# jitlink-check: ((*{4}(test_plt24dbl + 2)) & 0x0ffffff) = \
+# jitlink-check: (stub_addr(elf_reloc.o, external_addr24) - \
+# jitlink-check: test_plt24dbl) >> 1
+ .globl test_plt24dbl
+ .p2align 4
+test_plt24dbl:
+ bprp 0, 0, external_addr24 at plt
+ .size test_plt24dbl,.-test_plt24dbl
+
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/lit.local.cfg b/llvm/test/ExecutionEngine/JITLink/systemz/lit.local.cfg
new file mode 100644
index 0000000000000..caf81b69c06fd
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/lit.local.cfg
@@ -0,0 +1,2 @@
+if not "SystemZ" in config.root.targets:
+ config.unsupported = True
diff --git a/llvm/test/ExecutionEngine/lit.local.cfg b/llvm/test/ExecutionEngine/lit.local.cfg
index c748de14c8409..840ee60d2cf1d 100644
--- a/llvm/test/ExecutionEngine/lit.local.cfg
+++ b/llvm/test/ExecutionEngine/lit.local.cfg
@@ -1,4 +1,4 @@
-if config.root.native_target in ['Sparc', 'SystemZ', 'Hexagon', 'RISCV']:
+if config.root.native_target in ['Sparc', 'Hexagon', 'RISCV']:
config.unsupported = True
# ExecutionEngine tests are not expected to pass in a cross-compilation setup.
>From 04235320662f8292fc81e0d8577701c3585686e8 Mon Sep 17 00:00:00 2001
From: anoopkg6 <anoopkg6 at github.com>
Date: Tue, 17 Jun 2025 20:16:37 +0200
Subject: [PATCH 2/7] Resolve issues with conflicts
---
.../ExecutionEngine/JITLink/ELF_systemz.h | 4 ++--
.../ExecutionEngine/JITLink/ELF_systemz.cpp | 23 +++++++++++--------
2 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h
index c78bc7cc1f499..a996dfd9543df 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/ELF_systemz.h
@@ -25,8 +25,8 @@ namespace jitlink {
/// Note: The graph does not take ownership of the underlying buffer, nor copy
/// its contents. The caller is responsible for ensuring that the object buffer
/// outlives the graph.
-Expected<std::unique_ptr<LinkGraph>>
-createLinkGraphFromELFObject_systemz(MemoryBufferRef ObjectBuffer);
+Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromELFObject_systemz(
+ MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP);
/// jit-link the given object buffer, which must be a ELF systemz relocatable
/// object file.
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp
index 6d598d62b1fc2..47d2d4651f881 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp
@@ -64,7 +64,8 @@ class ELFJITLinker_systemz : public JITLinker<ELFJITLinker_systemz> {
auto DefineExternalGOTSymbolIfPresent =
createDefineExternalSectionStartAndEndSymbolsPass(
[&](LinkGraph &LG, Symbol &Sym) -> SectionRangeSymbolDesc {
- if (Sym.getName() == ELFGOTSymbolName)
+ if (Sym.getName() != nullptr &&
+ *Sym.getName() == ELFGOTSymbolName)
if (auto *GOTSection = G.findSectionByName(
systemz::GOTTableManager::getSectionName())) {
GOTSymbol = &Sym;
@@ -90,7 +91,7 @@ class ELFJITLinker_systemz : public JITLinker<ELFJITLinker_systemz> {
// Check for an existing defined symbol.
for (auto *Sym : GOTSection->symbols())
- if (Sym->getName() == ELFGOTSymbolName) {
+ if (Sym->getName() != nullptr && *Sym->getName() == ELFGOTSymbolName) {
GOTSymbol = Sym;
return Error::success();
}
@@ -112,7 +113,7 @@ class ELFJITLinker_systemz : public JITLinker<ELFJITLinker_systemz> {
// we just need to point the GOT symbol at some address in this graph.
if (!GOTSymbol) {
for (auto *Sym : G.external_symbols()) {
- if (Sym->getName() == ELFGOTSymbolName) {
+ if (Sym->getName() != nullptr && *Sym->getName() == ELFGOTSymbolName) {
auto Blocks = G.blocks();
if (!Blocks.empty()) {
G.makeAbsolute(*Sym, (*Blocks.begin())->getAddress());
@@ -365,14 +366,16 @@ class ELFLinkGraphBuilder_systemz
public:
ELFLinkGraphBuilder_systemz(StringRef FileName,
- const object::ELFFile<ELFT> &Obj, Triple TT,
- SubtargetFeatures Features)
- : ELFLinkGraphBuilder<ELFT>(Obj, std::move(TT), std::move(Features),
- FileName, systemz::getEdgeKindName) {}
+ const object::ELFFile<ELFT> &Obj,
+ std::shared_ptr<orc::SymbolStringPool> SSP,
+ Triple TT, SubtargetFeatures Features)
+ : ELFLinkGraphBuilder<ELFT>(Obj, std::move(SSP), std::move(TT),
+ std::move(Features), FileName,
+ systemz::getEdgeKindName) {}
};
-Expected<std::unique_ptr<LinkGraph>>
-createLinkGraphFromELFObject_systemz(MemoryBufferRef ObjectBuffer) {
+Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromELFObject_systemz(
+ MemoryBufferRef ObjectBuffer, std::shared_ptr<orc::SymbolStringPool> SSP) {
LLVM_DEBUG({
dbgs() << "Building jitlink graph for new input "
<< ObjectBuffer.getBufferIdentifier() << "...\n";
@@ -391,7 +394,7 @@ createLinkGraphFromELFObject_systemz(MemoryBufferRef ObjectBuffer) {
auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64BE>>(**ELFObj);
return ELFLinkGraphBuilder_systemz(
- (*ELFObj)->getFileName(), ELFObjFile.getELFFile(),
+ (*ELFObj)->getFileName(), ELFObjFile.getELFFile(), std::move(SSP),
(*ELFObj)->makeTriple(), std::move(*Features))
.buildGraph();
}
>From 72ff4e38533f1a9101365408590d6d5ccefb31fc Mon Sep 17 00:00:00 2001
From: anoopkg6 <anoopkg6 at github.com>
Date: Tue, 17 Jun 2025 21:26:26 +0200
Subject: [PATCH 3/7] Fix build error
---
.../llvm/ExecutionEngine/JITLink/systemz.h | 3 +--
llvm/lib/ExecutionEngine/JITLink/systemz.cpp | 17 ++++++++++++++---
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h
index e1498ff820fe6..d63446f35fffd 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h
@@ -992,16 +992,15 @@ class GOTTableManager : public TableManager<GOTTableManager> {
case systemz::Delta64FromGOT:
case systemz::Delta12JumpSlot:
case systemz::Delta16JumpSlot:
+ case systemz::Delta20JumpSlot:
case systemz::Delta32JumpSlot:
case systemz::Delta64JumpSlot:
- case systemz::Delta20JumpSlot: {
case systemz::DeltaPCRelGOT:
case systemz::DeltaPCRelGOTdbl:
case systemz::PCRel32GOTEntry:
case systemz::PCRel32JumpSlot:
KindToSet = E.getKind();
break;
- }
default:
return false;
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp
index 36ba857d8f5c4..c9276bedafe99 100644
--- a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp
@@ -22,9 +22,20 @@ const char NullPointerContent[8] = {0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
const char Pointer64JumpStubContent[14] = {
- static_cast<char>(0xC0), 0x10, 0x00, 0x00, 0x00, 0x00, // larl r1
- static_cast<char>(0xE3), 0x10, 0x10, 0x00, 0x00, 0x04, // LG 1, 0(1)
- static_cast<char>(0x07), 0xF1, // BCR 15, 1
+ static_cast<char>(0xC0u),
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00, // larl r1
+ static_cast<char>(0xE3u),
+ 0x10,
+ 0x10,
+ 0x00,
+ 0x00,
+ 0x04, // LG 1, 0(1)
+ static_cast<char>(0x07u),
+ static_cast<char>(0xF1u), // BCR 15, 1
};
const char *getEdgeKindName(Edge::Kind R) {
>From 7ec023ed49010ec23682fde7927fadc53b644f98 Mon Sep 17 00:00:00 2001
From: anoopkg6 <anoopkg6 at github.com>
Date: Thu, 17 Jul 2025 00:53:54 +0200
Subject: [PATCH 4/7] Fixed jitlink-check: CHECK-ERROR - error message format
changed.
---
.../ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s | 2 +-
.../ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s | 2 +-
.../ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s | 2 +-
.../ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s | 2 +-
.../ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s
index 3d1484acaf9ae..04e828685c040 100644
--- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs16.s
@@ -10,7 +10,7 @@
# jitlink-check: *{8}P = X
-# CHECK-ERROR: relocation target "X" {{.*}} is out of range of Pointer16 fixup
+# CHECK-ERROR: relocation target {{.*}} (X) is out of range of Pointer16 fixup
.text
.section .text.main
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s
index 2b3122b91ff5e..1a63acdb63d57 100644
--- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs32.s
@@ -10,7 +10,7 @@
# jitlink-check: *{8}P = X
-# CHECK-ERROR: relocation target "X" {{.*}} is out of range of Pointer32 fixup
+# CHECK-ERROR: relocation target {{.*}} (X) is out of range of Pointer32 fixup
.text
.section .text.main
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s
index 6b9d9503035f5..5f23f289140a6 100644
--- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_abs8.s
@@ -10,7 +10,7 @@
# jitlink-check: *{8}P = X
-# CHECK-ERROR: relocation target "X" {{.*}} is out of range of Pointer8 fixup
+# CHECK-ERROR: relocation target {{.*}} (X) is out of range of Pointer8 fixup
.text
.section .text.main
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s
index 3a5ebf9f3ba70..cf12cdc987ce3 100644
--- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp12.s
@@ -10,7 +10,7 @@
#
# Check success and failure cases of R_390_12 handling.
-# CHECK-ERROR: relocation target "DISP" {{.*}} is out of range of
+# CHECK-ERROR: relocation target {{.*}} (DISP) is out of range of
# CHECK-ERROR: Pointer12 fixup
# jitlink-check: decode_operand(main, 2) = DISP
diff --git a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s
index e6d22aff78f50..5c7de535cf8b4 100644
--- a/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s
+++ b/llvm/test/ExecutionEngine/JITLink/systemz/ELF_systemz_reloc_disp20.s
@@ -13,7 +13,7 @@
#
# Check success and failure cases of R_390_20 handling.
-# CHECK-ERROR: relocation target "DISP" {{.*}} is out of range of
+# CHECK-ERROR: relocation target {{.*}} (DISP) is out of range of
# CHECK-ERROR: Pointer20 fixup
# jitlink-check: decode_operand(main, 2) = DISP
>From a52657a9153ddb483452916cbf75b01fc47f9781 Mon Sep 17 00:00:00 2001
From: anoopkg6 <anoopkg6 at github.com>
Date: Sat, 1 Nov 2025 21:22:52 +0100
Subject: [PATCH 5/7] Incorporate code review feedback
---
.../llvm/ExecutionEngine/JITLink/systemz.h | 278 +++++-------------
.../ExecutionEngine/JITLink/ELF_systemz.cpp | 77 ++---
llvm/lib/ExecutionEngine/JITLink/systemz.cpp | 92 +++---
3 files changed, 140 insertions(+), 307 deletions(-)
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h
index d63446f35fffd..3f692e0ecc383 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h
@@ -213,7 +213,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// Errors:
/// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
/// symbol was not been defined.
- Delta64FromGOT,
+ RequestGOTAndTransformToDelta64FromGOT,
/// A 32-bit GOT delta.
///
@@ -227,7 +227,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// symbol was not been defined.
/// - The result of the fixup expression must fit into an int32, otherwise
/// an out-of-range error will be returned.
- Delta32FromGOT,
+ RequestGOTAndTransformToDelta32FromGOT,
/// A 16-bit GOT delta.
///
@@ -241,7 +241,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// symbol was not been defined.
/// - The result of the fixup expression must fit into an int16, otherwise
/// an out-of-range error will be returned.
- Delta16FromGOT,
+ RequestGOTAndTransformToDelta16FromGOT,
/// A 32-bit PC-relative branch.
///
@@ -257,7 +257,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// - The result of the fixup expression before shifting right by 1 must
/// be multiple of 2, otherwise an alignment error will be returned.
///
- BranchPCRelPLT32dbl,
+ DeltaPLT32dbl,
/// A 24-bit PC-relative branch.
///
@@ -270,7 +270,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// - The result of the fixup expression before shifting right by 1 must
/// be multiple of 2, otherwise an alignment error will be returned.
///
- BranchPCRelPLT24dbl,
+ DeltaPLT24dbl,
/// A 16-bit PC-relative branch.
///
@@ -283,7 +283,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// - The result of the fixup expression before shifting right by 1 must
/// be multiple of 2, otherwise an alignment error will be returned.
///
- BranchPCRelPLT16dbl,
+ DeltaPLT16dbl,
/// A 12-bit PC-relative branch.
///
@@ -296,14 +296,14 @@ enum EdgeKind_systemz : Edge::Kind {
/// - The result of the fixup expression before shifting right by 1 must
/// be multiple of 2, otherwise an alignment error will be returned.
///
- BranchPCRelPLT12dbl,
+ DeltaPLT12dbl,
/// A 64-bit PC-relative PLT address.
///
/// Fixup expression:
/// Fixup <- Target - Fixup + Addend : int64
///
- BranchPCRelPLT64,
+ DeltaPLT64,
/// A 32-bit PC-relative PLT address.
///
@@ -314,14 +314,13 @@ enum EdgeKind_systemz : Edge::Kind {
/// - The result of the fixup expression must fit into an int32, otherwise
/// an out-of-range error will be returned.
///
- BranchPCRelPLT32,
+ DeltaPLT32,
/// A 32-bit PC-relative branch to a pointer jump stub.
/// Create a jump stub block that jumps via the pointer at the given symbol.
///
/// Stub Content:
- /// larl %r1, ptr
- /// lg %r1, 0(%r1)
+ /// lgrl %r1, ptr
/// j %r1
///
/// Fixup expression at offset 2 of branch Instruction:
@@ -380,7 +379,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
/// symbol was not been defined.
///
- Delta64GOT,
+ RequestGOTAndTransformToDelta64,
/// A 32-bit GOT offset.
///
@@ -393,7 +392,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// - The result of the fixup expression must fit into an int32, otherwise
/// an out-of-range error will be returned.
///
- Delta32GOT,
+ RequestGOTAndTransformToDelta32,
/// A 20-bit GOT offset.
///
@@ -406,7 +405,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// - The result of the fixup expression must fit into an int20, otherwise
/// an out-of-range error will be returned.
///
- Delta20GOT,
+ RequestGOTAndTransformToDelta20,
/// A 16-bit GOT offset.
///
@@ -419,7 +418,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// - The result of the fixup expression must fit into an int16, otherwise
/// an out-of-range error will be returned.
///
- Delta16GOT,
+ RequestGOTAndTransformToDelta16,
/// A 12-bit GOT offset.
///
@@ -432,7 +431,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// - The result of the fixup expression must fit into an int12, otherwise
/// an out-of-range error will be returned.
///
- Delta12GOT,
+ RequestGOTAndTransformToDelta12,
/// A 32-bit PC rel. offset to GOT.
///
@@ -445,7 +444,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// - The result of the fixup expression must fit into an int32, otherwise
/// an out-of-range error will be returned.
///
- DeltaPCRelGOT,
+ RequestGOTAndTransformToDelta32GOTBase,
/// A 32-bit PC rel. offset to GOT shifted by 1.
///
@@ -460,83 +459,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// - The result of the fixup expression before shifting right by 1 must
/// be multiple of 2, otherwise an alignment error will be returned.
///
- DeltaPCRelGOTdbl,
-
- /// A 64-bit offset to Jump Slot.
- ///
- /// Fixup expression:
- /// Fixup <- Target - GOTBase + Addend : int64
- ///
- /// Errors:
- /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
- /// symbol was not been defined.
- ///
- Delta64JumpSlot,
-
- /// A 32-bit offset to Jump Slot.
- ///
- /// Fixup expression:
- /// Fixup <- Target - GOTBase + Addend : int32
- ///
- /// Errors:
- /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
- /// symbol was not been defined.
- /// - The result of the fixup expression must fit into an int32, otherwise
- /// an out-of-range error will be returned.
- ///
- Delta32JumpSlot,
-
- /// A 20-bit offset to Jump Slot.
- ///
- /// Fixup expression:
- /// Fixup <- Target - GOTBase + Addend : int20
- ///
- /// Errors:
- /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
- /// symbol was not been defined.
- /// - The result of the fixup expression must fit into an int20, otherwise
- /// an out-of-range error will be returned.
- ///
- Delta20JumpSlot,
-
- /// A 16-bit offset to Jump Slot.
- ///
- /// Fixup expression:
- /// Fixup <- Target - GOTBase + Addend : int16
- ///
- /// Errors:
- /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
- /// symbol was not been defined.
- /// - The result of the fixup expression must fit into an int16, otherwise
- /// an out-of-range error will be returned.
- ///
- Delta16JumpSlot,
-
- /// A 12-bit offset to Jump Slot.
- ///
- /// Fixup expression:
- /// Fixup <- Target - GOTBase + Addend : int12
- ///
- /// Errors:
- /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
- /// symbol was not been defined.
- /// - The result of the fixup expression must fit into an int12, otherwise
- /// an out-of-range error will be returned.
- ///
- Delta12JumpSlot,
-
- /// A 32-bit PC rel. offset to Jump Slot.
- ///
- /// Fixup expression:
- /// Fixup <- (Target - Fixup + Addend) >> 1 : int32
- ///
- /// Errors:
- /// - The result of the fixup expression before shifting right by 1 must
- /// fit into an int33, otherwise an out-of-range error will be returned.
- /// - The result of the fixup expression before shifting right by 1 must
- /// be multiple of 2, otherwise an alignment error will be returned.
- ///
- PCRel32JumpSlot,
+ RequestGOTAndTransformToDelta32GOTBasedbl,
/// A 32-bit PC rel. to GOT entry >> 1.
///
@@ -549,7 +472,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// - The result of the fixup expression before shifting right by 1 must
/// be multiple of 2, otherwise an alignment error will be returned.
///
- PCRel32GOTEntry,
+ RequestGOTAndTransformToDelta32dbl,
};
@@ -592,7 +515,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
uint64_t Value = S + A;
if (!LLVM_UNLIKELY(isUInt<32>(Value)))
return makeTargetOutOfRangeError(G, B, E);
- *(ubig32_t *)FixupPtr = Value;
+ write32be(FixupPtr, Value);
break;
}
case Pointer20: {
@@ -607,7 +530,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
uint64_t Value = S + A;
if (!LLVM_UNLIKELY(isUInt<16>(Value)))
return makeTargetOutOfRangeError(G, B, E);
- *(ubig16_t *)FixupPtr = Value;
+ write16be(FixupPtr, Value);
break;
}
case Pointer12: {
@@ -626,28 +549,28 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
}
case Delta64: {
int64_t Value = S + A - P;
- *(big64_t *)FixupPtr = Value;
+ write64be(FixupPtr, Value);
break;
}
case Delta32: {
int64_t Value = S + A - P;
if (!LLVM_UNLIKELY(isInt<32>(Value)))
return makeTargetOutOfRangeError(G, B, E);
- *(big32_t *)FixupPtr = Value;
+ write32be(FixupPtr, Value);
break;
}
case Delta16: {
int64_t Value = S + A - P;
if (!LLVM_UNLIKELY(isInt<16>(Value)))
return makeTargetOutOfRangeError(G, B, E);
- *(big16_t *)FixupPtr = Value;
+ write16be(FixupPtr, Value);
break;
}
case NegDelta32: {
int64_t Value = P + A - S;
if (!LLVM_UNLIKELY(isInt<32>(Value)))
return makeTargetOutOfRangeError(G, B, E);
- *(big32_t *)FixupPtr = Value;
+ write32be(FixupPtr, Value);
break;
}
case Delta32dbl: {
@@ -689,35 +612,37 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
(read16be(FixupPtr) & 0xF000) | ((Value >> 1) & 0x0FFF));
break;
}
- case Delta64FromGOT: {
+ case RequestGOTAndTransformToDelta64FromGOT: {
assert(GOTSymbol && "No GOT section symbol");
int64_t Value = S - GOTBase + A;
- *(big64_t *)FixupPtr = Value;
+ write64be(FixupPtr, Value);
break;
}
- case Delta32FromGOT: {
+ case RequestGOTAndTransformToDelta32FromGOT: {
assert(GOTSymbol && "No GOT section symbol");
int64_t Value = S - GOTBase + A;
if (!LLVM_UNLIKELY(isInt<32>(Value)))
return makeTargetOutOfRangeError(G, B, E);
- *(big32_t *)FixupPtr = Value;
+ write32be(FixupPtr, Value);
break;
}
- case Delta16FromGOT: {
+ case RequestGOTAndTransformToDelta16FromGOT: {
assert(GOTSymbol && "No GOT section symbol");
int64_t Value = S - GOTBase + A;
if (!LLVM_UNLIKELY(isInt<16>(Value)))
return makeTargetOutOfRangeError(G, B, E);
- *(big16_t *)FixupPtr = Value;
+ write16be(FixupPtr, Value);
break;
}
- case DeltaPCRelGOT: {
+ case RequestGOTAndTransformToDelta32GOTBase: {
assert(GOTSymbol && "No GOT section symbol");
int64_t Value = GOTBase + A - P;
- *(big32_t *)FixupPtr = Value;
+ if (!LLVM_UNLIKELY(isInt<32>(Value)))
+ return makeTargetOutOfRangeError(G, B, E);
+ write32be(FixupPtr, Value);
break;
}
- case DeltaPCRelGOTdbl: {
+ case RequestGOTAndTransformToDelta32GOTBasedbl: {
assert(GOTSymbol && "No GOT section symbol");
int64_t Value = (GOTBase + A - P);
if (!LLVM_UNLIKELY(isInt<33>(Value)))
@@ -727,7 +652,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
write32be(FixupPtr, Value >> 1);
break;
}
- case BranchPCRelPLT32dbl: {
+ case DeltaPLT32dbl: {
int64_t Value = (S + A - P);
if (!LLVM_UNLIKELY(isInt<33>(Value)))
return makeTargetOutOfRangeError(G, B, E);
@@ -736,7 +661,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
write32be(FixupPtr, Value >> 1);
break;
}
- case BranchPCRelPLT24dbl: {
+ case DeltaPLT24dbl: {
int64_t Value = (S + A - P);
if (!LLVM_UNLIKELY(isInt<25>(Value)))
return makeTargetOutOfRangeError(G, B, E);
@@ -745,7 +670,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
FixupPtr[2] = Value >> 1;
break;
}
- case BranchPCRelPLT16dbl: {
+ case DeltaPLT16dbl: {
int64_t Value = (S + A - P);
if (!LLVM_UNLIKELY(isInt<17>(Value)))
return makeTargetOutOfRangeError(G, B, E);
@@ -754,7 +679,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
write16be(FixupPtr, Value >> 1);
break;
}
- case BranchPCRelPLT12dbl: {
+ case DeltaPLT12dbl: {
int64_t Value = (S + A - P);
if (!LLVM_UNLIKELY(isInt<13>(Value)))
return makeTargetOutOfRangeError(G, B, E);
@@ -764,22 +689,22 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
(read16be(FixupPtr) & 0xF000) | ((Value >> 1) & 0x0FFF));
break;
}
- case BranchPCRelPLT64: {
+ case DeltaPLT64: {
int64_t Value = (S + A - P);
- *(big64_t *)FixupPtr = Value;
+ write64be(FixupPtr, Value);
break;
}
- case BranchPCRelPLT32: {
+ case DeltaPLT32: {
int64_t Value = (S + A - P);
if (!LLVM_UNLIKELY(isInt<32>(Value)))
return makeTargetOutOfRangeError(G, B, E);
- *(big32_t *)FixupPtr = Value;
+ write32be(FixupPtr, Value);
break;
}
case DeltaPLT64FromGOT: {
assert(GOTSymbol && "No GOT section symbol");
int64_t Value = (S + A - GOTBase);
- *(big64_t *)FixupPtr = Value;
+ write64be(FixupPtr, Value);
break;
}
case DeltaPLT32FromGOT: {
@@ -787,7 +712,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
int64_t Value = (S + A - GOTBase);
if (!LLVM_UNLIKELY(isInt<32>(Value)))
return makeTargetOutOfRangeError(G, B, E);
- *(big32_t *)FixupPtr = Value;
+ write32be(FixupPtr, Value);
break;
}
case DeltaPLT16FromGOT: {
@@ -795,7 +720,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
int64_t Value = (S + A - GOTBase);
if (!LLVM_UNLIKELY(isInt<16>(Value)))
return makeTargetOutOfRangeError(G, B, E);
- *(big16_t *)FixupPtr = Value;
+ write16be(FixupPtr, Value);
break;
}
case Branch32dblToStub: {
@@ -803,10 +728,10 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
if (!LLVM_UNLIKELY(isInt<33>(Value)))
return makeTargetOutOfRangeError(G, B, E);
char *AddrToPatch = FixupPtr + 2;
- *(big32_t *)AddrToPatch = (Value >> 1);
+ write32be(AddrToPatch, Value >> 1);
break;
}
- case PCRel32GOTEntry: {
+ case RequestGOTAndTransformToDelta32dbl: {
int64_t Value = (S + A - P);
if (!LLVM_UNLIKELY(isInt<33>(Value)))
return makeTargetOutOfRangeError(G, B, E);
@@ -815,21 +740,21 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
write32be(FixupPtr, Value >> 1);
break;
}
- case Delta64GOT: {
+ case RequestGOTAndTransformToDelta64: {
assert(GOTSymbol && "No GOT section symbol");
int64_t Value = S - GOTBase + A;
- *(big64_t *)FixupPtr = Value;
+ write64be(FixupPtr, Value);
break;
}
- case Delta32GOT: {
+ case RequestGOTAndTransformToDelta32: {
assert(GOTSymbol && "No GOT section symbol");
uint64_t Value = S - GOTBase + A;
if (!LLVM_UNLIKELY(isUInt<32>(Value)))
return makeTargetOutOfRangeError(G, B, E);
- *(big32_t *)FixupPtr = Value;
+ write32be(FixupPtr, Value);
break;
}
- case Delta20GOT: {
+ case RequestGOTAndTransformToDelta20: {
assert(GOTSymbol && "No GOT section symbol");
uint64_t Value = S - GOTBase + A;
if (!LLVM_UNLIKELY(isInt<20>(Value)))
@@ -838,15 +763,15 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
((Value & 0xFFF) << 16) | ((Value & 0xFF000) >> 4));
break;
}
- case Delta16GOT: {
+ case RequestGOTAndTransformToDelta16: {
assert(GOTSymbol && "No GOT section symbol");
uint64_t Value = S - GOTBase + A;
if (!LLVM_UNLIKELY(isUInt<16>(Value)))
return makeTargetOutOfRangeError(G, B, E);
- *(big16_t *)FixupPtr = Value;
+ write16be(FixupPtr, Value);
break;
}
- case Delta12GOT: {
+ case RequestGOTAndTransformToDelta12: {
assert(GOTSymbol && "No GOT section symbol");
uint64_t Value = S - GOTBase + A;
if (!LLVM_UNLIKELY(isUInt<12>(Value)))
@@ -854,54 +779,6 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
write16be(FixupPtr, (read16be(FixupPtr) & 0xF000) | Value);
break;
}
- case Delta64JumpSlot: {
- assert(GOTSymbol && "No GOT section symbol");
- uint64_t Value = S - GOTBase + A;
- *(big64_t *)FixupPtr = Value;
- break;
- }
- case Delta32JumpSlot: {
- assert(GOTSymbol && "No GOT section symbol");
- uint64_t Value = S - GOTBase + A;
- if (!LLVM_UNLIKELY(isUInt<32>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- *(big32_t *)FixupPtr = Value;
- break;
- }
- case Delta20JumpSlot: {
- assert(GOTSymbol && "No GOT section symbol");
- int64_t Value = S - GOTBase + A;
- if (!LLVM_UNLIKELY(isInt<20>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- write32be(FixupPtr, (read32be(FixupPtr) & 0xF00000FF) |
- ((Value & 0xFFF) << 16) | ((Value & 0xFF000) >> 4));
- break;
- }
- case Delta16JumpSlot: {
- assert(GOTSymbol && "No GOT section symbol");
- uint64_t Value = S - GOTBase + A;
- if (!LLVM_UNLIKELY(isUInt<16>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- *(big16_t *)FixupPtr = Value;
- break;
- }
- case Delta12JumpSlot: {
- assert(GOTSymbol && "No GOT section symbol");
- uint64_t Value = S - GOTBase + A;
- if (!LLVM_UNLIKELY(isUInt<13>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- write16be(FixupPtr, (read16be(FixupPtr) & 0xF000) | Value);
- break;
- }
- case PCRel32JumpSlot: {
- int64_t Value = S + A - P;
- if (!LLVM_UNLIKELY(isInt<33>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2)))
- return makeAlignmentError(FixupAddress, Value, 2, E);
- write32be(FixupPtr, Value >> 1);
- break;
- }
default:
return make_error<JITLinkError>(
"In graph " + G.getName() + ", section " + B.getSection().getName() +
@@ -922,8 +799,7 @@ inline ArrayRef<char> getGOTEntryBlockContent(LinkGraph &G) {
///
/// Contains the instruction sequence for an indirect jump via an in-memory
/// pointer:
-/// larl %r1, ptr
-/// lg %r1, 0(%r1)
+/// lgrl %r1, ptr
/// j %r1
constexpr size_t StubEntrySize = 14;
extern const char Pointer64JumpStubContent[StubEntrySize];
@@ -982,23 +858,17 @@ class GOTTableManager : public TableManager<GOTTableManager> {
return false;
Edge::Kind KindToSet = Edge::Invalid;
switch (E.getKind()) {
- case systemz::Delta12GOT:
- case systemz::Delta16GOT:
- case systemz::Delta20GOT:
- case systemz::Delta32GOT:
- case systemz::Delta64GOT:
- case systemz::Delta16FromGOT:
- case systemz::Delta32FromGOT:
- case systemz::Delta64FromGOT:
- case systemz::Delta12JumpSlot:
- case systemz::Delta16JumpSlot:
- case systemz::Delta20JumpSlot:
- case systemz::Delta32JumpSlot:
- case systemz::Delta64JumpSlot:
- case systemz::DeltaPCRelGOT:
- case systemz::DeltaPCRelGOTdbl:
- case systemz::PCRel32GOTEntry:
- case systemz::PCRel32JumpSlot:
+ case systemz::RequestGOTAndTransformToDelta12:
+ case systemz::RequestGOTAndTransformToDelta16:
+ case systemz::RequestGOTAndTransformToDelta20:
+ case systemz::RequestGOTAndTransformToDelta32:
+ case systemz::RequestGOTAndTransformToDelta64:
+ case systemz::RequestGOTAndTransformToDelta16FromGOT:
+ case systemz::RequestGOTAndTransformToDelta32FromGOT:
+ case systemz::RequestGOTAndTransformToDelta64FromGOT:
+ case systemz::RequestGOTAndTransformToDelta32GOTBase:
+ case systemz::RequestGOTAndTransformToDelta32GOTBasedbl:
+ case systemz::RequestGOTAndTransformToDelta32dbl:
KindToSet = E.getKind();
break;
default:
@@ -1042,12 +912,12 @@ class PLTTableManager : public TableManager<PLTTableManager> {
return false;
switch (E.getKind()) {
- case systemz::BranchPCRelPLT32:
- case systemz::BranchPCRelPLT64:
- case systemz::BranchPCRelPLT12dbl:
- case systemz::BranchPCRelPLT16dbl:
- case systemz::BranchPCRelPLT24dbl:
- case systemz::BranchPCRelPLT32dbl:
+ case systemz::DeltaPLT32:
+ case systemz::DeltaPLT64:
+ case systemz::DeltaPLT12dbl:
+ case systemz::DeltaPLT16dbl:
+ case systemz::DeltaPLT24dbl:
+ case systemz::DeltaPLT32dbl:
case systemz::DeltaPLT16FromGOT:
case systemz::DeltaPLT32FromGOT:
case systemz::DeltaPLT64FromGOT:
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp
index 47d2d4651f881..630736d3d1ad4 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp
@@ -240,27 +240,27 @@ class ELFLinkGraphBuilder_systemz
}
// Relocations targeting the PLT associated with the symbol.
case ELF::R_390_PLT64: {
- Kind = systemz::BranchPCRelPLT64;
+ Kind = systemz::DeltaPLT64;
break;
}
case ELF::R_390_PLT32: {
- Kind = systemz::BranchPCRelPLT32;
+ Kind = systemz::DeltaPLT32;
break;
}
case ELF::R_390_PLT32DBL: {
- Kind = systemz::BranchPCRelPLT32dbl;
+ Kind = systemz::DeltaPLT32dbl;
break;
}
case ELF::R_390_PLT24DBL: {
- Kind = systemz::BranchPCRelPLT24dbl;
+ Kind = systemz::DeltaPLT24dbl;
break;
}
case ELF::R_390_PLT16DBL: {
- Kind = systemz::BranchPCRelPLT16dbl;
+ Kind = systemz::DeltaPLT16dbl;
break;
}
case ELF::R_390_PLT12DBL: {
- Kind = systemz::BranchPCRelPLT12dbl;
+ Kind = systemz::DeltaPLT12dbl;
break;
}
case ELF::R_390_PLTOFF64: {
@@ -277,72 +277,53 @@ class ELFLinkGraphBuilder_systemz
}
// Relocations targeting the GOT entry associated with the symbol.
case ELF::R_390_GOTOFF64: {
- Kind = systemz::Delta64FromGOT;
+ Kind = systemz::RequestGOTAndTransformToDelta64FromGOT;
break;
}
- // Seems loke ‘R_390_GOTOFF32’.
case ELF::R_390_GOTOFF: {
- Kind = systemz::Delta32FromGOT;
+ Kind = systemz::RequestGOTAndTransformToDelta32FromGOT;
break;
}
case ELF::R_390_GOTOFF16: {
- Kind = systemz::Delta16FromGOT;
- break;
- }
- case ELF::R_390_GOT64: {
- Kind = systemz::Delta64GOT;
- break;
- }
- case ELF::R_390_GOT32: {
- Kind = systemz::Delta32GOT;
- break;
- }
- case ELF::R_390_GOT20: {
- Kind = systemz::Delta20GOT;
- break;
- }
- case ELF::R_390_GOT16: {
- Kind = systemz::Delta16GOT;
- break;
- }
- case ELF::R_390_GOT12: {
- Kind = systemz::Delta12GOT;
- break;
- }
- case ELF::R_390_GOTPC: {
- Kind = systemz::DeltaPCRelGOT;
- break;
- }
- case ELF::R_390_GOTPCDBL: {
- Kind = systemz::DeltaPCRelGOTdbl;
+ Kind = systemz::RequestGOTAndTransformToDelta16FromGOT;
break;
}
+ case ELF::R_390_GOT64:
case ELF::R_390_GOTPLT64: {
- Kind = systemz::Delta64JumpSlot;
+ Kind = systemz::RequestGOTAndTransformToDelta64;
break;
}
+ case ELF::R_390_GOT32:
case ELF::R_390_GOTPLT32: {
- Kind = systemz::Delta32JumpSlot;
+ Kind = systemz::RequestGOTAndTransformToDelta32;
break;
}
+ case ELF::R_390_GOT20:
case ELF::R_390_GOTPLT20: {
- Kind = systemz::Delta20JumpSlot;
+ Kind = systemz::RequestGOTAndTransformToDelta20;
break;
}
+ case ELF::R_390_GOT16:
case ELF::R_390_GOTPLT16: {
- Kind = systemz::Delta16JumpSlot;
+ Kind = systemz::RequestGOTAndTransformToDelta16;
break;
}
+ case ELF::R_390_GOT12:
case ELF::R_390_GOTPLT12: {
- Kind = systemz::Delta12JumpSlot;
+ Kind = systemz::RequestGOTAndTransformToDelta12;
break;
}
- case ELF::R_390_GOTPLTENT: {
- Kind = systemz::PCRel32JumpSlot;
+ case ELF::R_390_GOTPC: {
+ Kind = systemz::RequestGOTAndTransformToDelta32GOTBase;
break;
}
- case ELF::R_390_GOTENT: {
- Kind = systemz::PCRel32GOTEntry;
+ case ELF::R_390_GOTPCDBL: {
+ Kind = systemz::RequestGOTAndTransformToDelta32GOTBasedbl;
+ break;
+ }
+ case ELF::R_390_GOTENT:
+ case ELF::R_390_GOTPLTENT: {
+ Kind = systemz::RequestGOTAndTransformToDelta32dbl;
break;
}
default:
@@ -390,7 +371,7 @@ Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromELFObject_systemz(
return Features.takeError();
assert((*ELFObj)->getArch() == Triple::systemz &&
- "Only SystemZ (big endian) is supported for now");
+ "Only SystemZ is supported");
auto &ELFObjFile = cast<object::ELFObjectFile<object::ELF64BE>>(**ELFObj);
return ELFLinkGraphBuilder_systemz(
diff --git a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp
index c9276bedafe99..273f3345f10d6 100644
--- a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp
@@ -22,18 +22,12 @@ const char NullPointerContent[8] = {0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
const char Pointer64JumpStubContent[14] = {
- static_cast<char>(0xC0u),
- 0x10,
+ static_cast<char>(0xC4u),
+ 0x18,
0x00,
0x00,
0x00,
- 0x00, // larl r1
- static_cast<char>(0xE3u),
- 0x10,
- 0x10,
- 0x00,
- 0x00,
- 0x04, // LG 1, 0(1)
+ 0x00, // lgrl r1
static_cast<char>(0x07u),
static_cast<char>(0xF1u), // BCR 15, 1
};
@@ -70,58 +64,46 @@ const char *getEdgeKindName(Edge::Kind R) {
return "NegDelta64";
case NegDelta32:
return "NegDelta32";
- case Delta64FromGOT:
- return "Delta64FromGOT";
- case Delta32FromGOT:
- return "Delta32FromGOT";
- case Delta16FromGOT:
- return "Delta16FromGOT";
- case BranchPCRelPLT32dbl:
- return "BranchPCRelPLT32dbl";
- case BranchPCRelPLT24dbl:
- return "BranchPCRelPLT24dbl";
- case BranchPCRelPLT16dbl:
- return "BranchPCRelPLT16dbl";
- case BranchPCRelPLT12dbl:
- return "BranchPCRelPLT12dbl";
- case PCRel32GOTEntry:
- return "PCRel32GOTENTRY";
- case BranchPCRelPLT64:
- return "BranchPCRelPLT64";
- case BranchPCRelPLT32:
- return "BranchPCRelPLT32";
+ case RequestGOTAndTransformToDelta64FromGOT:
+ return "RequestGOTAndTransformToDelta64FromGOT";
+ case RequestGOTAndTransformToDelta32FromGOT:
+ return "RequestGOTAndTransformToDelta32FromGOT";
+ case RequestGOTAndTransformToDelta16FromGOT:
+ return "RequestGOTAndTransformToDelta16FromGOT";
+ case DeltaPLT32dbl:
+ return "DeltaPLT32dbl";
+ case DeltaPLT24dbl:
+ return "DeltaPLT24dbl";
+ case DeltaPLT16dbl:
+ return "DeltaPLT16dbl";
+ case DeltaPLT12dbl:
+ return "DeltaPLT12dbl";
+ case RequestGOTAndTransformToDelta32dbl:
+ return "RequestGOTAndTransformToDelta32dbl";
+ case DeltaPLT64:
+ return "DeltaPLT64";
+ case DeltaPLT32:
+ return "DeltaPLT32";
case DeltaPLT64FromGOT:
return "DeltaPLT64FromGOT";
case DeltaPLT32FromGOT:
return "DeltaPLT32FromGOT";
case DeltaPLT16FromGOT:
return "DeltaPLT16FromGOT";
- case Delta64GOT:
- return "Delta64GOT";
- case Delta32GOT:
- return "Delta32GOT";
- case Delta20GOT:
- return "Delta20GOT";
- case Delta16GOT:
- return "Delta16GOT";
- case Delta12GOT:
- return "Delta12GOT";
- case DeltaPCRelGOT:
- return "DeltaPCRelGOT";
- case DeltaPCRelGOTdbl:
- return "DeltaPCRelGOTdbl";
- case Delta64JumpSlot:
- return "Delta64JumpSlot";
- case Delta32JumpSlot:
- return "Delta32JumpSlot";
- case Delta20JumpSlot:
- return "Delta20JumpSlot";
- case Delta16JumpSlot:
- return "Delta16JumpSlot";
- case Delta12JumpSlot:
- return "Delta12JumpSlot";
- case PCRel32JumpSlot:
- return "PCRel32JumpSlot";
+ case RequestGOTAndTransformToDelta64:
+ return "RequestGOTAndTransformToDelta64";
+ case RequestGOTAndTransformToDelta32:
+ return "RequestGOTAndTransformToDelta32";
+ case RequestGOTAndTransformToDelta20:
+ return "RequestGOTAndTransformToDelta20";
+ case RequestGOTAndTransformToDelta16:
+ return "RequestGOTAndTransformToDelta16";
+ case RequestGOTAndTransformToDelta12:
+ return "RequestGOTAndTransformToDelta12";
+ case RequestGOTAndTransformToDelta32GOTBase:
+ return "RequestGOTAndTransformToDelta32GOTBase";
+ case RequestGOTAndTransformToDelta32GOTBasedbl:
+ return "RequestGOTAndTransformToDelta32GOTBasedbl";
default:
return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
}
>From c0cc3db1c4546c03495aea6468087a68f724bfa2 Mon Sep 17 00:00:00 2001
From: anoopkg6 <anoopkg6 at github.com>
Date: Tue, 4 Nov 2025 05:54:11 +0100
Subject: [PATCH 6/7] Incorporate code review feedback
---
.../llvm/ExecutionEngine/JITLink/systemz.h | 362 +++++++++---------
.../ExecutionEngine/JITLink/ELF_systemz.cpp | 4 +-
llvm/lib/ExecutionEngine/JITLink/systemz.cpp | 8 +-
3 files changed, 177 insertions(+), 197 deletions(-)
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h
index 3f692e0ecc383..ebb0d7042d430 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h
@@ -243,10 +243,10 @@ enum EdgeKind_systemz : Edge::Kind {
/// an out-of-range error will be returned.
RequestGOTAndTransformToDelta16FromGOT,
- /// A 32-bit PC-relative branch.
+ /// A 32-bit PC rel. PLT shifted by 1.
///
- /// Represents a PC-relative call or branch to a target. This can be used to
- /// identify, record, and/or patch call sites.
+ /// Delta from the fixup to the target. This will lead to creation of a
+ /// PLT stub.
///
/// Fixup expression:
/// Fixup <- (Target - Fixup + Addend) >> 1 : int32
@@ -259,7 +259,10 @@ enum EdgeKind_systemz : Edge::Kind {
///
DeltaPLT32dbl,
- /// A 24-bit PC-relative branch.
+ /// A 24-bit PC rel. PLT shifted by 1.
+ ///
+ /// Delta from the fixup to the target. This will lead to creation of a
+ /// PLT stub.
///
/// Fixup expression:
/// Fixup <- (Target - Fixup + Addend) >> 1 : int24
@@ -272,7 +275,10 @@ enum EdgeKind_systemz : Edge::Kind {
///
DeltaPLT24dbl,
- /// A 16-bit PC-relative branch.
+ /// A 16-bit PC rel. PLT shifted by 1.
+ ///
+ /// Delta from the fixup to the target. This will lead to creation of a
+ /// PLT stub.
///
/// Fixup expression:
/// Fixup <- (Target - Fixup + Addend) >> 1 : int16
@@ -285,7 +291,10 @@ enum EdgeKind_systemz : Edge::Kind {
///
DeltaPLT16dbl,
- /// A 12-bit PC-relative branch.
+ /// A 12-bit PC rel. PLT shifted by 1.
+ ///
+ /// Delta from the fixup to the target. This will lead to creation of a
+ /// PLT stub.
///
/// Fixup expression:
/// Fixup <- (Target - Fixup + Addend) >> 1 : int12
@@ -298,14 +307,20 @@ enum EdgeKind_systemz : Edge::Kind {
///
DeltaPLT12dbl,
- /// A 64-bit PC-relative PLT address.
+ /// A 64-bit PC rel. PLT address.
+ ///
+ /// Delta from the fixup to the target. This will lead to creation of a
+ /// PLT stub.
///
/// Fixup expression:
/// Fixup <- Target - Fixup + Addend : int64
///
DeltaPLT64,
- /// A 32-bit PC-relative PLT address.
+ /// A 32-bit PC rel. PLT address.
+ ///
+ /// Delta from the fixup to the target. This will lead to creation of a
+ /// PLT stub.
///
/// Fixup expression:
/// Fixup <- Target - Fixup + Addend : int32
@@ -316,25 +331,11 @@ enum EdgeKind_systemz : Edge::Kind {
///
DeltaPLT32,
- /// A 32-bit PC-relative branch to a pointer jump stub.
- /// Create a jump stub block that jumps via the pointer at the given symbol.
- ///
- /// Stub Content:
- /// lgrl %r1, ptr
- /// j %r1
- ///
- /// Fixup expression at offset 2 of branch Instruction:
- /// Fixup <- (Target - Fixup + Addend) >> 1 : int32
- ///
- /// Errors:
- /// - The result of the fixup expression before shifting right by 1 must
- /// fit into an int33, otherwise an out-of-range error will be returned.
- /// an out-of-range error will be returned.
- ///
- Branch32dblToStub,
-
/// A 64-bit offset from GOT to PLT.
///
+ /// Delta from the fixup to the target. This will lead to creation of a
+ /// PLT stub.
+ ///
/// Fixup expression:
/// Fixup <- Target - GOTBase + Addend : int64
///
@@ -357,6 +358,19 @@ enum EdgeKind_systemz : Edge::Kind {
///
DeltaPLT32FromGOT,
+ /// A 20-bit offset from GOT to PLT.
+ ///
+ /// Fixup expression:
+ /// Fixup <- Target - GOTBase + Addend : int20
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+ /// symbol was not been defined.
+ /// - The result of the fixup expression must fit into an int16, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ DeltaPLT20FromGOT,
+
/// A 16-bit offset from GOT to PLT.
///
/// Fixup expression:
@@ -370,69 +384,139 @@ enum EdgeKind_systemz : Edge::Kind {
///
DeltaPLT16FromGOT,
- /// A 64-bit GOT offset.
+ /// A 12-bit offset from GOT to PLT.
///
/// Fixup expression:
- /// Fixup <- Target - GOTBase + Addend : int64
+ /// Fixup <- Target - GOTBase + Addend : int12
///
/// Errors:
/// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
/// symbol was not been defined.
+ /// - The result of the fixup expression must fit into an int16, otherwise
+ /// an out-of-range error will be returned.
+ ///
+ DeltaPLT12FromGOT,
+
+ /// A GOT entry getter/constructor, transformed to Delta64 pointing at the GOT
+ /// entry for the original target.
+ ///
+ /// Indicates that this edge should be transformed into a Delta32 targeting
+ /// the GOT entry for the edge's current target, maintaining the same addend.
+ /// A GOT entry for the target should be created if one does not already
+ /// exist.
+ ///
+ /// Edges of this kind are usually handled by a GOT builder pass inserted by
+ /// default.
+ ///
+ /// Fixup expression:
+ /// NONE
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
+ /// phase will result in an assert/unreachable during the fixup phase.
///
RequestGOTAndTransformToDelta64,
- /// A 32-bit GOT offset.
+ /// A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT
+ /// entry for the original target.
+ ///
+ /// Indicates that this edge should be transformed into a Delta32 targeting
+ /// the GOT entry for the edge's current target, maintaining the same addend.
+ /// A GOT entry for the target should be created if one does not already
+ /// exist.
+ ///
+ /// Edges of this kind are usually handled by a GOT builder pass inserted by
+ /// default.
///
/// Fixup expression:
- /// Fixup <- Target - GOTBase + Addend : int32
+ /// NONE
///
/// Errors:
- /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
- /// symbol was not been defined.
- /// - The result of the fixup expression must fit into an int32, otherwise
- /// an out-of-range error will be returned.
+ /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
+ /// phase will result in an assert/unreachable during the fixup phase.
///
RequestGOTAndTransformToDelta32,
- /// A 20-bit GOT offset.
+ /// A GOT entry getter/constructor, transformed to Delta20 pointing at the GOT
+ /// entry for the original target.
+ ///
+ /// Indicates that this edge should be transformed into a Delta32 targeting
+ /// the GOT entry for the edge's current target, maintaining the same addend.
+ /// A GOT entry for the target should be created if one does not already
+ /// exist.
+ ///
+ /// Edges of this kind are usually handled by a GOT builder pass inserted by
+ /// default.
///
/// Fixup expression:
- /// Fixup <- Target - GOTBase + Addend : int20
+ /// NONE
///
/// Errors:
- /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
- /// symbol was not been defined.
- /// - The result of the fixup expression must fit into an int20, otherwise
- /// an out-of-range error will be returned.
+ /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
+ /// phase will result in an assert/unreachable during the fixup phase.
///
RequestGOTAndTransformToDelta20,
- /// A 16-bit GOT offset.
+ /// A GOT entry getter/constructor, transformed to Delta16 pointing at the GOT
+ /// entry for the original target.
+ ///
+ /// Indicates that this edge should be transformed into a Delta32 targeting
+ /// the GOT entry for the edge's current target, maintaining the same addend.
+ /// A GOT entry for the target should be created if one does not already
+ /// exist.
+ ///
+ /// Edges of this kind are usually handled by a GOT builder pass inserted by
+ /// default.
///
/// Fixup expression:
- /// Fixup <- Target - GOTBase + Addend : int16
+ /// NONE
///
/// Errors:
- /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
- /// symbol was not been defined.
- /// - The result of the fixup expression must fit into an int16, otherwise
- /// an out-of-range error will be returned.
+ /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
+ /// phase will result in an assert/unreachable during the fixup phase.
///
RequestGOTAndTransformToDelta16,
- /// A 12-bit GOT offset.
+ /// A GOT entry getter/constructor, transformed to Delta12 pointing at the GOT
+ /// entry for the original target.
+ ///
+ /// Indicates that this edge should be transformed into a Delta32 targeting
+ /// the GOT entry for the edge's current target, maintaining the same addend.
+ /// A GOT entry for the target should be created if one does not already
+ /// exist.
+ ///
+ /// Edges of this kind are usually handled by a GOT builder pass inserted by
+ /// default.
///
/// Fixup expression:
- /// Fixup <- Target - GOTBase + Addend : int12
+ /// NONE
///
/// Errors:
- /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
- /// symbol was not been defined.
- /// - The result of the fixup expression must fit into an int12, otherwise
- /// an out-of-range error will be returned.
+ /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
+ /// phase will result in an assert/unreachable during the fixup phase.
///
RequestGOTAndTransformToDelta12,
+ /// A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT
+ /// entry for the original target.
+ ///
+ /// Indicates that this edge should be transformed into a Delta32 targeting
+ /// the GOT entry for the edge's current target, maintaining the same addend.
+ /// A GOT entry for the target should be created if one does not already
+ /// exist.
+ ///
+ /// Edges of this kind are usually handled by a GOT builder pass inserted by
+ /// default.
+ ///
+ /// Fixup expression:
+ /// NONE
+ ///
+ /// Errors:
+ /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
+ /// phase will result in an assert/unreachable during the fixup phase.
+ ///
+ RequestGOTAndTransformToDelta32dbl,
+
/// A 32-bit PC rel. offset to GOT.
///
/// Fixup expression:
@@ -444,7 +528,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// - The result of the fixup expression must fit into an int32, otherwise
/// an out-of-range error will be returned.
///
- RequestGOTAndTransformToDelta32GOTBase,
+ Delta32GOTBase,
/// A 32-bit PC rel. offset to GOT shifted by 1.
///
@@ -459,20 +543,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// - The result of the fixup expression before shifting right by 1 must
/// be multiple of 2, otherwise an alignment error will be returned.
///
- RequestGOTAndTransformToDelta32GOTBasedbl,
-
- /// A 32-bit PC rel. to GOT entry >> 1.
- ///
- /// Fixup expression:
- /// Fixup <- (Target - Fixup + Addend) >> 1 : int32
- ///
- /// Errors:
- /// - The result of the fixup expression before shifting right by 1 must
- /// fit into an int33, otherwise an out-of-range error will be returned.
- /// - The result of the fixup expression before shifting right by 1 must
- /// be multiple of 2, otherwise an alignment error will be returned.
- ///
- RequestGOTAndTransformToDelta32dbl,
+ Delta32dblGOTBase,
};
@@ -547,12 +618,14 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
*(uint8_t *)FixupPtr = Value;
break;
}
- case Delta64: {
+ case Delta64:
+ case DeltaPLT64: {
int64_t Value = S + A - P;
write64be(FixupPtr, Value);
break;
}
- case Delta32: {
+ case Delta32:
+ case DeltaPLT32: {
int64_t Value = S + A - P;
if (!LLVM_UNLIKELY(isInt<32>(Value)))
return makeTargetOutOfRangeError(G, B, E);
@@ -573,7 +646,8 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
write32be(FixupPtr, Value);
break;
}
- case Delta32dbl: {
+ case Delta32dbl:
+ case DeltaPLT32dbl: {
int64_t Value = (S + A - P);
if (!LLVM_UNLIKELY(isInt<33>(Value)))
return makeTargetOutOfRangeError(G, B, E);
@@ -582,7 +656,8 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
write32be(FixupPtr, Value >> 1);
break;
}
- case Delta24dbl: {
+ case Delta24dbl:
+ case DeltaPLT24dbl: {
int64_t Value = (S + A - P);
if (!LLVM_UNLIKELY(isInt<25>(Value)))
return makeTargetOutOfRangeError(G, B, E);
@@ -593,7 +668,8 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
FixupPtr[2] = Value >> 1;
break;
}
- case Delta16dbl: {
+ case Delta16dbl:
+ case DeltaPLT16dbl: {
int64_t Value = (S + A - P);
if (!LLVM_UNLIKELY(isInt<17>(Value)))
return makeTargetOutOfRangeError(G, B, E);
@@ -602,7 +678,8 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
write16be(FixupPtr, Value >> 1);
break;
}
- case Delta12dbl: {
+ case Delta12dbl:
+ case DeltaPLT12dbl: {
int64_t Value = (S + A - P);
if (!LLVM_UNLIKELY(isInt<13>(Value)))
return makeTargetOutOfRangeError(G, B, E);
@@ -612,29 +689,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
(read16be(FixupPtr) & 0xF000) | ((Value >> 1) & 0x0FFF));
break;
}
- case RequestGOTAndTransformToDelta64FromGOT: {
- assert(GOTSymbol && "No GOT section symbol");
- int64_t Value = S - GOTBase + A;
- write64be(FixupPtr, Value);
- break;
- }
- case RequestGOTAndTransformToDelta32FromGOT: {
- assert(GOTSymbol && "No GOT section symbol");
- int64_t Value = S - GOTBase + A;
- if (!LLVM_UNLIKELY(isInt<32>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- write32be(FixupPtr, Value);
- break;
- }
- case RequestGOTAndTransformToDelta16FromGOT: {
- assert(GOTSymbol && "No GOT section symbol");
- int64_t Value = S - GOTBase + A;
- if (!LLVM_UNLIKELY(isInt<16>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- write16be(FixupPtr, Value);
- break;
- }
- case RequestGOTAndTransformToDelta32GOTBase: {
+ case Delta32GOTBase: {
assert(GOTSymbol && "No GOT section symbol");
int64_t Value = GOTBase + A - P;
if (!LLVM_UNLIKELY(isInt<32>(Value)))
@@ -642,7 +697,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
write32be(FixupPtr, Value);
break;
}
- case RequestGOTAndTransformToDelta32GOTBasedbl: {
+ case Delta32dblGOTBase: {
assert(GOTSymbol && "No GOT section symbol");
int64_t Value = (GOTBase + A - P);
if (!LLVM_UNLIKELY(isInt<33>(Value)))
@@ -652,55 +707,6 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
write32be(FixupPtr, Value >> 1);
break;
}
- case DeltaPLT32dbl: {
- int64_t Value = (S + A - P);
- if (!LLVM_UNLIKELY(isInt<33>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2)))
- return makeAlignmentError(FixupAddress, Value, 2, E);
- write32be(FixupPtr, Value >> 1);
- break;
- }
- case DeltaPLT24dbl: {
- int64_t Value = (S + A - P);
- if (!LLVM_UNLIKELY(isInt<25>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- FixupPtr[0] = Value >> 17;
- FixupPtr[1] = Value >> 9;
- FixupPtr[2] = Value >> 1;
- break;
- }
- case DeltaPLT16dbl: {
- int64_t Value = (S + A - P);
- if (!LLVM_UNLIKELY(isInt<17>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2)))
- return makeAlignmentError(FixupAddress, Value, 2, E);
- write16be(FixupPtr, Value >> 1);
- break;
- }
- case DeltaPLT12dbl: {
- int64_t Value = (S + A - P);
- if (!LLVM_UNLIKELY(isInt<13>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2)))
- return makeAlignmentError(FixupAddress, Value, 2, E);
- write16be(FixupPtr,
- (read16be(FixupPtr) & 0xF000) | ((Value >> 1) & 0x0FFF));
- break;
- }
- case DeltaPLT64: {
- int64_t Value = (S + A - P);
- write64be(FixupPtr, Value);
- break;
- }
- case DeltaPLT32: {
- int64_t Value = (S + A - P);
- if (!LLVM_UNLIKELY(isInt<32>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- write32be(FixupPtr, Value);
- break;
- }
case DeltaPLT64FromGOT: {
assert(GOTSymbol && "No GOT section symbol");
int64_t Value = (S + A - GOTBase);
@@ -723,38 +729,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
write16be(FixupPtr, Value);
break;
}
- case Branch32dblToStub: {
- int64_t Value = (S + A - P);
- if (!LLVM_UNLIKELY(isInt<33>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- char *AddrToPatch = FixupPtr + 2;
- write32be(AddrToPatch, Value >> 1);
- break;
- }
- case RequestGOTAndTransformToDelta32dbl: {
- int64_t Value = (S + A - P);
- if (!LLVM_UNLIKELY(isInt<33>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- if (!LLVM_UNLIKELY(isAlignmentCorrect(Value, 2)))
- return makeAlignmentError(FixupAddress, Value, 2, E);
- write32be(FixupPtr, Value >> 1);
- break;
- }
- case RequestGOTAndTransformToDelta64: {
- assert(GOTSymbol && "No GOT section symbol");
- int64_t Value = S - GOTBase + A;
- write64be(FixupPtr, Value);
- break;
- }
- case RequestGOTAndTransformToDelta32: {
- assert(GOTSymbol && "No GOT section symbol");
- uint64_t Value = S - GOTBase + A;
- if (!LLVM_UNLIKELY(isUInt<32>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- write32be(FixupPtr, Value);
- break;
- }
- case RequestGOTAndTransformToDelta20: {
+ case DeltaPLT20FromGOT: {
assert(GOTSymbol && "No GOT section symbol");
uint64_t Value = S - GOTBase + A;
if (!LLVM_UNLIKELY(isInt<20>(Value)))
@@ -763,15 +738,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
((Value & 0xFFF) << 16) | ((Value & 0xFF000) >> 4));
break;
}
- case RequestGOTAndTransformToDelta16: {
- assert(GOTSymbol && "No GOT section symbol");
- uint64_t Value = S - GOTBase + A;
- if (!LLVM_UNLIKELY(isUInt<16>(Value)))
- return makeTargetOutOfRangeError(G, B, E);
- write16be(FixupPtr, Value);
- break;
- }
- case RequestGOTAndTransformToDelta12: {
+ case DeltaPLT12FromGOT: {
assert(GOTSymbol && "No GOT section symbol");
uint64_t Value = S - GOTBase + A;
if (!LLVM_UNLIKELY(isUInt<12>(Value)))
@@ -832,7 +799,7 @@ inline Block &createPointerJumpStubBlock(LinkGraph &G, Section &StubSection,
Symbol &PointerSymbol) {
auto &B = G.createContentBlock(StubSection, getStubBlockContent(G),
orc::ExecutorAddr(), 8, 0);
- B.addEdge(Branch32dblToStub, 0, PointerSymbol, 0);
+ B.addEdge(Delta32dbl, 0, PointerSymbol, 0);
return B;
}
@@ -859,16 +826,28 @@ class GOTTableManager : public TableManager<GOTTableManager> {
Edge::Kind KindToSet = Edge::Invalid;
switch (E.getKind()) {
case systemz::RequestGOTAndTransformToDelta12:
+ KindToSet = systemz::DeltaPLT12FromGOT;
+ break;
case systemz::RequestGOTAndTransformToDelta16:
+ case systemz::RequestGOTAndTransformToDelta16FromGOT:
+ KindToSet = systemz::DeltaPLT16FromGOT;
+ break;
case systemz::RequestGOTAndTransformToDelta20:
+ KindToSet = systemz::DeltaPLT20FromGOT;
+ break;
case systemz::RequestGOTAndTransformToDelta32:
- case systemz::RequestGOTAndTransformToDelta64:
- case systemz::RequestGOTAndTransformToDelta16FromGOT:
case systemz::RequestGOTAndTransformToDelta32FromGOT:
+ KindToSet = systemz::DeltaPLT32FromGOT;
+ break;
+ case systemz::RequestGOTAndTransformToDelta64:
case systemz::RequestGOTAndTransformToDelta64FromGOT:
- case systemz::RequestGOTAndTransformToDelta32GOTBase:
- case systemz::RequestGOTAndTransformToDelta32GOTBasedbl:
+ KindToSet = systemz::DeltaPLT64FromGOT;
+ break;
case systemz::RequestGOTAndTransformToDelta32dbl:
+ KindToSet = systemz::DeltaPLT32dbl;
+ break;
+ case systemz::Delta32GOTBase:
+ case systemz::Delta32dblGOTBase:
KindToSet = E.getKind();
break;
default:
@@ -881,6 +860,7 @@ class GOTTableManager : public TableManager<GOTTableManager> {
<< B->getFixupAddress(E) << " (" << B->getAddress() << " + "
<< formatv("{0:x}", E.getOffset()) << ")\n";
});
+ E.setKind(KindToSet);
E.setTarget(getEntryForTarget(G, E.getTarget()));
return true;
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp
index 630736d3d1ad4..74d9531d3631f 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp
@@ -314,11 +314,11 @@ class ELFLinkGraphBuilder_systemz
break;
}
case ELF::R_390_GOTPC: {
- Kind = systemz::RequestGOTAndTransformToDelta32GOTBase;
+ Kind = systemz::Delta32GOTBase;
break;
}
case ELF::R_390_GOTPCDBL: {
- Kind = systemz::RequestGOTAndTransformToDelta32GOTBasedbl;
+ Kind = systemz::Delta32dblGOTBase;
break;
}
case ELF::R_390_GOTENT:
diff --git a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp
index 273f3345f10d6..4e64036ea1eac 100644
--- a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp
@@ -100,10 +100,10 @@ const char *getEdgeKindName(Edge::Kind R) {
return "RequestGOTAndTransformToDelta16";
case RequestGOTAndTransformToDelta12:
return "RequestGOTAndTransformToDelta12";
- case RequestGOTAndTransformToDelta32GOTBase:
- return "RequestGOTAndTransformToDelta32GOTBase";
- case RequestGOTAndTransformToDelta32GOTBasedbl:
- return "RequestGOTAndTransformToDelta32GOTBasedbl";
+ case Delta32GOTBase:
+ return "Delta32GOTBase";
+ case Delta32dblGOTBase:
+ return "Delta32dblGOTBase";
default:
return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
}
>From 47482b25280f7b78009def2013dd1c5afc2802a9 Mon Sep 17 00:00:00 2001
From: anoopkg6 <anoopkg6 at github.com>
Date: Wed, 5 Nov 2025 03:55:05 +0100
Subject: [PATCH 7/7] 1. Created GOTPC section for R_390_GOTPC and
R_390_GOTPCDBL relocation. 2. Incorporate code review feedback.
---
.../llvm/ExecutionEngine/JITLink/systemz.h | 264 ++++++++++--------
.../ExecutionEngine/JITLink/ELF_systemz.cpp | 23 +-
llvm/lib/ExecutionEngine/JITLink/systemz.cpp | 30 +-
3 files changed, 175 insertions(+), 142 deletions(-)
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h
index ebb0d7042d430..460ed429418b1 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/systemz.h
@@ -49,7 +49,7 @@ enum EdgeKind_systemz : Edge::Kind {
/// Fixup <- Target + Addend : uint20
///
/// Errors:
- /// - The target must reside in the mid 20-bits of the address space,
+ /// - The target must reside in the low 20-bits of the address space,
/// otherwise an out-of-range error will be returned.
///
Pointer20,
@@ -203,50 +203,67 @@ enum EdgeKind_systemz : Edge::Kind {
/// an out-of-range error will be returned.
NegDelta32,
- /// A 64-bit GOT delta.
+ /// A GOT entry getter/constructor, transformed to DeltaPLT64FromGOT pointing
+ /// at the GOT entry for the original target.
///
- /// Delta from the global offset table to the target
+ /// Indicates that this edge should be transformed into a DeltaPLT64FromGOT
+ /// targeting the GOT entry for the edge's current target, maintaining the
+ /// same addend. A GOT entry for the target should be created if one does
+ /// not already exist.
+ ///
+ /// Edges of this kind are usually handled by a GOT builder pass inserted by
+ /// default.
///
/// Fixup expression:
- /// Fixup <- Target - GOTSymbol + Addend : int64
+ /// NONE
///
/// Errors:
- /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
- /// symbol was not been defined.
- RequestGOTAndTransformToDelta64FromGOT,
+ /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
+ ///
+ RequestGOTAndTransformToDeltaPLT64FromGOT,
- /// A 32-bit GOT delta.
+ /// A GOT entry getter/constructor, transformed to DeltaPLT32FromGOT pointing
+ /// at the GOT entry for the original target.
+ ///
+ /// Indicates that this edge should be transformed into a DeltaPLT32FromGOT
+ /// targeting the GOT entry for the edge's current target, maintaining the
+ /// same addend. A GOT entry for the target should be created if one does
+ /// not already exist.
///
- /// Delta from the global offset table to the target
+ /// Edges of this kind are usually handled by a GOT builder pass inserted by
+ /// default.
///
/// Fixup expression:
- /// Fixup <- Target - GOTSymbol + Addend : int32
+ /// NONE
///
/// Errors:
- /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
- /// symbol was not been defined.
- /// - The result of the fixup expression must fit into an int32, otherwise
- /// an out-of-range error will be returned.
- RequestGOTAndTransformToDelta32FromGOT,
+ /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
+ ///
+ RequestGOTAndTransformToDeltaPLT32FromGOT,
- /// A 16-bit GOT delta.
+ /// A GOT entry getter/constructor, transformed to DeltaPLT16FromGOT pointing
+ /// at the GOT entry for the original target.
///
- /// Delta from the global offset table to the target
+ /// Indicates that this edge should be transformed into a DeltaPLT16FromGOT
+ /// targeting the GOT entry for the edge's current target, maintaining the
+ /// same addend. A GOT entry for the target should be created if one does
+ /// not already exist.
+ ///
+ /// Edges of this kind are usually handled by a GOT builder pass inserted by
+ /// default.
///
/// Fixup expression:
- /// Fixup <- Target - GOTSymbol + Addend : int16
+ /// NONE
///
/// Errors:
- /// - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
- /// symbol was not been defined.
- /// - The result of the fixup expression must fit into an int16, otherwise
- /// an out-of-range error will be returned.
- RequestGOTAndTransformToDelta16FromGOT,
+ /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
+ ///
+ RequestGOTAndTransformToDeltaPLT16FromGOT,
- /// A 32-bit PC rel. PLT shifted by 1.
+ /// A 32-bit Delta shifted by 1.
///
- /// Delta from the fixup to the target. This will lead to creation of a
- /// PLT stub.
+ /// Delta from the fixup to the PLT slot for the target. This will lead to
+ /// creation of a PLT stub.
///
/// Fixup expression:
/// Fixup <- (Target - Fixup + Addend) >> 1 : int32
@@ -259,10 +276,10 @@ enum EdgeKind_systemz : Edge::Kind {
///
DeltaPLT32dbl,
- /// A 24-bit PC rel. PLT shifted by 1.
+ /// A 24-bit Delta shifted by 1.
///
- /// Delta from the fixup to the target. This will lead to creation of a
- /// PLT stub.
+ /// Delta from the fixup to the PLT slot for the target. This will lead to
+ /// creation of a PLT stub.
///
/// Fixup expression:
/// Fixup <- (Target - Fixup + Addend) >> 1 : int24
@@ -275,10 +292,10 @@ enum EdgeKind_systemz : Edge::Kind {
///
DeltaPLT24dbl,
- /// A 16-bit PC rel. PLT shifted by 1.
+ /// A 16-bit Delta shifted by 1.
///
- /// Delta from the fixup to the target. This will lead to creation of a
- /// PLT stub.
+ /// Delta from the fixup to the PLT slot for the target. This will lead to
+ /// creation of a PLT stub.
///
/// Fixup expression:
/// Fixup <- (Target - Fixup + Addend) >> 1 : int16
@@ -291,10 +308,10 @@ enum EdgeKind_systemz : Edge::Kind {
///
DeltaPLT16dbl,
- /// A 12-bit PC rel. PLT shifted by 1.
+ /// A 12-bit Delta shifted by 1.
///
- /// Delta from the fixup to the target. This will lead to creation of a
- /// PLT stub.
+ /// Delta from the fixup to the PLT slot for the target. This will lead to
+ /// creation of a PLT stub.
///
/// Fixup expression:
/// Fixup <- (Target - Fixup + Addend) >> 1 : int12
@@ -307,20 +324,20 @@ enum EdgeKind_systemz : Edge::Kind {
///
DeltaPLT12dbl,
- /// A 64-bit PC rel. PLT address.
+ /// A 64-bit Delta.
///
- /// Delta from the fixup to the target. This will lead to creation of a
- /// PLT stub.
+ /// Delta from the fixup to the PLT slot for the target. This will lead to
+ /// creation of a PLT stub.
///
/// Fixup expression:
/// Fixup <- Target - Fixup + Addend : int64
///
DeltaPLT64,
- /// A 32-bit PC rel. PLT address.
+ /// A 32-bit Delta.
///
- /// Delta from the fixup to the target. This will lead to creation of a
- /// PLT stub.
+ /// Delta from the fixup to the PLT slot for the target. This will lead to
+ /// creation of a PLT stub.
///
/// Fixup expression:
/// Fixup <- Target - Fixup + Addend : int32
@@ -397,13 +414,13 @@ enum EdgeKind_systemz : Edge::Kind {
///
DeltaPLT12FromGOT,
- /// A GOT entry getter/constructor, transformed to Delta64 pointing at the GOT
- /// entry for the original target.
+ /// A GOT entry getter/constructor, transformed to DeltaPLT20FromGOT pointing
+ /// at the GOT entry for the original target.
///
- /// Indicates that this edge should be transformed into a Delta32 targeting
- /// the GOT entry for the edge's current target, maintaining the same addend.
- /// A GOT entry for the target should be created if one does not already
- /// exist.
+ /// Indicates that this edge should be transformed into a DeltaPLT20FromGOT
+ /// targeting the GOT entry for the edge's current target, maintaining the
+ /// same addend. A GOT entry for the target should be created if one does
+ /// not already exist.
///
/// Edges of this kind are usually handled by a GOT builder pass inserted by
/// default.
@@ -413,17 +430,16 @@ enum EdgeKind_systemz : Edge::Kind {
///
/// Errors:
/// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
- /// phase will result in an assert/unreachable during the fixup phase.
///
- RequestGOTAndTransformToDelta64,
+ RequestGOTAndTransformToDeltaPLT20FromGOT,
- /// A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT
- /// entry for the original target.
+ /// A GOT entry getter/constructor, transformed to DeltaPLT12FromGOT pointing
+ /// at the GOT entry for the original target.
///
- /// Indicates that this edge should be transformed into a Delta32 targeting
- /// the GOT entry for the edge's current target, maintaining the same addend.
- /// A GOT entry for the target should be created if one does not already
- /// exist.
+ /// Indicates that this edge should be transformed into a DeltaPLT12FromGOT
+ /// targeting the GOT entry for the edge's current target, maintaining the
+ /// same addend. A GOT entry for the target should be created if one does
+ /// not already exist.
///
/// Edges of this kind are usually handled by a GOT builder pass inserted by
/// default.
@@ -435,12 +451,12 @@ enum EdgeKind_systemz : Edge::Kind {
/// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
/// phase will result in an assert/unreachable during the fixup phase.
///
- RequestGOTAndTransformToDelta32,
+ RequestGOTAndTransformToDeltaPLT12FromGOT,
- /// A GOT entry getter/constructor, transformed to Delta20 pointing at the GOT
- /// entry for the original target.
+ /// A GOT entry getter/constructor, transformed to Delta32dbl pointing at
+ /// the GOT entry for the original target.
///
- /// Indicates that this edge should be transformed into a Delta32 targeting
+ /// Indicates that this edge should be transformed into a Delta32dbl targeting
/// the GOT entry for the edge's current target, maintaining the same addend.
/// A GOT entry for the target should be created if one does not already
/// exist.
@@ -455,38 +471,18 @@ enum EdgeKind_systemz : Edge::Kind {
/// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
/// phase will result in an assert/unreachable during the fixup phase.
///
- RequestGOTAndTransformToDelta20,
-
- /// A GOT entry getter/constructor, transformed to Delta16 pointing at the GOT
- /// entry for the original target.
- ///
- /// Indicates that this edge should be transformed into a Delta32 targeting
- /// the GOT entry for the edge's current target, maintaining the same addend.
- /// A GOT entry for the target should be created if one does not already
- /// exist.
- ///
- /// Edges of this kind are usually handled by a GOT builder pass inserted by
- /// default.
- ///
- /// Fixup expression:
- /// NONE
- ///
- /// Errors:
- /// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
- /// phase will result in an assert/unreachable during the fixup phase.
- ///
- RequestGOTAndTransformToDelta16,
+ RequestGOTAndTransformToDelta32dbl,
- /// A GOT entry getter/constructor, transformed to Delta12 pointing at the GOT
- /// entry for the original target.
+ /// A GOTPC entry getter/constructor, transformed to Delta32GOTBase
+ /// delta to GOT base.
///
- /// Indicates that this edge should be transformed into a Delta32 targeting
- /// the GOT entry for the edge's current target, maintaining the same addend.
- /// A GOT entry for the target should be created if one does not already
- /// exist.
+ /// Indicates that this edge should be transformed into a Delta32GOTBase
+ /// targeting the GOTPC entry for the edge's current target, maintaining
+ /// the same addend. A GOTPC entry for the target should be created if
+ /// one does not already exist.
///
- /// Edges of this kind are usually handled by a GOT builder pass inserted by
- /// default.
+ /// Edges of this kind are usually handled by a GOTPC builder pass inserted
+ /// by default.
///
/// Fixup expression:
/// NONE
@@ -494,19 +490,18 @@ enum EdgeKind_systemz : Edge::Kind {
/// Errors:
/// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
/// phase will result in an assert/unreachable during the fixup phase.
- ///
- RequestGOTAndTransformToDelta12,
+ RequestGOTPCAndTransformToDelta32GOTBase,
- /// A GOT entry getter/constructor, transformed to Delta32 pointing at the GOT
- /// entry for the original target.
+ /// A GOTPC entry getter/constructor, transformed to Delta32dblGOTBase
+ /// delta to GOT base.
///
- /// Indicates that this edge should be transformed into a Delta32 targeting
- /// the GOT entry for the edge's current target, maintaining the same addend.
- /// A GOT entry for the target should be created if one does not already
- /// exist.
+ /// Indicates that this edge should be transformed into a Delta32dblGOTBase
+ /// targeting the GOTPC entry for the edge's current target, maintaining
+ /// the same addend. A GOTPC entry for the target should be created if
+ /// one does not already exist.
///
- /// Edges of this kind are usually handled by a GOT builder pass inserted by
- /// default.
+ /// Edges of this kind are usually handled by a GOTPC builder pass inserted
+ /// by default.
///
/// Fixup expression:
/// NONE
@@ -514,10 +509,9 @@ enum EdgeKind_systemz : Edge::Kind {
/// Errors:
/// - *ASSERTION* Failure to handle edges of this kind prior to the fixup
/// phase will result in an assert/unreachable during the fixup phase.
- ///
- RequestGOTAndTransformToDelta32dbl,
+ RequestGOTPCAndTransformToDelta32dblGOTBase,
- /// A 32-bit PC rel. offset to GOT.
+ /// A 32-bit Delta to GOT base.
///
/// Fixup expression:
/// Fixup <- GOTBase - Fixup + Addend : int32
@@ -530,7 +524,7 @@ enum EdgeKind_systemz : Edge::Kind {
///
Delta32GOTBase,
- /// A 32-bit PC rel. offset to GOT shifted by 1.
+ /// A 32-bit Delta to GOT base shifted by 1.
///
/// Fixup expression:
/// Fixup <- (GOTBase - Fixup + Addend) >> 1 : int32
@@ -799,7 +793,7 @@ inline Block &createPointerJumpStubBlock(LinkGraph &G, Section &StubSection,
Symbol &PointerSymbol) {
auto &B = G.createContentBlock(StubSection, getStubBlockContent(G),
orc::ExecutorAddr(), 8, 0);
- B.addEdge(Delta32dbl, 0, PointerSymbol, 0);
+ B.addEdge(Delta32dbl, 2, PointerSymbol, 0);
return B;
}
@@ -825,31 +819,24 @@ class GOTTableManager : public TableManager<GOTTableManager> {
return false;
Edge::Kind KindToSet = Edge::Invalid;
switch (E.getKind()) {
- case systemz::RequestGOTAndTransformToDelta12:
+ case systemz::RequestGOTAndTransformToDeltaPLT12FromGOT:
KindToSet = systemz::DeltaPLT12FromGOT;
break;
- case systemz::RequestGOTAndTransformToDelta16:
- case systemz::RequestGOTAndTransformToDelta16FromGOT:
+ case systemz::RequestGOTAndTransformToDeltaPLT16FromGOT:
KindToSet = systemz::DeltaPLT16FromGOT;
break;
- case systemz::RequestGOTAndTransformToDelta20:
+ case systemz::RequestGOTAndTransformToDeltaPLT20FromGOT:
KindToSet = systemz::DeltaPLT20FromGOT;
break;
- case systemz::RequestGOTAndTransformToDelta32:
- case systemz::RequestGOTAndTransformToDelta32FromGOT:
+ case systemz::RequestGOTAndTransformToDeltaPLT32FromGOT:
KindToSet = systemz::DeltaPLT32FromGOT;
break;
- case systemz::RequestGOTAndTransformToDelta64:
- case systemz::RequestGOTAndTransformToDelta64FromGOT:
+ case systemz::RequestGOTAndTransformToDeltaPLT64FromGOT:
KindToSet = systemz::DeltaPLT64FromGOT;
break;
case systemz::RequestGOTAndTransformToDelta32dbl:
KindToSet = systemz::DeltaPLT32dbl;
break;
- case systemz::Delta32GOTBase:
- case systemz::Delta32dblGOTBase:
- KindToSet = E.getKind();
- break;
default:
return false;
}
@@ -931,6 +918,53 @@ class PLTTableManager : public TableManager<PLTTableManager> {
Section *StubsSection = nullptr;
};
+/// GOTPC Table Builder.
+class GOTPCTableManager : public TableManager<GOTPCTableManager> {
+public:
+ GOTPCTableManager(GOTTableManager &GOT) : GOT(GOT) {}
+
+ static StringRef getSectionName() { return "$__GOTPC"; }
+
+ bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
+ Edge::Kind KindToSet = Edge::Invalid;
+ switch (E.getKind()) {
+ case systemz::RequestGOTPCAndTransformToDelta32GOTBase:
+ KindToSet = systemz::Delta32GOTBase;
+ break;
+ case systemz::RequestGOTPCAndTransformToDelta32dblGOTBase:
+ KindToSet = systemz::Delta32dblGOTBase;
+ break;
+ default:
+ return false;
+ }
+ assert(KindToSet != Edge::Invalid &&
+ "Fell through switch, but no new kind to set");
+ DEBUG_WITH_TYPE("jitlink", {
+ dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
+ << B->getFixupAddress(E) << " (" << B->getAddress() << " + "
+ << formatv("{0:x}", E.getOffset()) << ")\n";
+ });
+ E.setKind(KindToSet);
+ E.setTarget(getEntryForTarget(G, E.getTarget()));
+ return true;
+ }
+
+ Symbol &createEntry(LinkGraph &G, Symbol &Target) {
+ return createAnonymousPointer(G, getGOTPCSection(G), &Target);
+ }
+
+private:
+ Section &getGOTPCSection(LinkGraph &G) {
+ if (!GOTPCSection)
+ GOTPCSection = &G.createSection(getSectionName(),
+ orc::MemProt::Read | orc::MemProt::Exec);
+ return *GOTPCSection;
+ }
+
+ GOTTableManager &GOT;
+ Section *GOTPCSection = nullptr;
+};
+
} // namespace systemz
} // namespace jitlink
} // namespace llvm
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp
index 74d9531d3631f..9ddba46e3b211 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_systemz.cpp
@@ -32,7 +32,8 @@ Error buildTables_ELF_systemz(LinkGraph &G) {
LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
systemz::GOTTableManager GOT;
systemz::PLTTableManager PLT(GOT);
- visitExistingEdges(G, GOT, PLT);
+ systemz::GOTPCTableManager GOTPC(GOT);
+ visitExistingEdges(G, GOT, PLT, GOTPC);
return Error::success();
}
@@ -277,48 +278,48 @@ class ELFLinkGraphBuilder_systemz
}
// Relocations targeting the GOT entry associated with the symbol.
case ELF::R_390_GOTOFF64: {
- Kind = systemz::RequestGOTAndTransformToDelta64FromGOT;
+ Kind = systemz::RequestGOTAndTransformToDeltaPLT64FromGOT;
break;
}
case ELF::R_390_GOTOFF: {
- Kind = systemz::RequestGOTAndTransformToDelta32FromGOT;
+ Kind = systemz::RequestGOTAndTransformToDeltaPLT32FromGOT;
break;
}
case ELF::R_390_GOTOFF16: {
- Kind = systemz::RequestGOTAndTransformToDelta16FromGOT;
+ Kind = systemz::RequestGOTAndTransformToDeltaPLT16FromGOT;
break;
}
case ELF::R_390_GOT64:
case ELF::R_390_GOTPLT64: {
- Kind = systemz::RequestGOTAndTransformToDelta64;
+ Kind = systemz::RequestGOTAndTransformToDeltaPLT64FromGOT;
break;
}
case ELF::R_390_GOT32:
case ELF::R_390_GOTPLT32: {
- Kind = systemz::RequestGOTAndTransformToDelta32;
+ Kind = systemz::RequestGOTAndTransformToDeltaPLT32FromGOT;
break;
}
case ELF::R_390_GOT20:
case ELF::R_390_GOTPLT20: {
- Kind = systemz::RequestGOTAndTransformToDelta20;
+ Kind = systemz::RequestGOTAndTransformToDeltaPLT20FromGOT;
break;
}
case ELF::R_390_GOT16:
case ELF::R_390_GOTPLT16: {
- Kind = systemz::RequestGOTAndTransformToDelta16;
+ Kind = systemz::RequestGOTAndTransformToDeltaPLT16FromGOT;
break;
}
case ELF::R_390_GOT12:
case ELF::R_390_GOTPLT12: {
- Kind = systemz::RequestGOTAndTransformToDelta12;
+ Kind = systemz::RequestGOTAndTransformToDeltaPLT12FromGOT;
break;
}
case ELF::R_390_GOTPC: {
- Kind = systemz::Delta32GOTBase;
+ Kind = systemz::RequestGOTPCAndTransformToDelta32GOTBase;
break;
}
case ELF::R_390_GOTPCDBL: {
- Kind = systemz::Delta32dblGOTBase;
+ Kind = systemz::RequestGOTPCAndTransformToDelta32dblGOTBase;
break;
}
case ELF::R_390_GOTENT:
diff --git a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp
index 4e64036ea1eac..7f6d18c04ca59 100644
--- a/llvm/lib/ExecutionEngine/JITLink/systemz.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/systemz.cpp
@@ -64,12 +64,12 @@ const char *getEdgeKindName(Edge::Kind R) {
return "NegDelta64";
case NegDelta32:
return "NegDelta32";
- case RequestGOTAndTransformToDelta64FromGOT:
- return "RequestGOTAndTransformToDelta64FromGOT";
- case RequestGOTAndTransformToDelta32FromGOT:
- return "RequestGOTAndTransformToDelta32FromGOT";
- case RequestGOTAndTransformToDelta16FromGOT:
- return "RequestGOTAndTransformToDelta16FromGOT";
+ case RequestGOTAndTransformToDeltaPLT64FromGOT:
+ return "RequestGOTAndTransformToDeltaPLT64FromGOT";
+ case RequestGOTAndTransformToDeltaPLT32FromGOT:
+ return "RequestGOTAndTransformToDeltaPLT32FromGOT";
+ case RequestGOTAndTransformToDeltaPLT16FromGOT:
+ return "RequestGOTAndTransformToDeltaPLT16FromGOT";
case DeltaPLT32dbl:
return "DeltaPLT32dbl";
case DeltaPLT24dbl:
@@ -90,16 +90,14 @@ const char *getEdgeKindName(Edge::Kind R) {
return "DeltaPLT32FromGOT";
case DeltaPLT16FromGOT:
return "DeltaPLT16FromGOT";
- case RequestGOTAndTransformToDelta64:
- return "RequestGOTAndTransformToDelta64";
- case RequestGOTAndTransformToDelta32:
- return "RequestGOTAndTransformToDelta32";
- case RequestGOTAndTransformToDelta20:
- return "RequestGOTAndTransformToDelta20";
- case RequestGOTAndTransformToDelta16:
- return "RequestGOTAndTransformToDelta16";
- case RequestGOTAndTransformToDelta12:
- return "RequestGOTAndTransformToDelta12";
+ case RequestGOTAndTransformToDeltaPLT20FromGOT:
+ return "RequestGOTAndTransformToDeltaPLT20FromGOT";
+ case RequestGOTAndTransformToDeltaPLT12FromGOT:
+ return "RequestGOTAndTransformToDeltaPLT12FromGOT";
+ case RequestGOTPCAndTransformToDelta32GOTBase:
+ return "RequestGOTPCAndTransformToDelta32GOTBase";
+ case RequestGOTPCAndTransformToDelta32dblGOTBase:
+ return "RequestGOTPCAndTransformToDelta32dblGOTBase";
case Delta32GOTBase:
return "Delta32GOTBase";
case Delta32dblGOTBase:
More information about the llvm-commits
mailing list