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

  // Always turn off warnings for empty initializers, since we really want to
  // employ/encourage this extension for zero-initialization of structures.
  DiagOpts.Warnings.push_back("no-gnu-empty-initializer");

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