一.配置环境
配置环境的话指路whitebird大佬的博客:
或者llvm的官方文档https://llvm.org/docs/GettingStarted.html
二.注意的点
一个是whitebird博客中是使用clion对llvm进行编译,在编译过程中如果llvm是在虚拟机上的话要在clion的设置中将toolchain换一下,从windows换成wsl
二是大佬用的是旧版指令和编写llvm pass 的方式,新版已经不能使用他博客中的方式编写
三.正式开始
首先入门可以查看官方文档,根据官方文档进行llvm pass的编写
可以发现其实官方文档所写的helloworld.h已经被创建了,那么我们根据他再在该文件夹中创建一个encode.h
写出如下代码:
1 |
|
这段代码写完可能会有run标红,不用管,否则编译opt的时候会报错
然后再在llvm/lib/Transforms/Utils中创建Encode.cpp,代码如下
1 |
|
然后在llvm/lib/Transforms/Utils的Cmakelists.txt中添加一个Encode.cpp
写完后在llvm/lib/Passes/PassRegistry.def中添加如下
1 | FUNCTION_PASS("encode",EncodePass()) |
在llvm/lib/Passes/PassBuilder.cpp添加
1 | #include "llvm/Transforms/Utils/Encode.h" |
然后在clion中重新编译
选择重新加载cmake项目
然后进入cmake-build-release文件夹重新编译
1 | ninja -j2 opt |
不过编译过程中我莫名其妙跳出来一个循环依赖问题
不过解决也很容易,只要在clion中进入lib/support/BLAKE3/里面的cmakelists.txt,把最后一行和Encode.cpp有关的内容删除即可(虽然我还不知道有什么影响,不过好像没什么影响)
后来发现出现循环的原因是clion中新建.cpp文件的时候会有一个添加到目标,默认值就是lib/support/BLAKE3/
正好是出现循环依赖中的一环(只探究到这里了,再深还没有什么发现)
然后编译完成就可以使用opt将pass用于我们的IR代码上啦
四.使用pass
先浅浅的写一个c语言的代码,创建成hello_clang.c
1 |
|
比如这样子,然后用clang进行编译,命令如下
1 | clang -O3 -emit-llvm hello_clang.c -S -o hello_clang.ll |
注意这个-O3一定要加上,它对.ll文件进行了优化,如果不加上,面临的就是
就是不管怎么样你编译出来的东西都没有办法被可爱的F.getname()识别,不管怎么样都抓耳挠腮但是官方给的.ll却可以正常运行让你怀疑你是不是有问题
总之当时被困了蛮久的,后来是在知乎上的某篇文章启发了我
然后后面就是正常的啦
用了两种方式去运行了pass,一种是官方文档描述的
还有一种是老版的就是搞个.so文件(不过说实话感觉有点没有必要)