省流:先运行动态加载的PASS,再运行预置的PASS。
加载过程
AI真的太好用了,我现在就是个审稿人,大意:
- 命令行入参允许传入多个plugin.so
- 每个plugin允许注册多个pass
- pass共有两类,一类是FunctionPass,一类是ModulePass
参数解析
文件: src/Option/OptionAction.cpp L644-L658
功能: 包含了处理 PLUGIN_PATH 选项的 lambda 函数,将插件路径添加到 GlobalOptions 的 pluginPaths 列表中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| { Options::ID::PLUGIN_PATH, [](GlobalOptions& opts, const OptionArgInstance& arg) { auto maybePath = opts.CheckInputFilePath(arg.value); auto suffix = GlobalOptions::GetSharedLibraryExtension(opts.host.os); if (maybePath.has_value()) { auto path = maybePath.value(); if ('.' + FileUtil::GetFileExtension(path) == suffix) { opts.pluginPaths.emplace_back(maybePath.value()); return true; } Errorf("'%s' requires a dynamic library path with '%s' suffix.\n", arg.name.c_str(), suffix.c_str()); return false; } Errorf("'%s' only accepts an existing dynamic library path.\n", arg.name.c_str()); return false; }},
|
寻找入口
文件: src/Frontend/CompilerInstance.cpp L264-L268, L279-L304, L314-L334
功能: PerformPluginLoad 方法遍历 pluginPaths,加载动态库。其内部调用的 MetaTransformPlugin::Get 方法负责打开动态库,查找 getMetaTransformPluginInfo 符号,并将其封装为 MetaTransformPluginInfo 结构体。随后,PerformPluginLoad 会调用 metaTransformPlugin.RegisterCallbackTo 来注册插件Pass。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| namespace { class MetaTransformPlugin { public: static MetaTransformPlugin Get(const std::string& path); void RegisterCallbackTo(MetaTransformPluginBuilder& mtm) const;
MetaTransformPlugin MetaTransformPlugin::Get(const std::string& path) { HANDLE handle = nullptr; #ifdef _WIN32 handle = InvokeRuntime::OpenSymbolTable(path); #elif defined(__linux__) || defined(__APPLE__) handle = InvokeRuntime::OpenSymbolTable(path, RTLD_NOW | RTLD_LOCAL); #endif if (!handle) { CJC_ABORT(); } void* fPtr = InvokeRuntime::GetMethod(handle, "getMetaTransformPluginInfo"); if (!fPtr) { CJC_ABORT(); } auto pluginInfo = reinterpret_cast<MetaTransformPluginInfo (*)()>(fPtr)(); return MetaTransformPlugin(path, pluginInfo, handle); }
bool CompilerInstance::PerformPluginLoad() { for (auto pluginPath : invocation.globalOptions.pluginPaths) { auto metaTransformPlugin = MetaTransformPlugin::Get(pluginPath); if (!metaTransformPlugin.IsValid()) { diag.DiagnoseRefactor(DiagKindRefactor::not_a_valid_plugin, DEFAULT_POSITION, pluginPath); } AddPluginHandle(metaTransformPlugin.GetHandle()); metaTransformPlugin.RegisterCallbackTo(metaTransformPluginBuilder); } return true; }
|
执行pass
文件: src/CHIR/CHIR.cpp L1271-L1307
功能: PerformPlugin 方法调用 metaTransformPluginBuilder.BuildCHIRPluginManager 来构建 Pass 管理器,然后遍历并执行所有注册的插件Pass。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| bool ToCHIR::PerformPlugin(CHIR::Package& package) { bool succeed = true; bool hasPluginForCHIR = false; Utils::ProfileRecorder recorder("CHIR", "Plugin Execution"); CHIRPluginManager chirPluginManager = ci.metaTransformPluginBuilder.BuildCHIRPluginManager(builder); chirPluginManager.ForEachMetaTransformConcept([&package, &hasPluginForCHIR](MetaTransformConcept& mtc) { if (!mtc.IsForCHIR()) { return; } hasPluginForCHIR = true; if (mtc.IsForFunc()) { for (auto func : package.GetGlobalFuncs()) { static_cast<MetaTransform<CHIR::Func>*>(&mtc)->Run(*func); } } else if (mtc.IsForPackage()) { static_cast<MetaTransform<CHIR::Package>*>(&mtc)->Run(package); } else { CJC_ASSERT(false && "Should not reach here."); } }); if (!succeed) { diag.DiagnoseRefactor(DiagKindRefactor::plugin_throws_exception, DEFAULT_POSITION); } else if (hasPluginForCHIR && builder.IsEnableIRCheckerAfterPlugin()) { DumpCHIRToFile("PLUGIN"); succeed = RunIRChecker(Phase::PLUGIN); } return succeed; }
|
内置Pass与动态加载Pass的执行顺序
执行顺序由 src/CHIR/CHIR.cpp 文件中的 ToCHIR::Run 方法严格定义。
核心执行流程:ToCHIR::Run 方法
文件: src/CHIR/CHIR.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| bool ToCHIR::Run() {
if (!TranslateToCHIR({})) { return false; }
if (!PerformPlugin(*chirPkg)) { return false; }
RunOptimizationPass(); DoClosureConversion();
return true; }
|
总结
简洁明了,一气呵成