Andrew Scull | 5e1ddfa | 2018-08-14 10:06:54 +0100 | [diff] [blame^] | 1 | //===- llvm/Support/Options.h - Debug options support -----------*- C++ -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | /// \file |
| 10 | /// This file declares helper objects for defining debug options that can be |
| 11 | /// configured via the command line. The new API currently builds on the cl::opt |
| 12 | /// API, but does not require the use of static globals. |
| 13 | /// |
| 14 | /// With this API options are registered during initialization. For passes, this |
| 15 | /// happens during pass initialization. Passes with options will call a static |
| 16 | /// registerOptions method during initialization that registers options with the |
| 17 | /// OptionRegistry. An example implementation of registerOptions is: |
| 18 | /// |
| 19 | /// static void registerOptions() { |
| 20 | /// OptionRegistry::registerOption<bool, Scalarizer, |
| 21 | /// &Scalarizer::ScalarizeLoadStore>( |
| 22 | /// "scalarize-load-store", |
| 23 | /// "Allow the scalarizer pass to scalarize loads and store", false); |
| 24 | /// } |
| 25 | /// |
| 26 | /// When reading data for options the interface is via the LLVMContext. Option |
| 27 | /// data for passes should be read from the context during doInitialization. An |
| 28 | /// example of reading the above option would be: |
| 29 | /// |
| 30 | /// ScalarizeLoadStore = |
| 31 | /// M.getContext().getOption<bool, |
| 32 | /// Scalarizer, |
| 33 | /// &Scalarizer::ScalarizeLoadStore>(); |
| 34 | /// |
| 35 | //===----------------------------------------------------------------------===// |
| 36 | |
| 37 | #ifndef LLVM_SUPPORT_OPTIONS_H |
| 38 | #define LLVM_SUPPORT_OPTIONS_H |
| 39 | |
| 40 | #include "llvm/ADT/DenseMap.h" |
| 41 | #include "llvm/Support/CommandLine.h" |
| 42 | |
| 43 | namespace llvm { |
| 44 | |
| 45 | namespace detail { |
| 46 | |
| 47 | // Options are keyed of the unique address of a static character synthesized |
| 48 | // based on template arguments. |
| 49 | template <typename ValT, typename Base, ValT(Base::*Mem)> class OptionKey { |
| 50 | public: |
| 51 | static char ID; |
| 52 | }; |
| 53 | |
| 54 | template <typename ValT, typename Base, ValT(Base::*Mem)> |
| 55 | char OptionKey<ValT, Base, Mem>::ID = 0; |
| 56 | |
| 57 | } // namespace detail |
| 58 | |
| 59 | /// \brief Singleton class used to register debug options. |
| 60 | /// |
| 61 | /// The OptionRegistry is responsible for managing lifetimes of the options and |
| 62 | /// provides interfaces for option registration and reading values from options. |
| 63 | /// This object is a singleton, only one instance should ever exist so that all |
| 64 | /// options are registered in the same place. |
| 65 | class OptionRegistry { |
| 66 | private: |
| 67 | DenseMap<void *, cl::Option *> Options; |
| 68 | |
| 69 | /// \brief Adds a cl::Option to the registry. |
| 70 | /// |
| 71 | /// \param Key unique key for option |
| 72 | /// \param O option to map to \p Key |
| 73 | /// |
| 74 | /// Allocated cl::Options are owned by the OptionRegistry and are deallocated |
| 75 | /// on destruction or removal |
| 76 | void addOption(void *Key, cl::Option *O); |
| 77 | |
| 78 | public: |
| 79 | ~OptionRegistry(); |
| 80 | OptionRegistry() {} |
| 81 | |
| 82 | /// \brief Returns a reference to the singleton instance. |
| 83 | static OptionRegistry &instance(); |
| 84 | |
| 85 | /// \brief Registers an option with the OptionRegistry singleton. |
| 86 | /// |
| 87 | /// \tparam ValT type of the option's data |
| 88 | /// \tparam Base class used to key the option |
| 89 | /// \tparam Mem member of \p Base used for keying the option |
| 90 | /// |
| 91 | /// Options are keyed off the template parameters to generate unique static |
| 92 | /// characters. The template parameters are (1) the type of the data the |
| 93 | /// option stores (\p ValT), the class that will read the option (\p Base), |
| 94 | /// and the member that the class will store the data into (\p Mem). |
| 95 | template <typename ValT, typename Base, ValT(Base::*Mem)> |
| 96 | static void registerOption(StringRef ArgStr, StringRef Desc, |
| 97 | const ValT &InitValue) { |
| 98 | cl::opt<ValT> *Option = new cl::opt<ValT>(ArgStr, cl::desc(Desc), |
| 99 | cl::Hidden, cl::init(InitValue)); |
| 100 | instance().addOption(&detail::OptionKey<ValT, Base, Mem>::ID, Option); |
| 101 | } |
| 102 | |
| 103 | /// \brief Returns the value of the option. |
| 104 | /// |
| 105 | /// \tparam ValT type of the option's data |
| 106 | /// \tparam Base class used to key the option |
| 107 | /// \tparam Mem member of \p Base used for keying the option |
| 108 | /// |
| 109 | /// Reads option values based on the key generated by the template parameters. |
| 110 | /// Keying for get() is the same as keying for registerOption. |
| 111 | template <typename ValT, typename Base, ValT(Base::*Mem)> ValT get() const { |
| 112 | auto It = Options.find(&detail::OptionKey<ValT, Base, Mem>::ID); |
| 113 | assert(It != Options.end() && "Option not in OptionRegistry"); |
| 114 | return *(cl::opt<ValT> *)It->second; |
| 115 | } |
| 116 | }; |
| 117 | |
| 118 | } // namespace llvm |
| 119 | |
| 120 | #endif |