/*
 * Copyright 2014, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Frontend/Utils.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 "rs_cc_options.h"
#include "slang.h"
#include "slang_assert.h"

#include <cstdlib>
#include <string>
#include <utility>
#include <vector>

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 llvm::opt::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, llvm::opt::Option::KIND##Class, \
        PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS                      \
  }                                                                            \
  ,
#include "RSCCOptions.inc"
#undef OPTION
#undef PREFIX
};

namespace {

class RSCCOptTable : public llvm::opt::OptTable {
 public:
  RSCCOptTable()
      : OptTable(RSCCInfoTable,
                 sizeof(RSCCInfoTable) / sizeof(RSCCInfoTable[0])) {}
};
}

namespace slang {

llvm::opt::OptTable *createRSCCOptTable() { return new RSCCOptTable(); }

// This function is similar to
// clang/lib/Frontend/CompilerInvocation::CreateFromArgs.
bool ParseArguments(const llvm::ArrayRef<const char *> &ArgsIn,
                    llvm::SmallVectorImpl<const char *> &Inputs,
                    RSCCOptions &Opts, clang::DiagnosticOptions &DiagOpts,
                    llvm::StringSaver &StringSaver) {
  // We use a different diagnostic engine for argument parsing from the rest of
  // the work.  This mimics what's done in clang.  I believe it is so the
  // argument parsing errors are well formatted while the full errors can be
  // influenced by command line arguments.
  llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> ArgumentParseDiagOpts(
      new clang::DiagnosticOptions());
  llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagIDs(
      new clang::DiagnosticIDs());
  DiagnosticBuffer DiagsBuffer;
  clang::DiagnosticsEngine DiagEngine(DiagIDs, &*ArgumentParseDiagOpts,
                                      &DiagsBuffer, false);

  // Populate a vector with the command line arguments, expanding command files
  // that have been included via the '@' argument.
  llvm::SmallVector<const char *, 256> ArgVector;
  ArgVector.append(ArgsIn.begin(), ArgsIn.end());
  llvm::cl::ExpandResponseFiles(StringSaver, llvm::cl::TokenizeGNUCommandLine,
                                ArgVector, false);

  std::unique_ptr<llvm::opt::OptTable> OptParser(createRSCCOptTable());
  unsigned MissingArgIndex = 0;
  unsigned MissingArgCount = 0;
  std::unique_ptr<llvm::opt::InputArgList> Args(
      OptParser->ParseArgs(ArgVector.begin() + 1, ArgVector.end(),
                           MissingArgIndex, MissingArgCount));

  // Check for missing argument error.
  if (MissingArgCount) {
    DiagEngine.Report(clang::diag::err_drv_missing_argument)
        << Args->getArgString(MissingArgIndex) << MissingArgCount;
  }

  // Issue errors on unknown arguments.
  for (llvm::opt::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);
  }

  DiagOpts.IgnoreWarnings = Args->hasArg(OPT_w);
  DiagOpts.Warnings = Args->getAllArgValues(OPT_W);

  for (llvm::opt::ArgList::const_iterator it = Args->begin(), ie = Args->end();
       it != ie; ++it) {
    const llvm::opt::Arg *A = *it;
    if (A->getOption().getKind() == llvm::opt::Option::InputClass)
      Inputs.push_back(A->getValue());
  }

  Opts.mIncludePaths = Args->getAllArgValues(OPT_I);

  Opts.mBitcodeOutputDir = Args->getLastArgValue(OPT_o);

  if (const llvm::opt::Arg *A = Args->getLastArg(OPT_M_Group)) {
    switch (A->getOption().getID()) {
    case OPT_M: {
      Opts.mEmitDependency = true;
      Opts.mOutputType = Slang::OT_Dependency;
      break;
    }
    case OPT_MD: {
      Opts.mEmitDependency = true;
      Opts.mOutputType = Slang::OT_Bitcode;
      break;
    }
    case OPT_MP: {
      Opts.mEmitDependency = true;
      Opts.mOutputType = Slang::OT_Bitcode;
      Opts.mEmitPhonyDependency = true;
      break;
    }
    default: { slangAssert(false && "Invalid option in M group!"); }
    }
  }

  if (const llvm::opt::Arg *A = Args->getLastArg(OPT_Output_Type_Group)) {
    switch (A->getOption().getID()) {
    case OPT_emit_asm: {
      Opts.mOutputType = Slang::OT_Assembly;
      break;
    }
    case OPT_emit_llvm: {
      Opts.mOutputType = Slang::OT_LLVMAssembly;
      break;
    }
    case OPT_emit_bc: {
      Opts.mOutputType = Slang::OT_Bitcode;
      break;
    }
    case OPT_emit_nothing: {
      Opts.mOutputType = Slang::OT_Nothing;
      break;
    }
    default: { slangAssert(false && "Invalid option in output type group!"); }
    }
  }

  if (Opts.mEmitDependency && ((Opts.mOutputType != Slang::OT_Bitcode) &&
                               (Opts.mOutputType != 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 = BCST_APK_RESOURCE;
  else if (BitcodeStorageValue == "jc")
    Opts.mBitcodeStorage = BCST_JAVA_CODE;
  else if (!BitcodeStorageValue.empty())
    DiagEngine.Report(clang::diag::err_drv_invalid_value)
        << OptParser->getOptionName(OPT_bitcode_storage) << BitcodeStorageValue;

  llvm::opt::Arg *lastBitwidthArg = Args->getLastArg(OPT_m32, OPT_m64);
  if (Args->hasArg(OPT_reflect_cpp)) {
    Opts.mBitcodeStorage = BCST_CPP_CODE;
    // mJavaReflectionPathBase can be set for C++ reflected builds.
    // Set it to the standard mBitcodeOutputDir (via -o) by default.
    if (Opts.mJavaReflectionPathBase.empty()) {
      Opts.mJavaReflectionPathBase = Opts.mBitcodeOutputDir;
    }

    // Check for bitwidth arguments.
    if (lastBitwidthArg) {
      if (lastBitwidthArg->getOption().matches(OPT_m32)) {
        Opts.mBitWidth = 32;
      } else {
        Opts.mBitWidth = 64;
      }
    }
  } else if (lastBitwidthArg) {
      // -m32/-m64 are forbidden for non-C++ reflection paths for non-eng builds
      // (they would make it too easy for a developer to accidentally create and
      // release an APK that has 32-bit or 64-bit bitcode but not both).
#ifdef __ENABLE_INTERNAL_OPTIONS
      if (lastBitwidthArg->getOption().matches(OPT_m32)) {
        Opts.mBitWidth = 32;
      } else {
        Opts.mBitWidth = 64;
      }
      Opts.mEmit3264 = false;
#else
      DiagEngine.Report(
          DiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
                                     "cannot use -m32/-m64 without specifying "
                                     "C++ reflection (-reflect-c++)"));
#endif
  }

  Opts.mDependencyOutputDir =
      Args->getLastArgValue(OPT_output_dep_dir, Opts.mBitcodeOutputDir);
  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);
  Opts.mVerbose = Args->hasArg(OPT_verbose);
  Opts.mASTPrint = Args->hasArg(OPT_ast_print);

  // Delegate options

  std::vector<std::string> DelegatedStrings;
  for (int Opt : std::vector<unsigned>{OPT_debug, OPT_print_after_all, OPT_print_before_all}) {
    if (Args->hasArg(Opt)) {
      // TODO: Don't assume that the option begins with "-"; determine this programmatically instead.
      DelegatedStrings.push_back(std::string("-") + std::string(OptParser->getOptionName(Opt)));
      slangAssert(OptParser->getOptionKind(Opt) == llvm::opt::Option::FlagClass);
    }
  }
  if (DelegatedStrings.size()) {
    std::vector<const char *> DelegatedCStrs;
    DelegatedCStrs.push_back(*ArgVector.data()); // program name
    std::for_each(DelegatedStrings.cbegin(), DelegatedStrings.cend(),
                  [&DelegatedCStrs](const std::string &String) { DelegatedCStrs.push_back(String.c_str()); });
    llvm::cl::ParseCommandLineOptions(DelegatedCStrs.size(), DelegatedCStrs.data());
  }

  // If we are emitting both 32-bit and 64-bit bitcode, we must embed it.

  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);

  if (Opts.mTargetAPI == 0) {
    Opts.mTargetAPI = UINT_MAX;
  }

  if ((Opts.mTargetAPI < 21) || (Opts.mBitcodeStorage == BCST_CPP_CODE))
    Opts.mEmit3264 = false;
  if (Opts.mEmit3264)
    Opts.mBitcodeStorage = BCST_JAVA_CODE;

  if (DiagEngine.hasErrorOccurred()) {
    llvm::errs() << DiagsBuffer.str();
    return false;
  }

  return true;
}
}
