Index: lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -729,6 +729,10 @@ // linker can handle it. GNU AS produces an error in this case. if (Sym->isExternal() || Value >= 0x400004) IsResolved = false; + // When an ARM function is called from a Thumb function, produce a + // relocation so the linker will use the correct branch instruction. + if (!Asm.isThumbFunc(Sym)) + IsResolved = false; } // 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 Index: test/MC/ARM/big-endian-thumb-fixup.s =================================================================== --- test/MC/ARM/big-endian-thumb-fixup.s +++ test/MC/ARM/big-endian-thumb-fixup.s @@ -4,6 +4,7 @@ .text .align 2 .code 16 + .thumb_func @ARM::fixup_arm_thumb_bl .section s_thumb_bl,"ax",%progbits Index: test/MC/ARM/mixed-arm-thumb-bl-fixup.s =================================================================== --- /dev/null +++ test/MC/ARM/mixed-arm-thumb-bl-fixup.s @@ -0,0 +1,47 @@ +@ RUN: llvm-mc < %s -triple armv7-linux-gnueabi -filetype=obj -o - \ +@ RUN: | llvm-readobj -r | FileCheck %s + + .code 16 + .thumb_func +thumb_caller: + bl internal_arm_fn + bl global_arm_fn + bl internal_thumb_fn + bl global_thumb_fn + + .globl arm_caller + .code 32 +arm_caller: + bl internal_arm_fn + bl global_arm_fn + bl internal_thumb_fn + bl global_thumb_fn + + .code 32 +internal_arm_fn: + bx lr + + .globl global_arm_fn + .type global_arm_fn,%function + .code 32 +global_arm_fn: + bx lr + + .code 16 + .thumb_func +internal_thumb_fn: + bx lr + + .globl global_thumb_fn + .code 16 + .thumb_func +global_thumb_fn: + bx lr + +@ CHECK: 0x0 R_ARM_THM_CALL internal_arm_fn 0x0 +@ CHECK: 0x4 R_ARM_THM_CALL global_arm_fn 0x0 +@ CHECK: 0xC R_ARM_THM_CALL global_thumb_fn 0x0 +@ CHECK: 0x10 R_ARM_CALL internal_arm_fn 0x0 +@ CHECK: 0x14 R_ARM_CALL global_arm_fn 0x0 +@ CHECK: 0x18 R_ARM_CALL internal_thumb_fn 0x0 +@ CHECK: 0x1C R_ARM_CALL global_thumb_fn 0x0 Index: test/MC/ARM/thumb-far-jump.s =================================================================== --- test/MC/ARM/thumb-far-jump.s +++ test/MC/ARM/thumb-far-jump.s @@ -22,5 +22,5 @@ main2: bx lr -@ CHECK-NOT: 0x0 R_ARM_THM_CALL end 0x0 +@ CHECK: 0x0 R_ARM_THM_CALL end 0x0 @ CHECK: 0x2004 R_ARM_THM_CALL main2 0x0