• 1338_龙书笔记_001_编译器的大概结构以及工作的基本流程


    全部学习汇总: GreyZhang/g_compilers: learn some basic compiler Principles, Techniques, and Tools (github.com)

    Page1:

    编译器:一种程序,读取编写好的程序代码翻译成等价的另外一种语言写出来的程序。

    解析器:不做翻译的工作,而是直接分析用户代码之后执行相应的动作。

    编译器生成的程序通常效率高,但是解析器由于会读取每一行用户代码因此可能有更好的诊断效果。

    Java融合了两种方式,翻译的过程是生成字节码的过程,执行的时候通过虚拟机来解析字节码。

    Page2:

    预处理器:把多个代码文件聚合到一块,同时把宏的缩写形式转换为源语言。

    编译的大概过程: 源程序-->预处理器-->(经过预处理的源程序)-->编译器-->(目标汇编程序)-->汇编器-->(可重定位机器代码)-->链接器(库文件)/加载器(把可执行目标文件放入内存)-->目标机器代码。

    目前,我接触到的嵌入式显然也是类似的过程。但是最后一步中的加载器部分多少有些不同,嵌入式并没有这样的过程,但是有一个与之类似的烧写以及启动过程。

    编译器一般由两部分组成,一部分是用来做分析的,另一部分是用来做综合的。其中分析的过程是把代码转换成一种中间表示,创建符号表。中间表示以及符号表都会传递给综合部分进行下一步处理。一般来说,分析叫做前端,综合叫做后端。在两个过程之间有一个与机器无关的优化阶段,但是优化是可选的。

    Page3:

    编译器的第一个步骤是词法分析或扫描,上面的这个图是一个编译器各个步骤的一个流程图。目前,这部分信息关注的是第一个处理模块。

    词法分析的各种术语在理解的时候给初步接触这些概念的我带来了一些冲击,这么快就出现了这么多的新词汇。但是结合给出来的例子,理解这个过程其实并不难。

    上面就是给出来的例子以及词法分析的过程。

    Page4

    这里介绍了编译器的第二个动作,语法分析或者叫做解析。其实是把第一个步骤词法分析的结果进行了一个中间状态表示的转换,这种中间的表示状态是一个树状数据结构。表示方法可能有一个或者多个,常用的表示方法就是语法树,这个在后面介绍语法以及语义分析中都经常用。

    这里,有给出了一个流程图,这是之前流程图的一个详细版本。目前所介绍的内容已经涉及到了前面的两个环节,但是后面的几个环节在这里也给出了具体的描述,看起来这个图还得结合后面的讲解继续理解。

    Page5:

    首先给出来了语义分析的介绍,这个是在语法分析之后的一个动作。英文名称叫做semantic,这个词我倒是在之前接触过很多,只要是在折腾emacs的时候。我希望emacs具备source insight那样的语义理解功能的时候做过配置。这样的功能,可以给写代码的人员一些辅助理解的信息。看起来,类似的功能其实也可以借助于编译器来实现。

    在这个过程中,编译器主要是做两部分工作。第一个是检查代码的语义是否与编程语言的要求一致;第二个是收集类型信息方式语法树或者符号表,这个类型信息将会用于后续的代码生成。这个过程中很重要的一点是做类型的冲突检查,如果发现了错误应该进行自动转换。如果自动转换不成立,则进行报错。如果符合了自动转换的条件,那么语法树会多出一个自动转换的处理节点。

    接着,给出来了中间代码生成的介绍。中间代码生成实在语法以及语义分析完成之后,这个过程会生成一些明确的低级语言或者类机器语言。可以把这个过程中生成的信息看做是一个抽象的机器程序。随之给出来的三地址的例子,在后面的内容中还有更详细的介绍,这里就不做进一步的分析了。

    最后,给出了代码优化的介绍。这里没有给出多少可执行的操作方法,但是这部分所涉及到的内容其实是跟我平时使用的编译器的优化选项正好是对应的。优化的目标可能不仅仅是速度,可能还有代码的大小、能耗等。

    Page6:

    介绍了代码生成的实现,主要是将中间表示转换成目标语言的一个处理。如果目标语言是机器语言,那么接下来的处理需要考虑寄存器以及内存的使用。这个转换过程不应该是一个直白的转换,还应该考虑如何合理使用寄存器才会有更好的效果。我之前看一个商用编译器版本升级中的bug修复似乎就看到了类似的描述,有一个版本升级其中很重要的一点就是降低了某几个寄存器的使用压力。

    如果代码的实现存在一个变量多个地方使用之类的要求,应该能够让编译器识别到相应符号的作用以及使用范围。这部分的实现,主要就是在符号表的管理中实现。

    Page7

    编译器本身也是一种软件,完成编译器的设计很多方法其实跟一般的软件设计也有共通之处。很重要的一点就是充分利用现在已经存在的软件开发环境,这样避免重复造轮子的同时还可以让我们的软件开发更加高效、通用。

    以上,是龙书开篇一部分信息的学习。这也算是我重新梳理编译器知识的一个简单的开端,希望后面的学习能够遇到更多有趣的东西。

  • 相关阅读:
    13.求面积[有问题]
    创建老版本react-native项目,以0.59.10为例(0.60.0之前的版本)
    spring--集成RocketMQ
    使用 SQL 加密函数实现数据列的加解密
    《刚刚问世》系列初窥篇-Java+Playwright自动化测试-1-环境准备与搭建
    【项目SpringBoot配置详解】
    【机器学习】文本多分类
    浮点型数据在内存中是如何存储的
    RDS:一致性处理事务的神器
    Android 如何在Android studio中快速创建raw和assets文件夹
  • 原文地址:https://blog.csdn.net/grey_csdn/article/details/126514626