reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
//===- llvm/Support/Options.h - Debug options support -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \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

/// 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;

  /// 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() {}

  /// Returns a reference to the singleton instance.
  static OptionRegistry &instance();

  /// 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);
  }

  /// 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