#ifndef LLVM_CODEGEN_MACHINEPASSMANAGER_H
#define LLVM_CODEGEN_MACHINEPASSMANAGER_H
#include "llvm/ADT/FunctionExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/Error.h"
#include <map>
namespace llvm {
class Module;
class Function;
class MachineFunction;
extern template class AnalysisManager<MachineFunction>;
class MachineFunctionAnalysisManager : public AnalysisManager<MachineFunction> {
public:
using Base = AnalysisManager<MachineFunction>;
MachineFunctionAnalysisManager() : FAM(nullptr), MAM(nullptr) {}
MachineFunctionAnalysisManager(FunctionAnalysisManager &FAM,
ModuleAnalysisManager &MAM)
: FAM(&FAM), MAM(&MAM) {}
MachineFunctionAnalysisManager(MachineFunctionAnalysisManager &&) = default;
MachineFunctionAnalysisManager &
operator=(MachineFunctionAnalysisManager &&) = default;
template <typename PassT> typename PassT::Result &getResult(Function &F) {
return FAM->getResult<PassT>(F);
}
template <typename PassT>
typename PassT::Result *getCachedResult(Function &F) {
return FAM->getCachedResult<PassT>(F);
}
template <typename PassT> typename PassT::Result &getResult(Module &M) {
return MAM->getResult<PassT>(M);
}
template <typename PassT> typename PassT::Result *getCachedResult(Module &M) {
return MAM->getCachedResult<PassT>(M);
}
using Base::getResult;
using Base::getCachedResult;
FunctionAnalysisManager *FAM;
ModuleAnalysisManager *MAM;
};
extern template class PassManager<MachineFunction>;
class MachineFunctionPassManager
: public PassManager<MachineFunction, MachineFunctionAnalysisManager> {
using Base = PassManager<MachineFunction, MachineFunctionAnalysisManager>;
public:
MachineFunctionPassManager(bool DebugLogging = false,
bool RequireCodeGenSCCOrder = false,
bool VerifyMachineFunction = false)
: RequireCodeGenSCCOrder(RequireCodeGenSCCOrder),
VerifyMachineFunction(VerifyMachineFunction) {}
MachineFunctionPassManager(MachineFunctionPassManager &&) = default;
MachineFunctionPassManager &
operator=(MachineFunctionPassManager &&) = default;
Error run(Module &M, MachineFunctionAnalysisManager &MFAM);
template <typename PassT> void addPass(PassT &&Pass) {
Base::addPass(std::forward<PassT>(Pass));
PassConceptT *P = Passes.back().get();
addDoInitialization<PassT>(P);
addDoFinalization<PassT>(P);
addRunOnModule<PassT>(P);
}
private:
template <typename PassT>
using has_init_t = decltype(std::declval<PassT &>().doInitialization(
std::declval<Module &>(),
std::declval<MachineFunctionAnalysisManager &>()));
template <typename PassT>
std::enable_if_t<!is_detected<has_init_t, PassT>::value>
addDoInitialization(PassConceptT *Pass) {}
template <typename PassT>
std::enable_if_t<is_detected<has_init_t, PassT>::value>
addDoInitialization(PassConceptT *Pass) {
using PassModelT =
detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
MachineFunctionAnalysisManager>;
auto *P = static_cast<PassModelT *>(Pass);
InitializationFuncs.emplace_back(
[=](Module &M, MachineFunctionAnalysisManager &MFAM) {
return P->Pass.doInitialization(M, MFAM);
});
}
template <typename PassT>
using has_fini_t = decltype(std::declval<PassT &>().doFinalization(
std::declval<Module &>(),
std::declval<MachineFunctionAnalysisManager &>()));
template <typename PassT>
std::enable_if_t<!is_detected<has_fini_t, PassT>::value>
addDoFinalization(PassConceptT *Pass) {}
template <typename PassT>
std::enable_if_t<is_detected<has_fini_t, PassT>::value>
addDoFinalization(PassConceptT *Pass) {
using PassModelT =
detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
MachineFunctionAnalysisManager>;
auto *P = static_cast<PassModelT *>(Pass);
FinalizationFuncs.emplace_back(
[=](Module &M, MachineFunctionAnalysisManager &MFAM) {
return P->Pass.doFinalization(M, MFAM);
});
}
template <typename PassT>
using is_machine_module_pass_t = decltype(std::declval<PassT &>().run(
std::declval<Module &>(),
std::declval<MachineFunctionAnalysisManager &>()));
template <typename PassT>
using is_machine_function_pass_t = decltype(std::declval<PassT &>().run(
std::declval<MachineFunction &>(),
std::declval<MachineFunctionAnalysisManager &>()));
template <typename PassT>
std::enable_if_t<!is_detected<is_machine_module_pass_t, PassT>::value>
addRunOnModule(PassConceptT *Pass) {}
template <typename PassT>
std::enable_if_t<is_detected<is_machine_module_pass_t, PassT>::value>
addRunOnModule(PassConceptT *Pass) {
static_assert(is_detected<is_machine_function_pass_t, PassT>::value,
"machine module pass needs to define machine function pass "
"api. sorry.");
using PassModelT =
detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
MachineFunctionAnalysisManager>;
auto *P = static_cast<PassModelT *>(Pass);
MachineModulePasses.emplace(
Passes.size() - 1,
[=](Module &M, MachineFunctionAnalysisManager &MFAM) {
return P->Pass.run(M, MFAM);
});
}
using FuncTy = Error(Module &, MachineFunctionAnalysisManager &);
SmallVector<llvm::unique_function<FuncTy>, 4> InitializationFuncs;
SmallVector<llvm::unique_function<FuncTy>, 4> FinalizationFuncs;
using PassIndex = decltype(Passes)::size_type;
std::map<PassIndex, llvm::unique_function<FuncTy>> MachineModulePasses;
bool RequireCodeGenSCCOrder;
bool VerifyMachineFunction;
};
}
#endif