llvm-isel-fuzzer: Handle a subset of backend flags in the executable name

Here we add a secondary option parser to llvm-isel-fuzzer (and provide
it for use with other fuzzers). With this, you can copy the fuzzer to
a name like llvm-isel-fuzzer:aarch64-gisel for a fuzzer that fuzzer
AArch64 with GlobalISel enabled, or fuzzer:x86_64 to fuzz x86, with no
flags required. This should be useful for running these in OSS-Fuzz.

Note that this handrolls a subset of cl::opts to recognize, rather
than embedding a complete command parser for argv[0]. If we find we
really need the flexibility of handling arbitrary options at some
point we can rethink this.

llvm-svn: 315545
diff --git a/llvm/lib/FuzzMutate/FuzzerCLI.cpp b/llvm/lib/FuzzMutate/FuzzerCLI.cpp
index 3b71cde..144f1f5 100644
--- a/llvm/lib/FuzzMutate/FuzzerCLI.cpp
+++ b/llvm/lib/FuzzMutate/FuzzerCLI.cpp
@@ -8,7 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/FuzzMutate/FuzzerCLI.h"
-#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Error.h"
@@ -31,6 +31,42 @@
   cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
 }
 
+void llvm::handleExecNameEncodedBEOpts(StringRef ExecName) {
+  std::vector<std::string> Args{ExecName};
+
+  auto NameAndArgs = ExecName.split(':');
+  if (NameAndArgs.second.empty())
+    return;
+
+  SmallVector<StringRef, 4> Opts;
+  NameAndArgs.second.split(Opts, '-');
+  for (StringRef Opt : Opts) {
+    if (Opt.equals("gisel")) {
+      Args.push_back("-global-isel");
+      // For now we default GlobalISel to -O0
+      Args.push_back("-O0");
+    } else if (Opt.startswith("O")) {
+      Args.push_back("-" + Opt.str());
+    } else if (auto Arch = Triple::getArchTypeForLLVMName(Opt)) {
+      Args.push_back("-mtriple=" + Opt.str());
+    } else {
+      errs() << ExecName << ": Unknown option: " << Opt << ".\n";
+      exit(1);
+    }
+  }
+  errs() << NameAndArgs.first << ": Injected args:";
+  for (int I = 1, E = Args.size(); I < E; ++I)
+    errs() << " " << Args[I];
+  errs() << "\n";
+
+  std::vector<const char *> CLArgs;
+  CLArgs.reserve(Args.size());
+  for (std::string &S : Args)
+    CLArgs.push_back(S.c_str());
+
+  cl::ParseCommandLineOptions(CLArgs.size(), CLArgs.data());
+}
+
 int llvm::runFuzzerOnInputs(int ArgC, char *ArgV[], FuzzerTestFun TestOne,
                             FuzzerInitFun Init) {
   errs() << "*** This tool was not linked to libFuzzer.\n"