[llvm] r265120 - [AArch64] Better errors for out-of-range fixups
Oliver Stannard via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 1 02:14:50 PDT 2016
Author: olista01
Date: Fri Apr 1 04:14:50 2016
New Revision: 265120
URL: http://llvm.org/viewvc/llvm-project?rev=265120&view=rev
Log:
[AArch64] Better errors for out-of-range fixups
When a fixup that can be resolved by the assembler is out of range, we should
report an error in the source, rather than crashing.
Differential Revision: http://reviews.llvm.org/D18402
Added:
llvm/trunk/test/MC/AArch64/fixup-out-of-range.s
Modified:
llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
llvm/trunk/test/MC/AArch64/ldr-pseudo-obj-errors.s
Modified: llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp?rev=265120&r1=265119&r2=265120&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp Fri Apr 1 04:14:50 2016
@@ -12,6 +12,7 @@
#include "MCTargetDesc/AArch64FixupKinds.h"
#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCELFObjectWriter.h"
#include "llvm/MC/MCFixupKindInfo.h"
@@ -134,14 +135,16 @@ static unsigned AdrImmBits(unsigned Valu
return (hi19 << 5) | (lo2 << 29);
}
-static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
+static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
+ MCContext *Ctx) {
+ unsigned Kind = Fixup.getKind();
int64_t SignedValue = static_cast<int64_t>(Value);
switch (Kind) {
default:
llvm_unreachable("Unknown fixup kind!");
case AArch64::fixup_aarch64_pcrel_adr_imm21:
- if (SignedValue > 2097151 || SignedValue < -2097152)
- report_fatal_error("fixup value out of range");
+ if (Ctx && (SignedValue > 2097151 || SignedValue < -2097152))
+ Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
return AdrImmBits(Value & 0x1fffffULL);
case AArch64::fixup_aarch64_pcrel_adrp_imm21:
return AdrImmBits((Value & 0x1fffff000ULL) >> 12);
@@ -149,54 +152,66 @@ static uint64_t adjustFixupValue(unsigne
case AArch64::fixup_aarch64_pcrel_branch19:
// Signed 21-bit immediate
if (SignedValue > 2097151 || SignedValue < -2097152)
- report_fatal_error("fixup value out of range");
+ if (Ctx) Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
+ if (Ctx && (Value & 0x3))
+ Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
// Low two bits are not encoded.
return (Value >> 2) & 0x7ffff;
case AArch64::fixup_aarch64_add_imm12:
case AArch64::fixup_aarch64_ldst_imm12_scale1:
// Unsigned 12-bit immediate
- if (Value >= 0x1000)
- report_fatal_error("invalid imm12 fixup value");
+ if (Ctx && Value >= 0x1000)
+ Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
return Value;
case AArch64::fixup_aarch64_ldst_imm12_scale2:
// Unsigned 12-bit immediate which gets multiplied by 2
- if (Value & 1 || Value >= 0x2000)
- report_fatal_error("invalid imm12 fixup value");
+ if (Ctx && (Value >= 0x2000))
+ Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
+ if (Ctx && (Value & 0x1))
+ Ctx->reportError(Fixup.getLoc(), "fixup must be 2-byte aligned");
return Value >> 1;
case AArch64::fixup_aarch64_ldst_imm12_scale4:
// Unsigned 12-bit immediate which gets multiplied by 4
- if (Value & 3 || Value >= 0x4000)
- report_fatal_error("invalid imm12 fixup value");
+ if (Ctx && (Value >= 0x4000))
+ Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
+ if (Ctx && (Value & 0x3))
+ Ctx->reportError(Fixup.getLoc(), "fixup must be 4-byte aligned");
return Value >> 2;
case AArch64::fixup_aarch64_ldst_imm12_scale8:
// Unsigned 12-bit immediate which gets multiplied by 8
- if (Value & 7 || Value >= 0x8000)
- report_fatal_error("invalid imm12 fixup value");
+ if (Ctx && (Value >= 0x8000))
+ Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
+ if (Ctx && (Value & 0x7))
+ Ctx->reportError(Fixup.getLoc(), "fixup must be 8-byte aligned");
return Value >> 3;
case AArch64::fixup_aarch64_ldst_imm12_scale16:
// Unsigned 12-bit immediate which gets multiplied by 16
- if (Value & 15 || Value >= 0x10000)
- report_fatal_error("invalid imm12 fixup value");
+ if (Ctx && (Value >= 0x10000))
+ Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
+ if (Ctx && (Value & 0xf))
+ Ctx->reportError(Fixup.getLoc(), "fixup must be 16-byte aligned");
return Value >> 4;
case AArch64::fixup_aarch64_movw:
- report_fatal_error("no resolvable MOVZ/MOVK fixups supported yet");
+ if (Ctx)
+ Ctx->reportError(Fixup.getLoc(),
+ "no resolvable MOVZ/MOVK fixups supported yet");
return Value;
case AArch64::fixup_aarch64_pcrel_branch14:
// Signed 16-bit immediate
- if (SignedValue > 32767 || SignedValue < -32768)
- report_fatal_error("fixup value out of range");
+ if (Ctx && (SignedValue > 32767 || SignedValue < -32768))
+ Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
// Low two bits are not encoded (4-byte alignment assumed).
- if (Value & 0x3)
- report_fatal_error("fixup not sufficiently aligned");
+ if (Ctx && (Value & 0x3))
+ Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
return (Value >> 2) & 0x3fff;
case AArch64::fixup_aarch64_pcrel_branch26:
case AArch64::fixup_aarch64_pcrel_call26:
// Signed 28-bit immediate
- if (SignedValue > 134217727 || SignedValue < -134217728)
- report_fatal_error("fixup value out of range");
+ if (Ctx && (SignedValue > 134217727 || SignedValue < -134217728))
+ Ctx->reportError(Fixup.getLoc(), "fixup value out of range");
// Low two bits are not encoded (4-byte alignment assumed).
- if (Value & 0x3)
- report_fatal_error("fixup not sufficiently aligned");
+ if (Ctx && (Value & 0x3))
+ Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned");
return (Value >> 2) & 0x3ffffff;
case FK_Data_1:
case FK_Data_2:
@@ -253,7 +268,7 @@ void AArch64AsmBackend::applyFixup(const
return; // Doesn't change encoding.
MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
// Apply any target-specific value adjustments.
- Value = adjustFixupValue(Fixup.getKind(), Value);
+ Value = adjustFixupValue(Fixup, Value, nullptr);
// Shift the value into position.
Value <<= Info.TargetOffset;
@@ -544,6 +559,12 @@ void ELFAArch64AsmBackend::processFixupV
// to the linker -- a relocation!
if ((uint32_t)Fixup.getKind() == AArch64::fixup_aarch64_pcrel_adrp_imm21)
IsResolved = false;
+
+ // Try to get the encoded value for the fixup as-if we're mapping it into
+ // the instruction. This allows adjustFixupValue() to issue a diagnostic
+ // if the value is invalid.
+ if (IsResolved)
+ (void)adjustFixupValue(Fixup, Value, &Asm.getContext());
}
}
Added: llvm/trunk/test/MC/AArch64/fixup-out-of-range.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AArch64/fixup-out-of-range.s?rev=265120&view=auto
==============================================================================
--- llvm/trunk/test/MC/AArch64/fixup-out-of-range.s (added)
+++ llvm/trunk/test/MC/AArch64/fixup-out-of-range.s Fri Apr 1 04:14:50 2016
@@ -0,0 +1,64 @@
+// RUN: not llvm-mc -triple aarch64--none-eabi -filetype obj < %s -o /dev/null 2>&1 | FileCheck %s
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
+ adr x0, distant
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
+ ldr x0, distant
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup not sufficiently aligned
+ ldr x0, unaligned
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
+ b.eq distant
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup not sufficiently aligned
+ b.eq unaligned
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
+ ldr x0, [x1, distant-.]
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup must be 8-byte aligned
+ ldr x0, [x1, unaligned-.]
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
+ ldr w0, [x1, distant-.]
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup must be 4-byte aligned
+ ldr w0, [x1, unaligned-.]
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
+ ldrh w0, [x1, distant-.]
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup must be 2-byte aligned
+ ldrh w0, [x1, unaligned-.]
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
+ ldrb w0, [x1, distant-.]
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
+ ldr q0, [x1, distant-.]
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup must be 16-byte aligned
+ ldr q0, [x1, unaligned-.]
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
+ tbz x0, #1, distant
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup not sufficiently aligned
+ tbz x0, #1, unaligned
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
+ b distant
+
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup not sufficiently aligned
+ b unaligned
+
+ .byte 0
+unaligned:
+ .byte 0
+
+ .space 1<<27
+ .balign 8
+distant:
+ .word 0
Modified: llvm/trunk/test/MC/AArch64/ldr-pseudo-obj-errors.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AArch64/ldr-pseudo-obj-errors.s?rev=265120&r1=265119&r2=265120&view=diff
==============================================================================
--- llvm/trunk/test/MC/AArch64/ldr-pseudo-obj-errors.s (original)
+++ llvm/trunk/test/MC/AArch64/ldr-pseudo-obj-errors.s Fri Apr 1 04:14:50 2016
@@ -8,6 +8,6 @@
.text
foo:
+// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: fixup value out of range
ldr x0, =0x10111
.space 0xdeadb0
-// CHECK: LVM ERROR: fixup value out of range
More information about the llvm-commits
mailing list