diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp @@ -26,6 +26,7 @@ #include "llvm/MC/MCValue.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" #include "llvm/TargetParser/Triple.h" using namespace llvm; @@ -155,7 +156,7 @@ default: llvm_unreachable("Unknown fixup kind!"); case AArch64::fixup_aarch64_pcrel_adr_imm21: - if (SignedValue > 2097151 || SignedValue < -2097152) + if (!isInt<21>(SignedValue)) Ctx.reportError(Fixup.getLoc(), "fixup value out of range"); return AdrImmBits(Value & 0x1fffffULL); case AArch64::fixup_aarch64_pcrel_adrp_imm21: @@ -168,8 +169,8 @@ return AdrImmBits((Value & 0x1fffff000ULL) >> 12); case AArch64::fixup_aarch64_ldr_pcrel_imm19: case AArch64::fixup_aarch64_pcrel_branch19: - // Signed 21-bit immediate - if (SignedValue > 2097151 || SignedValue < -2097152) + // Signed 19-bit immediate which gets multiplied by 4 + if (!isInt<21>(SignedValue)) Ctx.reportError(Fixup.getLoc(), "fixup value out of range"); if (Value & 0x3) Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned"); diff --git a/llvm/test/MC/AArch64/fixup-out-of-range-edge.s b/llvm/test/MC/AArch64/fixup-out-of-range-edge.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/fixup-out-of-range-edge.s @@ -0,0 +1,52 @@ +// RUN: not llvm-mc -triple aarch64--none-eabi -filetype obj < %s -o /dev/null 2>&1 | FileCheck %s + +// COM: Edge case testing for branches and ADR[P] +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: adr x0, adr_lower +adr_lower: + adr x0, adr_lower-(1<<20)-1 + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: adr x0, adr_upper +adr_upper: + adr x0, adr_upper+(1<<20) + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: b b_lower +b_lower: + b b_lower-(1<<27)-4 + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: b b_upper +b_upper: + b b_upper+(1<<27) + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: beq beq_lower +beq_lower: + beq beq_lower-(1<<20)-4 + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: beq beq_upper +beq_upper: + beq beq_upper+(1<<20) + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: ldr x0, ldr_lower +ldr_lower: + ldr x0, ldr_lower-(1<<20)-4 + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: ldr x0, ldr_upper +ldr_upper: + ldr x0, ldr_upper+(1<<20) + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: tbz x0, #1, tbz_lower +tbz_lower: + tbz x0, #1, tbz_lower-(1<<15)-4 + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: tbz x0, #1, tbz_upper +tbz_upper: + tbz x0, #1, tbz_upper+(1<<15) \ No newline at end of file