首页 > 解决方案 > 如何在 Clang 中自动注册和加载现代通行证?

问题描述

我正在尝试编写一个简单的“现代”LLVM 通行证并将其与 Clang 一起使用。我希望它能够使用如下命令运行: clang -Xclang -load -Xclang libMyPass.so file.cpp

有很多关于如何将 legacy pass 集成到 Clang 的手册。但是,关于新通行证管理器的信息并不多。我遇到了一系列名为“2018 年编写 LLVM Pass”的文章。但它只提到了将密码放在 LLVM 代码树中的情况。而且我需要在树外构建模块。

class MyPass : public llvm::PassInfoMixin<MyPass> {
public:
    llvm::PreservedAnalyses run(
        llvm::Function &F,
        llvm::FunctionAnalysisManager &FAM
    ) {
    // Pass code here
    }
};

extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
llvmGetPassPluginInfo() {
    return {
        LLVM_PLUGIN_API_VERSION, "MyPass", "v0.1",
        [](llvm::PassBuilder &PB) {
            PB.registerPipelineParsingCallback(
                [](
                    llvm::StringRef Name, llvm::FunctionPassManager &FPM,
                    llvm::ArrayRef <llvm::PassBuilder::PipelineElement>
                ) {
                    if (Name == "my-pass") {
                        FPM.addPass(MyPass());
                        return true;
                    }
                    return false;
                }
            );
        }
    };
}

目前,该通行证尚未执行。我试图查看 -print-after-all 选项输出并使用std::cout它来检测它是否已运行。我在日志中看不到我的通行证。我也无法在控制台窗口中看到我的调试输出。

标签: clangllvm

解决方案


两年后,关于这样做的信息仍然很少。我花了一段时间才弄清楚自己的通行证。

首先,让 clang 使用您的通行证库:

clang -O1 -fexperimental-new-pass-manager -fpass-plugin=libMyPass.so file.cpp

请注意,-O1标志很重要(我稍后会谈到)。

至于你的通行证,我找不到强制clang使用“解析管道”的方法,所以我们必须使用其他优化器扩展点之一llvm::PassBuilder(几乎所有这些都需要一个或更高的优化级别,因此-O1)。由于您的通行证run方法采用Function,因此我们需要一个采用 的扩展点回调FunctionPassManger。我们将使用registerVectorizerStartEPCallback.

class MyPass : public llvm::PassInfoMixin<MyPass> {
public:
    llvm::PreservedAnalyses run(
        llvm::Function &F,
        llvm::FunctionAnalysisManager &FAM
    ) {
    // Pass code here
    }
};

extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
llvmGetPassPluginInfo() {
    return {
        LLVM_PLUGIN_API_VERSION, "MyPass", "v0.1",
        [](llvm::PassBuilder &PB) {
            PB.registerVectorizerStartEPCallback(
                [](
                    llvm::FunctionPassManager &FPM,
                    llvm::OptimizationLevel &O
                ) {
                    FPM.addPass(MyPass());
                  }
            );
        }
    };
}

此代码仅在 LLVM 11 时才正确。更高版本具有新的PassBuilder扩展点,并已删除或重命名了一些旧扩展点。registerVectorizerStartEPCallback尽管如此,LLVM 13 中仍然存在。

我花了很长时间试图弄清楚是否可以通过构建新的FunctionPassMangager等来强制 clang 使用自定义通行证,但似乎没有办法让 clang 使用它。如果您想坚持使用树外通道,优化器扩展点似乎是您唯一的选择。

提示 - 在执行此类操作时,读取 LLVM 头文件或通过 clang 源代码树查找非常有帮助。


推荐阅读