The LLVM Intermediate Representation
官方的IR是由Instruction类产生的。IR有三种存在形式:
- 内存中的表示:Instruction 类
- 硬盘上的节省空间的表示:bitcode文件
- 硬盘上的可读文档:LLVM汇编文件
生成bitcode文件:
$ clang test.c -emit-llvm -c -o test.bc
生成汇编表示:
$ clang test.c -emit-llvm -S -c -o test.ll
二者之间可以相互转化:
$ llvm-as test.ll -o test.bc $ llvm-dis test.bc -o test.ll
从bitcode文件中提取某个函数:
$ llvm-extract -func=main test.bc -o test-main.bc
IR的内存中表示
内存中表示的相关头文件在include/llvm/IR目录下,下面是几个最为重要的类:
- Module类包含了整个翻译单元中用到的所有数据
- Function类包含与函数声明和定义相关的所有对象
- BasicBlock类封装了一系列的LLVM指令
- Instruction类代表了LLVM IR中的一些基本函数
可以用IRBuilder<> 来构建IR指令,然后调用SetInsertPoint方法设置要放置的位置。
可以通过bitcode来生成IR生成器:
$ llc -march=platform test.bc -o test.cpp
IR的优化
优化bitcode文件:
$ opt -O3 test.bc -o test-O3.bc
标准的编译时优化:
$ opt -std-compile-opts test.bc -o test-stdc.bc
标准的链接时优化:
$ llvm-link test1.bc test2.bc test3.bc -o=test.bc $ opt -std-link-opts test.bc -o test-stdl.bc
查看pass的占比:
$ clang -Xclang -print-stats -emit-llvm -O1 test.c -c -o test-O1.bc
查看pass的依赖关系:
$ opt test-O0.ll -debug-pass=Structure -mem2reg -S -o sum-O1.ll
自定义pass
FnArgCnt输出每个函数的参数个数和函数名:
$ cd <llvm_source_tree> $ mkdir lib/Transforms/FnArgCnt $ cd lib/Transforms/FnArgCnt
FnArgCnt.cpp代码如下:
#include "llvm/IR/Function.h" #include "llvm/Pass.h" #include "llvm/Supprot/raw_ostream.h" using namspace llvm; namespace { class FnArgCnt : public FunctionPass { public: static char ID; FnArgCnt() : FunctionPass(ID) {} virtual bool runOnFunction(Function &F) { errs() << "FnArgCnt --- "; errs() << F.getName() << ": "; errs() << F.getArgumentList().size() << '\n'; return false; } }; } char FnArgCnt::ID = 0; static RegisterPass<FnArgCnt> X("fnargcnt", "Function Argument Count Pass", false, false);
在相同的目录下创建Makefile:
# Makefile for FnArgCnt pass # Path to top level of LLVM hierarchy LEVEL = ../../.. # Name of the library to build LIBRARYNAME = LLVMFnArgCnt # Make the shared library become a loadable module so the tools can # dlopen/dlsym on the resulting library. LOADABLE_MODULE = 1 # Include the Makefile implementation stuff include $(LEVEL)/Makefile.common
在lib/Transforms/Makefile中添加FnArgCnt到PARALLEL_DIRS变量中:
PARALLEL_DIRS = Utils Instrumentation Scalar InstCombine IPO Vectorize Hello ObjCARC FnArgCnt
在运行./configure 后执行make,生成的共享库会放在Debug+Asserts/lib目录中。通过下列命令执行自定义pass:
$ opt -load /lib/LLVMFnArgCnt.dylib -fnargcnt < test.bc > /dev/null
作者:glob
出处:http://www.cnblogs.com/adera/
欢迎访问我的个人博客:https://blog.globs.site/
本文版权归作者和博客园共有,转载请注明出处。