24 | 中间代码:兼容不同的语言和硬件
该思维导图由 AI 生成,仅供参考
介于中间的语言
- 深入了解
- 翻译
- 解释
- 总结
LLVM汇编码是一种关键的中间代码表示形式,具有精确描述目标机器相关信息的特点,适用于生成高效的目标代码。文章介绍了中间代码的概念及其特点,重点讨论了三地址代码(TAC)和LLVM的IR格式。相比之下,LLVM的IR能够准确地描述与目标机器相关的具体信息,因此更适合用于生成目标代码,真正能够用于生产环境。此外,文章还详细介绍了LLVM汇编码的特点,采用静态单赋值代码形式,具有更多的细节信息,包括类型系统、全局变量和常量、元数据等。通过对LLVM汇编码的解析,读者可以了解其与传统汇编的区别,以及在代码优化方面的优势。总的来说,本文提供了全面的概览和实用信息,帮助读者了解中间代码及其特点。文章还介绍了LLVM IR的用法,通过示例代码和对应的LLVM汇编码,帮助读者更好地理解LLVM IR的特点和用法。通过本文的阅读,读者可以快速了解中间代码的技术特点,以及LLVM汇编码的应用概览,为进一步深入学习和应用提供了基础知识。
《编译原理之美》,新⼈⾸单¥59
全部留言(8)
- 最新
- 精选
- minghu6AST也是一种IR说得不严谨, AST显然是语义相关的, 要把AST转成类似LISP形式的树, 在这个过程中结构化地抽象掉语义, 这才算是一种IR 作者可能混淆了这两个概念.
作者回复: 你专注了一个有意思的问题。对概念的分析,往往非常有用。概念是一切的基础。值得我认真回答一下。 对于IR的定义,有狭义和窄义两种不同的理解。 从狭义的角度,IR是在AST之后,用于做优化的数据结构,这是我们大部分场景里提到IR时候的含义。我们用狭义的定义的时候,通常字节码也不算IR,因为它已经算是目标代码了,也主要不是用于优化的目的。 从广义的角度,IR是处于源代码和目标代码之间的各种能够表示代码的数据结构。 在wikipedia中,对AST有这么一段描述: Abstract syntax trees are data structures widely used in compilers to represent the structure of program code. An AST is usually the result of the syntax analysis phase of a compiler. It often serves as an intermediate representation of the program through several stages that the compiler requires, and has a strong impact on the final output of the compiler. 这里面,就指出AST是一种“intermediate representation”。而如果你去查IR的词条,里面也会有对AST的引用,跟字节码并列。 再加深一下理解: 1.基于AST能否做优化? 是可以的。在看JDK的编译器代码的时候,就能发现很多基于AST的优化。优化是不嫌早的。而因为JDK的前端编译器只是生成字节码而已,所以很多优化都是在AST上去做。 2.IR是否可以是树状结构(甚至直接就基于AST)? 我们把IR根据抽象层次的高低,分为HIR、MIR和LIR。对于HIR来说,不少是采用树状结构的,也保留了像循环、分枝判断这样的高层次结构。 根据方舟编译器早期释放出来的代码和文档,其Maple IR就是一个树状结构的。随着优化的进程,树的节点逐步变成低级别的操作,树的高度也会降低。不过,我不知道方舟编译器最新的版本是否还会保持这个设计。我最近会问问内部相关的人员。 3.字节码算不算IR? 我的观点:广义上算,因为它毕竟是中间格式,基于字节码还可以进一步做优化,比如Web Assembly就是这个设计。运行时读入Web Assembly以后,会启动JIT的过程,在这个过程中可以做优化。 狭义上不算,因为它已经是某个虚拟机的目标代码。 4.AST能否作为目标代码? 这是另一个极端。AST通常并不用于执行程序。但是,对于特别简单的脚本语言,或者一个公式解释器,基于AST运行也无不可。 5.中间代码是否包含语义? 不同层次的IR在语义上是等价的。虽然从AST到HIR一直到LIR使用的操作是不同的,语义的抽象程度是从高到低的,但它们是等价的。不同层次的IR适合做不同的优化。
2021-05-3059 - 沉淀的梦想对与LLVM的SSA有点不太理解,`=`和`store`指令的区别是什么呢?为什么`store`就不算赋值呢,看llvm字节码里经常`store`到同一个寄存器多次,这是不是有点违背SSA?
作者回复: store是把寄存器的内容,写到内存中。与之对应的指令是load。 是的,涉及内存访问的时候,是可以违背SSA的。这点你看得很细。非常值得表扬!我在第26讲提到了这个知识点。你提前就发现了。
2019-10-237 - 独钓寒江雪老师好,文中说,从其他基本块不可以跳转到入口基本块,也就是函数中的第一个基本块。那么,如果出现递归调用,是怎么处理的呢?
作者回复: (我对另一个同学的回答,这里拷贝一份) 递归相当于调用另一个函数。所有的参数、本地变量,要再来一份,也就是要创建一个新的活动记录(栈帧)。 不过,对于递归调用中的尾递归,编译器是可以做优化的,也就是不用再进行一次新的函数调用,从而节省了系统资源的开销。
2020-06-022 - ztxc第一行是整个基本块的唯一入口,从其他基本块跳转过来的时候,只能跳转到这个入口行,不能跳转到基本块中的其他行。 最后我要强调,从其他基本块不可以跳转到入口基本块,也就是函数中的第一个基本块。这个规定也是有利于做数据优化。 老师好,这两段不太理解。第一段是说跳转的入口基本块。第二段说不可以跳转。第二段的意思是说从本基本块内部不能跳转到本基本块的入口基本块吗?
作者回复: 不是。 第一段的意思:每个基本块中的代码都是从第一行执行到最后一行,不可能从别的地方跳转到这个基本块中间的一行,然后再继续执行,也不可能执行到中间就跳转出去。 第二段的意思:入口基本块是CFG中的一个特殊基本块,函数开始运行时就进入这个基本块。
2020-07-031 - coconutIfZ t1 Goto L1; 这个是不是不能算作tac,因为包含了ifZ、Goto两个操作2021-07-151
- Geek_e8d55ensw 无符号环绕怎么理解呢?2021-05-26
- lion_flyStatic Single Assignment:SSA(静态单赋值) Three Address Code,:TAC(三地址代码)2020-12-11
- 超越杨超越老师的demo,if条件语句的ir是不是写错了?看起来有些奇怪。2020-05-062