// Use alias_size() to get the size of AliasList.
// Use aliases() to get a range of all Alias objects in AliasList.
+ /// Detach \p IFunc from the list but don't delete it.
+ void removeIFunc(GlobalIFunc *IFunc) { IFuncList.remove(IFunc); }
+ /// Remove \p IFunc from the list and delete it.
+ void eraseIFunc(GlobalIFunc *IFunc) { IFuncList.erase(IFunc); }
+ /// Insert \p IFunc at the end of the alias list and take ownership.
+ void insertIFunc(GlobalIFunc *IFunc) { IFuncList.push_back(IFunc); }
+ // Use ifunc_size() to get the number of functions in IFuncList.
+ // Use ifuncs() to get the range of all IFuncs.
+
private: // Please use functions like insertAlias(), removeAlias() etc.
/// Get the Module's list of aliases (constant).
const AliasListType &getAliasList() const { return AliasList; }
static IFuncListType Module::*getSublistAccess(GlobalIFunc*) {
return &Module::IFuncList;
}
+ friend class llvm::SymbolTableListTraits<llvm::GlobalIFunc>;
+public:
/// Get the Module's list of named metadata (constant).
const NamedMDListType &getNamedMDList() const { return NamedMDList; }
/// Get the Module's list of named metadata.
if (IsAlias)
M->insertAlias(GA.release());
else
- M->getIFuncList().push_back(GI.release());
+ M->insertIFunc(GI.release());
assert(GV->getName() == Name && "Should not be a name conflict!");
return false;
AddressSpace) {
setResolver(Resolver);
if (ParentModule)
- ParentModule->getIFuncList().push_back(this);
+ ParentModule->insertIFunc(this);
}
GlobalIFunc *GlobalIFunc::create(Type *Ty, unsigned AddressSpace,
return new GlobalIFunc(Ty, AddressSpace, Link, Name, Resolver, ParentModule);
}
-void GlobalIFunc::removeFromParent() {
- getParent()->getIFuncList().remove(getIterator());
-}
+void GlobalIFunc::removeFromParent() { getParent()->removeIFunc(this); }
-void GlobalIFunc::eraseFromParent() {
- getParent()->getIFuncList().erase(getIterator());
-}
+void GlobalIFunc::eraseFromParent() { getParent()->eraseIFunc(this); }
const Function *GlobalIFunc::getResolverFunction() const {
return dyn_cast<Function>(getResolver()->stripPointerCastsAndAliases());
EXPECT_EQ(M->alias_size(), 1u);
}
+TEST(ModuleTest, IFuncList) {
+ // This tests all Module's functions that interact with Module::IFuncList.
+ LLVMContext C;
+ SMDiagnostic Err;
+ LLVMContext Context;
+ std::unique_ptr<Module> M = parseAssemblyString(R"(
+declare void @Foo()
+@GIF = ifunc void (), ptr @Foo
+)",
+ Err, Context);
+ Function *Foo = M->getFunction("Foo");
+ auto *GIF = M->getNamedIFunc("GIF");
+ EXPECT_EQ(M->ifunc_size(), 1u);
+ auto *NewGIF =
+ GlobalIFunc::create(Foo->getType(), 0, GlobalValue::ExternalLinkage,
+ "NewGIF", Foo, /*Parent=*/nullptr);
+ EXPECT_EQ(M->ifunc_size(), 1u);
+
+ M->insertIFunc(NewGIF);
+ EXPECT_EQ(&*std::prev(M->ifuncs().end()), NewGIF);
+
+ M->removeIFunc(NewGIF);
+ EXPECT_EQ(M->ifunc_size(), 1u);
+ M->insertIFunc(NewGIF);
+ EXPECT_EQ(M->ifunc_size(), 2u);
+ EXPECT_EQ(&*std::prev(M->ifuncs().end()), NewGIF);
+
+ auto Range = M->ifuncs();
+ EXPECT_EQ(&*Range.begin(), GIF);
+ EXPECT_EQ(&*std::next(Range.begin()), NewGIF);
+ EXPECT_EQ(std::next(Range.begin(), 2), Range.end());
+
+ M->removeIFunc(NewGIF);
+ EXPECT_EQ(M->ifunc_size(), 1u);
+
+ M->insertIFunc(NewGIF);
+ M->eraseIFunc(NewGIF);
+ EXPECT_EQ(M->ifunc_size(), 1u);
+}
+
} // end namespace