LLVM 中间语言参考
#概述
LLVM is a Static Single Assignment (SSA) based representation that provides type safety, low-level operations, flexibility, and the capability of representing ‘all’ high-level languages cleanly
更严谨, 更formal的 C 语言
LLVM IR 有三种形态: 位于llvm工具内存中, 以二进制格式存储(.bc文件), 以文本格式存储(.ll文件). 用 llvm-as
可以把 .ll 格式转换为 .bc 格式, llvm-dis
反之
LLVM IR 由和高级语言类似的语句组成.
变量采用 SSA 模式, 不能被重复赋值
#注释
从 ; 到行尾的部分是注释
#局部变量
LLVM IR 中的变量存储临时结果
变量名字以 % 开头, 变量名中可以有 . 等字符, 可以是纯数字
变量不需要提前声明, 赋值即定义变量
1 | %1 = mul i32 %0, 7 ; v1 = v0 * 7 |
#全局变量
全局变量名字以 @ 开头, 其他与局部变量类似
#类型
LLVM IR 必须指定每个变量, 函数的类型
不会发生自动类型转换 避免歧义
#函数
declare 声明函数
1 | declare <ResultType> @Name (argument*) |
define 定义函数
1 | define <ResultType> @Name (argument*) { |
#字符串
和c语言的一样
#标签 label
LLVM IR 的标签和 C 语言中类似
#类型系统
void 无值 无大小
iN N位整数
half/bfloat/float/double/fp128 浮点数
<ty>*
指针类型label 标签类型
token token类型
[<size> x <ty>]
数组类型1
@array = global [42 x i32] zeroinitializer
type { <ty> [, <ty>]* }
结构体类型type <{ <ty> [, <ty>]* }>
压缩结构体类型 不做对齐
#常量 Const
- true/false i1类型
- null 指针类型
- none token类型
#指令系统
#控制流指令
- ret
- br
- switch
- indirectbr
- invoke
#算术指令
- fneg
- add/fadd
- sub/fsub
- mul/fmul
- udiv/sdiv/fdiv
- urem/srem/frem
- shl
- lshr/ashr
- and/or/xor
#内存指令
#alloca 分配栈内存
1 | %ptr = alloca <type> |
背后是栈指针的改变
#load store 读取/写入值
1 | <result> = load [volatile] <ty>, ptr <pointer>[, align <alignment>] |
#指针偏移 Get Element Pointer (GEP)
1 | <result> = getelementptr <ty>, <ty>* <ptrval>, [i32 <idx>]+ |
GEP 仅计算指针加上偏移后的值, 本身并不进行任何数据的访问或修改
偏移按照指向对象的类型, 相当于 C 语言里面的 数组+偏移量 的模式
#类型转换指令
- trunc … to
- zext … to
- sext … to
#杂项指令
- icmp 整数向量比较
- fcmp 浮点数向量比较
- select 类似三元表达式
- freeze : stop propagation of undef and poison values
- call 函数调用
- va_arg 变长参数
#Phi 指令
有时需要对已经定义的变量赋一个新的值 (例如循环变量)
SSA 不允许这样做 -> phi 运算
1 | <result> = phi <ty> [<val0>, <label0>], [<val1>, <label1>] … |
根据前一个基本块是哪一个 选择对应的值
#内置函数
- va_start/va_end/va_copy
- abs/max/min/sin/cos/…
- ctlz/fshl/…