译者序
目前几乎没有关于LLVM IR(中间语言)的中文资料,因此本人在看英文手册的同时尝试翻译。限于水平和时间,本文只翻译了一小部分英文手册,如果发现理解有冲突之处,请以原文为准。
原文链接:http://llvm.org/docs/LangRef.html
摘要
本文档是一个LLVM汇编语言手册,LLVM 语言是一个Static Single Assignment (SSA)的中间语言,其特点:类型安全; 低级别操作;灵活;具有清晰表示“所有”高级语言的能力。它作为一个统一的代码表示,贯穿LLVM编译的各个阶段。
介绍
LLVM语言,旨在用于三个不同的形式:内存中的编译中间语言(IR),保存在硬盘上的bitcode(适合快速地被一个JIT编译器加载),一个可读性的汇编语言表示。如此,LLVM将为高效编译转换和分析提供一个强大的中间表示。事实上,LLVM的三种不同的形式都是等价的。本文档描述了人类可读的表征和符号。
LLVM语言旨在轻量、底层、同时富有表现力,类型化,易于扩展。LLVM语言目标是成为一种"通用中间语言",通过足够低层次使得高级语言可以清晰的映射到它。通过提供类型信息,LLVM语言可以作为优化的目标:例如,通过指针分析,可以证明,一个C自动变量从不当前函数之外访问,允许它被提升到一个简单的SSA值,而不是一个堆变量。
Well-Formedness
略...
标识符
LLVM标识符有2个基本类型:全局和局部。全局标识符(函数,全局变量)以“@”字符开头。本地标识符(注册名称,类型)以'%'字符开头。此外,有三种不同的格式标识符,用于不同的目的:
1、命名值以字母序列开头,例如:
%foo
, @DivisionByZero
, %a.really.long.identifier
. 正则表达式为: ‘[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*
‘.
2、非命名值以数字开头,例如:
3、常量,详见下文“常量”节。
%12
, @2
, %44
.
LLVM语言之所以使用特定的前缀,有2个理由:编译器不需要担心命名与保留字冲突,以及保留字在未来进行扩展代价更小。此外,非命名标识符允许编译器能够迅速拿出一个临时变量,而不必以避免符号表冲突。
LLVM语言的保留字和其他语言非常类似。不同的关键字对应不同的opcode('add', 'bitcast', 'ret'....),不同的类型名('void', 'i32'...)。他们不会和变量名重复,因为他们不以'@', '%'开头。
下面是一个LLVM语言例子,int x 乘以 8:
%result = mul i32 %X, 8
%result = shl i32 %X, 3
And the hard way:
%0 = add i32 %X, %X ; yields i32:%0 %1 = add i32 %0, %0 ; yields i32:%1 %result = add i32 %1, %1最后一个例子说明了LLVM语言的一些特征:
1、注释行以“;”开头
2、如果计算结果没有被赋值给一个命名值,那么一个临时非命名值会创建,并被赋值。
High Level Structure
Module Structure
LLVM程序由模块组成,每一个模块都是输入程序的一个翻译单元。每个模块包括:函数、全局变量、符号表。模块将被LLVM linker组合起来:合并函数(全局变量)定义,解决向前声明,合并符号表。下面是一个“hello world”模块:
; Declare the string constant as a global constant.
@.str = private unnamed_addr constant [13 x i8] c"hello world\0A\00"
; External declaration of the puts function
declare i32 @puts(i8* nocapture) nounwind
; Definition of main function
define i32 @main() { ; i32()*
; Convert [13 x i8]* to i8 *...
%cast210 = getelementptr [13 x i8], [13 x i8]* @.str, i64 0, i64 0
; Call puts function to write out the string to stdout.
call i32 @puts(i8* %cast210)
ret i32 0
}
; Named metadata
!0 = !{i32 42, null, !"string"}
!foo = !{!0}
|
所有的全局变量和函数都有一个如下的链接类型:
private
私有的全局值只能被当前模块的对象直接访问。
internal
和private类似,但是这个值作为一个局部符号出现在对象文件(ELF)中。这个和C语音中的"static"关键字保持一致。
available_externally
该值不会被输出到对象文件,一个available_externally值,等价于一个外部声明。
linkonce