/*
 * 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(llvm::makeArrayRef(RSCCInfoTable)) {}
};
}

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;
  // Skip over the command name, or we will mistakenly process it as a source file.
  ArgVector.append(ArgsIn.slice(1).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;
  llvm::opt::InputArgList Args =
      OptParser->ParseArgs(ArgVector, 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;
}
}
