//===- subzero/src/IceClFlags.cpp - Command line flags and parsing --------===//
//
//                        The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Defines commandline flags parsing of class Ice::ClFlags.
///
/// This currently relies on llvm::cl to parse. In the future, the minimal build
/// can have a simpler parser.
///
//===----------------------------------------------------------------------===//

#include "IceClFlags.h"

#include "IceClFlags.def"

#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#endif // __clang__

#include "llvm/Support/CommandLine.h"

#ifdef __clang__
#pragma clang diagnostic pop
#endif // __clang__

#include <utility>

namespace {
// cl is used to alias the llvm::cl types and functions that we need.
namespace cl {

using alias = llvm::cl::alias;

using aliasopt = llvm::cl::aliasopt;

using llvm::cl::CommaSeparated;

using desc = llvm::cl::desc;

template <typename T> using initializer = llvm::cl::initializer<T>;

template <typename T> initializer<T> init(const T &Val) {
  return initializer<T>(Val);
}

template <typename T> using list = llvm::cl::list<T>;

using llvm::cl::NotHidden;

template <typename T> using opt = llvm::cl::opt<T>;

using llvm::cl::ParseCommandLineOptions;

using llvm::cl::Positional;

template <typename T> using ValuesClass = llvm::cl::ValuesClass<T>;

template <typename T, typename... A>
ValuesClass<T> values(const char *Arg, T Val, const char *Desc, A &&... Args) {
  return llvm::cl::values(Arg, Val, Desc, std::forward<A>(Args)..., nullptr);
}

using llvm::cl::value_desc;
} // end of namespace cl

// cl_type_traits is used to convert between a tuple of <T, cl_detail::*flag> to
// the appropriate (llvm::)cl object.
template <typename B, typename CL> struct cl_type_traits {};

template <typename T>
struct cl_type_traits<T, ::Ice::cl_detail::dev_list_flag> {
  using cl_type = cl::list<T>;
};

template <typename T> struct cl_type_traits<T, ::Ice::cl_detail::dev_opt_flag> {
  using cl_type = cl::opt<T>;
};

template <typename T>
struct cl_type_traits<T, ::Ice::cl_detail::release_opt_flag> {
  using cl_type = cl::opt<T>;
};

#define X(Name, Type, ClType, ...)                                             \
  cl_type_traits<Type, Ice::cl_detail::ClType>::cl_type Name##Obj(__VA_ARGS__);
COMMAND_LINE_FLAGS
#undef X

// Add declarations that do not need to add members to ClFlags below.
cl::alias AllowExternDefinedSymbolsA(
    "allow-extern", cl::desc("Alias for --allow-externally-defined-symbols"),
    cl::NotHidden, cl::aliasopt(AllowExternDefinedSymbolsObj));

std::string AppNameObj;

} // end of anonymous namespace

namespace Ice {

ClFlags ClFlags::Flags;

void ClFlags::parseFlags(int argc, const char *const *argv) {
  cl::ParseCommandLineOptions(argc, argv);
  AppNameObj = argv[0];
}

namespace {
// flagInitOrStorageTypeDefault is some template voodoo for peeling off the
// llvm::cl modifiers from a flag's declaration, until its initial value is
// found. If none is found, then the default value for the storage type is
// returned.
template <typename Ty> Ty flagInitOrStorageTypeDefault() { return Ty(); }

template <typename Ty, typename T, typename... A>
Ty flagInitOrStorageTypeDefault(cl::initializer<T> &&Value, A &&...) {
  return Value.Init;
}

// is_cl_initializer is used to prevent an ambiguous call between the previous
// version of flagInitOrStorageTypeDefault, and the next, which is flagged by
// g++.
template <typename T> struct is_cl_initializer {
  static constexpr bool value = false;
};

template <typename T> struct is_cl_initializer<cl::initializer<T>> {
  static constexpr bool value = true;
};

template <typename Ty, typename T, typename... A>
typename std::enable_if<!is_cl_initializer<T>::value, Ty>::type
flagInitOrStorageTypeDefault(T &&, A &&... Other) {
  return flagInitOrStorageTypeDefault<Ty>(std::forward<A>(Other)...);
}

} // end of anonymous namespace

void ClFlags::resetClFlags() {
#define X(Name, Type, ClType, ...)                                             \
  Name = flagInitOrStorageTypeDefault<                                         \
      detail::cl_type_traits<Type, cl_detail::ClType>::storage_type>(          \
      __VA_ARGS__);
  COMMAND_LINE_FLAGS
#undef X
}

namespace {

// toSetterParam is template magic that is needed to convert between (llvm::)cl
// objects and the arguments to ClFlags' setters. ToSetterParam is a traits
// object that we need in order for the multiple specializations to
// toSetterParam to agree on their return type.
template <typename T> struct ToSetterParam { using ReturnType = const T &; };

template <> struct ToSetterParam<cl::list<Ice::VerboseItem>> {
  using ReturnType = Ice::VerboseMask;
};

template <typename T>
typename ToSetterParam<T>::ReturnType toSetterParam(const T &Param) {
  return Param;
}

template <>
ToSetterParam<cl::list<Ice::VerboseItem>>::ReturnType
toSetterParam(const cl::list<Ice::VerboseItem> &Param) {
  Ice::VerboseMask VMask = Ice::IceV_None;
  // Don't generate verbose messages if routines to dump messages are not
  // available.
  if (BuildDefs::dump()) {
    for (unsigned i = 0; i != Param.size(); ++i)
      VMask |= Param[i];
  }
  return VMask;
}

} // end of anonymous namespace

void ClFlags::getParsedClFlags(ClFlags &OutFlags) {
#define X(Name, Type, ClType, ...) OutFlags.set##Name(toSetterParam(Name##Obj));
  COMMAND_LINE_FLAGS
#undef X

  // If any value needs a non-trivial parsed value, set it below.
  OutFlags.setAllowExternDefinedSymbols(AllowExternDefinedSymbolsObj ||
                                        DisableInternalObj);
  OutFlags.setDisableHybridAssembly(DisableHybridAssemblyObj ||
                                    (OutFileTypeObj != Ice::FT_Iasm));
  OutFlags.ForceO2.init(OutFlags.getForceO2String());
  OutFlags.TestStatus.init(OutFlags.getTestStatusString());
  OutFlags.TimingFocus.init(OutFlags.getTimingFocusOnString());
  OutFlags.TranslateOnly.init(OutFlags.getTranslateOnlyString());
  OutFlags.VerboseFocus.init(OutFlags.getVerboseFocusOnString());
}

} // end of namespace Ice
