Separate out option processing from llvm-rs-cc.cpp.

Change-Id: I8abcc6d91820d8e6963f6579a5c6bbb95d6e2c7c
diff --git a/llvm-rs-cc.cpp b/llvm-rs-cc.cpp
index 40209e0..338ebe1 100644
--- a/llvm-rs-cc.cpp
+++ b/llvm-rs-cc.cpp
@@ -14,17 +14,9 @@
  * limitations under the License.
  */
 
-#include <cstdlib>
-#include <list>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
+#include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Driver/DriverDiagnostic.h"
 #include "clang/Driver/Options.h"
-
-#include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Frontend/Utils.h"
 
@@ -32,9 +24,6 @@
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/OwningPtr.h"
 
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/ArgList.h"
-#include "llvm/Option/Option.h"
 #include "llvm/Option/OptTable.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ManagedStatic.h"
@@ -44,19 +33,16 @@
 #include "llvm/Support/system_error.h"
 #include "llvm/Target/TargetMachine.h"
 
+#include "rs_cc_options.h"
 #include "slang.h"
 #include "slang_assert.h"
 #include "slang_diagnostic_buffer.h"
 #include "slang_rs.h"
 #include "slang_rs_reflect_utils.h"
 
-using clang::driver::options::DriverOption;
-using llvm::opt::arg_iterator;
-using llvm::opt::Arg;
-using llvm::opt::ArgList;
-using llvm::opt::InputArgList;
-using llvm::opt::Option;
-using llvm::opt::OptTable;
+#include <list>
+#include <set>
+#include <string>
 
 // SaveStringInSet, ExpandArgsFromBuf and ExpandArgv are all copied from
 // $(CLANG_ROOT)/tools/driver/driver.cpp for processing argc/argv passed in
@@ -72,256 +58,6 @@
                        llvm::SmallVectorImpl<const char*> &ArgVector,
                        std::set<std::string> &SavedStrings);
 
-enum {
-  OPT_INVALID = 0,  // This is not an option ID.
-#define PREFIX(NAME, VALUE)
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
-               HELPTEXT, METAVAR) OPT_##ID,
-#include "RSCCOptions.inc"
-  LastOption
-#undef OPTION
-#undef PREFIX
-};
-
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
-               HELPTEXT, METAVAR)
-#include "RSCCOptions.inc"
-#undef OPTION
-#undef PREFIX
-
-static const OptTable::Info RSCCInfoTable[] = {
-#define PREFIX(NAME, VALUE)
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
-               HELPTEXT, METAVAR)   \
-  { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \
-    FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
-#include "RSCCOptions.inc"
-#undef OPTION
-#undef PREFIX
-};
-
-class RSCCOptTable : public OptTable {
- public:
-  RSCCOptTable()
-      : OptTable(RSCCInfoTable,
-                 sizeof(RSCCInfoTable) / sizeof(RSCCInfoTable[0])) {
-  }
-};
-
-OptTable *createRSCCOptTable() {
-  return new RSCCOptTable();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-class RSCCOptions {
- public:
-  // The include search paths
-  std::vector<std::string> mIncludePaths;
-
-  // The output directory, if any.
-  std::string mOutputDir;
-
-  // The output type
-  slang::Slang::OutputType mOutputType;
-
-  unsigned mAllowRSPrefix : 1;
-
-  // The name of the target triple to compile for.
-  std::string mTriple;
-
-  // The name of the target CPU to generate code for.
-  std::string mCPU;
-
-  // The list of target specific features to enable or disable -- this should
-  // be a list of strings starting with by '+' or '-'.
-  std::vector<std::string> mFeatures;
-
-  std::string mJavaReflectionPathBase;
-
-  std::string mJavaReflectionPackageName;
-
-  std::string mRSPackageName;
-
-  slang::BitCodeStorageType mBitcodeStorage;
-
-  unsigned mOutputDep : 1;
-
-  std::string mOutputDepDir;
-
-  std::vector<std::string> mAdditionalDepTargets;
-
-  unsigned mShowHelp : 1;  // Show the -help text.
-  unsigned mShowVersion : 1;  // Show the -version text.
-
-  unsigned int mTargetAPI;
-
-  // Enable emission of debugging symbols
-  unsigned mDebugEmission : 1;
-
-  // The optimization level used in CodeGen, and encoded in emitted bitcode
-  llvm::CodeGenOpt::Level mOptimizationLevel;
-
-  RSCCOptions() {
-    mOutputType = slang::Slang::OT_Bitcode;
-    // Triple/CPU/Features must be hard-coded to our chosen portable ABI.
-    mTriple = "armv7-none-linux-gnueabi";
-    mCPU = "";
-    slangAssert(mFeatures.empty());
-    mFeatures.push_back("+long64");
-    mBitcodeStorage = slang::BCST_APK_RESOURCE;
-    mOutputDep = 0;
-    mShowHelp = 0;
-    mShowVersion = 0;
-    mTargetAPI = RS_VERSION;
-    mDebugEmission = 0;
-    mOptimizationLevel = llvm::CodeGenOpt::Aggressive;
-  }
-};
-
-// ParseArguments -
-static void ParseArguments(llvm::SmallVectorImpl<const char*> &ArgVector,
-                           llvm::SmallVectorImpl<const char*> &Inputs,
-                           RSCCOptions &Opts,
-                           clang::DiagnosticsEngine &DiagEngine) {
-  if (ArgVector.size() > 1) {
-    const char **ArgBegin = ArgVector.data() + 1;
-    const char **ArgEnd = ArgVector.data() + ArgVector.size();
-    unsigned MissingArgIndex, MissingArgCount;
-    llvm::OwningPtr<OptTable> OptParser(createRSCCOptTable());
-    llvm::OwningPtr<InputArgList> Args(
-      OptParser->ParseArgs(ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount));
-
-    // Check for missing argument error.
-    if (MissingArgCount)
-      DiagEngine.Report(clang::diag::err_drv_missing_argument)
-        << Args->getArgString(MissingArgIndex) << MissingArgCount;
-
-    clang::DiagnosticOptions DiagOpts;
-    DiagOpts.IgnoreWarnings = Args->hasArg(OPT_w);
-    DiagOpts.Warnings = Args->getAllArgValues(OPT_W);
-    clang::ProcessWarningOptions(DiagEngine, DiagOpts);
-
-    // Issue errors on unknown arguments.
-    for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
-        ie = Args->filtered_end(); it != ie; ++it)
-      DiagEngine.Report(clang::diag::err_drv_unknown_argument)
-        << (*it)->getAsString(*Args);
-
-    for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
-        it != ie; ++it) {
-      const Arg *A = *it;
-      if (A->getOption().getKind() == Option::InputClass)
-        Inputs.push_back(A->getValue());
-    }
-
-    Opts.mIncludePaths = Args->getAllArgValues(OPT_I);
-
-    Opts.mOutputDir = Args->getLastArgValue(OPT_o);
-
-    if (const Arg *A = Args->getLastArg(OPT_M_Group)) {
-      switch (A->getOption().getID()) {
-        case OPT_M: {
-          Opts.mOutputDep = 1;
-          Opts.mOutputType = slang::Slang::OT_Dependency;
-          break;
-        }
-        case OPT_MD: {
-          Opts.mOutputDep = 1;
-          Opts.mOutputType = slang::Slang::OT_Bitcode;
-          break;
-        }
-        default: {
-          slangAssert(false && "Invalid option in M group!");
-        }
-      }
-    }
-
-    if (const Arg *A = Args->getLastArg(OPT_Output_Type_Group)) {
-      switch (A->getOption().getID()) {
-        case OPT_emit_asm: {
-          Opts.mOutputType = slang::Slang::OT_Assembly;
-          break;
-        }
-        case OPT_emit_llvm: {
-          Opts.mOutputType = slang::Slang::OT_LLVMAssembly;
-          break;
-        }
-        case OPT_emit_bc: {
-          Opts.mOutputType = slang::Slang::OT_Bitcode;
-          break;
-        }
-        case OPT_emit_nothing: {
-          Opts.mOutputType = slang::Slang::OT_Nothing;
-          break;
-        }
-        default: {
-          slangAssert(false && "Invalid option in output type group!");
-        }
-      }
-    }
-
-    if (Opts.mOutputDep &&
-        ((Opts.mOutputType != slang::Slang::OT_Bitcode) &&
-         (Opts.mOutputType != slang::Slang::OT_Dependency)))
-      DiagEngine.Report(clang::diag::err_drv_argument_not_allowed_with)
-          << Args->getLastArg(OPT_M_Group)->getAsString(*Args)
-          << Args->getLastArg(OPT_Output_Type_Group)->getAsString(*Args);
-
-    Opts.mAllowRSPrefix = Args->hasArg(OPT_allow_rs_prefix);
-
-    Opts.mJavaReflectionPathBase =
-        Args->getLastArgValue(OPT_java_reflection_path_base);
-    Opts.mJavaReflectionPackageName =
-        Args->getLastArgValue(OPT_java_reflection_package_name);
-
-    Opts.mRSPackageName = Args->getLastArgValue(OPT_rs_package_name);
-
-    llvm::StringRef BitcodeStorageValue =
-        Args->getLastArgValue(OPT_bitcode_storage);
-    if (BitcodeStorageValue == "ar")
-      Opts.mBitcodeStorage = slang::BCST_APK_RESOURCE;
-    else if (BitcodeStorageValue == "jc")
-      Opts.mBitcodeStorage = slang::BCST_JAVA_CODE;
-    else if (!BitcodeStorageValue.empty())
-      DiagEngine.Report(clang::diag::err_drv_invalid_value)
-          << OptParser->getOptionName(OPT_bitcode_storage)
-          << BitcodeStorageValue;
-
-    if (Args->hasArg(OPT_reflect_cpp)) {
-      Opts.mBitcodeStorage = slang::BCST_CPP_CODE;
-      // mJavaReflectionPathBase can be set for C++ reflected builds.
-      // Set it to the standard mOutputDir (via -o) by default.
-      if (Opts.mJavaReflectionPathBase.empty()) {
-        Opts.mJavaReflectionPathBase = Opts.mOutputDir;
-      }
-    }
-
-    Opts.mOutputDepDir =
-        Args->getLastArgValue(OPT_output_dep_dir, Opts.mOutputDir);
-    Opts.mAdditionalDepTargets =
-        Args->getAllArgValues(OPT_additional_dep_target);
-
-    Opts.mShowHelp = Args->hasArg(OPT_help);
-    Opts.mShowVersion = Args->hasArg(OPT_version);
-    Opts.mDebugEmission = Args->hasArg(OPT_emit_g);
-
-    size_t OptLevel = clang::getLastArgIntValue(*Args,
-                                                OPT_optimization_level,
-                                                3,
-                                                DiagEngine);
-
-    Opts.mOptimizationLevel = OptLevel == 0 ? llvm::CodeGenOpt::None
-                                            : llvm::CodeGenOpt::Aggressive;
-
-    Opts.mTargetAPI = clang::getLastArgIntValue(*Args,
-                                                OPT_target_api,
-                                                RS_VERSION,
-                                                DiagEngine);
-  }
-}
-
 static const char *DetermineOutputFile(const std::string &OutputDir,
                                        const char *InputFile,
                                        slang::Slang::OutputType OutputType,
@@ -397,7 +133,7 @@
 int main(int argc, const char **argv) {
   std::set<std::string> SavedStrings;
   llvm::SmallVector<const char*, 256> ArgVector;
-  RSCCOptions Opts;
+  slang::RSCCOptions Opts;
   llvm::SmallVector<const char*, 16> Inputs;
   std::string Argv0;
 
@@ -420,7 +156,7 @@
 
   slang::Slang::GlobalInitialization();
 
-  ParseArguments(ArgVector, Inputs, Opts, DiagEngine);
+  slang::ParseArguments(ArgVector, Inputs, Opts, DiagEngine);
 
   // Exits when there's any error occurred during parsing the arguments
   if (DiagEngine.hasErrorOccurred()) {
@@ -429,7 +165,7 @@
   }
 
   if (Opts.mShowHelp) {
-    llvm::OwningPtr<OptTable> OptTbl(createRSCCOptTable());
+    llvm::OwningPtr<llvm::opt::OptTable> OptTbl(slang::createRSCCOptTable());
     OptTbl->PrintHelp(llvm::outs(), Argv0.c_str(),
                       "Renderscript source compiler");
     return 0;