diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h --- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h @@ -52,7 +52,10 @@ /// Arm and Thumb). Arm_Call = FirstArmRelocation, - LastArmRelocation = Arm_Call, + /// Write immediate value for (unconditional) PC-relative branch without link. + Arm_Jump24, + + LastArmRelocation = Arm_Jump24, /// /// Relocations of class Thumb16 and Thumb32 (covers Thumb instruction subset) @@ -149,12 +152,16 @@ /// template struct FixupInfo {}; -template <> struct FixupInfo { +template <> struct FixupInfo { static constexpr uint32_t Opcode = 0x0a000000; - static constexpr uint32_t OpcodeMask = 0x0e000000; + static constexpr uint32_t OpcodeMask = 0x0f000000; static constexpr uint32_t ImmMask = 0x00ffffff; static constexpr uint32_t Unconditional = 0xe0000000; static constexpr uint32_t CondMask = 0xe0000000; // excluding BLX bit +}; + +template <> struct FixupInfo : public FixupInfo { + static constexpr uint32_t OpcodeMask = 0x0e000000; static constexpr uint32_t BitH = 0x01000000; static constexpr uint32_t BitBlx = 0x10000000; }; diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp --- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch32.cpp @@ -40,6 +40,8 @@ return aarch32::Data_Delta32; case ELF::R_ARM_CALL: return aarch32::Arm_Call; + case ELF::R_ARM_JUMP24: + return aarch32::Arm_Jump24; case ELF::R_ARM_THM_CALL: return aarch32::Thumb_Call; case ELF::R_ARM_THM_JUMP24: @@ -64,6 +66,8 @@ return ELF::R_ARM_ABS32; case aarch32::Arm_Call: return ELF::R_ARM_CALL; + case aarch32::Arm_Jump24: + return ELF::R_ARM_JUMP24; case aarch32::Thumb_Call: return ELF::R_ARM_THM_CALL; case aarch32::Thumb_Jump24: diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp --- a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp @@ -292,6 +292,11 @@ return makeUnexpectedOpcodeError(G, R, Kind); return decodeImmBA1BlA1BlxA2(R.Wd); + case Arm_Jump24: + if (!checkOpcode(R)) + return makeUnexpectedOpcodeError(G, R, Kind); + return decodeImmBA1BlA1BlxA2(R.Wd); + default: return make_error( "In graph " + G.getName() + ", section " + B.getSection().getName() + @@ -399,10 +404,25 @@ TargetAddress |= 0x01; switch (Kind) { + case Arm_Jump24: { + if (!checkOpcode(R)) + return makeUnexpectedOpcodeError(G, R, Kind); + if (hasTargetFlags(TargetSymbol, ThumbSymbol)) + return make_error("Branch relocation needs interworking " + "stub when bridging to ARM: " + + StringRef(G.getEdgeKindName(Kind))); + + int64_t Value = TargetAddress - FixupAddress + Addend; + + if (!isInt<26>(Value)) + return makeTargetOutOfRangeError(G, B, E); + writeImmediate(R, encodeImmBA1BlA1BlxA2(Value)); + + return Error::success(); + } case Arm_Call: { if (!checkOpcode(R)) return makeUnexpectedOpcodeError(G, R, Kind); - if ((R.Wd & FixupInfo::CondMask) != FixupInfo::Unconditional) return make_error("Relocation expects an unconditional " @@ -577,6 +597,7 @@ KIND_NAME_CASE(Data_Delta32) KIND_NAME_CASE(Data_Pointer32) KIND_NAME_CASE(Arm_Call) + KIND_NAME_CASE(Arm_Jump24) KIND_NAME_CASE(Thumb_Call) KIND_NAME_CASE(Thumb_Jump24) KIND_NAME_CASE(Thumb_MovwAbsNC) diff --git a/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_static_arm_reloc.s b/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_static_arm_reloc.s --- a/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_static_arm_reloc.s +++ b/llvm/test/ExecutionEngine/JITLink/AArch32/ELF_static_arm_reloc.s @@ -28,6 +28,26 @@ bx lr .size call_target, .-call_target +# CHECK-TYPE: {{[0-9a-f]+}} R_ARM_JUMP24 jump24_target +# CHECK-INSTR: 00000008 : +# CHECK-INSTR: 8: eafffffe b 0x8 +# CHECK-INSTR: 0000000c : +# CHECK-INSTR: c: e12fff1e bx lr +# jitlink-check: decode_operand(jump24_site, 0) = jump24_target - next_pc(jump24_site) - 4 + .globl jump24_site + .type jump24_site,%function + .p2align 2 +jump24_site: + b.w jump24_target + .size jump24_site, .-jump24_site + + .globl jump24_target + .type jump24_target,%function + .p2align 2 +jump24_target: + bx lr + .size jump24_target, .-jump24_target + # Empty main function for jitlink to be happy .globl main .type main,%function