我目前正在使用 LLVM 15.0.0,并在使用 New Pass Manager 和
llvm::PassInfoMixin
时面临挑战。我的目标是在 FunctionPass 中插入对特定函数的调用,但该函数未在模块中声明。据我所知,在 FunctionPass 的上下文中,不允许直接修改模块(例如添加函数声明)(docs)。
使用旧版通行证管理器,我可以使用 doInitialization 和 doFinalization 进行此类模块级更改,但这些在新通行证管理器中不可用(除非我遗漏了某些内容?)。我正在寻找有关如何在执行函数传递之前在模块中正确声明函数的指导。 (函数定义本身将在链接期间可用。)
这是我当前方法的简要概述:
class MyFunctionPass : public llvm::PassInfoMixin<MyFunctionPass> {
public:
llvm::PreservedAnalyses run(llvm::Function &F, llvm::FunctionAnalysisManager &AM) {
// Try to find if declaration exists
llvm::Module *M = F.getParent();
llvm::Function *funcToCall = M->getFunction("externalFunctionName");
if (!funcToCall) {
// Function is not declared, need to declare it here or handle this case
// Using M would not work. Modifying the Module here is not allowed
}
// Insert calls to funcToCall in F
// ...
return llvm::PreservedAnalyses::all();
}
};
我正在使用 opt 动态调用 pass:
opt -load-pass-plugin=MyFunctionPass.so -passes='myfunctionpass' -disable-output testcase.ll
我了解 New Pass Manager 鼓励关注点分离,并且 FunctionPass 不应修改模块结构。但是,我不确定如何在其他地方声明该函数,或者是否可以在新通行证管理器的限制范围内采取替代方法。
可能的解决方法
llvm::PassInfoMixin
准备 FunctionPass。例如,也许使用构造函数。LLVM 15 中是否有任何推荐的实践或模式来处理此类场景?
任何见解、代码示例或相关文档的引用将不胜感激。
这里的关键也许是你不应该在 FunctionPass 中添加函数的原因:
不过,在这种情况下我会这么做。您在处理第一个函数时创建一个外部函数,并且不删除任何函数。这不是 LLVM 作者想要禁止的修改。
函数传递不对外部函数进行操作,因此对于其他传递来说这是一个空操作(在某种程度上对于传递管理器也是如此)。此外,传递管理器是否迭代新函数并不重要,因此您的更改是安全的。但请确保将被调用的函数保持在外部;)