使用 LLVM 15 中的 llvm::PassInfoMixin 声明要在 FunctionPass 中使用的函数以及 New Pass Manager

问题描述 投票:0回答:1

我目前正在使用 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 不应修改模块结构。但是,我不确定如何在其他地方声明该函数,或者是否可以在新通行证管理器的限制范围内采取替代方法。

可能的解决方法

  1. 我不确定是否有办法在模块中声明函数,以使用
    llvm::PassInfoMixin
    准备 FunctionPass。例如,也许使用构造函数。
  2. 我可以为此使用单独的 ModulePass,并以某种方式确保它在我的 FunctionPass 之前运行。 (不知道如何使其成为必需。)

LLVM 15 中是否有任何推荐的实践或模式来处理此类场景?

任何见解、代码示例或相关文档的引用将不胜感激。

c++ compiler-construction llvm llvm-ir dynamic-loading
1个回答
0
投票

这里的关键也许是你不应该在 FunctionPass 中添加函数的原因:

  • FunctionPass 的调用者迭代函数列表,添加函数会更改该列表。在迭代列表时更改列表是臭名昭著的 bug 磁石。人们对新创建的函数是否会在同一循环中处理、意外创建无限循环等做出错误的假设
  • LLVM努力为通证提供简单、可靠的环境。在处理函数时更改要处理的函数集会给其他过程带来复杂性。

不过,在这种情况下我会这么做。您在处理第一个函数时创建一个外部函数,并且不删除任何函数。这不是 LLVM 作者想要禁止的修改。

函数传递不对外部函数进行操作,因此对于其他传递来说这是一个空操作(在某种程度上对于传递管理器也是如此)。此外,传递管理器是否迭代新函数并不重要,因此您的更改是安全的。但请确保将被调用的函数保持在外部;)

© www.soinside.com 2019 - 2024. All rights reserved.