今天开始总结编译原理的知识,但是感觉这门课有难度,嗯?无妨,就是干。第一篇:编译器简介及编译器结构概述。
  下方的图片摘自编译器设计第二版。本文参考编译器设计第二版(橡书)和编译原理第三版(陈火旺版)。

编译器简介

编译器是什么?

  我们平时编程所用的语言是高级语言,而机器只能识别机器语言。那什么做桥梁?编译器做桥梁。编译器是一个复杂的程序,它的工作是 将源语言程序(一般是高级语言)转化为 目标语言程序(一般是低级语言)。也就是下图所示:

【编译原理】编译器简介及编译器结构概述

  需要注意的是,不要纠结于编译器的源语言 是不是高级语言,目标语言是不是低级语言,编译器 的作用就是将一种语言 转化 为另一种等价的语言。(所谓等价指的是 hi 的中文意思 是 你好 而不是再见)。
  比如 有些编译器 可以将高级语言程序转换为另外的高级语言程序,这类编译器叫做 源到源的转换器。又比如,有些编译器 可以将低级语言程序 转换 为 高级语言程序,这类编译器叫做 反编译器
  当然回到常规的编译器来讲,机器要执行指令并产生结果,就必须要有编译器将高级语言程序转化为低级语言程序的这个过程。但是,有些语言则不同(如书中所提Perl ,Scheme,APL),他们更多依赖的是解释器,那解释器是怎么工作的?

解释器怎么工作的?

  解释器的执行工作和编译器不同,编译器是将源程序转化为目标语言程序之后,让机器去执行目标语言程序。而解释器是一边解释,一边执行,不会产生目标程序。如下图所示:
【编译原理】编译器简介及编译器结构概述
  当然有些语言比较特殊,它们要想产生结果,既需要编译,又需要解释。如Java ,首先,Java通过编译器转换为字节码,这个过程是编译过程,然后,通过JVM解释执行字节码,这个过程是解释过程。

编译的基本原则

编译器必须保持被编译程序的语义。

 简单理解为 输入hi ,输出应该是你好,而不是再见。

编译器必须以某种可察觉的方式改进输入程序。

 简单理解为编译过程很复杂,我们要尽可能优化。

编译器结构

从功能初步理解编译器

  回到编译器的工作:理解输入源程序,并转化为目标程序。那么,我们可以将理解输入源程序当做是编译器要做的一个工作,这个工作叫做前端,同样的,我们可以将转化为目标程序当做是编译器要做的一个工作,这个工作就是后端
  前端的工作是将源程序进行处理,并产生一个结果,以待后端使用,这个结果称为IR(Intermediate Representation),也就是中间表示。后端接收这个中间形式然后把它转为指定机器的语言集。如下图所示:

【编译原理】编译器简介及编译器结构概述

进一步理解编译器

  后端接收的IR,应当是高效的,这样能让后端产生一个更快或是更小的目标程序,当然,如书上所说,一份好的IR还有其他的好处,如让后端产生更少缺页异常或耗能较少的程序。

  所以为了优化IR,就有了优化器,优化器的作用就是分析IR并产生新的IR,以改进IR。不难发现,优化器也可以看做是编译器。具体图片如下所示:
【编译原理】编译器简介及编译器结构概述

遍,趟(Pass)

  在进一步分析编译器之前,有必要了解遍(也称作趟)的意思。所谓遍,是指对源程序或中间表示IR从头到尾扫描一次,并做有关的工作处理,生成新的中间表示IR或是目标程序的过程。这个过程就叫做遍
  每一遍是从外存上获取上一次遍的结果为开始,完成工作后,将新的结果存储到外存上为结束。每遍工作完成后,所占用的存贮空间大部分会被释放。
  所以一次优化, 即旧的IR到新的IR的过程,就是一遍。

再进一步看编译器

  实际的编译器当然要复杂地多,前端,优化器,后端都被细分成了更多的阶段。
【编译原理】编译器简介及编译器结构概述
  前端由两趟或是三趟组成,处理源语言的各种细节,并产生初步的IR。优化器由若干趟形成,每一趟都将输入的IR进一步处理。后端由若干趟组成,每趟都是对输入的IR处理,使之更接近目标语言的机器集。

  需要注意的是,每一趟都应该满足编译器的基本原则之一:不能修改原有语义。还有就是优化器通常不能产生最优的IR,毕竟,针对不同的机器,还要经过后端的若干趟,才可能产生接近最优的目标程序。

  写完收工!

相关文章: