LLVM IR 被设计为一种轻量级,底层的语言用来描述各种上层的语言,对于不同的语言,都可以归纳为同一种IR的格式。
标示符:
LLVM的标识符分为全局标识符和局部标识符。 全局标识符以'@'开头,局部标识符以'%'为开头。
1. 命名过的数值会被标识为一个带有前缀的字符串,类似于%foo, @DivisionByZoo.具体的语法是:
[%@][a-zA-Z$._][a-zA-z$._0-9]*
特殊字符可以使用反斜杠'\xx'的形式标示。
2. 未命名过的数值(临时变量之类)采用数字加前缀的方式,类似于%12,@2
3. 临时变量的数字是逐个递增的
4. 注释以';'为开头,直到该行结束
模块结构:
LLVM的程序是有模块组合而成的。每个模块包含函数,全局变量和符号表入口。模块也有可能被LLVM链接器绑定在一起。
; 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]* @.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
!1 = metadata !{i32 42}
!foo = !{!1, null}
这是官方文档上hello world的示例
这个例子中,有一个全局变量.str,一个脘部函数puts,一个函数定义main,和一个命名的元数据foo。
一般来讲,模块是由一些列的全局数据组成的(包括函数和数值),LLVM使用一个指向内存地址的指针来标识。
链接类型:
所有的全局数据都需要声明一种链接方式。下面是几种常见的链接类型:
private: 只可在当前模块内被访问。由于是模块的私有变量,不会出现在符号表中。
internal:于private类似,表示C中的'static'
available_externally: 可以被用来实现内联和优化,以便被模块之外调用。 只能用于定义,不能用于声明。
linkonce: 当做链接操作时,定义为linkonce的数据会和其他模块中定义为linkonce的数据合并,可以被用作内联函数,模板或其他需要RTTI的地方。如果一个被定义为 linkonce的数据从没被引用过,那么它是被允许被丢弃的。
weak:与linkonce类似,但是如果数据为被引用过,也不会被丢弃。
common:与weak类似,用于C中的临时变量。
external: 如果没有显式的定义任何一种链接类型,就采用external为默认类型。这种类型表明它是模块外部可见和使用的。
dllimport/dllexport: 制作dll的时候使用的。