编译器设计之路

实现编译器设计之路复写传播的基础

例7-5 局部复写传播的实例。关于复写传播的方法,应该并不难理解。实际上,复写传播的意义就是在于尽可能减少程序中的活跃变量的个数。复写传播虽然成效显著,但并不是万能的。在一些特殊的情况下,复写传播是可能失效的。这种代码形态已经不是复写传播讨论的范畴了。同时,令B5成为B2、B3的唯一后继基本块。
理论教育 2023-11-04

编译器设计路线中的文件声明部分

在正式编译之前,先由预处理器将包含的头文件直接合并入某一主文件中。在Pascal语言中,USES通常只是用于说明包含文件的列表,但它并不是合并文件的插入点,这与#include指令也是不同的。而合法的插入点应该位于过程函数声明部分之前。实际上,语义子程序在分析USES声明结构时,只需记录包含文件的列表,以备后用即可。程序4-4 semantic.cpp上述的semantic012并不完整,这里仅列出了与USES声明相关的
理论教育 2023-11-04

编译器设计之路:语法树描述和讨论

例3-5 用语法树描述例3-4的最右推导过程。构造语法树步骤:1)文法开始符为E,将E构造为语法树的根。图3-1 3*5+(1-i)的语法树6)最终,语法树所有叶结点自左至右排列就是3*5+(1-i),表明3*5+(1-i)是文法的句子。语法树的步步成长和推导的步步展开之间是完全一致的。下面,笔者对图3-1的语法树作深入讨论。读者不难发现语法树的叶子分布在树的不同层次上。这与语法树的构造顺序有关。
理论教育 2023-11-04

编译器设计之路中的goto语句翻译成果

众所周知,结构化程序设计并不提倡使用goto或类似语句。下面,笔者先来谈谈goto语句翻译的几个重点。C语言没有标号声明机制,在分析向后跳转的goto语句时,由于目标标号的定义点位于goto语句之后,使编译器无法获得目标标号的任何信息。无论何种处理方案都必须保证任何goto语句的目标标号都是存在唯一定义点的。不过,由于goto语句的向后跳转的情形,使得最后一种检查不能即时进行。
理论教育 2023-11-04

大师风采|NiklausWirth编译器设计之路

Niklaus Wirth:瑞士计算机科学家,Pascal、Modula语言创始人,结构化程序设计思想的提出者。Wirth被誉为“Pascal之父”。在程序设计语言与编译器设计领域,Wirth的主要贡献在于:● 设计与实现了Pascal。20世纪80年代后期,Wirth又致力于“Oberon计划”的研究,设计并实现了一个超越Pascal与Modula的Oberon语言。与Pascal、Modula相比,Oberon语言更安全,它引入了数组越界检查、垃圾回收、强类型检查等机制。2007年,Wirth实现了Oberon-07,其目标机是32位ARM处理器。
理论教育 2023-11-04

编译器设计之路:表达式翻译基础

在第5章中,笔者已经提到了表达式翻译的基本思想。例6-2 计算表达式3+5 x2-4的值。上述常量表达式的计算实例,旨在说明编译器是如何计算表达式的。Tl、T2、T3是编译器临时变量,在表达式翻译过程中,每次运算的结果都必须用临时变量保存。至此,笔者已经详细解释了手工实现表达式的翻译的过程,并获得了一个相对完整的IR序列。这个过程就是实际表达式翻译的抽象模型,值得推敲。
理论教育 2023-11-04

使用自动代码生成器构建编译器

应用模式文件实现目标代码生成器的优点就是便于修改、维护与移植。不可否认的是,一些经典的自动代码生成器更热衷基于树、DAG、前缀波兰代码等形式的IR实现,而不是传统的三地址代码。这种设计的主要优点是可以最大程度上减少代码生成器对IR形式的要求。本书将讨论基于三地址代码的自动代码生成器的实现,这种实现方法更多关注的是算法的第2、3步。
理论教育 2023-11-04

编译器设计之路-三地址代码概述

前面已经提到了三地址代码的概念。在众多IR中,三地址代码是最为常用的。不过,三地址代码同样存在级别差异。当然,级别主要就是取决于三地址代码的操作符及操作分量的复杂性。其中,抽象程度是三地址代码设计中的重要因素之一。一般而言,三地址代码将包含大部分低级操作,即目标机所支持的指令。不过,这并不意味着三地址代码就是机器指令系统的映射。
理论教育 2023-11-04

编译器设计之路:实现语法分析

图3-4 语法分析在编译器中的地位语法分析器的输入就是词法分析器输出的单词流。语法分析器没有统一的形式输出形式。事实上,很多编译器将语法分析器作为一个主控模块,由语法分析器驱动语义分析器的方式完成语义分析及中间代码生成。在这种情况下,语法分析器并没有显式的输出。这一观点的提出主要是由于基于归约方式的语法分析器通常借助于语法树描述整个输入源程序的语法层次。这两类语法分析法各有优缺点。
理论教育 2023-11-04

编译器设计之路中的符号表含义及问题

在编译过程中,编译器根据源程序声明语句收集各类语法元素的信息,并在符号表中建立相应的表项记录。从应用的角度来说,寄希望于从符号表获得一切关于输入源程序的符号信息的思想是可以理解的,但是,当符号表成为一本万宝全书时,问题也就随之而来了。因此,C编译器的符号表必须存在描述此信息的字段,而Pascal编译器则不必考虑。由于Neo Pascal语言是一种命令式语言,所以本书所讨论的符号表更多情况下适用于命令式语言编译器的构造。
理论教育 2023-11-04

SSA形式:初学者注意事项,编译器优化效果较好

对于初学者而言,深入讨论SSA可能并不太适合。因此,与其他IR方案相比,SSA是相对较新的IR形式。事实上,真正满足SSA形式的实例几乎是不存在的,也就是说,在实际程序中对一个变量多次赋值的情况是不可避免的。例10-11 SSA实例分析。值得注意的是,本例中所有的被赋值变量只可能存在一次被赋值的情形,这是SSA的基本要求。在处理完成后,编译器最终还会将SSA的形式还原到原始状态。不过,SSA的优化效果较好,因此这种影响并不太明显。
理论教育 2023-11-04

NeoPascal编译器设计之路:声明部分实现

从本章开始,读者将大量接触Neo Pascal的源代码。因此,笔者相信阅读与分析实际编译器的源代码可能是最佳的学习方法。Neo Pascal语义分析器是由100多个语义子程序构成,而语义子程序的调用完全由语法分析器驱动,即语法制导。本小节主要分析符号表管理部分的源代码,而IR生成部分析源代码将在第5、6章中详述。因此,笔者将语法结构(即文法)进行适当分类,然后,详细分析该结构相关的语义子程序。
理论教育 2023-11-04

编译器设计之路:栈式存储分配基础

栈式存储分配的基本思想就是每当进入一个过程时,就在控制栈顶为该过程分配所需的数据空间,当一个过程工作完毕返回时,它在栈顶的数据空间也随即释放。例8-1 过程调用的分析。当然,其中某些项允许为空,编译器不必分配相应的空间。main函数在执行前同样需要保护寄存器现场。2)返回地址压栈。其中,包括保护寄存器现场、分配临时数据、局部变量等存储空间。
理论教育 2023-11-04

编译器设计之路-代码生成器结构

前面,已经详细介绍了寄存器分配的基本思想与实现。本小节将关注代码生成器主体结构的源码实现。前面主要讨论了指令模板的相关数据结构,这是剖析代码生成器源码的重要基础。代码生成器是以操作数来源作为主线实现的,下面就来看看代码生成器的实现细节。代码生成器对数据流信息的依赖程度是比较大的,尤其在评估死变量时。代码生成器将从系统文件夹中的AsmScheme.txt文件读取指令模板库。代码生成是以过程为单位进行的。
理论教育 2023-11-04

编译器设计之路:IA-32体系结构的目标机结构解析

正如人们所知的,代码生成是一种与目标机密切相关的技术,因此,笔者有必要对目标机结构作简单介绍。通常,IA-32体系结构指的就是从Intel 386到最新的32位奔腾4处理器,是Intel经典的32位机系统。2.基本寄存器在i386系统中,通常提供了8个通用寄存器、6个段寄存器、1个标志寄存器和1个指令指针。在实际目标机中,除了用作数据存储之外,有时,通用寄存器还有一些特殊的功能与应用限制,这是编译器设计者需要考虑的因素。
理论教育 2023-11-04

编译器设计之路:深入学习,了解ANTLR与Yacc的灵活性

无论是从构造技术,还是从形式语言理论而言,关于语法分析器的资源都是最丰富的。在现代编译器设计中,ANTLR已经逐渐被设计者接受。当然,与Yacc相比,ANTLR凸现的是其灵活性,而Yacc就显得更学术派。
理论教育 2023-11-04
-已经加载完成-