Index: llvm/lib/Transforms/Utils/CloneModule.cpp =================================================================== --- llvm/lib/Transforms/Utils/CloneModule.cpp +++ llvm/lib/Transforms/Utils/CloneModule.cpp @@ -109,6 +109,15 @@ VMap[&I] = GA; } + for (const GlobalIFunc &I : M.ifuncs()) { + // Defer setting the resolver function until after functions are cloned. + auto *GI = + GlobalIFunc::create(I.getValueType(), I.getAddressSpace(), + I.getLinkage(), I.getName(), nullptr, New.get()); + GI->copyAttributesFrom(&I); + VMap[&I] = GI; + } + // Now that all of the things that global variable initializer can refer to // have been created, loop through and copy the global variable referrers // over... We also set the attributes on the global now. @@ -184,6 +193,12 @@ GA->setAliasee(MapValue(C, VMap)); } + for (const GlobalIFunc &I : M.ifuncs()) { + GlobalIFunc *GI = cast(VMap[&I]); + if (const Constant *Resolver = I.getResolver()) + GI->setResolver(MapValue(Resolver, VMap)); + } + // And named metadata.... for (const NamedMDNode &NMD : M.named_metadata()) { NamedMDNode *NewNMD = New->getOrInsertNamedMetadata(NMD.getName()); Index: llvm/unittests/Transforms/Utils/CloningTest.cpp =================================================================== --- llvm/unittests/Transforms/Utils/CloningTest.cpp +++ llvm/unittests/Transforms/Utils/CloningTest.cpp @@ -922,6 +922,23 @@ GV->addMetadata(LLVMContext::MD_type, *MDNode::get(C, {})); GV->setComdat(CD); + // Add ifuncs + { + const unsigned AddrSpace = 123; + auto *FuncPtrTy = Type::getInt8Ty(C)->getPointerTo(123); + auto *FuncTy = FunctionType::get(FuncPtrTy, false); + + auto *ResolverF = Function::Create(FuncTy, GlobalValue::PrivateLinkage, + AddrSpace, "resolver", OldM); + BasicBlock *ResolverBody = BasicBlock::Create(C, "", ResolverF); + ReturnInst::Create(C, ConstantPointerNull::get(FuncPtrTy), ResolverBody); + + GlobalIFunc *GI = GlobalIFunc::create(FuncTy, AddrSpace, + GlobalValue::LinkOnceODRLinkage, + "an_ifunc", ResolverF, OldM); + GI->setVisibility(GlobalValue::ProtectedVisibility); + } + { // Add an empty compile unit first that isn't otherwise referenced, to // confirm that compile units get cloned in the correct order. @@ -1087,4 +1104,19 @@ Function *NewF = NewM->getFunction("f"); EXPECT_EQ(CD, NewF->getComdat()); } + +TEST_F(CloneModule, IFunc) { + ASSERT_EQ(1u, NewM->ifunc_size()); + + const GlobalIFunc &IFunc = *NewM->ifunc_begin(); + EXPECT_EQ("an_ifunc", IFunc.getName()); + EXPECT_EQ(GlobalValue::LinkOnceODRLinkage, IFunc.getLinkage()); + EXPECT_EQ(GlobalValue::ProtectedVisibility, IFunc.getVisibility()); + EXPECT_EQ(123u, IFunc.getAddressSpace()); + + const Function *Resolver = IFunc.getResolverFunction(); + ASSERT_NE(nullptr, Resolver); + EXPECT_EQ("resolver", Resolver->getName()); + EXPECT_EQ(GlobalValue::PrivateLinkage, Resolver->getLinkage()); +} }