[llvm] 193a809 - [JITLink][AArch64] Implement R_AARCH64_CONDBR19
Job Noorman via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 26 01:22:57 PDT 2023
Author: Job Noorman
Date: 2023-04-26T10:22:36+02:00
New Revision: 193a8092fb334dbc24edc3bf47c7884cf124f1ce
URL: https://github.com/llvm/llvm-project/commit/193a8092fb334dbc24edc3bf47c7884cf124f1ce
DIFF: https://github.com/llvm/llvm-project/commit/193a8092fb334dbc24edc3bf47c7884cf124f1ce.diff
LOG: [JITLink][AArch64] Implement R_AARCH64_CONDBR19
This relocation is used for the 19-bit immediate in conditional branch
and compare and branch instructions.
Reviewed By: lhames
Differential Revision: https://reviews.llvm.org/D149138
Added:
Modified:
llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
Removed:
################################################################################
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
index 33c09e1a2a315..b8d83ccaddc60 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
@@ -107,6 +107,28 @@ enum EdgeKind_aarch64 : Edge::Kind {
/// out-of-range error will be returned.
Branch26PCRel,
+ /// A 19-bit PC-relative conditional branch.
+ ///
+ /// Represents a PC-relative conditional branch to a target within +/-1Mb. The
+ /// target must be 32-bit aligned.
+ ///
+ /// Fixup expression:
+ /// Fixup <- (Target - Fixup + Addend) >> 2 : int19
+ ///
+ /// Notes:
+ /// The '19' in the name refers to the number operand bits and follows the
+ /// naming convention used by the corresponding ELF relocation.
+ /// Since the low two bits must be zero (because of the 32-bit alignment of
+ /// the target) the operand is effectively a signed 21-bit number.
+ ///
+ ///
+ /// Errors:
+ /// - The result of the unshifted part of the fixup expression must be
+ /// 32-bit aligned otherwise an alignment error will be returned.
+ /// - The result of the fixup expression must fit into an int19 otherwise an
+ /// out-of-range error will be returned.
+ CondBranch19PCRel,
+
/// A 16-bit slice of the target address (which slice depends on the
/// instruction at the fixup location).
///
@@ -299,6 +321,16 @@ inline bool isLoadStoreImm12(uint32_t Instr) {
return (Instr & LoadStoreImm12Mask) == 0x39000000;
}
+inline bool isCondBranchImm19(uint32_t Instr) {
+ constexpr uint32_t CondBranchImm19Mask = 0xfe000000;
+ return (Instr & CondBranchImm19Mask) == 0x54000000;
+}
+
+inline bool isCompAndBranchImm19(uint32_t Instr) {
+ constexpr uint32_t CompAndBranchImm19Mask = 0x7e000000;
+ return (Instr & CompAndBranchImm19Mask) == 0x34000000;
+}
+
// Returns the amount the address operand of LD/ST (imm12)
// should be shifted right by.
//
@@ -431,6 +463,24 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
*(ulittle32_t *)FixupPtr = FixedInstr;
break;
}
+ case CondBranch19PCRel: {
+ assert((FixupAddress.getValue() & 0x3) == 0 &&
+ "Conditional branch is not 32-bit aligned");
+ uint32_t RawInstr = *(ulittle32_t *)FixupPtr;
+ assert((isCondBranchImm19(RawInstr) || isCompAndBranchImm19(RawInstr)) &&
+ "RawInstr is not a conditional branch");
+ int64_t Delta = E.getTarget().getAddress() + E.getAddend() - FixupAddress;
+ if (Delta & 0x3)
+ return make_error<JITLinkError>(
+ "Conditional branch literal target is not 32-bit "
+ "aligned");
+ if (!isInt<21>(Delta))
+ return makeTargetOutOfRangeError(G, B, E);
+ uint32_t EncodedImm = ((static_cast<uint32_t>(Delta) >> 2) & 0x7ffff) << 5;
+ uint32_t FixedInstr = RawInstr | EncodedImm;
+ *(ulittle32_t *)FixupPtr = FixedInstr;
+ break;
+ }
case Page21: {
uint64_t TargetPage =
(E.getTarget().getAddress().getValue() + E.getAddend()) &
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
index ab47f86859dd6..9df1126277e9a 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
@@ -58,6 +58,7 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
ELFMovwAbsG1,
ELFMovwAbsG2,
ELFMovwAbsG3,
+ ELFCondBr19,
ELFAbs32,
ELFAbs64,
ELFPrel32,
@@ -99,6 +100,8 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
return ELFMovwAbsG2;
case ELF::R_AARCH64_MOVW_UABS_G3:
return ELFMovwAbsG3;
+ case ELF::R_AARCH64_CONDBR19:
+ return ELFCondBr19;
case ELF::R_AARCH64_ABS32:
return ELFAbs32;
case ELF::R_AARCH64_ABS64:
@@ -287,6 +290,16 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
Kind = aarch64::MoveWide16;
break;
}
+ case ELFCondBr19: {
+ uint32_t Instr = *(const ulittle32_t *)FixupContent;
+ if (!aarch64::isCondBranchImm19(Instr) &&
+ !aarch64::isCompAndBranchImm19(Instr))
+ return make_error<JITLinkError>("R_AARCH64_CONDBR19 target is not a "
+ "conditional branch instruction");
+
+ Kind = aarch64::CondBranch19PCRel;
+ break;
+ }
case ELFAbs32: {
Kind = aarch64::Pointer32;
break;
diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
index 1011fa81f750f..587b87d1d02f1 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
@@ -47,6 +47,8 @@ const char *getEdgeKindName(Edge::Kind R) {
return "MoveWide16";
case LDRLiteral19:
return "LDRLiteral19";
+ case CondBranch19PCRel:
+ return "CondBranch19PCRel";
case Page21:
return "Page21";
case PageOffset12:
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
index 3eb72e5b2456a..a74f37e22d331 100644
--- a/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
+++ b/llvm/test/ExecutionEngine/JITLink/AArch64/ELF_relocations.s
@@ -241,6 +241,30 @@ test_ld64_gotlo12_external:
ldr x0, [x0, :got_lo12:external_data]
.size test_ld64_gotlo12_external, .-test_ld64_gotlo12_external
+# Check R_AARCH64_CONDBR19 for compare and branch instructions
+#
+# jitlink-check: decode_operand(test_condbr19_cbz, 1) = \
+# jitlink-check: (test_condbr19_cbz_target - test_condbr19_cbz)[21:2]
+ .globl test_condbr19_cbz, test_condbr19_cbz_target
+ .p2align 2
+test_condbr19_cbz:
+ cbz x0, test_condbr19_cbz_target
+ .skip (1 << 19)
+test_condbr19_cbz_target:
+ .size test_condbr19_cbz, .-test_condbr19_cbz
+
+# Check R_AARCH64_CONDBR19 for conditional branch instructions
+#
+# jitlink-check: decode_operand(test_condbr19_bc, 1) = \
+# jitlink-check: (test_condbr19_bc_target - test_condbr19_bc)[21:2]
+ .globl test_condbr19_bc, test_condbr19_bc_target
+ .p2align 2
+test_condbr19_bc:
+ b.eq test_condbr19_bc_target
+ .skip (1 << 19)
+test_condbr19_bc_target:
+ .size test_condbr19_bc, .-test_condbr19_bc
+
.globl named_data
.p2align 4
.type named_data, at object
More information about the llvm-commits
mailing list