能力值:
( LV7,RANK:101 )
2 楼
板块放错了,望版主移动到翻译板块
能力值:
( LV1,RANK:0 )
3 楼
感谢分享
能力值:
(RANK:350 )
4 楼
微笑明天
板块放错了,望版主移动到翻译板块
移过来了,建议同一篇文章,文章不长时,用跟帖的形式发上来。
能力值:
( LV7,RANK:101 )
5 楼
Writing LLVM Pass in 2018-part III 原文https://medium.com/@mshockwave/writing-llvm-pass-in-2018-part-iii-d44cd0c2c354 你已经能够写一个pass并用opt来动态加载。但你希望能够在 opt 或者 clang 中自动运行你的pass。本文将介绍一些将你的pass整合进legacy PassManager pipeline的方法。下篇文章将介绍如何整合进clang的命令选项。 为了在Pass pipeline中默认运行Pass,我们需要了解pipeline是如何开始构建的. PassManagerBuilder 这个builder类用于构建legacy PassManager和默认的pass pipeline.但这个builder class文件的路径有些奇怪,在 include/llvm/Transforms/IPO/PassManagerBuilder.h 和 lib/Transform/IPO/PassManagerBuilder.cpp 中,而不是在 IR 或者 PasManager 文件夹中。 在 PassManagerBuilder 类中,有很多顾名思义的函数,比如 addInstructionCombiningPass 和 addFunctionSimplificationPasses 这些函数可以向pipeline中添加某个pass的目录。 除了显式调用它们来更新候选Pass列表,在代码里有许多地方使用OptLevel属性,即我们熟悉的 -O1 , -O2 命令行选项,通过它们的优先级级别添加Pass 让我们看一下其中一个通用入口 populateFuntionPassManager void PassManagerBuilder::populateFunctionPassManager( legacy::FunctionPassManager &FPM) { //...Some code skipped... if (OptLevel == 0) return; addInitialAliasAnalysisPasses(FPM); FPM.add(createCFGSimplificationPass()); FPM.add(createSROAPass()); FPM.add(createEarlyCSEPass()); FPM.add(createLowerExpectIntrinsicPass()); } 在此之前,我们只知道一种运行我们pass的方法:用下面的代码来注册 static RegisterPass<MyPass> X("my-pass", ...); 然后用 opt 加上 -load=MyPass.so -my-pas 选项来运行。 然而,如果它已经在源代码树里了,每次动态地载入与运行一个遍是奇怪且不必要的。 因此,从上面的代码,我们看到如果一个Pass已经在LLVM源代码树里,我们所需做的一切是创建一个带有几个工厂方法的Pass,例如 createSROAPass ,然后显式调用 legacy::FunctionPassManager:: add(…) 将期望的Pass加入pipeline。 不幸,这还没完。事实证明,在构建好源码内建的Pass之前,还有几个简单的设置(这是为什么我写这篇文章)。下面是检查清单: 1. createXXXXPass 函数 2. initializeXXXPassPass 函数/ InitializedPasses.h 文件 3. INITIALIZE_PASS_BEGIN / END / DEPENDENCY 代码 4. 将你的 initializeXXXPassPass 放在合适的地方 5. LinkAllPasses.h 文件 6. 将你的 createXXXPass 放在合适的地方 上面的列表清单是完成这些任务通常的次序,当然它们间没有特定的优先级。让我们从上到下来解读。 创建函数 createXXXXPass函数 第一项,早先提到的,是相当简单明了的,通常它仅需要3行代码来实现: FunctionPass* llvm::createMyAwesomePass() { return new MyAwesomePass(); } new一个Pass的实例并返回它。注意它是在llvm名字空间里的一个全局静态函数,因此不要忘记前缀 llvm:: 或者用 namespace llvm{...} 围绕它。 initializeXXXPassPass函数 接下来的两个设置,实际上都是 initializeXXXPassPass 函数。这个函数将为Pass创建一个内部Pass信息入口(internal Pass info entry),并把它和其依赖项注册到 PassManager 。这类似于用于动态载入Pass的 RegisterPass<MyPass> (...) 。为了实现这个函数,首先我们把函数声明放在 include/llvm/initializePasses.h 里 // ...Previous lines... void initializeModuleSummaryIndexWrapperPassPass(PassRegistry&); void initializeMustExecutePrinterPass(PassRegistry&); // ----------------------------- void initializeMyAwesomePassPass(PassRegistry&); // ----------------------------- void initializeNameAnonGlobalLegacyPassPass(PassRegistry&); // . 在我们自己pass的源代码中,添加下面几行 INITIALIZE_PASS_BEGIN(MyAwesomePass, "my-awesome-pass", "Some description for the Pass", false, false) INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) // Or whatever your Pass dependencies INITIALIZE_PASS_END(MyAwesomePass, "my-awesome-pass", "Some description for the Pass", false, false) 其实际上就是构建了 initializeXXXPassPass 函数 调用函数 现在我们已经实现了 initializeXXXPassPass 和 createXXXPass 函数。接着我们要把他们放到合适的地方。现来看前者。 initializeXXXPassPass 有两个地方我们需要调用initializeXXXPassPass函数。第一个是在你的Pass类的构造函数中 MyAwesomePass() : FunctionPass(ID) { initializeMyAwesomePassPass(*PassRegistry::getPassRegistry()); } 第二个是在上层的初始化函数中(initialization function).例如,如果你的pass是一个在 lib/Analysis 文件夹下面的analysis pass,将下面几行加入 lib/Analysis/Analysis.cpp 文件中: void llvm::initializeAnalysis(PassRegistry &Registry) { //...Other initialization function calls initializeMyAwesomePassPass(Registry); //... } 如果pass是一个在 lib/Transforms/Scalar 下的transformation pass,那么要修改的文件就是 lib/Transforms/Scalar/Scalar.cpp createXXXPass 让我们接着来看 createXXXPass 函数。为了防止对这些 createXXXPass 符号进行某些激进的链接时优化,我们需要在 include/llvm/LinkAllPasses.h 里添加一个假的函数调用 struct ForcePassLinking { ForcePassLinking() { //... (void) llvm::createMyAwesomePass(); //... } } 最后,在本文前面提到的 PassManagerBuilder 里的 createXXXPass 函数中添加一个真正的函数调用。你可以增加更多复杂的逻辑,在特定的优化层级条件下,将你的pass插入pipeline,但我通常把这个函数调用放在 populateXXXPassManager 中的某处,这也在前面提到了: void PassManagerBuilder::populateFunctionPassManager( legacy::FunctionPassManager &FPM) { //...Some code skipped... if (OptLevel == 0) return; addInitialAliasAnalysisPasses(FPM); FPM.add(createCFGSimplificationPass()); FPM.add(createSROAPass()); // Here you are! FPM.add(createMyAwesomePass()); FPM.add(createEarlyCSEPass()); FPM.add(createLowerExpectIntrinsicPass()); } 不管是旧版本还是新版本,构造pass pipeline一直是PassManager里一个有趣的话题。仍然有许多其他因素影响pass pipeline的信息。前面章节仅提供在旧版PassManager中默认运行你的pass的最简单的方式。 我认为这是将你的pass放入LLVM源代码树所需的所有额外要求。希望这使得你的LLVM开发更容易 :-)
能力值:
( LV4,RANK:40 )
6 楼
微笑明天
Writing LLVM Pass in 2018-part III
原文https://medium.com/@mshockwave/writing-llvm-pass-in-2018-part- ...
还是整整吧,这个帖的排版不友好,谢谢分享