diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 7db700472cb..698487980c3 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -565,11 +565,18 @@ void ARMAsmBackend::processFixupValue(const MCAssembler &Asm, 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().AliasedSymbol(); + MCSymbolData &SymData = Asm.getSymbolData(Sym); + IsResolved = (SymData.getFragment() == DF); + } // 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 // symbol's thumb-ness to get interworking right. if (A && ((unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_blx || - (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl || (unsigned)Fixup.getKind() == ARM::fixup_arm_blx || (unsigned)Fixup.getKind() == ARM::fixup_arm_uncondbl || (unsigned)Fixup.getKind() == ARM::fixup_arm_condbl)) diff --git a/test/MC/ARM/thumb-far-jump.s b/test/MC/ARM/thumb-far-jump.s new file mode 100644 index 00000000000..2fd2c567d13 --- /dev/null +++ b/test/MC/ARM/thumb-far-jump.s @@ -0,0 +1,26 @@ +@ RUN: llvm-mc < %s -triple thumbv5-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -r | FileCheck %s + .syntax unified + + .text + .align 2 + .globl main + .type main,%function + .thumb_func +main: + bl end + .space 8192 +end: + bl main2 + bx lr + + .text + .align 2 + .globl main2 + .type main2,%function + .thumb_func +main2: + bx lr + +@ CHECK-NOT: 0x0 R_ARM_THM_CALL end 0x0 +@ CHECK: 0x2004 R_ARM_THM_CALL main2 0x0