本文为看雪论坛优秀文章
看雪论坛作者ID:LeadroyaL
struct PassPluginLibraryInfo {
/// The API version understood by this plugin, usually \c
/// LLVM_PLUGIN_API_VERSION
uint32_t APIVersion;
/// A meaningful name of the plugin.
const char *PluginName;
/// The version of the plugin.
const char *PluginVersion;
/// The callback for registering plugin passes with a \c PassBuilder
/// instance
void (*RegisterPassBuilderCallbacks)(PassBuilder &);
};
extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo() {
return {LLVM_PLUGIN_API_VERSION,
"Skeleton",
"1.0.0",
[](PassBuilder &PB) {
//xxxxxxx
}};
}
(xxx)Analyses,与加载pass不相关
build(xxx)Pipeline,与加载pass不相关
parsePassPipiline,尝试处理给定的处理串,可能用于测试
printPassNames,打印所有的Pass
registerAnalysisRegistrationCallback,与加载pass不相关
register(xxx)EPCallback,核心API,与Legacy比较像
registerPipelineParsingCallback,给opt用的,opt --load-pass-plugin=libPass.so -passes=passName1,passName2 可以触发到
void registerPeepholeEPCallback(
const std::function<void(FunctionPassManager &, OptimizationLevel)> &C) {
PeepholeEPCallbacks.push_back(C);
}
➜ /tmp clang -fpass-plugin=libSkeletonPass.so test.c
llvmGetPassPluginInfo
isRequired invoked
Module name is test.c!
PB.registerPipelineStartEPCallback(myCallback);
void myCallback(llvm::ModulePassManager &PM, llvm::PassBuilder::OptimizationLevel Level) {
PM.addPass(TestPass());
}
class TestPass {
public:
static StringRef name() {
errs() << "name invoked\n";
return "TestPass";
}
static bool isRequired() {
errs() << "isRequired invoked\n";
return true;
}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
errs() << "Module name is " << M.getName() << "!\n";
return PreservedAnalyses::all();
}
};
static StringRef name 必须,表示 pass 的名字。可以使用 PassInfoMixin 模板快速实现该API。
static bool isRequired 可选,如果返回true,则该pass不会被跳过。
PreservedAnalyses run(Module &M, ModuleAnalysisManager &) 必选,ModulePass 需要这里是 llvm::Module 和 ModuleAnalysisManager,FunctionPass 需要这里是 Function 和 FunctionAnalysisManager。
extern template class PassManager<Module>;
/// Convenience typedef for a pass manager over modules.
using ModulePassManager = PassManager<Module>;
template <typename IRUnitT,
typename AnalysisManagerT = AnalysisManager<IRUnitT>,
typename... ExtraArgTs>
class PassManager : public PassInfoMixin<
PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>> {
//xxxxxxxx
}
/////////////////////
template <typename DerivedT> struct PassInfoMixin {
/// Gets the name of the pass we are mixed into.
static StringRef name() {
static_assert(std::is_base_of<PassInfoMixin, DerivedT>::value,
"Must pass the derived type as the template argument!");
StringRef Name = getTypeName<DerivedT>();
if (Name.startswith("llvm::"))
Name = Name.drop_front(strlen("llvm::"));
return Name;
}
};
/////////////////////
using ModuleAnalysisManager = AnalysisManager<Module>;
template <typename IRUnitT,
typename AnalysisManagerT = AnalysisManager<IRUnitT>,
typename... ExtraArgTs>
class PassManager : public PassInfoMixin<
PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...>> {
template <typename PassT>
std::enable_if_t<!std::is_same<PassT, PassManager>::value>
addPass(PassT &&Pass) {
using PassModelT =
detail::PassModel<IRUnitT, PassT, PreservedAnalyses, AnalysisManagerT,
ExtraArgTs...>;
Passes.emplace_back(new PassModelT(std::forward<PassT>(Pass)));
}
template <typename PassT>
std::enable_if_t<std::is_same<PassT, PassManager>::value>
addPass(PassT &&Pass) {
for (auto &P : Pass.Passes)
Passes.emplace_back(std::move(P));
}
}
ModulePass 需要这里是 llvm::Module 和 ModuleAnalysisManager,FunctionPass 需要这里是 Function 和 FunctionAnalysisManager。
template <typename IRUnitT, typename PassT, typename PreservedAnalysesT,
typename AnalysisManagerT, typename... ExtraArgTs>
struct PassModel : PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...> {
explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
// We have to explicitly define all the special member functions because MSVC
// refuses to generate them.
PassModel(const PassModel &Arg) : Pass(Arg.Pass) {}
PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {}
//xxxxxxxxxxx
PreservedAnalysesT run(IRUnitT &IR, AnalysisManagerT &AM,
ExtraArgTs... ExtraArgs) override {
return Pass.run(IR, AM, ExtraArgs...);
}
StringRef name() const override { return PassT::name(); }
template <typename T>
using has_required_t = decltype(std::declval<T &>().isRequired());
template <typename T>
static std::enable_if_t<is_detected<has_required_t, T>::value, bool>
passIsRequiredImpl() {
return T::isRequired();
}
template <typename T>
static std::enable_if_t<!is_detected<has_required_t, T>::value, bool>
passIsRequiredImpl() {
return false;
}
bool isRequired() const override { return passIsRequiredImpl<PassT>(); }
PassT Pass;
};
template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
struct PassConcept {
// Boiler plate necessary for the container of derived classes.
virtual ~PassConcept() = default;
/// The polymorphic API which runs the pass over a given IR entity.
///
/// Note that actual pass object can omit the analysis manager argument if
/// desired. Also that the analysis manager may be null if there is no
/// analysis manager in the pass pipeline.
virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManagerT &AM,
ExtraArgTs... ExtraArgs) = 0;
/// Polymorphic method to access the name of a pass.
virtual StringRef name() const = 0;
/// Polymorphic method to to let a pass optionally exempted from skipping by
/// PassInstrumentation.
/// To opt-in, pass should implement `static bool isRequired()`. It's no-op
/// to have `isRequired` always return false since that is the default.
virtual bool isRequired() const = 0;
};
struct TestPass : PassInfoMixin<TestPass> {
public:
static bool isRequired() {
errs() << "isRequired invoked\n";
return true;
}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
errs() << "Module name is " << M.getName() << "!\n";
return PreservedAnalyses::all();
}
};
如果修改了IR,返回 PreservedAnalyses::none,表示之前的优化分析全部不需要保留
如果修改了IR,返回一个集合,表示该集合中的pass不需要再次被执行了
如果没有修改IR,则返回 PreservedAnalyses::all,表示分析集全部需要保留
PB.registerPipelineStartEPCallback(
[](ModulePassManager &MPM, OptimizationLevel Level) {
FunctionPassManager FPM;
FPM.addPass(HelloWorld());
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
});
void registerPipelineParsingCallback(
const std::function<bool(StringRef Name, ModulePassManager &,
ArrayRef<PipelineElement>)> &C) {
ModulePipelineParsingCallbacks.push_back(C);
}
看雪ID:LeadroyaL
https://bbs.pediy.com/user-home-735539.htm
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!