diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -2356,12 +2356,14 @@ } else if (Subtarget->isTargetCOFF()) { assert(Subtarget->isTargetWindows() && "Windows is the only supported COFF target"); - unsigned TargetFlags = GV->hasDLLImportStorageClass() - ? ARMII::MO_DLLIMPORT - : ARMII::MO_NO_FLAG; + unsigned TargetFlags = ARMII::MO_NO_FLAG; + if (GV->hasDLLImportStorageClass()) + TargetFlags = ARMII::MO_DLLIMPORT; + else if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) + TargetFlags = ARMII::MO_COFFSTUB; Callee = DAG.getTargetGlobalAddress(GV, dl, PtrVt, /*offset=*/0, TargetFlags); - if (GV->hasDLLImportStorageClass()) + if (TargetFlags & (ARMII::MO_DLLIMPORT | ARMII::MO_COFFSTUB)) Callee = DAG.getLoad(PtrVt, dl, DAG.getEntryNode(), DAG.getNode(ARMISD::Wrapper, dl, PtrVt, Callee), diff --git a/llvm/test/CodeGen/ARM/tail-call-weak.ll b/llvm/test/CodeGen/ARM/tail-call-weak.ll --- a/llvm/test/CodeGen/ARM/tail-call-weak.ll +++ b/llvm/test/CodeGen/ARM/tail-call-weak.ll @@ -5,14 +5,17 @@ declare i8* @f() declare extern_weak i8* @g(i8*) -; weak symbol resolution occurs statically in PE/COFF, ensure that we permit -; tail calls on weak externals when targeting a COFF environment. define void @test() { %call = tail call i8* @f() %call1 = tail call i8* @g(i8* %call) ret void } -; CHECK-COFF: b g +; CHECK-COFF: movw r0, :lower16:.refptr.g +; CHECK-COFF: movt r0, :upper16:.refptr.g +; CHECK-COFF: ldr r4, [r0] +; CHECK-COFF: mov r1, r4 +; CHECK-COFF: bx r1 + ; CHECK-OTHER: bl {{_?}}g