diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -767,6 +767,8 @@ return false; bool IsDirect = Func != nullptr; + if (TLI.isPositionIndependent() && Func && Func->isInterposable()) + IsDirect = false; if (!IsDirect && isa(Call->getCalledOperand())) return false; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -1077,13 +1077,18 @@ } if (Callee->getOpcode() == ISD::GlobalAddress) { - // If the callee is a GlobalAddress node (quite common, every direct call - // is) turn it into a TargetGlobalAddress node so that LowerGlobalAddress - // doesn't at MO_GOT which is not needed for direct calls. GlobalAddressSDNode* GA = cast(Callee); - Callee = DAG.getTargetGlobalAddress(GA->getGlobal(), DL, - getPointerTy(DAG.getDataLayout()), - GA->getOffset()); + // llvm::dbgs() << "LowerCall: " << GA->getGlobal()->getName() << "\n"; + if (!isPositionIndependent() || !GA->getGlobal()->isInterposable()) { + // llvm::dbgs() << "is decl\n"; + // If the callee is a GlobalAddress node (quite common, every direct call + // is) turn it into a TargetGlobalAddress node so that LowerGlobalAddress + // doesn't add MO_GOT which is not needed for direct calls (to + // non-interposable functions); + Callee = DAG.getTargetGlobalAddress(GA->getGlobal(), DL, + getPointerTy(DAG.getDataLayout()), + GA->getOffset()); + } Callee = DAG.getNode(WebAssemblyISD::Wrapper, DL, getPointerTy(DAG.getDataLayout()), Callee); } @@ -1577,7 +1582,10 @@ unsigned OperandFlags = 0; if (isPositionIndependent()) { const GlobalValue *GV = GA->getGlobal(); - if (getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV)) { + // llvm::dbgs() << "LowerGlobalAddress: " << GV->getName() << "\n"; + if (getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV) && + !GV->isInterposable()) { + // llvm::dbgs() << "DSO local\n"; MachineFunction &MF = DAG.getMachineFunction(); MVT PtrVT = getPointerTy(MF.getDataLayout()); const char *BaseName; @@ -1600,6 +1608,7 @@ return DAG.getNode(ISD::ADD, DL, VT, BaseAddr, SymAddr); } else { + // llvm::dbgs() << "not DSO local\n"; OperandFlags = WebAssemblyII::MO_GOT; } } diff --git a/llvm/test/CodeGen/WebAssembly/call-pic.ll b/llvm/test/CodeGen/WebAssembly/call-pic.ll --- a/llvm/test/CodeGen/WebAssembly/call-pic.ll +++ b/llvm/test/CodeGen/WebAssembly/call-pic.ll @@ -9,7 +9,7 @@ @indirect_func = hidden global i32 ()* @foo @alias_func = hidden alias i32 (), i32 ()* @local_function -define i32 @local_function() { +define hidden i32 @local_function() { ret i32 1 }