[NFC][IR] Make Module::getIFuncList() private.
authorVasileios Porpodas <vporpodas@google.com>
Tue, 7 Feb 2023 03:43:13 +0000 (19:43 -0800)
committerVasileios Porpodas <vporpodas@google.com>
Tue, 14 Feb 2023 17:28:06 +0000 (09:28 -0800)
This patch adds several missing IFuncList modifier functions, like
removeIFunc(), eraseIFunc() and insertIFunc().
There is no longer need to access the list directly so it also makes
getIFuncList() private.

Differential Revision: https://reviews.llvm.org/D143968

llvm/include/llvm/IR/Module.h
llvm/lib/AsmParser/LLParser.cpp
llvm/lib/IR/Globals.cpp
llvm/unittests/IR/ModuleTest.cpp

index 920729f..200f39b 100644 (file)
@@ -572,6 +572,15 @@ public:
   // 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; }
@@ -592,7 +601,9 @@ public:
   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.
index 2db5e7d..580fc3e 100644 (file)
@@ -1143,7 +1143,7 @@ bool LLParser::parseAliasOrIFunc(const std::string &Name, LocTy NameLoc,
   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;
index 7cf812c..667f591 100644 (file)
@@ -575,7 +575,7 @@ GlobalIFunc::GlobalIFunc(Type *Ty, unsigned AddressSpace, LinkageTypes Link,
                    AddressSpace) {
   setResolver(Resolver);
   if (ParentModule)
-    ParentModule->getIFuncList().push_back(this);
+    ParentModule->insertIFunc(this);
 }
 
 GlobalIFunc *GlobalIFunc::create(Type *Ty, unsigned AddressSpace,
@@ -584,13 +584,9 @@ 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());
index f9d682d..8b675ba 100644 (file)
@@ -199,4 +199,44 @@ declare void @Foo()
   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