编译原理实战课
宫文学
北京物演科技CEO
立即订阅
2948 人已学习
课程目录
已更新 29 讲 / 共 53 讲
0/4登录后,你可以任选4讲全文学习。
课前必读 (2讲)
开篇词 | 在真实世界的编译器中游历
免费
学习指南 | 如何学习这门编译原理实战课?
预备知识篇 (9讲)
01 | 编译的全过程都悄悄做了哪些事情?
02 | 词法分析:用两种方式构造有限自动机
03 | 语法分析:两个基本功和两种算法思路
04 | 语义分析:让程序符合语义规则
05 | 运行时机制:程序如何运行,你有发言权
06 | 中间代码:不是只有一副面孔
07 | 代码优化:跟编译器做朋友,让你的代码飞起来
08 | 代码生成:如何实现机器相关的优化?
知识地图 | 一起来复习编译技术核心概念与算法
不定期加餐 (1讲)
不定期加餐1 | 远程办公,需要你我具备什么样的素质?
真实编译器解析篇 (17讲)
09 | Java编译器(一):手写的编译器有什么优势?
10 | Java编译器(二):语法分析之后,还要做些什么?
11 | Java编译器(三):属性分析和数据流分析
12 | Java编译器(四):去除语法糖和生成字节码
13 | Java JIT编译器(一):动手修改Graal编译器
14 | Java JIT编译器(二):Sea of Nodes为何如此强大?
15 | Java JIT编译器(三):探究内联和逃逸分析的算法原理
16 | Java JIT编译器(四):Graal的后端是如何工作的?
17 | Python编译器(一):如何用工具生成编译器?
18 | Python编译器(二):从AST到字节码
19 | Python编译器(三):运行时机制
20 | JavaScript编译器(一):V8的解析和编译过程
21 | JavaScript编译器(二):V8的解释器和优化编译器
22 | Julia编译器(一):如何让动态语言性能很高?
23 | Julia编译器(二):如何利用LLVM的优化和后端功能?
24 | Go语言编译器:把它当作教科书吧
25 | MySQL编译器(一):解析一条SQL语句的执行过程
编译原理实战课
15
15
1.0x
00:00/00:00
登录|注册

06 | 中间代码:不是只有一副面孔

宫文学 2020-06-12
你好,我是宫文学。今天这一讲,我来带你认识一下中间代码(IR)。
IR,也就是中间代码(Intermediate Representation,有时也称 Intermediate Code,IC),它是编译器中很重要的一种数据结构。编译器在做完前端工作以后,首先就是生成 IR,并在此基础上执行各种优化算法,最后再生成目标代码。
所以说,编译技术的 IR 非常重要,它是运行各种优化算法、代码生成算法的基础。不过,鉴于 IR 的设计一般与编译器密切相关,而一些教科书可能更侧重于讲理论,所以对 IR 的介绍就不那么具体。这就导致我们对 IR 有非常多的疑问,比如:
IR 都有哪些不同的设计,可以分成什么类型?
IR 有像高级语言和汇编代码那样的标准书写格式吗?
IR 可以采用什么数据结构来实现?
为了帮助你把对 IR 的认识从抽象变得具体,我今天就从全局的视角和你一起梳理下 IR 有关的认知。
首先,我们来了解一下 IR 的用途,并一起看看由于用途不同导致 IR 分成的多个层次。

IR 的用途和层次

设计 IR 的目的,是要满足编译器中的各种需求。需求的不同,就会导致 IR 的设计不同。通常情况下,IR 有两种用途,一种是用来做分析和变换的,一种是直接用于解释执行的。我们先来看第一种。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《编译原理实战课》,如需阅读全部文章,
请订阅文章所属专栏新⼈⾸单¥29.9
立即订阅
登录 后留言

精选留言(5)

  • qinsi
    关于思考题,SSA只允许给变量赋一次值,如果是循环的话就意味着要创建循环次数那么多的临时变量了?如果SSA有函数/子程序的写法的话,是否就可以把循环改写成函数的递归调用呢?类似这样:

    int loop(i, a, result) {
      if (i < a) {
        int sum = result + i;
        return loop(i + 1, a, sum);
      }
      return result;
    }

    int bar(a) {
      int sum = 0;
      int i = 0;
      return loop(i, a, sum);
    }

    如果是在实机上运行且没有尾递归优化的话,相当于是把临时变量都创建在栈上了。

    作者回复: 这个问题很有意思。你问的这个问题其实挺深入,涉及静态分析和动态分析的区别。

    是这样的。我们在做编译的时候,大部分时候是做静态的分析,仅仅基于程序文本,不看它运行时的状态。

    所以,我们说一个变量从词法角度(Lexically)做了一次赋值就行了。注意,我这里说的词法,不是指词法分析的词法,而是指仅通过程序文本的结构决定。词法作用域(Lexical Scope)中词法,也是同一个意思。

    回到你的问题,SSA说的是词法角度的使用和定义(use-def)关系。因为我们的优化算法,基本上也都是静态分析。实际运行时被赋值多次,并不影响静态分析的结果。死代码消除也好,公共子表达式消除也好,都不影响。

    2020-06-12
    2
  • 茶底
    老师为啥go的内容只有一章啊,go内置token/ast等库,yacc三方库也有,写起轮子很舒服,希望宫老师能多讲一些go的。

    作者回复: 是这样的。因为各个编译器虽然有不同,但还是有共性的。有些内容,在前面的编译器里讲了,后面就不用重复了。
    这也是我们课程设计的目的:分析每个编译器都是一次认知迭代。到最后,你认识每个编译器的速度会越来越快。

    2020-06-12
    1
  • Jxin
    看龙书。感觉也是只分了hir(中间表达形式)和lir(目标机器语言)。两者可以分别做机器无关代码优化和技术相关代码优化。

    作者回复: 对,高和低也就是个相对概念,没有绝对统一的标准。
    Graal编译器(Java的一个JIT编译器)里也是用的hir和lir两个概念做区分就行了。

    2020-06-19
  • 阿木
    循环其实也是分支语句,只是它可以往上跳

    作者回复: 没错!

    2020-06-16
  • leaf
    看过cliff click在95年左右的文章“A Simple Graph-Based Intermediate Representation”,“Global Code Motion Global Value Numbering”,“Combining Analysis, Combining Optimization”,也是介绍PDG的,老师推荐的这篇文章是87年的,之前不知道,想请教click的文章与老师推荐的文章大概是什么关系

    作者回复: click的文章时间更晚一点,描述得更具象一点,阅读起来也更容易,没有那么多数学公式。v8和Graal编译器相关的论文都引用了click的文章。我在第10讲,Graal IR部分,也加了click的论文的链接。
    click除了描述基于图的IR,还有几篇论文是描述基于这种IR的算法实现。

    2020-06-14
收起评论
5
返回
顶部