Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Move-assignment for llvm::Module (NFC) #117270

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

joker-eph
Copy link
Collaborator

Move-assignment is quite convenient in various situation, and work-around having it available is very convoluted.

@llvmbot
Copy link
Member

llvmbot commented Nov 22, 2024

@llvm/pr-subscribers-llvm-ir

Author: Mehdi Amini (joker-eph)

Changes

Move-assignment is quite convenient in various situation, and work-around having it available is very convoluted.


Full diff: https://github.com/llvm/llvm-project/pull/117270.diff

3 Files Affected:

  • (modified) llvm/include/llvm/IR/Module.h (+6-3)
  • (modified) llvm/lib/IR/Module.cpp (+36)
  • (modified) llvm/unittests/IR/ModuleTest.cpp (+78)
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index 528e19af5518df..12b50fc506516e 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -256,9 +256,12 @@ class LLVM_ABI Module {
   /// The module destructor. This will dropAllReferences.
   ~Module();
 
-/// @}
-/// @name Module Level Accessors
-/// @{
+  /// Move assignment.
+  Module &operator=(Module &&Other);
+
+  /// @}
+  /// @name Module Level Accessors
+  /// @{
 
   /// Get the module identifier which is, essentially, the name of the module.
   /// @returns the module identifier as a string
diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp
index ab48d3e4101b72..57946f21ed97e1 100644
--- a/llvm/lib/IR/Module.cpp
+++ b/llvm/lib/IR/Module.cpp
@@ -78,6 +78,42 @@ Module::Module(StringRef MID, LLVMContext &C)
   Context.addModule(this);
 }
 
+Module &Module::operator=(Module &&Other) {
+  assert(&Context == &Other.Context && "Module must be in the same Context");
+
+  dropAllReferences();
+  
+
+  ModuleID = std::move(Other.ModuleID);
+  SourceFileName = std::move(Other.SourceFileName);
+  IsNewDbgInfoFormat = std::move(Other.IsNewDbgInfoFormat);
+
+  GlobalList.clear();
+  GlobalList.splice(GlobalList.begin(), Other.GlobalList);
+
+  FunctionList.clear();
+  FunctionList.splice(FunctionList.begin(), Other.FunctionList);
+
+  AliasList.clear();
+  AliasList.splice(AliasList.begin(), Other.AliasList);
+
+  IFuncList.clear();
+  IFuncList.splice(IFuncList.begin(), Other.IFuncList);
+
+  NamedMDList.clear();
+  NamedMDList.splice(NamedMDList.begin(), Other.NamedMDList);
+  GlobalScopeAsm = std::move(Other.GlobalScopeAsm);
+  OwnedMemoryBuffer = std::move(Other.OwnedMemoryBuffer);
+  Materializer = std::move(Other.Materializer);
+  TargetTriple = std::move(Other.TargetTriple);
+  DL = std::move(Other.DL);
+  CurrentIntrinsicIds = std::move(Other.CurrentIntrinsicIds);
+  UniquedIntrinsicNames = std::move(Other.UniquedIntrinsicNames);
+  ModuleFlags = std::move(Other.ModuleFlags);
+  Context.addModule(this);
+  return *this;
+}
+
 Module::~Module() {
   Context.removeModule(this);
   dropAllReferences();
diff --git a/llvm/unittests/IR/ModuleTest.cpp b/llvm/unittests/IR/ModuleTest.cpp
index c18301d5e6d758..5735c6cfe6e4d0 100644
--- a/llvm/unittests/IR/ModuleTest.cpp
+++ b/llvm/unittests/IR/ModuleTest.cpp
@@ -14,6 +14,7 @@
 #include "llvm/Pass.h"
 #include "llvm/Support/RandomNumberGenerator.h"
 #include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/raw_ostream.h"
 #include "gtest/gtest.h"
 
 #include <random>
@@ -326,4 +327,81 @@ TEST(ModuleTest, GlobalList) {
   EXPECT_EQ(M->global_size(), 1u);
 }
 
+TEST(ModuleTest, MoveAssign) {
+  // This tests that we can move-assign modules, we parse two modules and
+  // move assign the second one to the first one, and check that the print
+  // is equal to what we loaded.
+  LLVMContext C;
+  SMDiagnostic Err;
+  LLVMContext Context;
+  std::unique_ptr<Module> M1 = parseAssemblyString(R"(
+; ModuleID = '<string>'
+source_filename = "<string1>"
+
+@GV1 = external global i32
+
+@GA1 = alias void (), ptr @Foo1
+
+define void @Foo1() {
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+!llvm.dbg.cu = !{!1}
+!foo1 = !{!3}
+!bar1 = !{!4}
+
+!0 = !{i32 2, !"Debug Info Version", i32 3}
+!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang1", isOptimized: true, flags: "-O2", runtimeVersion: 0, splitDebugFilename: "abc.debug", emissionKind: LineTablesOnly)
+!2 = !DIFile(filename: "path/to/file1", directory: "/path/to/dir1")
+!3 = !DILocation(line: 12, column: 34, scope: !4)
+!4 = distinct !DISubprogram(name: "foo1", scope: null, spFlags: DISPFlagDefinition, unit: !1)
+)",
+                                                Err, Context);
+  ASSERT_TRUE(M1.get());
+
+  StringLiteral M2Str = R"(
+; ModuleID = '<string>'
+source_filename = "<string2>"
+
+@GV2 = external global i32
+
+@GA2 = alias void (), ptr @Foo2
+
+define void @Foo2() {
+  ret void
+}
+
+!llvm.module.flags = !{!0}
+!llvm.dbg.cu = !{!1}
+!foo2 = !{!3}
+!bar2 = !{!4}
+
+!0 = !{i32 2, !"Debug Info Version", i32 3}
+!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang2", isOptimized: true, flags: "-O2", runtimeVersion: 0, splitDebugFilename: "abc.debug", emissionKind: LineTablesOnly)
+!2 = !DIFile(filename: "path/to/file2", directory: "/path/to/dir2")
+!3 = !DILocation(line: 1234, column: 56, scope: !4)
+!4 = distinct !DISubprogram(name: "foo2", scope: null, spFlags: DISPFlagDefinition, unit: !1)
+)";
+  {
+    std::unique_ptr<Module> M2 = parseAssemblyString(M2Str,
+                                                Err, Context);
+    ASSERT_TRUE(M2.get());
+    auto *GV1 = M1->getNamedValue("GV1");
+    ASSERT_TRUE(GV1);
+    auto *GV2 = M2->getNamedValue("GV2");
+    ASSERT_TRUE(GV2);
+    ASSERT_EQ(GV2->getParent(), &*M2);
+    *M1 = std::move(*M2);
+    ASSERT_EQ(GV2->getParent(), &*M1);
+  }
+   
+  std::string M1Print;
+  {
+    llvm::raw_string_ostream Os(M1Print);
+    Os << "\n" << *M1;
+  }
+  ASSERT_EQ(M2Str, M1Print);
+}
+
 } // end namespace

Copy link

github-actions bot commented Nov 22, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Move-assignment is quite convenient in various situation, and work-around
having it available is very convoluted.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants