[llvm-branch-commits] [libc] bf03eba - [libc] Refactor WrapperGen to make the flow cleaner.

Siva Chandra Reddy via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Dec 17 09:01:37 PST 2020


Author: Siva Chandra Reddy
Date: 2020-12-17T08:56:45-08:00
New Revision: bf03eba1f99b8408e6f8961256ffb3409df7f995

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

LOG: [libc] Refactor WrapperGen to make the flow cleaner.

Reviewed By: michaelrj

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

Added: 
    

Modified: 
    libc/test/utils/tools/WrapperGen/wrappergen_test.cpp
    libc/utils/tools/WrapperGen/Main.cpp

Removed: 
    


################################################################################
diff  --git a/libc/test/utils/tools/WrapperGen/wrappergen_test.cpp b/libc/test/utils/tools/WrapperGen/wrappergen_test.cpp
index 4cb7a31de942..923b318288ea 100644
--- a/libc/test/utils/tools/WrapperGen/wrappergen_test.cpp
+++ b/libc/test/utils/tools/WrapperGen/wrappergen_test.cpp
@@ -72,8 +72,12 @@ TEST_F(WrapperGenTest, RunWrapperGenAndGetNoErrors) {
       llvm::None, llvm::StringRef(STDOutFile.get().TmpName),
       llvm::StringRef(STDErrFile.get().TmpName)};
 
-  llvm::StringRef ArgV[] = {ProgPath, llvm::StringRef(IncludeArg),
-                            llvm::StringRef(APIArg), "--name", "strlen"};
+  llvm::StringRef ArgV[] = {ProgPath,
+                            llvm::StringRef(IncludeArg),
+                            llvm::StringRef(APIArg),
+                            "--gen-wrapper",
+                            "--name",
+                            "strlen"};
 
   int ExitCode =
       llvm::sys::ExecuteAndWait(ProgPath, ArgV, llvm::None, Redirects);
@@ -90,8 +94,12 @@ TEST_F(WrapperGenTest, RunWrapperGenOnStrlen) {
       llvm::None, llvm::StringRef(STDOutFile.get().TmpName),
       llvm::StringRef(STDErrFile.get().TmpName)};
 
-  llvm::StringRef ArgV[] = {ProgPath, llvm::StringRef(IncludeArg),
-                            llvm::StringRef(APIArg), "--name", "strlen"};
+  llvm::StringRef ArgV[] = {ProgPath,
+                            llvm::StringRef(IncludeArg),
+                            llvm::StringRef(APIArg),
+                            "--gen-wrapper",
+                            "--name",
+                            "strlen"};
 
   int ExitCode =
       llvm::sys::ExecuteAndWait(ProgPath, ArgV, llvm::None, Redirects);
@@ -116,7 +124,7 @@ TEST_F(WrapperGenTest, RunWrapperGenOnStrlen) {
   // would break this test.
 }
 
-TEST_F(WrapperGenTest, RunWrapperGenOnStrlenWithAliasee) {
+TEST_F(WrapperGenTest, GenAliasForStrlen) {
   llvm::Optional<llvm::StringRef> Redirects[] = {
       llvm::None, llvm::StringRef(STDOutFile.get().TmpName),
       llvm::StringRef(STDErrFile.get().TmpName)};
@@ -124,8 +132,9 @@ TEST_F(WrapperGenTest, RunWrapperGenOnStrlenWithAliasee) {
   llvm::StringRef ArgV[] = {ProgPath,
                             llvm::StringRef(IncludeArg),
                             llvm::StringRef(APIArg),
-                            "--aliasee",
-                            "STRLEN_ALIAS",
+                            "--gen-alias",
+                            "--mangled-name",
+                            "__llvm_libc_strlen_mangled_name",
                             "--name",
                             "strlen"};
 
@@ -142,35 +151,38 @@ TEST_F(WrapperGenTest, RunWrapperGenOnStrlenWithAliasee) {
   auto STDOutOrError = llvm::MemoryBuffer::getFile(STDOutFile.get().TmpName);
   std::string STDOutOutput = STDOutOrError.get()->getBuffer().str();
 
-  ASSERT_EQ(STDOutOutput, "extern \"C\" size_t strlen(const char * __arg0) "
-                          "__attribute__((alias(\"STRLEN_ALIAS\")));\n");
+  ASSERT_EQ(STDOutOutput,
+            "extern \"C\" size_t strlen(const char * __arg0) "
+            "__attribute__((alias(\"__llvm_libc_strlen_mangled_name\")));\n");
   // TODO:(michaelrj) Figure out how to make this output comparison
   // less brittle. Currently it's just comparing the output of the program
   // to an exact string, this means that even a small formatting change
   // would break this test.
 }
 
-TEST_F(WrapperGenTest, DeclStrlenAliasUsingAliaseeFile) {
+TEST_F(WrapperGenTest, DeclStrlenAliasUsingMangledNameFile) {
   llvm::Optional<llvm::StringRef> Redirects[] = {
       llvm::None, llvm::StringRef(STDOutFile.get().TmpName),
       llvm::StringRef(STDErrFile.get().TmpName)};
 
-  const char *AliaseeFileContent = "abc\nxyz__llvm_libcSTRLEN_ALIAS\nijk\n";
-  llvm::SmallVector<char> AliaseeFilePath;
-  auto AliaseeFileCreateError = llvm::sys::fs::createUniqueFile(
-      "libc-wrappergen-test-aliasee-file-%%-%%-%%-%%.txt", AliaseeFilePath);
-  ASSERT_FALSE(AliaseeFileCreateError);
-  auto AliaseeFileWriteError = llvm::writeFileAtomically(
+  const char *MangledNameFileContent =
+      "abc\nxyz__llvm_libc_strlen_mangled_name\nijk\n";
+  llvm::SmallVector<char> MangledNameFilePath;
+  auto MangledNameFileCreateError = llvm::sys::fs::createUniqueFile(
+      "libc-wrappergen-test-aliasee-file-%%-%%-%%-%%.txt", MangledNameFilePath);
+  ASSERT_FALSE(MangledNameFileCreateError);
+  auto MangledNameFileWriteError = llvm::writeFileAtomically(
       "libc-wrappergen-temp-test-aliasee-file-%%-%%-%%-%%.txt",
-      llvm::StringRef(AliaseeFilePath.data()),
-      llvm::StringRef(AliaseeFileContent));
-  ASSERT_FALSE(AliaseeFileWriteError);
+      llvm::StringRef(MangledNameFilePath.data()),
+      llvm::StringRef(MangledNameFileContent));
+  ASSERT_FALSE(MangledNameFileWriteError);
 
   llvm::StringRef ArgV[] = {ProgPath,
                             llvm::StringRef(IncludeArg),
                             llvm::StringRef(APIArg),
-                            "--aliasee-file",
-                            llvm::StringRef(AliaseeFilePath.data()),
+                            "--gen-alias",
+                            "--mangled-name-file",
+                            llvm::StringRef(MangledNameFilePath.data()),
                             "--name",
                             "strlen"};
 
@@ -187,9 +199,10 @@ TEST_F(WrapperGenTest, DeclStrlenAliasUsingAliaseeFile) {
   auto STDOutOrError = llvm::MemoryBuffer::getFile(STDOutFile.get().TmpName);
   std::string STDOutOutput = STDOutOrError.get()->getBuffer().str();
 
-  ASSERT_EQ(STDOutOutput,
-            "extern \"C\" size_t strlen(const char * __arg0) "
-            "__attribute__((alias(\"xyz__llvm_libcSTRLEN_ALIAS\")));\n");
+  ASSERT_EQ(
+      STDOutOutput,
+      "extern \"C\" size_t strlen(const char * __arg0) "
+      "__attribute__((alias(\"xyz__llvm_libc_strlen_mangled_name\")));\n");
 }
 
 /////////////////////////////////////////////////////////////////////
@@ -199,8 +212,7 @@ TEST_F(WrapperGenTest, DeclStrlenAliasUsingAliaseeFile) {
 // return errors
 /////////////////////////////////////////////////////////////////////
 
-TEST_F(WrapperGenTest,
-       RunWrapperGenOnStrlenWithAliaseeAndAliaseeFileWhichIsError) {
+TEST_F(WrapperGenTest, RunWrapperGenOnStrlenWithMangledNameAndMangledNameFile) {
   llvm::Optional<llvm::StringRef> Redirects[] = {
       llvm::None, llvm::StringRef(STDOutFile.get().TmpName),
       llvm::StringRef(STDErrFile.get().TmpName)};
@@ -208,10 +220,11 @@ TEST_F(WrapperGenTest,
   llvm::StringRef ArgV[] = {ProgPath,
                             llvm::StringRef(IncludeArg),
                             llvm::StringRef(APIArg),
-                            "--aliasee",
-                            "STRLEN_ALIAS",
-                            "--aliasee-file",
-                            "STRLEN_ALIAS_FILE",
+                            "--gen-alias",
+                            "--mangled-name",
+                            "__llvm_libc_strlen_mangled_name",
+                            "--mangled-name-file",
+                            "non-existant-mangled-name-file.txt",
                             "--name",
                             "strlen"};
 
@@ -223,8 +236,9 @@ TEST_F(WrapperGenTest,
   auto STDErrOrError = llvm::MemoryBuffer::getFile(STDErrFile.get().TmpName);
   std::string STDErrOutput = STDErrOrError.get()->getBuffer().str();
 
-  ASSERT_EQ(STDErrOutput, "error: The options 'aliasee' and 'aliasee-file' "
-                          "cannot be specified simultaniously.\n");
+  ASSERT_EQ(STDErrOutput,
+            "error: The options 'mangled-name' and 'mangled-name-file' "
+            "cannot be specified simultaniously.\n");
 
   auto STDOutOrError = llvm::MemoryBuffer::getFile(STDOutFile.get().TmpName);
   std::string STDOutOutput = STDOutOrError.get()->getBuffer().str();
@@ -239,8 +253,12 @@ TEST_F(WrapperGenTest, RunWrapperGenOnBadFuncName) {
 
   llvm::StringRef BadFuncName = "FAKE_TEST_FUNC";
 
-  llvm::StringRef ArgV[] = {ProgPath, llvm::StringRef(IncludeArg),
-                            llvm::StringRef(APIArg), "--name", BadFuncName};
+  llvm::StringRef ArgV[] = {ProgPath,
+                            llvm::StringRef(IncludeArg),
+                            llvm::StringRef(APIArg),
+                            "--gen-wrapper",
+                            "--name",
+                            BadFuncName};
 
   int ExitCode =
       llvm::sys::ExecuteAndWait(ProgPath, ArgV, llvm::None, Redirects);
@@ -260,17 +278,21 @@ TEST_F(WrapperGenTest, RunWrapperGenOnBadFuncName) {
   ASSERT_EQ(STDOutOutput, "");
 }
 
-TEST_F(WrapperGenTest, RunWrapperGenOnStrlenWithBadAliaseeFile) {
+TEST_F(WrapperGenTest, RunWrapperGenOnStrlenWithBadMangledNameFile) {
   llvm::Optional<llvm::StringRef> Redirects[] = {
       llvm::None, llvm::StringRef(STDOutFile.get().TmpName),
       llvm::StringRef(STDErrFile.get().TmpName)};
 
-  llvm::StringRef BadAliaseeFileName = "FILE_THAT_DOESNT_EXIST.txt";
+  llvm::StringRef BadMangledNameFileName = "FILE_THAT_DOESNT_EXIST.txt";
 
-  llvm::StringRef ArgV[] = {
-      ProgPath,         llvm::StringRef(IncludeArg), llvm::StringRef(APIArg),
-      "--aliasee-file", BadAliaseeFileName,          "--name",
-      "strlen"};
+  llvm::StringRef ArgV[] = {ProgPath,
+                            llvm::StringRef(IncludeArg),
+                            llvm::StringRef(APIArg),
+                            "--gen-alias",
+                            "--mangled-name-file",
+                            BadMangledNameFileName,
+                            "--name",
+                            "strlen"};
 
   int ExitCode =
       llvm::sys::ExecuteAndWait(ProgPath, ArgV, llvm::None, Redirects);
@@ -280,8 +302,8 @@ TEST_F(WrapperGenTest, RunWrapperGenOnStrlenWithBadAliaseeFile) {
   auto STDErrOrError = llvm::MemoryBuffer::getFile(STDErrFile.get().TmpName);
   std::string STDErrOutput = STDErrOrError.get()->getBuffer().str();
 
-  ASSERT_EQ(STDErrOutput, ("error: Unable to read the aliasee file " +
-                           BadAliaseeFileName + "\n")
+  ASSERT_EQ(STDErrOutput, ("error: Unable to read the mangled name file " +
+                           BadMangledNameFileName + "\n")
                               .str());
 
   auto STDOutOrError = llvm::MemoryBuffer::getFile(STDOutFile.get().TmpName);
@@ -290,21 +312,23 @@ TEST_F(WrapperGenTest, RunWrapperGenOnStrlenWithBadAliaseeFile) {
   ASSERT_EQ(STDOutOutput, "");
 }
 
-TEST_F(WrapperGenTest, RunWithAliaseeFileMissingLLVMLibcName) {
+TEST_F(WrapperGenTest, RunWithMangledNameFileMissingLLVMLibcName) {
   llvm::Optional<llvm::StringRef> Redirects[] = {
       llvm::None, llvm::StringRef(STDOutFile.get().TmpName),
       llvm::StringRef(STDErrFile.get().TmpName)};
 
-  llvm::SmallVector<char> AliaseeFilePath;
-  auto AliaseeFileCreateError = llvm::sys::fs::createUniqueFile(
-      "libc-wrappergen-test-aliasee-file-%%-%%-%%-%%.txt", AliaseeFilePath);
-  ASSERT_FALSE(AliaseeFileCreateError);
+  llvm::SmallVector<char> MangledNameFilePath;
+  auto MangledNameFileCreateError = llvm::sys::fs::createUniqueFile(
+      "libc-wrappergen-test-mangled-name-file-%%-%%-%%-%%.txt",
+      MangledNameFilePath);
+  ASSERT_FALSE(MangledNameFileCreateError);
 
   llvm::StringRef ArgV[] = {ProgPath,
                             llvm::StringRef(IncludeArg),
                             llvm::StringRef(APIArg),
-                            "--aliasee-file",
-                            llvm::StringRef(AliaseeFilePath.data()),
+                            "--gen-alias",
+                            "--mangled-name-file",
+                            llvm::StringRef(MangledNameFilePath.data()),
                             "--name",
                             "strlen"};
 
@@ -317,6 +341,6 @@ TEST_F(WrapperGenTest, RunWithAliaseeFileMissingLLVMLibcName) {
   std::string STDErrOutput = STDErrOrError.get()->getBuffer().str();
 
   ASSERT_EQ(STDErrOutput, ("error: Did not find an LLVM libc mangled name in " +
-                           AliaseeFilePath + "\n")
+                           MangledNameFilePath + "\n")
                               .str());
 }

diff  --git a/libc/utils/tools/WrapperGen/Main.cpp b/libc/utils/tools/WrapperGen/Main.cpp
index 7c43f611daac..5711827b457c 100644
--- a/libc/utils/tools/WrapperGen/Main.cpp
+++ b/libc/utils/tools/WrapperGen/Main.cpp
@@ -10,38 +10,68 @@
 
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/JSON.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/TableGen/Error.h"
 #include "llvm/TableGen/Main.h"
 
+#include <fstream>
+#include <map>
 #include <sstream>
 #include <string>
 
+llvm::cl::opt<bool>
+    GenWrapper("gen-wrapper",
+               llvm::cl::desc("Generate a C wrapper for <name>."));
+llvm::cl::opt<bool> GenAlias("gen-alias",
+                             llvm::cl::desc("Generate a C alias for <name>."));
+
 llvm::cl::opt<std::string>
     FunctionName("name", llvm::cl::desc("Name of the function to be wrapped."),
                  llvm::cl::value_desc("<function name>"), llvm::cl::Required);
-llvm::cl::opt<std::string>
-    AliaseeString("aliasee",
-                  llvm::cl::desc("Declare as an alias to this C name."),
-                  llvm::cl::value_desc("<aliasee string>"));
-llvm::cl::opt<std::string>
-    AliaseeFile("aliasee-file",
-                llvm::cl::desc("Declare as an alias to the C name read from "
-                               "this file."),
-                llvm::cl::value_desc("<path to a file containing alias name>"));
+llvm::cl::opt<std::string> MangledNameString(
+    "mangled-name", llvm::cl::desc("Declare as an alias to this mangled name."),
+    llvm::cl::value_desc("<aliasee string>"));
+llvm::cl::opt<std::string> MangledNameFile(
+    "mangled-name-file",
+    llvm::cl::desc("Declare as an alias to the C name read from "
+                   "this file."),
+    llvm::cl::value_desc("<path to a file containing alias name>"));
 llvm::cl::opt<std::string>
     AppendToFile("append-to-file",
                  llvm::cl::desc("Append the generated content at the end of "
                                 "the contents of this file."),
                  llvm::cl::value_desc("<path to a file>"));
 
-static std::string GetAliaseeName() {
-  if (AliaseeString.size() > 0)
-    return AliaseeString;
+void validateOpts() {
+  int ActionCount = 0;
+  if (GenWrapper)
+    ++ActionCount;
+  if (GenAlias)
+    ++ActionCount;
+  if (ActionCount != 1) {
+    llvm::PrintFatalError("Exactly one of {--gen-wrapper, --gen-alias} "
+                          "should be specified");
+  }
+  if (!MangledNameString.empty() && !MangledNameFile.empty()) {
+    llvm::PrintFatalError("The options 'mangled-name' and 'mangled-name-file' "
+                          "cannot be specified simultaneously.");
+  }
+}
+
+static std::string getMangledName() {
+  if (!MangledNameString.empty())
+    return MangledNameString;
 
-  auto ErrorOrBuf = llvm::MemoryBuffer::getFile(AliaseeFile);
+  if (MangledNameFile.empty())
+    llvm::PrintFatalError("At least one of --mangled-name or "
+                          "--mangled-name-file should be specified.");
+
+  auto ErrorOrBuf = llvm::MemoryBuffer::getFile(MangledNameFile);
   if (!ErrorOrBuf)
-    llvm::PrintFatalError("Unable to read the aliasee file " + AliaseeFile);
+    llvm::PrintFatalError("Unable to read the mangled name file " +
+                          MangledNameFile);
   llvm::StringRef FileContent = ErrorOrBuf.get()->getBuffer().trim();
   llvm::SmallVector<llvm::StringRef> Lines;
   FileContent.split(Lines, '\n');
@@ -50,47 +80,32 @@ static std::string GetAliaseeName() {
       return std::string(L);
   }
   llvm::PrintFatalError("Did not find an LLVM libc mangled name in " +
-                        AliaseeFile);
+                        MangledNameFile);
   return std::string();
 }
 
-static bool WrapperGenMain(llvm::raw_ostream &OS, llvm::RecordKeeper &Records) {
-  if (!AliaseeString.empty() && !AliaseeFile.empty()) {
-    llvm::PrintFatalError("The options 'aliasee' and 'aliasee-file' cannot "
-                          "be specified simultaniously.");
+void writeAppendToFile(llvm::raw_ostream &OS) {
+  auto ErrorOrBuf = llvm::MemoryBuffer::getFile(AppendToFile);
+  if (!ErrorOrBuf) {
+    llvm::PrintFatalError("Unable to read the file '" + AppendToFile +
+                          "' to append to.");
   }
+  OS << ErrorOrBuf.get()->getBuffer().trim() << '\n';
+}
 
-  llvm_libc::APIIndexer Indexer(Records);
+llvm::Record *getFunctionSpec(const llvm_libc::APIIndexer &Indexer) {
   auto Iter = Indexer.FunctionSpecMap.find(FunctionName);
   if (Iter == Indexer.FunctionSpecMap.end()) {
     llvm::PrintFatalError("Function '" + FunctionName +
                           "' not found in any standard spec.");
   }
-
-  bool EmitAlias = !(AliaseeString.empty() && AliaseeFile.empty());
-
-  if (!EmitAlias && AppendToFile.empty()) {
-    // If not emitting an alias, and not appending to another file,
-    // we should include the implementation header to ensure the wrapper
-    // compiles.
-    // To avoid all confusion, we include the implementation header using the
-    // full path (relative to the libc directory.)
-    std::string Header = Indexer.FunctionToHeaderMap[FunctionName];
-    auto RelPath =
-        llvm::StringRef(Header).drop_back(2); // Drop the ".h" suffix.
-    OS << "#include \"src/" << RelPath << "/" << FunctionName << ".h\"\n";
-  }
-  if (!AppendToFile.empty()) {
-    auto ErrorOrBuf = llvm::MemoryBuffer::getFile(AppendToFile);
-    if (!ErrorOrBuf) {
-      llvm::PrintFatalError("Unable to read the file '" + AppendToFile +
-                            "' to append to.");
-    }
-    OS << ErrorOrBuf.get()->getBuffer().trim() << '\n';
-  }
-
   auto &NameSpecPair = *Iter;
-  llvm::Record *FunctionSpec = NameSpecPair.second;
+  return NameSpecPair.second;
+}
+
+std::pair<std::string, bool> writeFunctionHeader(llvm_libc::APIIndexer &Indexer,
+                                                 llvm::Record *FunctionSpec,
+                                                 llvm::raw_ostream &OS) {
   llvm::Record *RetValSpec = FunctionSpec->getValueAsDef("Return");
   llvm::Record *ReturnType = RetValSpec->getValueAsDef("ReturnType");
   std::string ReturnTypeString = Indexer.getTypeAsString(ReturnType);
@@ -133,22 +148,51 @@ static bool WrapperGenMain(llvm::raw_ostream &OS, llvm::RecordKeeper &Records) {
       CallArgs << ", ";
     }
   }
+  return make_pair(CallArgs.str(), ShouldReturn);
+}
 
-  if (EmitAlias) {
-    OS << ") __attribute__((alias(\"" << GetAliaseeName() << "\")));\n";
+static bool generateWrapper(llvm::raw_ostream &OS,
+                            llvm::RecordKeeper &Records) {
+  llvm_libc::APIIndexer Indexer(Records);
+  llvm::Record *FunctionSpec = getFunctionSpec(Indexer);
+  if (AppendToFile.empty()) {
+    std::string Header = Indexer.FunctionToHeaderMap[FunctionName];
+    auto RelPath =
+        llvm::StringRef(Header).drop_back(2); // Drop the ".h" suffix.
+    OS << "#include \"src/" << RelPath << "/" << FunctionName << ".h\"\n";
   } else {
-    // TODO: Arg types of the C++ implementation functions need not
-    // match the standard types. Either handle such 
diff erences here, or
-    // avoid such a thing in the implementations.
-    OS << ") {\n"
-       << "  " << (ShouldReturn ? "return " : "")
-       << "__llvm_libc::" << FunctionName << "(" << CallArgs.str() << ");\n"
-       << "}\n";
+    writeAppendToFile(OS);
   }
+  auto Pair = writeFunctionHeader(Indexer, FunctionSpec, OS);
+  OS << ") {\n"
+     << "  " << (Pair.second ? "return " : "")
+     << "__llvm_libc::" << FunctionName << "(" << Pair.first << ");\n"
+     << "}\n";
+  return false;
+}
+
+static bool generateAlias(llvm::raw_ostream &OS, llvm::RecordKeeper &Records) {
+  if (!AppendToFile.empty())
+    writeAppendToFile(OS);
+  llvm_libc::APIIndexer Indexer(Records);
+  llvm::Record *FunctionSpec = getFunctionSpec(Indexer);
+  auto Pair = writeFunctionHeader(Indexer, FunctionSpec, OS);
+  OS << ") __attribute__((alias(\"" << getMangledName() << "\")));\n";
   return false;
 }
 
+static bool wrapperGenMain(llvm::raw_ostream &OS, llvm::RecordKeeper &Records) {
+  validateOpts();
+
+  if (GenWrapper)
+    return generateWrapper(OS, Records);
+  if (GenAlias)
+    return generateAlias(OS, Records);
+
+  __builtin_unreachable();
+}
+
 int main(int argc, char *argv[]) {
   llvm::cl::ParseCommandLineOptions(argc, argv);
-  return TableGenMain(argv[0], WrapperGenMain);
+  return TableGenMain(argv[0], wrapperGenMain);
 }


        


More information about the llvm-branch-commits mailing list