1 //===-- "main" function of libc-wrappergen --------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "utils/LibcTableGenUtil/APIIndexer.h"
10 
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/Support/CommandLine.h"
13 #include "llvm/TableGen/Error.h"
14 #include "llvm/TableGen/Main.h"
15 
16 #include <sstream>
17 #include <string>
18 
19 llvm::cl::opt<std::string>
20     FunctionName("name", llvm::cl::desc("Name of the function to be wrapped."),
21                  llvm::cl::value_desc("<function name>"), llvm::cl::Required);
22 
23 static bool WrapperGenMain(llvm::raw_ostream &OS, llvm::RecordKeeper &Records) {
24   llvm_libc::APIIndexer Indexer(Records);
25   auto Iter = Indexer.FunctionSpecMap.find(FunctionName);
26   if (Iter == Indexer.FunctionSpecMap.end()) {
27     llvm::PrintFatalError("Function '" + FunctionName +
28                           "' not found in any standard spec.");
29   }
30 
31   // To avoid all confusion, we include the implementation header using the
32   // full path (relative the libc directory.)
33   std::string Header = Indexer.FunctionToHeaderMap[FunctionName];
34   auto RelPath = llvm::StringRef(Header).drop_back(2); // Drop the ".h" suffix.
35   OS << "#include \"src/" << RelPath << "/" << FunctionName << ".h\"\n";
36 
37   auto &NameSpecPair = *Iter;
38   llvm::Record *FunctionSpec = NameSpecPair.second;
39   llvm::Record *RetValSpec = FunctionSpec->getValueAsDef("Return");
40   llvm::Record *ReturnType = RetValSpec->getValueAsDef("ReturnType");
41   OS << "extern \"C\" " << Indexer.getTypeAsString(ReturnType) << " "
42      << FunctionName << "(";
43 
44   auto ArgsList = FunctionSpec->getValueAsListOfDefs("Args");
45   std::stringstream CallArgs;
46   std::string ArgPrefix("__arg");
47   for (size_t i = 0; i < ArgsList.size(); ++i) {
48     llvm::Record *ArgType = ArgsList[i]->getValueAsDef("ArgType");
49     auto TypeName = Indexer.getTypeAsString(ArgType);
50     OS << TypeName << " " << ArgPrefix << i;
51     CallArgs << ArgPrefix << i;
52     if (i < ArgsList.size() - 1) {
53       OS << ", ";
54       CallArgs << ", ";
55     }
56   }
57 
58   // TODO: Arg types of the C++ implementation functions need not
59   // match the standard types. Either handle such differences here, or
60   // avoid such a thing in the implementations.
61   OS << ") {\n"
62      << "  return __llvm_libc::" << FunctionName << "(" << CallArgs.str()
63      << ");\n"
64      << "}\n";
65 
66   return false;
67 }
68 
69 int main(int argc, char *argv[]) {
70   llvm::cl::ParseCommandLineOptions(argc, argv);
71   return TableGenMain(argv[0], WrapperGenMain);
72 }
73