From: Rafael Espindola Date: Wed, 4 Nov 2015 23:00:39 +0000 (+0000) Subject: Slightly saner handling of thumb branches. X-Git-Tag: android-x86-7.1-r4~41864 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=dc486f17195c8ff05804f034ddc8988fa9052eab;p=android-x86%2Fexternal-llvm.git Slightly saner handling of thumb branches. The generic infrastructure already did a lot of work to decide if the fixup value is know or not. It doesn't make sense to reimplement a very basic case: same fragment. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252090 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 9c9747fa554..fd678fb132e 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -620,6 +620,7 @@ void ARMAsmBackend::processFixupValue(const MCAssembler &Asm, const MCValue &Target, uint64_t &Value, bool &IsResolved) { const MCSymbolRefExpr *A = Target.getSymA(); + const MCSymbol *Sym = A ? &A->getSymbol() : nullptr; // Some fixups to thumb function symbols need the low bit (thumb bit) // twiddled. if ((unsigned)Fixup.getKind() != ARM::fixup_arm_ldst_pcrel_12 && @@ -628,18 +629,23 @@ void ARMAsmBackend::processFixupValue(const MCAssembler &Asm, (unsigned)Fixup.getKind() != ARM::fixup_thumb_adr_pcrel_10 && (unsigned)Fixup.getKind() != ARM::fixup_t2_adr_pcrel_12 && (unsigned)Fixup.getKind() != ARM::fixup_arm_thumb_cp) { - if (A) { - const MCSymbol &Sym = A->getSymbol(); - if (Asm.isThumbFunc(&Sym)) + if (Sym) { + if (Asm.isThumbFunc(Sym)) Value |= 1; } } - // For Thumb1 BL instruction, it is possible to be a long jump between - // the basic blocks of the same function. Thus, we would like to resolve - // the offset when the destination has the same MCFragment. - if (A && (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl) { - const MCSymbol &Sym = A->getSymbol(); - IsResolved = (Sym.getFragment() == DF); + if (IsResolved && (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl) { + assert(Sym && "How did we resolve this?"); + + // If the symbol is external the linker will handle it. + // FIXME: Should we handle it as an optimization? + if (Sym->isExternal()) { + IsResolved = false; + } else { + if (Value >= 0x400004) + Asm.getContext().reportFatalError(Fixup.getLoc(), + "out of range for branch"); + } } // We must always generate a relocation for BL/BLX instructions if we have // a symbol to reference, as the linker relies on knowing the destination diff --git a/test/MC/ARM/thumb-branches-err.s b/test/MC/ARM/thumb-branches-err.s new file mode 100644 index 00000000000..624ebeeb037 --- /dev/null +++ b/test/MC/ARM/thumb-branches-err.s @@ -0,0 +1,7 @@ +@ RUN: not llvm-mc < %s -triple thumbv5-linux-gnueabi -filetype=obj -o %t 2>&1 | FileCheck %s + + bl end + .space 0x400000 +end: + +@ CHECK: out of range for branch diff --git a/test/MC/ARM/thumb-branches.s b/test/MC/ARM/thumb-branches.s new file mode 100644 index 00000000000..4870e821623 --- /dev/null +++ b/test/MC/ARM/thumb-branches.s @@ -0,0 +1,20 @@ +@ RUN: llvm-mc < %s -triple thumbv5-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -r | FileCheck %s + + + bl end + .space 0x3fffff +end: + + bl end2 + .space 0x3fffff + .global end2 +end2: + + bl end3 + .space 0x400000 + .global end3 +end3: + +@ CHECK: 0x400003 R_ARM_THM_CALL end2 0x0 +@ CHECK: 0x800006 R_ARM_THM_CALL end3 0x0