[PM] Remove the IRUnitT typedef requirement for analysis passes.

Since the analysis managers were split into explicit function and module
analysis managers, it is now completely trivial to specify this when
building up the concept and model types explicitly, and it is impossible
to end up with a type error at run time. We instantiate a template when
registering a pass that will enforce the requirement at a type-system
level, and we produce a dynamic error on all the other query paths to
the analysis manager if the pass in question isn't registered.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195447 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chandler Carruth 2013-11-22 11:46:33 +00:00
parent 3f081983cc
commit d984cdc17e
2 changed files with 4 additions and 22 deletions

View File

@ -327,14 +327,11 @@ template <typename IRUnitT> struct AnalysisPassConcept {
/// Can wrap any type which implements a suitable \c run method. The method /// Can wrap any type which implements a suitable \c run method. The method
/// must accept the IRUnitT as an argument and produce an object which can be /// must accept the IRUnitT as an argument and produce an object which can be
/// wrapped in a \c AnalysisResultModel. /// wrapped in a \c AnalysisResultModel.
template <typename PassT> template <typename IRUnitT, typename PassT>
struct AnalysisPassModel : AnalysisPassConcept<typename PassT::IRUnitT> { struct AnalysisPassModel : AnalysisPassConcept<IRUnitT> {
AnalysisPassModel(PassT Pass) : Pass(llvm_move(Pass)) {} AnalysisPassModel(PassT Pass) : Pass(llvm_move(Pass)) {}
virtual AnalysisPassModel *clone() { return new AnalysisPassModel(Pass); } virtual AnalysisPassModel *clone() { return new AnalysisPassModel(Pass); }
// FIXME: Replace PassT::IRUnitT with type traits when we use C++11.
typedef typename PassT::IRUnitT IRUnitT;
// FIXME: Replace PassT::Result with type traits when we use C++11. // FIXME: Replace PassT::Result with type traits when we use C++11.
typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result> typedef AnalysisResultModel<IRUnitT, PassT, typename PassT::Result>
ResultModelT; ResultModelT;
@ -418,8 +415,6 @@ public:
/// If there is not a valid cached result in the manager already, this will /// If there is not a valid cached result in the manager already, this will
/// re-run the analysis to produce a valid result. /// re-run the analysis to produce a valid result.
template <typename PassT> const typename PassT::Result &getResult(Module *M) { template <typename PassT> const typename PassT::Result &getResult(Module *M) {
LLVM_STATIC_ASSERT((is_same<typename PassT::IRUnitT, Module *>::value),
"The analysis pass must be over a Module.");
assert(ModuleAnalysisPasses.count(PassT::ID()) && assert(ModuleAnalysisPasses.count(PassT::ID()) &&
"This analysis pass was not registered prior to being queried"); "This analysis pass was not registered prior to being queried");
@ -438,20 +433,16 @@ public:
/// populate /// populate
/// the manager with all of the analysis passes available. /// the manager with all of the analysis passes available.
template <typename PassT> void registerPass(PassT Pass) { template <typename PassT> void registerPass(PassT Pass) {
LLVM_STATIC_ASSERT((is_same<typename PassT::IRUnitT, Module *>::value),
"The analysis pass must be over a Module.");
assert(!ModuleAnalysisPasses.count(PassT::ID()) && assert(!ModuleAnalysisPasses.count(PassT::ID()) &&
"Registered the same analysis pass twice!"); "Registered the same analysis pass twice!");
ModuleAnalysisPasses[PassT::ID()] = ModuleAnalysisPasses[PassT::ID()] =
new detail::AnalysisPassModel<PassT>(llvm_move(Pass)); new detail::AnalysisPassModel<Module *, PassT>(llvm_move(Pass));
} }
/// \brief Invalidate a specific analysis pass for an IR module. /// \brief Invalidate a specific analysis pass for an IR module.
/// ///
/// Note that the analysis result can disregard invalidation. /// Note that the analysis result can disregard invalidation.
template <typename PassT> void invalidate(Module *M) { template <typename PassT> void invalidate(Module *M) {
LLVM_STATIC_ASSERT((is_same<typename PassT::IRUnitT, Module *>::value),
"The analysis pass must be over a Module.");
assert(ModuleAnalysisPasses.count(PassT::ID()) && assert(ModuleAnalysisPasses.count(PassT::ID()) &&
"This analysis pass was not registered prior to being invalidated"); "This analysis pass was not registered prior to being invalidated");
invalidateImpl(PassT::ID(), M); invalidateImpl(PassT::ID(), M);
@ -500,8 +491,6 @@ public:
/// re-run the analysis to produce a valid result. /// re-run the analysis to produce a valid result.
template <typename PassT> template <typename PassT>
const typename PassT::Result &getResult(Function *F) { const typename PassT::Result &getResult(Function *F) {
LLVM_STATIC_ASSERT((is_same<typename PassT::IRUnitT, Function *>::value),
"The analysis pass must be over a Function.");
assert(FunctionAnalysisPasses.count(PassT::ID()) && assert(FunctionAnalysisPasses.count(PassT::ID()) &&
"This analysis pass was not registered prior to being queried"); "This analysis pass was not registered prior to being queried");
@ -520,20 +509,16 @@ public:
/// populate /// populate
/// the manager with all of the analysis passes available. /// the manager with all of the analysis passes available.
template <typename PassT> void registerPass(PassT Pass) { template <typename PassT> void registerPass(PassT Pass) {
LLVM_STATIC_ASSERT((is_same<typename PassT::IRUnitT, Function *>::value),
"The analysis pass must be over a Function.");
assert(!FunctionAnalysisPasses.count(PassT::ID()) && assert(!FunctionAnalysisPasses.count(PassT::ID()) &&
"Registered the same analysis pass twice!"); "Registered the same analysis pass twice!");
FunctionAnalysisPasses[PassT::ID()] = FunctionAnalysisPasses[PassT::ID()] =
new detail::AnalysisPassModel<PassT>(llvm_move(Pass)); new detail::AnalysisPassModel<Function *, PassT>(llvm_move(Pass));
} }
/// \brief Invalidate a specific analysis pass for an IR module. /// \brief Invalidate a specific analysis pass for an IR module.
/// ///
/// Note that the analysis result can disregard invalidation. /// Note that the analysis result can disregard invalidation.
template <typename PassT> void invalidate(Function *F) { template <typename PassT> void invalidate(Function *F) {
LLVM_STATIC_ASSERT((is_same<typename PassT::IRUnitT, Function *>::value),
"The analysis pass must be over a Function.");
assert(FunctionAnalysisPasses.count(PassT::ID()) && assert(FunctionAnalysisPasses.count(PassT::ID()) &&
"This analysis pass was not registered prior to being invalidated"); "This analysis pass was not registered prior to being invalidated");
invalidateImpl(PassT::ID(), F); invalidateImpl(PassT::ID(), F);
@ -617,7 +602,6 @@ private:
/// pass. /// pass.
class FunctionAnalysisManagerModuleProxy { class FunctionAnalysisManagerModuleProxy {
public: public:
typedef Module *IRUnitT;
class Result; class Result;
static void *ID() { return (void *)&PassID; } static void *ID() { return (void *)&PassID; }

View File

@ -21,8 +21,6 @@ namespace {
class TestAnalysisPass { class TestAnalysisPass {
public: public:
typedef Function *IRUnitT;
struct Result { struct Result {
Result(int Count) : InstructionCount(Count) {} Result(int Count) : InstructionCount(Count) {}
int InstructionCount; int InstructionCount;