Index: llvm/trunk/include/llvm/IR/LLVMContext.h =================================================================== --- llvm/trunk/include/llvm/IR/LLVMContext.h +++ llvm/trunk/include/llvm/IR/LLVMContext.h @@ -18,6 +18,7 @@ #include "llvm-c/Core.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Options.h" namespace llvm { @@ -163,6 +164,14 @@ void emitError(const Instruction *I, const Twine &ErrorStr); void emitError(const Twine &ErrorStr); + /// \brief Query for a debug option's value. + /// + /// This function returns typed data populated from command line parsing. + template + ValT getOption() const { + return OptionRegistry::instance().template get(); + } + private: LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION; void operator=(LLVMContext&) LLVM_DELETED_FUNCTION; Index: llvm/trunk/include/llvm/PassSupport.h =================================================================== --- llvm/trunk/include/llvm/PassSupport.h +++ llvm/trunk/include/llvm/PassSupport.h @@ -82,6 +82,15 @@ CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ } +#define INITIALIZE_PASS_WITH_OPTIONS(PassName, Arg, Name, Cfg, Analysis) \ + INITIALIZE_PASS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \ + PassName::registerOptions(); \ + INITIALIZE_PASS_END(PassName, Arg, Name, Cfg, Analysis) + +#define INITIALIZE_PASS_WITH_OPTIONS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \ + INITIALIZE_PASS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \ + PassName::registerOptions(); \ + template Pass *callDefaultCtor() { return new PassName(); } Index: llvm/trunk/include/llvm/Support/Options.h =================================================================== --- llvm/trunk/include/llvm/Support/Options.h +++ llvm/trunk/include/llvm/Support/Options.h @@ -0,0 +1,115 @@ +//===- 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( +/// "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().template getOption(); +/// +//===----------------------------------------------------------------------===// + +#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 class OptionKey { +public: + static char ID; +}; + +template +char OptionKey::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 teh same place. +class OptionRegistry { +private: + DenseMap 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 owened 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. + /// + /// \param ValT type of the option's data + /// \param Base class used to key the option + /// \param 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 memeber that the class will store the data into (\p Mem). + template + static void registerOption(const char *ArgStr, const char *Desc, + const ValT &InitValue) { + cl::opt *Option = new cl::opt(ArgStr, cl::desc(Desc), + cl::Hidden, cl::init(InitValue)); + instance().addOption(&detail::OptionKey::ID, Option); + } + + /// \brief Returns the value of the option. + /// + /// \param ValT type of the option's data + /// \param Base class used to key the option + /// \param 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 ValT get() const { + auto It = Options.find(&detail::OptionKey::ID); + assert(It != Options.end() && "Option not in OptionRegistry"); + return *(cl::opt *)It->second; + } +}; + +} // namespace llvm Index: llvm/trunk/lib/Support/CMakeLists.txt =================================================================== --- llvm/trunk/lib/Support/CMakeLists.txt +++ llvm/trunk/lib/Support/CMakeLists.txt @@ -40,6 +40,7 @@ MemoryBuffer.cpp MemoryObject.cpp MD5.cpp + Options.cpp PluginLoader.cpp PrettyStackTrace.cpp RandomNumberGenerator.cpp Index: llvm/trunk/lib/Support/CommandLine.cpp =================================================================== --- llvm/trunk/lib/Support/CommandLine.cpp +++ llvm/trunk/lib/Support/CommandLine.cpp @@ -113,9 +113,15 @@ } void Option::removeArgument() { - assert(NextRegistered && "argument never registered"); - assert(RegisteredOptionList == this && "argument is not the last registered"); - RegisteredOptionList = NextRegistered; + if (RegisteredOptionList == this) { + RegisteredOptionList = NextRegistered; + MarkOptionsChanged(); + return; + } + Option *O = RegisteredOptionList; + for (; O->NextRegistered != this; O = O->NextRegistered) + ; + O->NextRegistered = NextRegistered; MarkOptionsChanged(); } Index: llvm/trunk/lib/Support/Options.cpp =================================================================== --- llvm/trunk/lib/Support/Options.cpp +++ llvm/trunk/lib/Support/Options.cpp @@ -0,0 +1,33 @@ +//===- llvm/Support/Options.cpp - 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. +// +//===----------------------------------------------------------------------===// +// +// This file implements the helper objects for defining debug options using the +// new API built on cl::opt, but not requiring the use of static globals. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Options.h" +#include "llvm/Support/ManagedStatic.h" + +using namespace llvm; + +OptionRegistry::~OptionRegistry() { + for (auto IT = Options.begin(); IT != Options.end(); ++IT) + delete IT->second; +} + +void OptionRegistry::addOption(void *Key, cl::Option *O) { + assert(Options.find(Key) == Options.end() && + "Argument with this key already registerd"); + Options.insert(std::make_pair(Key, O)); +} + +static ManagedStatic OR; + +OptionRegistry &OptionRegistry::instance() { return *OR; } Index: llvm/trunk/lib/Transforms/Scalar/Scalarizer.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/Scalarizer.cpp +++ llvm/trunk/lib/Transforms/Scalar/Scalarizer.cpp @@ -150,6 +150,16 @@ bool visitLoadInst(LoadInst &); bool visitStoreInst(StoreInst &); + static void registerOptions() { + // This is disabled by default because having separate loads and stores + // makes it more likely that the -combiner-alias-analysis limits will be + // reached. + OptionRegistry::registerOption( + "scalarize-load-store", + "Allow the scalarizer pass to scalarize loads and store", false); + } + private: Scatterer scatter(Instruction *, Value *); void gather(Instruction *, const ValueVector &); @@ -164,19 +174,14 @@ GatherList Gathered; unsigned ParallelLoopAccessMDKind; const DataLayout *DL; + bool ScalarizeLoadStore; }; char Scalarizer::ID = 0; } // end anonymous namespace -// This is disabled by default because having separate loads and stores makes -// it more likely that the -combiner-alias-analysis limits will be reached. -static cl::opt ScalarizeLoadStore - ("scalarize-load-store", cl::Hidden, cl::init(false), - cl::desc("Allow the scalarizer pass to scalarize loads and store")); - -INITIALIZE_PASS(Scalarizer, "scalarizer", "Scalarize vector operations", - false, false) +INITIALIZE_PASS_WITH_OPTIONS(Scalarizer, "scalarizer", + "Scalarize vector operations", false, false); Scatterer::Scatterer(BasicBlock *bb, BasicBlock::iterator bbi, Value *v, ValueVector *cachePtr) @@ -236,7 +241,10 @@ bool Scalarizer::doInitialization(Module &M) { ParallelLoopAccessMDKind = - M.getContext().getMDKindID("llvm.mem.parallel_loop_access"); + M.getContext().getMDKindID("llvm.mem.parallel_loop_access"); + ScalarizeLoadStore = + M.getContext() + .template getOption(); return false; }