//===- subzero/src/IceClFlags.h - Cl Flags for translation ------*- C++ -*-===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Declares Ice::ClFlags which implements command line processing.
///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICECLFLAGS_H
#define SUBZERO_SRC_ICECLFLAGS_H
#include "IceDefs.h"
#include "IceBuildDefs.h"
#include "IceClFlags.def"
#include "IceRangeSpec.h"
#include "IceTypes.h"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#endif // __clang__
#include "llvm/IRReader/IRReader.h"
#ifdef __clang__
#pragma clang diagnostic pop
#endif // __clang__
#include <string>
#include <utility>
#include <vector>
#ifndef PNACL_LLVM
namespace llvm {
// \brief Define the expected format of the file.
enum NaClFileFormat {
// LLVM IR source or bitcode file (as appropriate).
LLVMFormat,
// PNaCl bitcode file.
PNaClFormat,
// Autodetect if PNaCl or LLVM format.
AutodetectFileFormat
};
} // end of namespace llvm
#endif // !PNACL_LLVM
namespace Ice {
// detail defines the type cl_type_traits, which is used to define the
// getters/setters for the ClFlags class. It converts the cl_detail::*_flag
// types to appropriate types for the several getters and setters created.
namespace detail {
// Base cl_type_traits.
template <typename B, typename CL> struct cl_type_traits {};
// cl_type_traits specialized cl::list<std::string>, non-MINIMAL build.
template <> struct cl_type_traits<std::string, cl_detail::dev_list_flag> {
using storage_type = std::vector<std::string>;
};
// cl_type_traits specialized cl::list<Ice::VerboseItem>, non-MINIMAL build.
template <> struct cl_type_traits<Ice::VerboseItem, cl_detail::dev_list_flag> {
using storage_type = Ice::VerboseMask;
};
// cl_type_traits specialized cl::opt<T>, non-MINIMAL build.
template <typename T> struct cl_type_traits<T, cl_detail::dev_opt_flag> {
using storage_type = T;
};
// cl_type_traits specialized cl::opt<T>, MINIMAL build.
template <typename T> struct cl_type_traits<T, cl_detail::release_opt_flag> {
using storage_type = T;
};
} // end of namespace detail
/// Define variables which configure translation and related support functions.
class ClFlags {
ClFlags(const ClFlags &) = delete;
ClFlags &operator=(const ClFlags &) = delete;
public:
/// User defined constructor.
ClFlags() { resetClFlags(); }
/// The command line flags.
static ClFlags Flags;
/// \brief Parse commmand line options for Subzero.
///
/// This is done use cl::ParseCommandLineOptions() and the static variables of
/// type cl::opt defined in IceClFlags.cpp
static void parseFlags(int argc, const char *const *argv);
/// Reset all configuration options to their nominal values.
void resetClFlags();
/// \brief Retrieve the configuration option state
///
/// This is defined by static variables
/// anonymous_namespace{IceClFlags.cpp}::AllowErrorRecoveryObj,
/// anonymous_namespace{IceClFlags.cpp}::AllowIacaMarksObj,
/// ...
static void getParsedClFlags(ClFlags &OutFlags);
#define X(Name, Type, ClType, ...) \
private: \
using Name##StorageType = \
detail::cl_type_traits<Type, cl_detail::ClType>::storage_type; \
\
Name##StorageType Name; \
\
template <bool E> \
typename std::enable_if<E, void>::type set##Name##Impl( \
Name##StorageType Value) { \
Name = std::move(Value); \
} \
\
template <bool E> \
typename std::enable_if<!E, void>::type set##Name##Impl(Name##StorageType) { \
} \
\
public: \
Name##StorageType get##Name() const { return Name; } \
void set##Name(Name##StorageType Value) { \
/* TODO(jpp): figure out which optional flags are used in minimal, and \
what are the defaults for them. */ \
static constexpr bool Enable = \
std::is_same<cl_detail::ClType, cl_detail::release_opt_flag>::value || \
!BuildDefs::minimal() || true; \
set##Name##Impl<Enable>(std::move(Value)); \
} \
\
private:
COMMAND_LINE_FLAGS
#undef X
public:
bool isSequential() const { return NumTranslationThreads == 0; }
bool isParseParallel() const {
return getParseParallel() && !isSequential() && getBuildOnRead();
}
std::string getAppName() const { return AppName; }
void setAppName(const std::string &Value) { AppName = Value; }
/// \brief Get the value of ClFlags::GenerateUnitTestMessages
///
/// Note: If dump routines have been turned off, the error messages
/// will not be readable. Hence, turn off.
bool getGenerateUnitTestMessages() const {
return !BuildDefs::dump() || GenerateUnitTestMessages;
}
/// Set ClFlags::GenerateUnitTestMessages to a new value
void setGenerateUnitTestMessages(bool NewValue) {
GenerateUnitTestMessages = NewValue;
}
bool matchForceO2(GlobalString Name, uint32_t Number) const {
return ForceO2.match(Name, Number);
}
bool matchSplitInsts(const std::string &Name, uint32_t Number) const {
return SplitInsts.match(Name, Number);
}
bool matchTestStatus(GlobalString Name, uint32_t Number) const {
return TestStatus.match(Name, Number);
}
bool matchTimingFocus(GlobalString Name, uint32_t Number) const {
return TimingFocus.match(Name, Number);
}
bool matchTranslateOnly(GlobalString Name, uint32_t Number) const {
return TranslateOnly.match(Name, Number);
}
bool matchVerboseFocusOn(GlobalString Name, uint32_t Number) const {
return VerboseFocus.match(Name, Number);
}
bool matchVerboseFocusOn(const std::string &Name, uint32_t Number) const {
return VerboseFocus.match(Name, Number);
}
private:
std::string AppName;
/// Initialized to false; not set by the command line.
bool GenerateUnitTestMessages;
RangeSpec ForceO2;
RangeSpec SplitInsts;
RangeSpec TestStatus;
RangeSpec TimingFocus;
RangeSpec TranslateOnly;
RangeSpec VerboseFocus;
};
inline const ClFlags &getFlags() { return ClFlags::Flags; }
} // end of namespace Ice
#endif // SUBZERO_SRC_ICECLFLAGS_H