[libc-commits] [libc] bf03eba - [libc] Refactor WrapperGen to make the flow cleaner.
Siva Chandra Reddy via libc-commits
libc-commits at lists.llvm.org
Thu Dec 17 08:56:55 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 libc-commits
mailing list