[libc-commits] [libc] a32af82 - [libc] Add a tool called WrapperGen.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Thu Jul 30 16:07:42 PDT 2020


Author: Siva Chandra Reddy
Date: 2020-07-30T16:07:26-07:00
New Revision: a32af8252fde237a3936c4f2f5bee1dfb0cf5ea8

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

LOG: [libc] Add a tool called WrapperGen.

This tool will be used to generate C wrappers for the C++ LLVM libc
implementations. This change does not hook this tool up to anything yet.
However, it can be useful for cases where one does not want to run the
objcopy step (to insert the C symbol in the object file) but can make use
of LTO to eliminate the cost of the additional wrapper call. This can be
relevant for certain downstream platforms. If this tool can benefit other
libc platforms in general, then it can be integrated into the build system
with options to use or not use the wrappers. An example of such a
platform is CUDA.

Reviewed By: abrachet

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

Added: 
    libc/utils/tools/CMakeLists.txt
    libc/utils/tools/WrapperGen/CMakeLists.txt
    libc/utils/tools/WrapperGen/Main.cpp

Modified: 
    libc/utils/CMakeLists.txt
    libc/utils/LibcTableGenUtil/APIIndexer.cpp
    libc/utils/LibcTableGenUtil/APIIndexer.h

Removed: 
    


################################################################################
diff  --git a/libc/utils/CMakeLists.txt b/libc/utils/CMakeLists.txt
index ec1308927bf9..a55182065d20 100644
--- a/libc/utils/CMakeLists.txt
+++ b/libc/utils/CMakeLists.txt
@@ -4,4 +4,5 @@ add_subdirectory(LibcTableGenUtil)
 add_subdirectory(HdrGen)
 add_subdirectory(MPFRWrapper)
 add_subdirectory(testutils)
+add_subdirectory(tools)
 add_subdirectory(UnitTest)

diff  --git a/libc/utils/LibcTableGenUtil/APIIndexer.cpp b/libc/utils/LibcTableGenUtil/APIIndexer.cpp
index 6ef9a6576b87..16aef5880bff 100644
--- a/libc/utils/LibcTableGenUtil/APIIndexer.cpp
+++ b/libc/utils/LibcTableGenUtil/APIIndexer.cpp
@@ -97,8 +97,9 @@ void APIIndexer::indexStandardSpecDef(llvm::Record *StandardSpec) {
 
       auto FunctionSpecList = HeaderSpec->getValueAsListOfDefs("Functions");
       for (llvm::Record *FunctionSpec : FunctionSpecList) {
-        FunctionSpecMap[std::string(FunctionSpec->getValueAsString("Name"))] =
-            FunctionSpec;
+        auto FunctionName = std::string(FunctionSpec->getValueAsString("Name"));
+        FunctionSpecMap[FunctionName] = FunctionSpec;
+        FunctionToHeaderMap[FunctionName] = std::string(Header);
       }
 
       auto EnumerationSpecList =

diff  --git a/libc/utils/LibcTableGenUtil/APIIndexer.h b/libc/utils/LibcTableGenUtil/APIIndexer.h
index 8fa87113610e..7b4d62a38c61 100644
--- a/libc/utils/LibcTableGenUtil/APIIndexer.h
+++ b/libc/utils/LibcTableGenUtil/APIIndexer.h
@@ -65,6 +65,8 @@ class APIIndexer {
   NameToRecordMapping MacroDefsMap;
   NameToRecordMapping TypeDeclsMap;
 
+  std::unordered_map<std::string, std::string> FunctionToHeaderMap;
+
   NameSet Structs;
   NameSet Enumerations;
   NameSet Functions;

diff  --git a/libc/utils/tools/CMakeLists.txt b/libc/utils/tools/CMakeLists.txt
new file mode 100644
index 000000000000..e975b7f293af
--- /dev/null
+++ b/libc/utils/tools/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(WrapperGen)

diff  --git a/libc/utils/tools/WrapperGen/CMakeLists.txt b/libc/utils/tools/WrapperGen/CMakeLists.txt
new file mode 100644
index 000000000000..fe8ffcce94a5
--- /dev/null
+++ b/libc/utils/tools/WrapperGen/CMakeLists.txt
@@ -0,0 +1,8 @@
+set(LLVM_LINK_COMPONENTS Support)
+
+add_tablegen(libc-wrappergen llvm-libc
+  Main.cpp
+)
+
+target_include_directories(libc-wrappergen PRIVATE ${LIBC_SOURCE_DIR})
+target_link_libraries(libc-wrappergen PRIVATE LibcTableGenUtil)

diff  --git a/libc/utils/tools/WrapperGen/Main.cpp b/libc/utils/tools/WrapperGen/Main.cpp
new file mode 100644
index 000000000000..ae606d1b66fa
--- /dev/null
+++ b/libc/utils/tools/WrapperGen/Main.cpp
@@ -0,0 +1,72 @@
+//===-- "main" function of libc-wrappergen --------------------------------===//
+//
+// 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 "utils/LibcTableGenUtil/APIIndexer.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Main.h"
+
+#include <sstream>
+#include <string>
+
+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);
+
+static bool WrapperGenMain(llvm::raw_ostream &OS, llvm::RecordKeeper &Records) {
+  llvm_libc::APIIndexer Indexer(Records);
+  auto Iter = Indexer.FunctionSpecMap.find(FunctionName);
+  if (Iter == Indexer.FunctionSpecMap.end()) {
+    llvm::PrintFatalError("Function '" + FunctionName +
+                          "' not found in any standard spec.");
+  }
+
+  // To avoid all confusion, we include the implementation header using the
+  // full path (relative 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";
+
+  auto &NameSpecPair = *Iter;
+  llvm::Record *FunctionSpec = NameSpecPair.second;
+  llvm::Record *RetValSpec = FunctionSpec->getValueAsDef("Return");
+  llvm::Record *ReturnType = RetValSpec->getValueAsDef("ReturnType");
+  OS << "extern \"C\" " << Indexer.getTypeAsString(ReturnType) << " "
+     << FunctionName << "(";
+
+  auto ArgsList = FunctionSpec->getValueAsListOfDefs("Args");
+  std::stringstream CallArgs;
+  std::string ArgPrefix("__arg");
+  for (size_t i = 0; i < ArgsList.size(); ++i) {
+    llvm::Record *ArgType = ArgsList[i]->getValueAsDef("ArgType");
+    auto TypeName = Indexer.getTypeAsString(ArgType);
+    OS << TypeName << " " << ArgPrefix << i;
+    CallArgs << ArgPrefix << i;
+    if (i < ArgsList.size() - 1) {
+      OS << ", ";
+      CallArgs << ", ";
+    }
+  }
+
+  // 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"
+     << "  return __llvm_libc::" << FunctionName << "(" << CallArgs.str()
+     << ");\n"
+     << "}\n";
+
+  return false;
+}
+
+int main(int argc, char *argv[]) {
+  llvm::cl::ParseCommandLineOptions(argc, argv);
+  return TableGenMain(argv[0], WrapperGenMain);
+}


        


More information about the libc-commits mailing list