[llvm] 491375c - [SandboxIR][NFC] Move BasicBlock class into a separate file (#110194)

via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 27 09:21:45 PDT 2024


Author: vporpo
Date: 2024-09-27T09:21:42-07:00
New Revision: 491375cc4eb24adba66b0f8af3f0dd52530f7554

URL: https://github.com/llvm/llvm-project/commit/491375cc4eb24adba66b0f8af3f0dd52530f7554
DIFF: https://github.com/llvm/llvm-project/commit/491375cc4eb24adba66b0f8af3f0dd52530f7554.diff

LOG: [SandboxIR][NFC] Move BasicBlock class into a separate file (#110194)

Added: 
    llvm/include/llvm/SandboxIR/BasicBlock.h
    llvm/lib/SandboxIR/BasicBlock.cpp

Modified: 
    llvm/include/llvm/SandboxIR/SandboxIR.h
    llvm/lib/SandboxIR/CMakeLists.txt
    llvm/lib/SandboxIR/Constant.cpp
    llvm/lib/SandboxIR/SandboxIR.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/SandboxIR/BasicBlock.h b/llvm/include/llvm/SandboxIR/BasicBlock.h
new file mode 100644
index 00000000000000..93e79e2a421f96
--- /dev/null
+++ b/llvm/include/llvm/SandboxIR/BasicBlock.h
@@ -0,0 +1,112 @@
+//===- BasicBlock.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SANDBOXIR_BASICBLOCK_H
+#define LLVM_SANDBOXIR_BASICBLOCK_H
+
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/SandboxIR/Value.h"
+
+namespace llvm::sandboxir {
+
+class BasicBlock;
+class Function;
+class Instruction;
+
+/// Iterator for `Instruction`s in a `BasicBlock.
+/// \Returns an sandboxir::Instruction & when derereferenced.
+class BBIterator {
+public:
+  using 
diff erence_type = std::ptr
diff _t;
+  using value_type = Instruction;
+  using pointer = value_type *;
+  using reference = value_type &;
+  using iterator_category = std::bidirectional_iterator_tag;
+
+private:
+  llvm::BasicBlock *BB;
+  llvm::BasicBlock::iterator It;
+  Context *Ctx;
+  pointer getInstr(llvm::BasicBlock::iterator It) const;
+
+public:
+  BBIterator() : BB(nullptr), Ctx(nullptr) {}
+  BBIterator(llvm::BasicBlock *BB, llvm::BasicBlock::iterator It, Context *Ctx)
+      : BB(BB), It(It), Ctx(Ctx) {}
+  reference operator*() const { return *getInstr(It); }
+  BBIterator &operator++();
+  BBIterator operator++(int) {
+    auto Copy = *this;
+    ++*this;
+    return Copy;
+  }
+  BBIterator &operator--();
+  BBIterator operator--(int) {
+    auto Copy = *this;
+    --*this;
+    return Copy;
+  }
+  bool operator==(const BBIterator &Other) const {
+    assert(Ctx == Other.Ctx && "BBIterators in 
diff erent context!");
+    return It == Other.It;
+  }
+  bool operator!=(const BBIterator &Other) const { return !(*this == Other); }
+  /// \Returns the SBInstruction that corresponds to this iterator, or null if
+  /// the instruction is not found in the IR-to-SandboxIR tables.
+  pointer get() const { return getInstr(It); }
+  /// \Returns the parent BB.
+  BasicBlock *getNodeParent() const;
+};
+
+/// Contains a list of sandboxir::Instruction's.
+class BasicBlock : public Value {
+  /// Builds a graph that contains all values in \p BB in their original form
+  /// i.e., no vectorization is taking place here.
+  void buildBasicBlockFromLLVMIR(llvm::BasicBlock *LLVMBB);
+  friend class Context;     // For `buildBasicBlockFromIR`
+  friend class Instruction; // For LLVM Val.
+
+  BasicBlock(llvm::BasicBlock *BB, Context &SBCtx)
+      : Value(ClassID::Block, BB, SBCtx) {
+    buildBasicBlockFromLLVMIR(BB);
+  }
+
+public:
+  ~BasicBlock() = default;
+  /// For isa/dyn_cast.
+  static bool classof(const Value *From) {
+    return From->getSubclassID() == Value::ClassID::Block;
+  }
+  Function *getParent() const;
+  using iterator = BBIterator;
+  iterator begin() const;
+  iterator end() const {
+    auto *BB = cast<llvm::BasicBlock>(Val);
+    return iterator(BB, BB->end(), &Ctx);
+  }
+  std::reverse_iterator<iterator> rbegin() const {
+    return std::make_reverse_iterator(end());
+  }
+  std::reverse_iterator<iterator> rend() const {
+    return std::make_reverse_iterator(begin());
+  }
+  Context &getContext() const { return Ctx; }
+  Instruction *getTerminator() const;
+  bool empty() const { return begin() == end(); }
+  Instruction &front() const;
+  Instruction &back() const;
+
+#ifndef NDEBUG
+  void verify() const final;
+  void dumpOS(raw_ostream &OS) const final;
+#endif
+};
+
+} // namespace llvm::sandboxir
+
+#endif // LLVM_SANDBOXIR_BASICBLOCK_H

diff  --git a/llvm/include/llvm/SandboxIR/SandboxIR.h b/llvm/include/llvm/SandboxIR/SandboxIR.h
index 02246c303ab614..2376450d190115 100644
--- a/llvm/include/llvm/SandboxIR/SandboxIR.h
+++ b/llvm/include/llvm/SandboxIR/SandboxIR.h
@@ -110,6 +110,7 @@
 #include "llvm/IR/User.h"
 #include "llvm/IR/Value.h"
 #include "llvm/SandboxIR/Argument.h"
+#include "llvm/SandboxIR/BasicBlock.h"
 #include "llvm/SandboxIR/Constant.h"
 #include "llvm/SandboxIR/Context.h"
 #include "llvm/SandboxIR/Module.h"
@@ -191,95 +192,6 @@ class CmpInst;
 class ICmpInst;
 class FCmpInst;
 
-/// Iterator for `Instruction`s in a `BasicBlock.
-/// \Returns an sandboxir::Instruction & when derereferenced.
-class BBIterator {
-public:
-  using 
diff erence_type = std::ptr
diff _t;
-  using value_type = Instruction;
-  using pointer = value_type *;
-  using reference = value_type &;
-  using iterator_category = std::bidirectional_iterator_tag;
-
-private:
-  llvm::BasicBlock *BB;
-  llvm::BasicBlock::iterator It;
-  Context *Ctx;
-  pointer getInstr(llvm::BasicBlock::iterator It) const;
-
-public:
-  BBIterator() : BB(nullptr), Ctx(nullptr) {}
-  BBIterator(llvm::BasicBlock *BB, llvm::BasicBlock::iterator It, Context *Ctx)
-      : BB(BB), It(It), Ctx(Ctx) {}
-  reference operator*() const { return *getInstr(It); }
-  BBIterator &operator++();
-  BBIterator operator++(int) {
-    auto Copy = *this;
-    ++*this;
-    return Copy;
-  }
-  BBIterator &operator--();
-  BBIterator operator--(int) {
-    auto Copy = *this;
-    --*this;
-    return Copy;
-  }
-  bool operator==(const BBIterator &Other) const {
-    assert(Ctx == Other.Ctx && "BBIterators in 
diff erent context!");
-    return It == Other.It;
-  }
-  bool operator!=(const BBIterator &Other) const { return !(*this == Other); }
-  /// \Returns the SBInstruction that corresponds to this iterator, or null if
-  /// the instruction is not found in the IR-to-SandboxIR tables.
-  pointer get() const { return getInstr(It); }
-  /// \Returns the parent BB.
-  BasicBlock *getNodeParent() const;
-};
-
-/// Contains a list of sandboxir::Instruction's.
-class BasicBlock : public Value {
-  /// Builds a graph that contains all values in \p BB in their original form
-  /// i.e., no vectorization is taking place here.
-  void buildBasicBlockFromLLVMIR(llvm::BasicBlock *LLVMBB);
-  friend class Context;     // For `buildBasicBlockFromIR`
-  friend class Instruction; // For LLVM Val.
-
-  BasicBlock(llvm::BasicBlock *BB, Context &SBCtx)
-      : Value(ClassID::Block, BB, SBCtx) {
-    buildBasicBlockFromLLVMIR(BB);
-  }
-
-public:
-  ~BasicBlock() = default;
-  /// For isa/dyn_cast.
-  static bool classof(const Value *From) {
-    return From->getSubclassID() == Value::ClassID::Block;
-  }
-  Function *getParent() const;
-  using iterator = BBIterator;
-  iterator begin() const;
-  iterator end() const {
-    auto *BB = cast<llvm::BasicBlock>(Val);
-    return iterator(BB, BB->end(), &Ctx);
-  }
-  std::reverse_iterator<iterator> rbegin() const {
-    return std::make_reverse_iterator(end());
-  }
-  std::reverse_iterator<iterator> rend() const {
-    return std::make_reverse_iterator(begin());
-  }
-  Context &getContext() const { return Ctx; }
-  Instruction *getTerminator() const;
-  bool empty() const { return begin() == end(); }
-  Instruction &front() const;
-  Instruction &back() const;
-
-#ifndef NDEBUG
-  void verify() const final;
-  void dumpOS(raw_ostream &OS) const final;
-#endif
-};
-
 /// A sandboxir::User with operands, opcode and linked with previous/next
 /// instructions in an instruction list.
 class Instruction : public sandboxir::User {

diff  --git a/llvm/lib/SandboxIR/BasicBlock.cpp b/llvm/lib/SandboxIR/BasicBlock.cpp
new file mode 100644
index 00000000000000..7eba53ffb5ec4a
--- /dev/null
+++ b/llvm/lib/SandboxIR/BasicBlock.cpp
@@ -0,0 +1,163 @@
+//===- BasicBlock.cpp - The BasicBlock class of Sandbox IR ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/SandboxIR/BasicBlock.h"
+#include "llvm/SandboxIR/Context.h"
+#include "llvm/SandboxIR/SandboxIR.h" // TODO: remove this
+
+namespace llvm::sandboxir {
+
+BBIterator &BBIterator::operator++() {
+  auto ItE = BB->end();
+  assert(It != ItE && "Already at end!");
+  ++It;
+  if (It == ItE)
+    return *this;
+  Instruction &NextI = *cast<sandboxir::Instruction>(Ctx->getValue(&*It));
+  unsigned Num = NextI.getNumOfIRInstrs();
+  assert(Num > 0 && "Bad getNumOfIRInstrs()");
+  It = std::next(It, Num - 1);
+  return *this;
+}
+
+BBIterator &BBIterator::operator--() {
+  assert(It != BB->begin() && "Already at begin!");
+  if (It == BB->end()) {
+    --It;
+    return *this;
+  }
+  Instruction &CurrI = **this;
+  unsigned Num = CurrI.getNumOfIRInstrs();
+  assert(Num > 0 && "Bad getNumOfIRInstrs()");
+  assert(std::prev(It, Num - 1) != BB->begin() && "Already at begin!");
+  It = std::prev(It, Num);
+  return *this;
+}
+
+BasicBlock *BBIterator::getNodeParent() const {
+  llvm::BasicBlock *Parent = const_cast<BBIterator *>(this)->It.getNodeParent();
+  return cast<BasicBlock>(Ctx->getValue(Parent));
+}
+
+BasicBlock::iterator::pointer
+BasicBlock::iterator::getInstr(llvm::BasicBlock::iterator It) const {
+  return cast_or_null<Instruction>(Ctx->getValue(&*It));
+}
+
+Function *BasicBlock::getParent() const {
+  auto *BB = cast<llvm::BasicBlock>(Val);
+  auto *F = BB->getParent();
+  if (F == nullptr)
+    // Detached
+    return nullptr;
+  return cast_or_null<Function>(Ctx.getValue(F));
+}
+
+void BasicBlock::buildBasicBlockFromLLVMIR(llvm::BasicBlock *LLVMBB) {
+  for (llvm::Instruction &IRef : reverse(*LLVMBB)) {
+    llvm::Instruction *I = &IRef;
+    Ctx.getOrCreateValue(I);
+    for (auto [OpIdx, Op] : enumerate(I->operands())) {
+      // Skip instruction's label operands
+      if (isa<llvm::BasicBlock>(Op))
+        continue;
+      // Skip metadata
+      if (isa<llvm::MetadataAsValue>(Op))
+        continue;
+      // Skip asm
+      if (isa<llvm::InlineAsm>(Op))
+        continue;
+      Ctx.getOrCreateValue(Op);
+    }
+  }
+#if !defined(NDEBUG)
+  verify();
+#endif
+}
+
+BasicBlock::iterator BasicBlock::begin() const {
+  llvm::BasicBlock *BB = cast<llvm::BasicBlock>(Val);
+  llvm::BasicBlock::iterator It = BB->begin();
+  if (!BB->empty()) {
+    auto *V = Ctx.getValue(&*BB->begin());
+    assert(V != nullptr && "No SandboxIR for BB->begin()!");
+    auto *I = cast<Instruction>(V);
+    unsigned Num = I->getNumOfIRInstrs();
+    assert(Num >= 1u && "Bad getNumOfIRInstrs()");
+    It = std::next(It, Num - 1);
+  }
+  return iterator(BB, It, &Ctx);
+}
+
+Instruction *BasicBlock::getTerminator() const {
+  auto *TerminatorV =
+      Ctx.getValue(cast<llvm::BasicBlock>(Val)->getTerminator());
+  return cast_or_null<Instruction>(TerminatorV);
+}
+
+Instruction &BasicBlock::front() const {
+  auto *BB = cast<llvm::BasicBlock>(Val);
+  assert(!BB->empty() && "Empty block!");
+  auto *SBI = cast<Instruction>(getContext().getValue(&*BB->begin()));
+  assert(SBI != nullptr && "Expected Instr!");
+  return *SBI;
+}
+
+Instruction &BasicBlock::back() const {
+  auto *BB = cast<llvm::BasicBlock>(Val);
+  assert(!BB->empty() && "Empty block!");
+  auto *SBI = cast<Instruction>(getContext().getValue(&*BB->rbegin()));
+  assert(SBI != nullptr && "Expected Instr!");
+  return *SBI;
+}
+
+#ifndef NDEBUG
+void BasicBlock::dumpOS(raw_ostream &OS) const {
+  llvm::BasicBlock *BB = cast<llvm::BasicBlock>(Val);
+  const auto &Name = BB->getName();
+  OS << Name;
+  if (!Name.empty())
+    OS << ":\n";
+  // If there are Instructions in the BB that are not mapped to SandboxIR, then
+  // use a crash-proof dump.
+  if (any_of(*BB, [this](llvm::Instruction &I) {
+        return Ctx.getValue(&I) == nullptr;
+      })) {
+    OS << "<Crash-proof mode!>\n";
+    DenseSet<Instruction *> Visited;
+    for (llvm::Instruction &IRef : *BB) {
+      Value *SBV = Ctx.getValue(&IRef);
+      if (SBV == nullptr)
+        OS << IRef << " *** No SandboxIR ***\n";
+      else {
+        auto *SBI = dyn_cast<Instruction>(SBV);
+        if (SBI == nullptr) {
+          OS << IRef << " *** Not a SBInstruction!!! ***\n";
+        } else {
+          if (Visited.insert(SBI).second)
+            OS << *SBI << "\n";
+        }
+      }
+    }
+  } else {
+    for (auto &SBI : *this) {
+      SBI.dumpOS(OS);
+      OS << "\n";
+    }
+  }
+}
+
+void BasicBlock::verify() const {
+  assert(isa<llvm::BasicBlock>(Val) && "Expected BasicBlock!");
+  for (const auto &I : *this) {
+    I.verify();
+  }
+}
+#endif // NDEBUG
+
+} // namespace llvm::sandboxir

diff  --git a/llvm/lib/SandboxIR/CMakeLists.txt b/llvm/lib/SandboxIR/CMakeLists.txt
index 50374de59761e2..deea86d442d395 100644
--- a/llvm/lib/SandboxIR/CMakeLists.txt
+++ b/llvm/lib/SandboxIR/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_llvm_component_library(LLVMSandboxIR
   Argument.cpp
+  BasicBlock.cpp
   Constant.cpp
   Context.cpp
   Module.cpp

diff  --git a/llvm/lib/SandboxIR/Constant.cpp b/llvm/lib/SandboxIR/Constant.cpp
index 83b33f72f19d40..6f1eb1e74347d9 100644
--- a/llvm/lib/SandboxIR/Constant.cpp
+++ b/llvm/lib/SandboxIR/Constant.cpp
@@ -7,8 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/SandboxIR/Constant.h"
+#include "llvm/SandboxIR/Argument.h"
+#include "llvm/SandboxIR/BasicBlock.h"
 #include "llvm/SandboxIR/Context.h"
-#include "llvm/SandboxIR/SandboxIR.h" // TODO: Try to remove this
 
 namespace llvm::sandboxir {
 

diff  --git a/llvm/lib/SandboxIR/SandboxIR.cpp b/llvm/lib/SandboxIR/SandboxIR.cpp
index 42df9df8119733..5baeffef32e5e5 100644
--- a/llvm/lib/SandboxIR/SandboxIR.cpp
+++ b/llvm/lib/SandboxIR/SandboxIR.cpp
@@ -11,6 +11,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/SandboxIR/Argument.h"
+#include "llvm/SandboxIR/BasicBlock.h"
 #include "llvm/Support/Debug.h"
 #include <sstream>
 
@@ -106,38 +107,6 @@ int OperandUseIterator::operator-(const OperandUseIterator &Other) const {
   return ThisOpNo - OtherOpNo;
 }
 
-BBIterator &BBIterator::operator++() {
-  auto ItE = BB->end();
-  assert(It != ItE && "Already at end!");
-  ++It;
-  if (It == ItE)
-    return *this;
-  Instruction &NextI = *cast<sandboxir::Instruction>(Ctx->getValue(&*It));
-  unsigned Num = NextI.getNumOfIRInstrs();
-  assert(Num > 0 && "Bad getNumOfIRInstrs()");
-  It = std::next(It, Num - 1);
-  return *this;
-}
-
-BBIterator &BBIterator::operator--() {
-  assert(It != BB->begin() && "Already at begin!");
-  if (It == BB->end()) {
-    --It;
-    return *this;
-  }
-  Instruction &CurrI = **this;
-  unsigned Num = CurrI.getNumOfIRInstrs();
-  assert(Num > 0 && "Bad getNumOfIRInstrs()");
-  assert(std::prev(It, Num - 1) != BB->begin() && "Already at begin!");
-  It = std::prev(It, Num);
-  return *this;
-}
-
-BasicBlock *BBIterator::getNodeParent() const {
-  llvm::BasicBlock *Parent = const_cast<BBIterator *>(this)->It.getNodeParent();
-  return cast<BasicBlock>(Ctx->getValue(Parent));
-}
-
 const char *Instruction::getOpcodeName(Opcode Opc) {
   switch (Opc) {
 #define OP(OPC)                                                                \
@@ -2089,120 +2058,3 @@ ConstantTokenNone *ConstantTokenNone::get(Context &Ctx) {
   auto *LLVMC = llvm::ConstantTokenNone::get(Ctx.LLVMCtx);
   return cast<ConstantTokenNone>(Ctx.getOrCreateConstant(LLVMC));
 }
-
-BasicBlock::iterator::pointer
-BasicBlock::iterator::getInstr(llvm::BasicBlock::iterator It) const {
-  return cast_or_null<Instruction>(Ctx->getValue(&*It));
-}
-
-Function *BasicBlock::getParent() const {
-  auto *BB = cast<llvm::BasicBlock>(Val);
-  auto *F = BB->getParent();
-  if (F == nullptr)
-    // Detached
-    return nullptr;
-  return cast_or_null<Function>(Ctx.getValue(F));
-}
-
-void BasicBlock::buildBasicBlockFromLLVMIR(llvm::BasicBlock *LLVMBB) {
-  for (llvm::Instruction &IRef : reverse(*LLVMBB)) {
-    llvm::Instruction *I = &IRef;
-    Ctx.getOrCreateValue(I);
-    for (auto [OpIdx, Op] : enumerate(I->operands())) {
-      // Skip instruction's label operands
-      if (isa<llvm::BasicBlock>(Op))
-        continue;
-      // Skip metadata
-      if (isa<llvm::MetadataAsValue>(Op))
-        continue;
-      // Skip asm
-      if (isa<llvm::InlineAsm>(Op))
-        continue;
-      Ctx.getOrCreateValue(Op);
-    }
-  }
-#if !defined(NDEBUG)
-  verify();
-#endif
-}
-
-BasicBlock::iterator BasicBlock::begin() const {
-  llvm::BasicBlock *BB = cast<llvm::BasicBlock>(Val);
-  llvm::BasicBlock::iterator It = BB->begin();
-  if (!BB->empty()) {
-    auto *V = Ctx.getValue(&*BB->begin());
-    assert(V != nullptr && "No SandboxIR for BB->begin()!");
-    auto *I = cast<Instruction>(V);
-    unsigned Num = I->getNumOfIRInstrs();
-    assert(Num >= 1u && "Bad getNumOfIRInstrs()");
-    It = std::next(It, Num - 1);
-  }
-  return iterator(BB, It, &Ctx);
-}
-
-Instruction *BasicBlock::getTerminator() const {
-  auto *TerminatorV =
-      Ctx.getValue(cast<llvm::BasicBlock>(Val)->getTerminator());
-  return cast_or_null<Instruction>(TerminatorV);
-}
-
-Instruction &BasicBlock::front() const {
-  auto *BB = cast<llvm::BasicBlock>(Val);
-  assert(!BB->empty() && "Empty block!");
-  auto *SBI = cast<Instruction>(getContext().getValue(&*BB->begin()));
-  assert(SBI != nullptr && "Expected Instr!");
-  return *SBI;
-}
-
-Instruction &BasicBlock::back() const {
-  auto *BB = cast<llvm::BasicBlock>(Val);
-  assert(!BB->empty() && "Empty block!");
-  auto *SBI = cast<Instruction>(getContext().getValue(&*BB->rbegin()));
-  assert(SBI != nullptr && "Expected Instr!");
-  return *SBI;
-}
-
-#ifndef NDEBUG
-void BasicBlock::dumpOS(raw_ostream &OS) const {
-  llvm::BasicBlock *BB = cast<llvm::BasicBlock>(Val);
-  const auto &Name = BB->getName();
-  OS << Name;
-  if (!Name.empty())
-    OS << ":\n";
-  // If there are Instructions in the BB that are not mapped to SandboxIR, then
-  // use a crash-proof dump.
-  if (any_of(*BB, [this](llvm::Instruction &I) {
-        return Ctx.getValue(&I) == nullptr;
-      })) {
-    OS << "<Crash-proof mode!>\n";
-    DenseSet<Instruction *> Visited;
-    for (llvm::Instruction &IRef : *BB) {
-      Value *SBV = Ctx.getValue(&IRef);
-      if (SBV == nullptr)
-        OS << IRef << " *** No SandboxIR ***\n";
-      else {
-        auto *SBI = dyn_cast<Instruction>(SBV);
-        if (SBI == nullptr) {
-          OS << IRef << " *** Not a SBInstruction!!! ***\n";
-        } else {
-          if (Visited.insert(SBI).second)
-            OS << *SBI << "\n";
-        }
-      }
-    }
-  } else {
-    for (auto &SBI : *this) {
-      SBI.dumpOS(OS);
-      OS << "\n";
-    }
-  }
-}
-
-void BasicBlock::verify() const {
-  assert(isa<llvm::BasicBlock>(Val) && "Expected BasicBlock!");
-  for (const auto &I : *this) {
-    I.verify();
-  }
-}
-
-#endif // NDEBUG


        


More information about the llvm-commits mailing list