//===------ aarch32.h - Generic JITLink arm/thumb 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 arm/thumb objects. // //===----------------------------------------------------------------------===// #ifndef LLVM_EXECUTIONENGINE_JITLINK_AARCH32 #define LLVM_EXECUTIONENGINE_JITLINK_AARCH32 #include "TableManager.h" #include "llvm/ExecutionEngine/JITLink/JITLink.h" #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h" #include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/Error.h" namespace llvm { namespace jitlink { namespace aarch32 { /// Check whether the given target flags are set for this Symbol. bool hasTargetFlags(Symbol &Sym, TargetFlagsType Flags); /// JITLink-internal AArch32 fixup kinds enum EdgeKind_aarch32 : Edge::Kind { … }; /// Flags enum for AArch32-specific symbol properties enum TargetFlags_aarch32 : TargetFlagsType { … }; /// Human-readable name for a given CPU architecture kind const char *getCPUArchName(ARMBuildAttrs::CPUArch K); /// Get a human-readable name for the given AArch32 edge kind. const char *getEdgeKindName(Edge::Kind K); /// AArch32 uses stubs for a number of purposes, like branch range extension /// or interworking between Arm and Thumb instruction subsets. /// /// Stub implementations vary depending on CPU architecture (v4, v6, v7), /// instruction subset and branch type (absolute/PC-relative). /// /// For each kind of stub, the StubsFlavor defines one concrete form that is /// used throughout the LinkGraph. /// /// Stubs are often called "veneers" in the official docs and online. /// enum class StubsFlavor { … }; /// JITLink sub-arch configuration for Arm CPU models struct ArmConfig { … }; /// Obtain the sub-arch configuration for a given Arm CPU model. inline ArmConfig getArmConfigForCPUArch(ARMBuildAttrs::CPUArch CPUArch) { … } /// Immutable pair of halfwords, Hi and Lo, with overflow check struct HalfWords { … }; /// FixupInfo base class is required for dynamic lookups. struct FixupInfoBase { … }; /// FixupInfo checks for Arm edge kinds work on 32-bit words struct FixupInfoArm : public FixupInfoBase { … }; /// FixupInfo check for Thumb32 edge kinds work on a pair of 16-bit halfwords struct FixupInfoThumb : public FixupInfoBase { … }; /// Collection of named constants per fixup kind /// /// Mandatory entries: /// Opcode - Values of the op-code bits in the instruction, with /// unaffected bits nulled /// OpcodeMask - Mask with all bits set that encode the op-code /// /// Other common entries: /// ImmMask - Mask with all bits set that encode the immediate value /// RegMask - Mask with all bits set that encode the register /// /// Specializations can add further custom fields without restrictions. /// template <EdgeKind_aarch32 Kind> struct FixupInfo { … }; struct FixupInfoArmBranch : public FixupInfoArm { … }; template <> struct FixupInfo<Arm_Jump24> : public FixupInfoArmBranch { … }; template <> struct FixupInfo<Arm_Call> : public FixupInfoArmBranch { … }; struct FixupInfoArmMov : public FixupInfoArm { … }; template <> struct FixupInfo<Arm_MovtAbs> : public FixupInfoArmMov { … }; template <> struct FixupInfo<Arm_MovwAbsNC> : public FixupInfoArmMov { … }; template <> struct FixupInfo<Thumb_Jump24> : public FixupInfoThumb { … }; template <> struct FixupInfo<Thumb_Call> : public FixupInfoThumb { … }; struct FixupInfoThumbMov : public FixupInfoThumb { … }; template <> struct FixupInfo<Thumb_MovtAbs> : public FixupInfoThumbMov { … }; template <> struct FixupInfo<Thumb_MovtPrel> : public FixupInfoThumbMov { … }; template <> struct FixupInfo<Thumb_MovwAbsNC> : public FixupInfoThumbMov { … }; template <> struct FixupInfo<Thumb_MovwPrelNC> : public FixupInfoThumbMov { … }; /// Helper function to read the initial addend for Data-class relocations. Expected<int64_t> readAddendData(LinkGraph &G, Block &B, Edge::OffsetT Offset, Edge::Kind Kind); /// Helper function to read the initial addend for Arm-class relocations. Expected<int64_t> readAddendArm(LinkGraph &G, Block &B, Edge::OffsetT Offset, Edge::Kind Kind); /// Helper function to read the initial addend for Thumb-class relocations. Expected<int64_t> readAddendThumb(LinkGraph &G, Block &B, Edge::OffsetT Offset, Edge::Kind Kind, const ArmConfig &ArmCfg); /// Read the initial addend for a REL-type relocation. It's the value encoded /// in the immediate field of the fixup location by the compiler. inline Expected<int64_t> readAddend(LinkGraph &G, Block &B, Edge::OffsetT Offset, Edge::Kind Kind, const ArmConfig &ArmCfg) { … } /// Helper function to apply the fixup for Data-class relocations. Error applyFixupData(LinkGraph &G, Block &B, const Edge &E); /// Helper function to apply the fixup for Arm-class relocations. Error applyFixupArm(LinkGraph &G, Block &B, const Edge &E); /// Helper function to apply the fixup for Thumb-class relocations. Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E, const ArmConfig &ArmCfg); /// Apply fixup expression for edge to block content. inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E, const ArmConfig &ArmCfg) { … } /// Populate a Global Offset Table from edges that request it. class GOTBuilder : public TableManager<GOTBuilder> { … }; /// Stubs builder emits non-position-independent Arm stubs for pre-v7 CPUs. /// These architectures have no MovT/MovW instructions and don't support Thumb2. /// BL is the only Thumb instruction that can generate stubs and they can always /// be transformed into BLX. class StubsManager_prev7 { … }; /// Stubs builder for v7 emits non-position-independent Arm and Thumb stubs. class StubsManager_v7 { … }; } // namespace aarch32 } // namespace jitlink } // namespace llvm #endif // LLVM_EXECUTIONENGINE_JITLINK_AARCH32