//===- llvm/Support/Options.h - Debug options support -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// \file /// This file declares helper objects for defining debug options that can be /// configured via the command line. The new API currently builds on the cl::opt /// API, but does not require the use of static globals. /// /// With this API options are registered during initialization. For passes, this /// happens during pass initialization. Passes with options will call a static /// registerOptions method during initialization that registers options with the /// OptionRegistry. An example implementation of registerOptions is: /// /// static void registerOptions() { /// OptionRegistry::registerOption<bool, Scalarizer, /// &Scalarizer::ScalarizeLoadStore>( /// "scalarize-load-store", /// "Allow the scalarizer pass to scalarize loads and store", false); /// } /// /// When reading data for options the interface is via the LLVMContext. Option /// data for passes should be read from the context during doInitialization. An /// example of reading the above option would be: /// /// ScalarizeLoadStore = /// M.getContext().getOption<bool, /// Scalarizer, /// &Scalarizer::ScalarizeLoadStore>(); /// //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_OPTIONS_H #define LLVM_SUPPORT_OPTIONS_H #include "llvm/ADT/DenseMap.h" #include "llvm/Support/CommandLine.h" namespace llvm { namespace detail { // Options are keyed of the unique address of a static character synthesized // based on template arguments. template <typename ValT, typename Base, ValT(Base::*Mem)> class OptionKey { public: static char ID; }; template <typename ValT, typename Base, ValT(Base::*Mem)> char OptionKey<ValT, Base, Mem>::ID = 0; } // namespace detail /// \brief Singleton class used to register debug options. /// /// The OptionRegistry is responsible for managing lifetimes of the options and /// provides interfaces for option registration and reading values from options. /// This object is a singleton, only one instance should ever exist so that all /// options are registered in the same place. class OptionRegistry { private: DenseMap<void *, cl::Option *> Options; /// \brief Adds a cl::Option to the registry. /// /// \param Key unique key for option /// \param O option to map to \p Key /// /// Allocated cl::Options are owned by the OptionRegistry and are deallocated /// on destruction or removal void addOption(void *Key, cl::Option *O); public: ~OptionRegistry(); OptionRegistry() {} /// \brief Returns a reference to the singleton instance. static OptionRegistry &instance(); /// \brief Registers an option with the OptionRegistry singleton. /// /// \tparam ValT type of the option's data /// \tparam Base class used to key the option /// \tparam Mem member of \p Base used for keying the option /// /// Options are keyed off the template parameters to generate unique static /// characters. The template parameters are (1) the type of the data the /// option stores (\p ValT), the class that will read the option (\p Base), /// and the member that the class will store the data into (\p Mem). template <typename ValT, typename Base, ValT(Base::*Mem)> static void registerOption(StringRef ArgStr, StringRef Desc, const ValT &InitValue) { cl::opt<ValT> *Option = new cl::opt<ValT>(ArgStr, cl::desc(Desc), cl::Hidden, cl::init(InitValue)); instance().addOption(&detail::OptionKey<ValT, Base, Mem>::ID, Option); } /// \brief Returns the value of the option. /// /// \tparam ValT type of the option's data /// \tparam Base class used to key the option /// \tparam Mem member of \p Base used for keying the option /// /// Reads option values based on the key generated by the template parameters. /// Keying for get() is the same as keying for registerOption. template <typename ValT, typename Base, ValT(Base::*Mem)> ValT get() const { auto It = Options.find(&detail::OptionKey<ValT, Base, Mem>::ID); assert(It != Options.end() && "Option not in OptionRegistry"); return *(cl::opt<ValT> *)It->second; } }; } // namespace llvm #endif