LLVM IR 语法

译者序
    目前几乎没有关于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、非命名值以数字开头,例如: %12, @2, %44.
    3、常量,详见下文“常量”节。
    LLVM语言之所以使用特定的前缀,有2个理由:编译器不需要担心命名与保留字冲突,以及保留字在未来进行扩展代价更小。此外,非命名标识符允许编译器能够迅速拿出一个临时变量,而不必以避免符号表冲突。
    LLVM语言的保留字和其他语言非常类似。不同的关键字对应不同的opcode('add', 'bitcast', 'ret'....),不同的类型名('void', 'i32'...)。他们不会和变量名重复,因为他们不以'@', '%'开头。
    下面是一个LLVM语言例子,int x 乘以 8:
    %result = mul i32 %X, 8
After strength reduction:
      %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、如果计算结果没有被赋值给一个命名值,那么一个临时非命名值会创建,并被赋值。
    3 、临时非命名值,是从‘0’开始,按顺序递增命名的。注意基本块和非命名的函数参数也包含在这里。

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}
    在一般情况下,一个模块的组成:函数和全局变量类的全局值、一个指向一个存储器位置指针(在本例,一个指向字符数组,和一个指针的函数),和linker type(详见下文)。

Linkage Types(链接类型    
    所有的全局变量和函数都有一个如下的链接类型:
    private
        私有的全局值只能被当前模块的对象直接访问。
    internal
        和private类似,但是这个值作为一个局部符号出现在对象文件(ELF)中。这个和C语音中的"static"关键字保持一致。
    available_externally       
       该值不会被输出到对象文件,一个available_externally值,等价于一个外部声明。
    linkonce
  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值