windows上的LLVM pass瞎折腾记录
想了解下LLVM的代码风格和优化过程,就从写LLVM pass入手吧,做个踩坑记录…
文章最后有逐步骤的操作记录,Tips内记录关键点和思路
Tips:
- 首先不要在win上折腾llvm pass(本篇结束…),官方不支持得改代码,但是折腾一半实在是杠上了,所以还是硬着头皮搞了
- LLVM-PROJECT是各种工程的集合,写pass的话关注c语言前端clang,IR优化器opt这两个工程就好
- LLVM不同版本间差别很大,很多网络上的资料隔一个版本就不行了,所以这次一是能固定版本复现二是想搞清楚为啥就不行了三是尝试新方式
- 因为就是想用最新的llvm版本,在跟着飘云阁的哪个llvm文章的时候cmake出的工程没法编译,报有函数找不到符号,明显就是llvm的新版本加入了一些函数,实现在其他的lib里面,通过定位函数名-定位文件名-定位工程lib名的方式找齐然后修改cmake脚本成功构建
- 不想改pass还要重新编译llvm那个大工程所以怎么着都得用动态插件的形式才能实现,动态插件分两种一种是clang的插件形式一种是opt的插件形式,opt的插件形式网络上教程较多一般都是linux平台加载一个so然后用-pass=xxx调用 对clang生成的ll代码进行pass处理,遇到了各种问题比如win上的dll路径给他结果告诉我找不到所以根本连加载都没加载起来,具体是啥原因不清楚,但是本身先用clang编译出ll再进行opt指定的操作就不太方便所以最后还是选择了clang插件的方式
- 啥是clang插件?其实clang本身不像opt那样再命令行里面支持-load一个动态链接库的形式,所以所谓的clang插件是手动给clang的pass过程插入一个加载固定名称的dll并调用其固定函数名的导出函数的代码。如此这个固定名称的dll就成了我们的插件了,后续pass开发只编译这样的dll放到clang同目录下即可,实现了和llvm工程编译步骤分离的需要(还不是因为llvm工程编译太慢了)
- 如此生成的clang之后使用clang.exe test.cpp -o test.exe却并没有调用到populateModulePassManager函数中去,所以所谓的动态插件加载代码都没被执行,这个问题卡了最久然后突然想到看过llvm关于pass的介绍好像有介绍说啥新pass和旧pass来着,然后仔细查了下llvm的官方文档发现13.0.1版本以及是默认开启新的pass管理流程了,所以旧的pass管理函数populateModulePassManager就没走到。如果编译的时候想要编译旧的pass流程可以再cmake配置里面把LLVM_ENABLE_NEW_PASS_MANAGER关了,但是可以用更简单的方式:给clang调用的时候加一个-flegacy-pass-manager参数即可
- 第7点实际上以及搞定了只不过写pass的时候得按照旧的pass逻辑去写(其实大部分资料也都是旧pass),但是因为就是想折腾一下怎么不加上述参数也能实现llvm的动态插件机制(即新的pass逻辑),但是试了下好像不太行,想着关键是找到新pass流程中对应的populateModulePassManager函数,结果发现的疑似这样的函数PassBuilder::parseModulePass并没有被调用,这个类是初始化了的但是这个函数没被调用,不清楚啥情况。目前的思路是参考怎么再llvm内部用静态链接实现的addPass,然后就复用这样的流程然后把addpass里面的对象改为动态获取,但是看了一圈好像这样的addpass都是用的opt插件的形式(即:导出指定函数llvmGetPassPluginInfo,然后被opt -load加载),实际上不是llvm内的插件形式;还有种思路是跟踪-flegacy-pass-manager参数代码找到llvm中的新pass管理逻辑,具体实现方式还没找到,后续找到会更新(见第9点)
- 跟踪populateModulePassManager的引用网上找发现关键开关CGOpts.LegacyPassManager,因此确认新旧pass模式的函数区别为旧pass走EmitAssembly流程新pass走EmitAssemblyWithNewPassManager流程,后续新pass测试成功继续更新如何分离新pass和llvm 13.0增加clang动态插件

本文记录了在Windows环境下尝试使用最新LLVM版本开发pass,克服了官方不支持的挑战,重点讲述了如何在Clang插件和新旧pass管理流程间操作,包括动态加载DLL、版本兼容性处理及pass的分离与集成。
最低0.47元/天 解锁文章
1190

被折叠的 条评论
为什么被折叠?



