将多个步骤组合成趟
- 一个编译器的逻辑组成方式
- 在一个特定的实现中,多个步骤的活动可以被组合成一趟(pass).
- 每趟读入一个文件并产生一个输出文件。
- 比如:前段步骤中的语法分析、词法分析、语义分析、以及中间代码生成可以被组合一起成为一趟。代码优化可以作为一个可选趟。然后又一个为特定目标机生成代码的后端趟。
- 有些编译器的集合是围绕着,一组精心设计的中间表示形式而创建的。这些中间表示形式使得我们可以吧特定语言的前段和特定目标机的后端相结合。使用这些集合,可以吧不同的前段和某个目标机的后端结合起来,为不同源语言建立该目标机上的编译器。一个前端和不同目标机的后端结合,建立针对不同目标机的编译器。
构造编译工具
- 写编译器的人可以充分利用现代的软件开发环境,包含了:
- 语言编译器、调试器、版本管理、程序描述器、测试管理等工具。还有一些更加专业的工具实现编译器的不同阶段。
- 这些工具使用专用的语言描述实现特定的组件,其中很多工具使用了相当复杂的算法。能隐藏生成算法的细节,并且生成的组件易于和编译器的其他部分相集成。
- 语法分析器的生成器、扫描器的生成器、语法制导翻译引擎、代码生成器的生成器、数据流分析引擎、编译器构造工具集
- 通过数学方法抽象出,问题本质从而解决现实世界中复杂问题。
- 编译器所做的任何翻译都不能改变被编译源程序的含义。
- 编译器主要是研究如何设计正确的数学模型和选择正确算法的研究。设计和选择算法还要考虑对通用性及功能的要求与简单性及有效性之间的平衡。
- 上下文无关文法:描述程序涉及语言的语法结构。比如:嵌套的括号和控制结构。
- 优化: 编译器为了生成比浅显直观的代码更加高效的代码而做的工作。但是并不恰当,没有办法证明一个编译器生成的代码比完成相同任务的其他代码更快。
- 现代编译器所做的代码优化更加复杂,,是因为处理器体系结构更加复杂了,也就有了更多改进代码执行方式的机会。
编译器的优化必须满足下边的设计目标
- 优化必须是正确的,不能改变被编译程序的含义。
- 优化必须要改善程序很多的性能。
- 优化所需的时间必须保持在合理的范围内
- 所需工程方面的工作必须是可管理的
- 数组和结构和循环调用,如果仅仅只是把每个高级结构和数据存取的运算直接翻译成机器代码,得到的代码将会非常低效。编译器的一个重要组成部分称为数据流优化,他可以对程序的数据流进行分析,并消除这些构造之间的冗余。
面对对象主要的思想
针对计算机体系结构的优化
- 计算机体系结构的快速发展,也为新的编译器技术提出了越来越多的需求:并行、内存层次结构。
- 并行:可以出现在多个不同的层次上,指令称次上,多个运算可以被同事执行。同一个应用的不同线程可以再不同的处理器上运行。
- 内存层次结构:一个内存的乘次结构由不通速度和大小的存储器组成。离处理器最近的最快。但是容量小。如果一个程序大部分内存访问,都能用由层次结构,最快的层满足。那么程序的平准内存访问时间就会被降低。
专用体系结构
- 数据流及其、向量机、VLIW(非常长指令字)机器、SIMD(单指令、多数据)处理器阵列、心动阵列、共享内存的多处理器、分布式内存的多处理器。每种体系结构概念的发展都伴随着响应编译器技术的研究和发展。
数据流分析
- 通过数据流分析技术静态的(在程序运行起来之前)定位错误。数据流分析,可以在所有可能执行的路径上找到错误。而不是像程序测试那样,仅仅只是在输入数据组合执行的路径上找到错误。原本为,编译器优化所开发的数据流分析技术可以用来创建响应的工具。
类型检查
- 类型检查是一种有效,且被充分研究的技术。他可以用来捕捉程序中的不一致性。可以用来检测一些错误。运算被作用于错误类型的对象上。或者传递给一个过程的参数和该过程的范型不匹配。通过分析程序中的数据流,程序分析还可以做出比检查错误类型更多的工作。
- 这种技术也可以用来捕捉某种安全漏洞,攻击者向程序提供一个字符串或者其他数据。而这些数据没有被程序谨慎使用。一个用户提供的字符串可以被加上“危险的标号”。如果没有检查这个字符串能够在某个程序点上影响代码的控制流,那么就存在一个潜在的安全漏洞。
边界检查
- 很多系统中的安全漏洞都是因为用从c语言编写的程序中的缓冲区溢出造成的。因为c语言没有数组边界检查,所以必须由用户保证对数组的访问没有超出边界。因为不能检验用户提供的数据是否可能溢出一个缓冲区,程序可能被欺骗。把一个数据存到缓冲区之外。
- 用来消除程序中冗余区间检查的数据流分析技术也可以用来定位缓冲区溢出错误。没有指出一个潜在的缓冲区溢出错误有可能危及系统的安全性,虽然使用简单的分析技术进行区间检查优化就已经足够了,但是错误勘测工具中获得高质量的结果需要复杂的技术。比如过程之间跟踪指针值得技术。
静态和动态的区别
- 一个语言使用的策略支持编译器静态决定某个问题。可以说这个语言使用了一个静态策略。或者说这个问题可以再编译时决定
- 一个只允许程序运行的时候做出的策略被称为动态策略。
- 名字和内存位置的关联,及之后和值得关联可以用两个映射来描述。这两个映射随着程序的运行而改变。
- 环境:是一个从名字到存储位置的映射。应为变量就是指内存位置即c语言中的术语左值。
- 状态:是一个从内存位置到他们值的映射。以c语言的术语来说,即状态吧左值映射为他们响应的右值。
- 标识符a是一个表达式(x+1)的宏。但是x到底是什么?
- 不能静态的解析x,就是通过程序文本。检查所有当前函数的作用域规则,选择最近调用的且具有一个对x的声明的函数。对x的使用就是指向这个声明。
- 动态作用域解析对多态过程是必不可少的,所谓多态就是指对于同一名字根据参数类型具有两个或者多个定义的过程。
参数传递机制
- 值调用:对实在的参数求值(如果他是表达式)或者拷贝(如果他是变量)。这些字被放在属于被调用过程的相应形式参数的内存位置上。
- 引用调用:实在参数的地址作为相应的形式参数的值被传递给被调用者。在被调用者的代码中使用形式参数时,实现方法是沿着这个指针找到调用者指明的内存位置。
- 名调用:被调用者的运行方式好像是用实在参数以字面方式替换了被调用者的代码中的形式参数一样。形式参数是一个代码了实在参数的宏,当前被调用过程的局部名字需要进行重命名。以便把他们和调用者中的名字区分开来。
- 别名 :两个形式参数指向同一个位置,这样的变量称为另一个变量的别名。任意两个看起来从不同的形式参数中获得值得变量也可能变成对方的别名。
总结
- 语言处理器:一个集成的软件开发环境,其中很多种类的语言处理器,比如编译器、解释器、汇编器、连接器、加载器、调试器以及程序概要提取工具
- 编译器的步骤:一个编译器的运作需要一系列的步骤,每个步骤吧源程序从一个中间表示转换成另一个中间表示
- 编译器设计中的建模:编译器设计是理论对实践有很大影响的领域之一。已知在编译器设计中有用的模型包括自动机、文法、正则表达式、树形结构和很多其他理论概念。
- 代码优化:虽然代码不能真正达到最优化,但提高代码效率的科学既复杂有重要。是编译研究的一个主要部分
- 作用域规则:一个x的声明的作用域是一段上下文,在此上下文中对x的使用指向这个声明。
- 环境:名字和内存位置关联、然后在和值关联。环境把值映射成存储位置、状态吧位置映射到他的值
- 别名:当参数以引用方式传递,两个形式参数可能指向同一个对象,可能造成一个变量改变另一个变量的值。
posted @
2019-03-25 16:52
一生热爱
阅读(
429)
评论()
编辑
收藏
举报