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