mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-26 07:24:25 +00:00
Defining a new API for debug options that doesn't rely on static global cl::opts.
Summary: This is based on the discussions from the LLVMDev thread: http://lists.cs.uiuc.edu/pipermail/llvmdev/2014-August/075886.html Reviewers: chandlerc Reviewed By: chandlerc Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D5389 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219854 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -18,6 +18,7 @@
|
|||||||
#include "llvm-c/Core.h"
|
#include "llvm-c/Core.h"
|
||||||
#include "llvm/Support/CBindingWrapping.h"
|
#include "llvm/Support/CBindingWrapping.h"
|
||||||
#include "llvm/Support/Compiler.h"
|
#include "llvm/Support/Compiler.h"
|
||||||
|
#include "llvm/Support/Options.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
@ -163,6 +164,14 @@ public:
|
|||||||
void emitError(const Instruction *I, const Twine &ErrorStr);
|
void emitError(const Instruction *I, const Twine &ErrorStr);
|
||||||
void emitError(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 <typename ValT, typename Base, ValT(Base::*Mem)>
|
||||||
|
ValT getOption() const {
|
||||||
|
return OptionRegistry::instance().template get<ValT, Base, Mem>();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION;
|
LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION;
|
||||||
void operator=(LLVMContext&) LLVM_DELETED_FUNCTION;
|
void operator=(LLVMContext&) LLVM_DELETED_FUNCTION;
|
||||||
|
@ -82,6 +82,15 @@ class TargetMachine;
|
|||||||
CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \
|
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<typename PassName>
|
template<typename PassName>
|
||||||
Pass *callDefaultCtor() { return new PassName(); }
|
Pass *callDefaultCtor() { return new PassName(); }
|
||||||
|
|
||||||
|
115
include/llvm/Support/Options.h
Normal file
115
include/llvm/Support/Options.h
Normal file
@ -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<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().template getOption<bool,
|
||||||
|
/// Scalarizer,
|
||||||
|
/// &Scalarizer::ScalarizeLoadStore>();
|
||||||
|
///
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#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 teh 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 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 <typename ValT, typename Base, ValT(Base::*Mem)>
|
||||||
|
static void registerOption(const char *ArgStr, const char *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.
|
||||||
|
///
|
||||||
|
/// \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 <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
|
@ -40,6 +40,7 @@ add_llvm_library(LLVMSupport
|
|||||||
MemoryBuffer.cpp
|
MemoryBuffer.cpp
|
||||||
MemoryObject.cpp
|
MemoryObject.cpp
|
||||||
MD5.cpp
|
MD5.cpp
|
||||||
|
Options.cpp
|
||||||
PluginLoader.cpp
|
PluginLoader.cpp
|
||||||
PrettyStackTrace.cpp
|
PrettyStackTrace.cpp
|
||||||
RandomNumberGenerator.cpp
|
RandomNumberGenerator.cpp
|
||||||
|
@ -113,9 +113,15 @@ void Option::addArgument() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Option::removeArgument() {
|
void Option::removeArgument() {
|
||||||
assert(NextRegistered && "argument never registered");
|
if (RegisteredOptionList == this) {
|
||||||
assert(RegisteredOptionList == this && "argument is not the last registered");
|
RegisteredOptionList = NextRegistered;
|
||||||
RegisteredOptionList = NextRegistered;
|
MarkOptionsChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Option *O = RegisteredOptionList;
|
||||||
|
for (; O->NextRegistered != this; O = O->NextRegistered)
|
||||||
|
;
|
||||||
|
O->NextRegistered = NextRegistered;
|
||||||
MarkOptionsChanged();
|
MarkOptionsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
33
lib/Support/Options.cpp
Normal file
33
lib/Support/Options.cpp
Normal file
@ -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<OptionRegistry> OR;
|
||||||
|
|
||||||
|
OptionRegistry &OptionRegistry::instance() { return *OR; }
|
@ -150,6 +150,16 @@ public:
|
|||||||
bool visitLoadInst(LoadInst &);
|
bool visitLoadInst(LoadInst &);
|
||||||
bool visitStoreInst(StoreInst &);
|
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<bool, Scalarizer,
|
||||||
|
&Scalarizer::ScalarizeLoadStore>(
|
||||||
|
"scalarize-load-store",
|
||||||
|
"Allow the scalarizer pass to scalarize loads and store", false);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Scatterer scatter(Instruction *, Value *);
|
Scatterer scatter(Instruction *, Value *);
|
||||||
void gather(Instruction *, const ValueVector &);
|
void gather(Instruction *, const ValueVector &);
|
||||||
@ -164,19 +174,14 @@ private:
|
|||||||
GatherList Gathered;
|
GatherList Gathered;
|
||||||
unsigned ParallelLoopAccessMDKind;
|
unsigned ParallelLoopAccessMDKind;
|
||||||
const DataLayout *DL;
|
const DataLayout *DL;
|
||||||
|
bool ScalarizeLoadStore;
|
||||||
};
|
};
|
||||||
|
|
||||||
char Scalarizer::ID = 0;
|
char Scalarizer::ID = 0;
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
// This is disabled by default because having separate loads and stores makes
|
INITIALIZE_PASS_WITH_OPTIONS(Scalarizer, "scalarizer",
|
||||||
// it more likely that the -combiner-alias-analysis limits will be reached.
|
"Scalarize vector operations", false, false);
|
||||||
static cl::opt<bool> 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)
|
|
||||||
|
|
||||||
Scatterer::Scatterer(BasicBlock *bb, BasicBlock::iterator bbi, Value *v,
|
Scatterer::Scatterer(BasicBlock *bb, BasicBlock::iterator bbi, Value *v,
|
||||||
ValueVector *cachePtr)
|
ValueVector *cachePtr)
|
||||||
@ -236,7 +241,10 @@ Value *Scatterer::operator[](unsigned I) {
|
|||||||
|
|
||||||
bool Scalarizer::doInitialization(Module &M) {
|
bool Scalarizer::doInitialization(Module &M) {
|
||||||
ParallelLoopAccessMDKind =
|
ParallelLoopAccessMDKind =
|
||||||
M.getContext().getMDKindID("llvm.mem.parallel_loop_access");
|
M.getContext().getMDKindID("llvm.mem.parallel_loop_access");
|
||||||
|
ScalarizeLoadStore =
|
||||||
|
M.getContext()
|
||||||
|
.template getOption<bool, Scalarizer, &Scalarizer::ScalarizeLoadStore>();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user