参考书:《Getting Started with LLVM Core Libraries》
LLVM IR 内存表示:
1. 内存中的 IR 表示更接近目前的LLVM语法,关于IR头文件位于目录include/llvm/IR,下边是一些重要的类:
- Module类:可以理解为一个源文件读进内存中就是一个module,module包含所有数据和函数。它声明了Module::iterator,可以通过 begin() and end() 来拿到它
- Function类:显而易见是函数类,使用isDeclaration() 判断是否是函数声明,使用getArgumentList()获取函数参数列表,举例:
for (Function::iterator i = function. begin(), e = function.end(); i != e; ++i)
{
//something
}
- BasicBlock 类:一个函数包含多个基础块,一个基础块包含多条指令(instructions)。
每一个基础块一定由 terminator instruction 结尾(跳转指令或者返回指令);
函数的第一个基础块是入口,叫做 entry,一定不是其他分支指令的目标。 - Instruction 类:是LLVM IR 执行的最小单元,可以通过这些方法 isAssociative(), isCommutative(), isIdempotent(), or isTerminator() 判断,使用getOpcode() 可以知道指令的实际功能,返回值是llvm::Instruction 提前定义好的一个枚举类型。
2. 其他功能强大的类:Value and User接口,一个继承Value 的类意味着定义了一个可以在其他地方使用的结果,而一个继承User 的类意味着这个实体使用了一个或多个Value接口;Function and Instruction 即是Value的子类也是User的子类,而BasicBlock 还是Value的子类。下边来深入理解一下:
- Value 类:
定义了use_begin() 和 use_end() 方法,可以遍历Users,所以可以很容易获取def-use 链;
使用 getName() 获取名字;
任何一个LLVM value 都是唯一的定义;
方法replaceAllUsesWith(Value *) 可以全局替换所有value的使用,这是SSA的一个优点,可以很轻松的进行指令替换和速度优化。 - User 类:
定义了方法op_begin() 和 op_end()可以快速获取value的接口和使用,他表示了use-def链。