参考网站:LLVM语言参考手册
摘要
LLVM是基于静态单赋值(SSA)的表示形式。之所以为单赋值,每个名字在SSA中仅被赋值一次。它可提供类型安全性,低级操作,灵活性并能清晰地表示“所有”高级语言的功能。它是在LLVM编译策略的所有阶段中使用的通用代码表示形式。
LLVM代码表示以三种不同的形式来使用:作为内存中的编译器IR,作为磁盘上的位代码表示(适用于即时编译器的快速加载)以及作为人类可读的程序集语言表示。这使LLVM可以为有效的编译器转换和分析提供强大的中间表示,同时提供调试和可视化转换的自然方法。LLVM的三种不同形式都是等效的。
1 标识符
两种基本类型:全局和本地。全局标识符(函数、全局变量)用’@‘字符开头;本地标识符(寄存器名称、类型)用’%'字符开头。
此外,还有三种不同的标识符格式:
- 命名值以带有前缀的字符串表示。例如%foo,@DivisionByZero, %a.really.long.identifier。实际使用的正则表达式为“ [%@][-a-zA-Z . ] [ − a − z A − Z ._][-a-zA-Z .][−a−zA−Z._0-9]*”。在名称中需要其他字符的标识符可以用引号引起来。可以使用"\xx"wherexx是十六进制字符的ASCII码对特殊字符进行转义。这样,任何字符都可以用在名称值中,甚至可以用引号引起来。该"\01"前缀可用于全局值以抑制重整。
- 未命名的值以带有前缀的无符号数字表示。例如%12,@2,%44。
- 常量。
LLVM要求值以前缀开头有两个原因:编译器无需担心带有保留字的名称冲突,并且将来可以扩展保留字的集合而不会带来任何损失。此外,未命名的标识符使编译器可以快速提出一个临时变量,而不必避免符号表冲突。
LLVM中的保留字与其他语言中的保留字非常相似。有一些关键字用于不同的操作码(“,add”,“ bitcast,”ret等),原始类型名称(“,void”,“i32等等”)等。这些保留字不能与变量名冲突,因为它们都不以前缀字符(’%‘或’@’)开头。
2 类型
LLVM类型系统是中间表示形式的最重要特征之一。类型化使许多优化可以直接在中间表示上执行,而不必在转换之前对另一方面进行额外的分析。
2.1 空类型(void type)
不代表任何值且没有大小
2.2 函数类型(function type)
由返回类型和形参类型列表组成。
2.3 first class type
该类型的值是唯一可以通过指令生成的值。
2.3.1 single value types
(1) integer type:为所需的整数类型指定任意位宽度
examples:
i32 表示一个32位整数
i1942652表示一个超过1百万的超级大整数
(2) floating-point types
Type | Description |
---|---|
half | 16-bit floating-point value |
bfloat | 16-bit “brain” floating-point value (7-bit significand). Provides the same number of exponent bits as float, so that it matches its dynamic range, but with greatly reduced precision. Used in Intel’s AVX-512 BF16 extensions and Arm’s ARMv8.6-A extensions, among others. |
float | 32-bit floating-point value |
double | 64-bit floating-point value |
fp128 | 128-bit floating-point value (113-bit significand) |
x86_fp80 | 80-bit floating-point value (X87) |
ppc_fp128 | 128-bit floating-point value (two 64-bits) |
(3) x86_mmx type:表示保存在x86机器上的MMX寄存器中的值。
x86_mmx
(4) pointer type:用于指定内存位置,指针用于引用内存中的对象
<type>*
examples:
[4 x i32]* 指的是指向4个i32值的数组的指针
(5) 向量类型(vector type)
向量类型是表示元素向量的简单派生类型
Syntax:
< <# elements> x <elementtype> > ; Fixed-length vector
< vscale x <# elements> x <elementtype> > ; Scalable vector
examples:
<4 x i32>表示4个32位整数值向量
<vscale x 4 x i32>表示4个32位整数值的倍数的向量
2.3.2 label type
表示代码标签
Syntax:
label
2.3.3 token type
若一个值与一条指令相关,但该值的所有用法均无法掩盖该指令,即可使用token type。
Syntax:
token
2.3.4 metadata type
表示嵌入的元数据
Syntax:
metadata
2.3.5 aggregate types
聚合类型是可以包含多个成员类型的派生类型的子集。
(1) array type
数组类型是一个非常简单的派生类型,它在内存中按顺序排列元素。
Syntax:
[<# elements> x <elementtype>]
examples:
[40 x i32]表示40个32位整数值的数组
[3 x [4 x i32]]表示34的32位整数值的数组
[12 x [10 x float]]表示1210的单精度浮点值数组
(2) structure type
结构类型用于表示内存中数据成员的集合。
Syntax:
%T1 = type { <type list> } ; Identified normal struct type
%T2 = type <{ <type list> }> ; Identified packed struct type
若结构是“压缩”结构,这表示结构的对齐是一个字节,并且元素之间没有填充。在非压缩结构中,字段类型之间的填充是按照模块中DataLayout字符串的定义插入的。
examples:
{ i32, i32, i32 }表示3个32位整数值的3倍。
<{ i8, i32 }>表示大小为5字节的压缩结构。
(3) opaque structure type
不透明结构类型用于表示没有指定主体的命名结构类型。
Syntax:
%X = type opaque
%52 = type opaque
3 常量
3.1 简单常量(Simple Constants)
- Boolean constants:true/false
- Integer constants:如4
- Floating-point constants:如3.4
- Null pointer constants:如null
- Token constants:如none
3.2 Complex Constants
- Structure constants:类似于结构类型定义的符号表示,如{i32 4,float 3.8}
- Array constants:类似于数组类型定义的符号表示,如[i32 5,i32 7]
- Vector constants:类似于向量类型定义的符号表示,如< i32 42, i32 11, i32 74, i32 100 >
- Zero initialization:将任何类型的值初始化为零,包括标量和聚合类型
- Metadata node:没有任何类型的常量元组
3.3 Global Variable and Function Addresses
全局变量和函数的地址总是隐式有效的(链接时间)常量。当使用全局标识符时,这些常量被显式引用,并且总是具有指针类型。
3.4 Undefined Values
字符串“undef”可以在任何需要常量的地方使用,并指示值的用户可能接收到未指定的位模式。Undefined Values可以是任何类型(除了“label”或“void”)并且可以在允许常量的任何地方使用。
3.4 Poison Value
错误操作的结果。
3.5 Well-Defined Values
某个值没有未定义位也没有有毒位,则该值定义良好。若聚合数据或向量的元整定义良好则其也定义良好。
3.6 Addresses of Basic Blocks
“blockaddress”常量计算指定函数中指定基本块的地址,并且始终具有i8*类型。
3.7 DSO Local Equivalent
“dso_local_equivalent”常量表示一个函数,该函数在功能上等价于给定的函数,但总是在当前链接单元中被定义。
3.8 Constant Expressions
常量表达式可将涉及其他常量的表达式用作常量。常量表达式可以是任何first class类型,并且可以涉及任何没有副作用的LLVM操作(例如,不支持load和call)。
一些常量表达式的语法:
- trunc (CST to TYPE)
- zext (CST to TYPE)
- sext (CST to TYPE)
- fptrunc (CST to TYPE)
- fpext (CST to TYPE)
- fptoui (CST to TYPE)
- fptosi (CST to TYPE)
- uitofp (CST to TYPE)
- sitofp (CST to TYPE)
- ptrtoint (CST to TYPE)
- inttoptr (CST to TYPE)
- bitcast (CST to TYPE)
- addrspacecast (CST to TYPE)
- getelementptr (TY, CSTPTR, IDX0, IDX1, …), getelementptr inbounds (TY, CSTPTR, IDX0, IDX1, …)
- select (COND, VAL1, VAL2)
- icmp COND (VAL1, VAL2)
- fcmp COND (VAL1, VAL2)
- extractelement (VAL, IDX)
- insertelement (VAL, ELT, IDX)
- shufflevector (VEC1, VEC2, IDXMASK)
- extractvalue (VAL, IDX0, IDX1, …)
- insertvalue (VAL, ELT, IDX0, IDX1, …)
- OPCODE (LHS, RHS)