[译] LLVM IR中间码指令集

这篇博客主要介绍了LLVM IR(Intermediate Representation)的详细内容,包括LLVM IR的作用、三种不同形式的等价表示,以及LLVM IR的格式规范和标识符类型。文中还举例说明了LLVM IR中的保留字、注释、临时值的命名和编号,以及高层结构如模块、全局变量和函数的定义。博主强调了LLVM IR在编译器优化、调试和可视化转换中的重要性,并指出中文资源的匮乏问题。
摘要由CSDN通过智能技术生成

最近在研究这个东西, 实在百度不到, 最后在谷歌上找到英文手册. 

英文手册地址:https://llvm.org/docs/LangRef.html

先说点废话: 

     国内的IT水平离世界顶级水平差距实在有点大, 个人感觉 有些因素导致这个结果:

     1.化身广告商的百度, 想找点专业文章, 没戏. 

     2.墙. 有用的文档在墙外,不翻墙看不到. 

     3.收费论文查询. 实在看不起, 没钱啊. 在这个事情上收费简直是个生孩子没P眼的生意. 

     4.中文论文太水. 例如:导师的崇高感和师娘的优美感

     5.论文权重问题,引致优秀论文从来都是发表在国外.

以下是 谷哥翻译的结果, 我的英文水平太烂, 大家可以对照 英文版一起看. 我就是对照着看的. 


LLVM语言参考手册

本文档是LLVM汇编语言的参考手册。LLVM是基于静态单一分配(SSA)的表示形式,可提供类型安全性,低级操作,灵活性以及清晰地表示“所有”高级语言的功能。它是在LLVM编译策略的所有阶段中使用的通用代码表示形式。

简介
LLVM代码表示被设计为以三种不同的形式使用:作为内存中的编译器IR,作为磁盘上的位代码表示(适用于即时编译器的快速加载)以及作为人类可读的程序集语言表示。这使LLVM可以为有效的编译器转换和分析提供强大的中间表示,同时提供调试和可视化转换的自然方法。LLVM的三种不同形式都是等效的。本文档描述了人类可读的表示形式和符号。

LLVM表示的目标是轻量级和低级,同时要表现,键入和扩展。它的目标是成为一种“通用IR”,因为其级别足够低,可以将高级思想清晰地映射到它(类似于微处理器如何成为“通用IR”,从而允许将许多源语言映射到它们)。 )。通过提供类型信息,LLVM可以用作优化的目标:例如,通过指针分析,可以证明从未在当前函数之外访问C自动变量,从而将其提升为简单的SSA值而不是内存位置。

格式正确
重要的是要注意,该文档描述了“格式良好”的L​​LVM汇编语言。解析器接受的内容与“格式正确”的内容之间存在差异。例如,以下指令在语法上尚可,但格式不正确:

%x = add i32 1, %x
因为的定义%x并不支配其所有用途。LLVM基础结构提供了一个验证通行证,可用于验证LLVM模块格式正确。此过程在解析输入程序集后由解析器自动运行,而在输出位代码之前由优化器自动运行。验证程序遍历指出的违规表示转换遍历中存在错误或输入到解析器。

标识符
LLVM标识符有两种基本类型:全局和本地。全局标识符(函数,全局变量)以'@' 字符开头。本地标识符(寄存器名称,类型)以'%'字符开头 。此外,出于不同的目的,存在三种不同的标识符格式:

命名值以带有前缀的字符串表示。例如%foo,@DivisionByZero, %a.really.long.identifier。实际使用的正则表达式为“ [%@][-a-zA-Z$._][-a-zA-Z$._0-9]*”。在名称中需要其他字符的标识符可以用引号引起来。可以使用"\xx"where xx是十六进制字符的ASCII码对特殊字符进行转义。这样,任何字符都可以用在名称值中,甚至可以用引号引起来。该"\01"前缀可用于全局值以抑制篡改。
未命名的值以带有前缀的无符号数字值表示。例如%12,@2,%44。
常量,在下面的常量部分中介绍。
LLVM要求值以前缀开头有两个原因:编译器不必担心带有保留字的名称冲突,并且将来可以扩展保留字的集合而不会带来任何损失。此外,未命名的标识符使编译器可以快速提出一个临时变量,而不必避免符号表冲突。

LLVM中的保留字与其他语言中的保留字非常相似。有一些关键字用于不同的操作码(“,add”,“ bitcast,” ret等),原始类型名称(“,void”,“ i32等等”)等。这些保留字不能与变量名冲突,因为它们都不以前缀字符('%'或'@')开头。

这是将整数变量' %X'乘以8 的LLVM代码示例:

简单的方法:

%result = mul i32 %X, 8
强度降低后:

%result = shl i32 %X, 3
困难的方法:

%0 = add i32 %X, %X           ; yields i32:%0
%1 = add i32 %0, %0           ; yields i32:%1
%result = add i32 %1, %1
最后一种乘以%X8的方法说明了LLVM的几个重要词汇特征:

注释以'分隔,;直到行尾。
未将计算结果分配给命名值时,将创建未命名的临时对象。
未命名的临时文件按顺序编号(使用按功能递增的计数器,从0开始)。请注意,该编号中包括基本块和未命名的功能参数。例如,如果没有为条目基本块指定标签名称,并且所有功能参数都被命名,则它将获得数字0。
它还显示了我们在本文档中遵循的约定。在演示指令时,我们将在指令后附上注释,该注释定义产生的值的类型和名称。

高层结构
模块结构
LLVM程序由组成Module,每个都是输入程序的翻译单元。每个模块由函数,全局变量和符号表条目组成。可以将模块与LLVM链接器组合在一起,后者可以合并函数(和全局变量)定义,解析前向声明并合并符号表条目。这是“ 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}
这个例子是由高达全局变量命名为“ .str”,在一个外部声明“ puts”函数, 函数定义为“ main”,并 命名为元数据 “ foo”。

通常,模块由全局值列表组成(其中函数和全局变量均为全局值)。全局值由指向内存位置的指针(在这种情况下,指向char数组的指针和指向函数的指针)表示,并具有以下链接类型之一。

联动类型
所有全局变量和函数都具有以下链接类型之一:

private

具有“ private”链接的全局值只能由当前模块中的对象直接访问。特别是,将代码链接到具有私有全局值的模块中可能会导致在需要时将私有重命名以避免冲突。因为该符号是模块专用的,所以可以更新所有引用。这不会显示在目标文件的任何符号表中。

internal

与private相似,但是该值STB_LOCAL在目标文件中显示为本地符号(对于ELF)。这对应static于C中关键字' ' 的概念。

 

 

CSDN 不让发长文, 没办法了, 读者请自行翻译吧, 用chrome浏览器就行.  外国的月亮真他妈的圆~~~~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值