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,69 @@ +// 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_range + .p2align 2 +adr_lower_range: + .word 0 + .space 1<<20 + adr x0, adr_lower_range + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: adr x0, adr_upper_range + .p2align 2 + adr x0, adr_upper_range + .space (1<<20)-4 +adr_upper_range: + .word 0 + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: b b_lower_range + .p2align 2 +b_lower_range: + .word 0 + .space (1<<27) + b b_lower_range + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: b b_upper_range + .p2align 2 + b b_upper_range + .space (1<<27)-4 + .p2align 2 +b_upper_range: + .word 0 + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: beq beq_lower_range + .p2align 2 +beq_lower_range: + .word 0 + .space (1<<20) + beq beq_lower_range + .p2align 2 + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: beq beq_upper_range + beq beq_upper_range + .space (1<<20)-4 + .p2align 2 +beq_upper_range: + .word 0 + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: tbz x0, #1, tbz_lower_range + .p2align 2 +tbz_lower_range: + .word 0 + .space (1<<15) + tbz x0, #1, tbz_lower_range + +// CHECK-LABEL: :{{[0-9]+}}:{{[0-9]+}}: error: fixup value out of range +// CHECK-NEXT: tbz x0, #1, tbz_upper_range + .p2align 2 + tbz x0, #1, tbz_upper_range + .space (1<<15)-4 + .p2align 2 +tbz_upper_range: + .word 0