├── .gitignore ├── Assignments ├── ass1.pdf ├── ass2.pdf ├── ass3.pdf ├── ass4.pdf ├── ass5.pdf └── README.md ├── Documents ├── assets │ ├── image-20240104155109160.png │ ├── image-20240104160051496.png │ ├── image-20240104160642366.png │ ├── image-20240104161235220.png │ ├── image-20240104161516043.png │ ├── image-20240104161954411.png │ ├── image-20240104163357305.png │ ├── image-20240104164523361.png │ ├── image-20240104164940427.png │ ├── image-20240104170500373.png │ ├── image-20240104190656308.png │ ├── image-20240104193850405.png │ ├── image-20240104194326369.png │ ├── image-20240104201843666.png │ ├── image-20240104202817543.png │ ├── image-20240104213638961.png │ ├── image-20240104215038356.png │ └── image-20240104215103661.png ├── README.md ├── Project 3.md └── Project 4.md ├── .gitmodules ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /Assignments/ass1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Assignments/ass1.pdf -------------------------------------------------------------------------------- /Assignments/ass2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Assignments/ass2.pdf -------------------------------------------------------------------------------- /Assignments/ass3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Assignments/ass3.pdf -------------------------------------------------------------------------------- /Assignments/ass4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Assignments/ass4.pdf -------------------------------------------------------------------------------- /Assignments/ass5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Assignments/ass5.pdf -------------------------------------------------------------------------------- /Documents/assets/image-20240104155109160.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104155109160.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104160051496.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104160051496.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104160642366.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104160642366.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104161235220.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104161235220.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104161516043.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104161516043.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104161954411.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104161954411.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104163357305.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104163357305.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104164523361.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104164523361.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104164940427.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104164940427.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104170500373.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104170500373.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104190656308.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104190656308.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104193850405.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104193850405.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104194326369.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104194326369.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104201843666.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104201843666.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104202817543.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104202817543.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104213638961.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104213638961.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104215038356.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104215038356.png -------------------------------------------------------------------------------- /Documents/assets/image-20240104215103661.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XIA-Jinyi/BuptCompiler/HEAD/Documents/assets/image-20240104215103661.png -------------------------------------------------------------------------------- /Documents/README.md: -------------------------------------------------------------------------------- 1 | # 相关文档 2 | 3 | 由于课程没有提供 [Project 3](https://github.com/XIA-Jinyi/BuptCompiler/blob/main/Documents/Project%203.md) 和 [Project 4](https://github.com/XIA-Jinyi/BuptCompiler/blob/main/Documents/Project%204.md) 的相关文档,所以作者参考南方科技大学 CS323 课程的相关文档,撰写了这两份中文文档。 4 | 5 | --- 6 | 7 | __项目主页__:[BuptCompiler](https://github.com/XIA-Jinyi/BuptCompiler) 8 | -------------------------------------------------------------------------------- /Assignments/README.md: -------------------------------------------------------------------------------- 1 | # Assignments 2 | 3 | 这里提供了作者 5 次 assignments 的答案,不保证完全正确,仅供参考。 4 | 文档的 LaTeX 源代码可以在 [Assignments 仓库](https://github.com/XIA-Jinyi/BuptCompiler-Assignments)找到。 5 | 6 | 如果发现了问题,欢迎提 [issue](https://github.com/XIA-Jinyi/BuptCompiler/issues) 或者 [PR](https://github.com/XIA-Jinyi/BuptCompiler/pulls)。 7 | 8 | --- 9 | 10 | __项目主页__:[BuptCompiler](https://github.com/XIA-Jinyi/BuptCompiler) -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Project1"] 2 | path = Project1 3 | url = https://github.com/XIA-Jinyi/BuptCompiler-Project1.git 4 | [submodule "Project2"] 5 | path = Project2 6 | url = https://github.com/XIA-Jinyi/BuptCompiler-Project2.git 7 | [submodule "Labs"] 8 | path = Labs 9 | url = https://github.com/XIA-Jinyi/BuptCompiler-Labs.git 10 | [submodule "Assignments/source"] 11 | path = Assignments/source 12 | url = https://github.com/XIA-Jinyi/BuptCompiler-Assignments.git 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BuptCompiler: 北邮网安编译原理资料 2 | 3 | 这个仓库是作者学习相关课程时的一些文档、作业和实验代码。所有内容均为作者原创或参考其他资料自己编写而成。 4 | 5 | 如果你觉得这份资料有价值,请动动手指点亮 Star ⭐️,你的支持是对我最大的鼓励! 6 | 7 | ## 📦 内容 8 | 9 | - 🗒️ __Assignments:__ 作业 10 | 11 | 作者提供了自己 5 次作业的答案。 12 | 13 | PDF 文档可以在 [Assignments 目录](https://github.com/XIA-Jinyi/BuptCompiler/tree/main/Assignments)下找到。 14 | 15 | LaTeX 源代码可以在 [Assignments 仓库](https://github.com/XIA-Jinyi/BuptCompiler-Assignments)下找到。 16 | 17 | - 🔬 __Labs:__ 实验 18 | 19 | 作者提供了自己 6 次实验的源代码和报告,可以在 [Labs 仓库](https://github.com/XIA-Jinyi/BuptCompiler-Labs)下找到。 20 | 21 | - 💻 __Projects:__ 项目 22 | 23 | 作者提供了自己 2 次项目的源代码和报告,可以在 [Project1 仓库](https://github.com/XIA-Jinyi/BuptCompiler-Project1)和 [Project2 仓库](https://github.com/XIA-Jinyi/BuptCompiler-Project2)下找到。 24 | 25 | - 📖 __Documents:__ 文档 26 | 27 | 课程没有提供 [Project 3](https://xia-jinyi.github.io/BuptCompiler/Documents/Project%203) 和 [Project 4](https://xia-jinyi.github.io/BuptCompiler/Documents/Project%204) 的相关文档,作者参考相关文档,撰写了这两份中文文档。可以在 [Documents 目录](https://github.com/XIA-Jinyi/BuptCompiler/tree/main/Documents)下找到。 28 | 29 | ## 💬 反馈 30 | 31 | 如果你有任何问题或建议,欢迎提交 [Issue](https://github.com/XIA-Jinyi/BuptCompiler/issues) 或 [Pull Request](https://github.com/XIA-Jinyi/BuptCompiler/pulls)。 32 | 33 | 你也可以通过[作者主页](https://xia-jinyi.github.io/)的联系方式与作者取得联系。 34 | 35 | ## ⚖️ 许可 36 | 37 | 本仓库的所有内容均采用 [GPL-3.0 license](https://github.com/XIA-Jinyi/BuptCompiler/blob/main/LICENSE) 进行许可。 38 | 39 | ## 🙏🏻 感谢 40 | 41 | 感谢 Y. Guo 老师的教学与 G. Yang, F. Meng 两位助教的付出。感谢 K. Huang, G. He, 两位 Y. Zhang, D. Wang, Z. Fang, Q. Liu, R. Luo, J. He 等同学的讨论与帮助。感谢所有参考资料的提供者。 42 | 43 | ## 🔗 链接 44 | 45 | [![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=XIA-Jinyi&repo=BuptCompiler-Assignments&description)](https://github.com/XIA-Jinyi/BuptCompiler-Assignments) 46 | [![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=XIA-Jinyi&repo=BuptCompiler-Labs&description)](https://github.com/XIA-Jinyi/BuptCompiler-Labs) 47 | [![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=XIA-Jinyi&repo=BuptCompiler-Project1&description)](https://github.com/XIA-Jinyi/BuptCompiler-Project1) 48 | [![Readme Card](https://github-readme-stats.vercel.app/api/pin/?username=XIA-Jinyi&repo=BuptCompiler-Project2&description)](https://github.com/XIA-Jinyi/BuptCompiler-Project2) 49 | -------------------------------------------------------------------------------- /Documents/Project 3.md: -------------------------------------------------------------------------------- 1 | # 阶段 3:中间代码生成 2 | 3 | ## 1. 概述 4 | 5 | 到目前为止,我们已经完成了 BPL 编译器的分析部分,准备进入综合(或生成)部分。 目前,您的编译器可以识别有效的 BPL 程序。 在第 3 阶段,编译器将为给定的源程序生成中间表示 (IR)。 IR 可以进一步优化以获得更好的运行时性能。 6 | 7 | 大多数编译器首先将源程序翻译为某种形式的 IR,然后将其转换为机器代码。 IR 是原始源代码的独立于机器和语言的表示。 尽管两次转换代码会带来额外的成本,但使用 IR 可以增强抽象性,并在前端和后端之间实现更清晰的分离。 IR 还有助于高级编译器优化。 事实上,大多数优化都是在中间代码上完成的,而不是源代码或目标代码。 8 | 9 | 从更广泛的意义上讲,IR可以是编译阶段原始程序的任何形式,例如词法分析器生成的标记流、语法分析器生成的解析树、代码生成器生成的三地址代码等。 当我们在这个项目中谈论IR时,我们主要指的是三地址代码(TAC),其中每条指令最多可以有三个操作数(地址)。 我们将在附录 A 中详细说明我们的 TAC 指令集。我们提供了一个模拟器来执行生成的 TAC,该模拟器也安装在我们的实验室虚拟机中。 10 | 11 | 您将继续在语义分析器之上生成代码。 还请注意保持代码的可维护性和可扩展性,因为 SPL 编译器的后续部分依赖于您在这里的工作。 12 | 13 | ## 2. 实验环境 14 | 15 | 我们准备了一个 IR 模拟器,以便您可以运行生成的 TAC。 它已经安装在实验室虚拟机中。 它是用 Python 模块 urwid 构建的。 如果您想在自己的计算机上运行它,请确保您已经安装了 urwid。 注意urwid不支持Windows环境。(略) 16 | 17 | ## 3. 中间表示 18 | 19 | 在表示格式方面,有线性IR、树IR、图IR等。在第一阶段,我们将源代码转换为解析树,它在概念上是树IR的一种形式。 此阶段的输出(TAC 指令)是一种线性 IR。 您还可以将 TAC 指令组织成图 IR,其中节点表示不跳转的指令序列,边表示两个基本块之间的无条件/条件跳转。 这种 IR 称为控制流图,它有助于许多现代编译器优化,例如常量传播和死代码消除。 20 | 21 | 通常情况下,从某些语法节点翻译过来的 TAC 段不会立即打印出来,因为您可能会重新组织代码结构或对中间代码进行优化。 因此,您需要将它们存储在内存中,然后再将它们打印到生成的代码文件中。 为此,重要的是要考虑如何使用正确的数据结构来存储它们。 22 | 23 | TAC 通常存储在一组四元组中。 每个四元组都是一个对象(记录),由四个字段组成:一个运算符、两个操作数(源)和一个目标(结果)。 为了形成块,编译器需要一种连接各个四元组的机制。 下图显示了用于实现表达式 `a - 2 * b` 的 TAC 的三种不同结构。 24 | 25 | image-20240104155109160 26 | 27 | 图 a 是最直接的实现,其中预先分配了一个大数组。 数组中的每个元素都存储一条 TAC 指令。 然而,它的效率较低。 每次在中间插入一条新指令时,都应该将所有后续元素向后拉一位。 此外,代码大小受到数组长度的限制。 指针数组实现(图 b)继承了数组实现的相同限制,只是移动元素更便宜,因为只交换地址,而不是四元组列表。 更推荐使用图 c 中的双向链表,尽管它比前两种样式更复杂。 链表数据结构在插入、删除和元素替换方面都是高效的。 而且,它不需要预先分配空间,因此代码大小可以任意大(只要内存足够)。 28 | 29 | ## 4. 运行时环境 30 | 31 | 编程语言提供了硬件细节的抽象,例如名称、范围、数据类型、运算符、函数和控制流结构。 然而,现代计算机硬件只能理解低级原语,例如,32/64 位整数的算术运算、数据移动和布尔表达式的控制结构。 编译器必须与操作系统配合以支持目标体系结构上的高级抽象。 32 | 33 | 为此,编译器不能仅仅翻译代码。 它还应该生成额外的代码,以通过低级操作来维护高级功能。 在代码生成过程中,编译器应该管理目标机机制,以便生成的代码可以在相同的运行时环境中运行。 运行时环境包含许多与目标机器相关的细节。 在此阶段,我们仅讨论一些一般概念以及如何用我们的 TAC 规范来表示它们。 在下一阶段,我们将介绍更多有关目标运行时的信息,即 MIPS 架构。 34 | 35 | ### 4.1. 数据表示 36 | 37 | 许多高级语言提供各种简单的数据类型: 38 | 39 | - 字符:1 或 2(宽字符)字节; 40 | - 整数:2、4 或 8 字节; 41 | - 布尔值:1 位(通常至少使用 1 个完整字节)。 42 | 43 | 大多数硬件直接支持这些类型。 此外,C 语言中的指针类型存储为无符号整数。 它们的范围取决于目标体系结构,即支持最大 4GB 内存寻址的 32 位计算机为 4 字节,64 位计算机为 8 字节。 实际上,在低级别上,指针和无符号整数之间几乎没有什么区别:它们都是数字,唯一的区别是编译器如何解释这些数字。 44 | 45 | image-20240104160051496 46 | 47 | 数组在连续的内存空间中存储一组元素。 这些元素在存储器中从低地址位置到高地址位置连续存储。上图显示了 C 风格的数组表示形式。 顶部标签代表每个元素的起始地址,而 `b` 是单个元素的宽度。 回想一下,名称 `arr` 是一个常量指针,它指向数组的起始地址。 一般来说,对于具有 `n` 个元素的一维数组 `arr`,第 `i` 个(从 0 开始计数)元素存储在内存位置 `arr+i*b` 中。 BPL程序的运行时也采用这种数组表示形式。 48 | 49 | 多维数组的编码有两种策略:真正的多维数组(图 a)和数组的数组(图 b)。 真正的多维数组是一个连续的块。 在行优先配置中,行被一个接一个地存储。 对于 $m × n$ 32 位整数数组,元素 `arr[i][j]` 的地址为 `arr + 4 * (n * i + j)`。 50 | 51 | image-20240104160642366 52 | 53 | 在数组的数组表示中,访问一个元素涉及两次指针取消引用,而之前的表示只需要一次。 数组的数组更耗费空间:对于一个 $n_1 \times n_2 \times\cdots\times n_k$ 数组,数据字段与真实表示完全相同,但会多出 $n_1 \times n_2 \times\cdots\times n_{k-1}$ 个指针字段。 BPL 运行时采用第一种策略。 尽管如此,第二种方法仍然因其灵活性而被认为是有利的。 54 | 55 | 结构变量通过在连续块中顺序分配字段来存储,然后由基地址加成员偏移量表示成员访问。 结构体类型 `struct{int i; char c; double d;}` 需要 13 个字节,各个字段位于距基地址 0、4 和 5 个字节的偏移处。 然而,它实际上会为此结构分配 16 个字节,因为它将在字段之间插入填充,以便每个字段从对齐的边界开始,如下图所示。 56 | 57 | image-20240104161516043 58 | 59 | BPL运行时仅限于整数类型,因此不必考虑数据结构对齐。 但是,如果您想支持更多样化的数据类型,例如 `char` 或 `short`,您应该注意 MIPS 架构要求运行时内存中的所有变量都与地址长度对齐(32 位机器上为 4 字节)。 60 | 61 | ### 4.2. 函数调用 62 | 63 | 每个活动函数都有自己的激活记录,其中存储与函数调用相关的信息。 这些信息包括参数、局部变量、寄存器、返回地址等。在大多数架构中,激活记录存储在堆栈中,因此函数的激活记录也称为堆栈帧。 64 | 65 | 在这个项目中,您将不会处理有关如何维护堆栈帧的细节,因为它是依赖于机器的。 您应使用 `ARG` 语句显式传递参数,然后使用 `CALL` 语句通过函数的标识符调用函数。 66 | 67 | 传递参数有两种主要方法:按值传递和按引用传递。 在 BPL 运行时中,原始类型参数按其真实值传递。 当函数处于活动状态时,这些值在堆栈帧上有自己的副本,并且更改副本不会影响它们位于调用者帧中的原始值。 对于派生类型参数,被调用函数接受其引用,即其起始地址。 在 C 语言中,我们将显式传递结构体指针以避免复制整个结构体,而在 BPL 中,结构体参数会隐式转换为其起始地址。 这种运行时行为应该由编译器维护:要传递结构变量 `s1`,您应该通过 `ARG &s1` 而不是 `ARG s1` 推送它; 要访问特定偏移量处的成员,应将基地址添加到偏移量,然后使用解引用运算符 `*` 访问新地址。 68 | 69 | 以相反的顺序压入参数的原因是什么(见附录)? 答案与调用序列的内存布局有关。 以 Linux-x86 运行时为例: 70 | 71 | image-20240104161954411 72 | 73 | 当调用函数时,一个新的帧将被压入堆栈。 这里,“压入”动作包含多个步骤:首先将参数压入(从高地址到低地址),然后将返回地址记录在参数之上,最后准备局部变量的内存单元。 从局部变量到参数的内存部分构成了被调用者的新堆栈帧。 74 | 75 | 由于参数是一个一个压入的,因此第一个压入的参数位于堆栈底部(高地址),最后一个压入堆栈顶部(低地址)。 这就是为什么我们应该以相反的顺序推动它们。 这样,在函数体中获取参数就很简单:参数将由返回地址寄存器的偏移量表示。 在该示例中,参数 1 可以用 `%ret+4` 表示,参数 i 可以用 `%ret+4*i` 表示。 这里,4(字节)是32位机器上的地址长度。(实际上,没有 `%ret` 寄存器,但是 `%ebp` 寄存器以常量偏移量存储 `%ret`。) 76 | 77 | ## 5. 翻译方案 78 | 79 | 要从解析树生成 TAC,您需要按后序遍历树,然后根据某些特定模式转换树节点。 您将使用语法制导的翻译来完成此任务。 在实现时,您必须为每个非终结符 X 实现一组 `translate_X` 函数,并直接或间接递归地调用这些函数。 我们将介绍一些翻译特定产生式的示例,尽管可能还有其他翻译方式,例如构造相应的控制流图并通过跳转指令链接基本块。 80 | 81 | ### 5.1. 表达式 82 | 83 | 我们将表达式分为基本表达式和条件表达式。 它们占据了我们 `BPL` 语言规范中语法符号 Exp 的 26 条重写规则的一部分。 本节列出了他们的一些翻译方案。 84 | 85 | #### 5.1.1. 基本表达式 86 | 87 | 下表显示了基本表达的翻译方案。 我们假设您在第 2 阶段构建的符号表是全局可访问的。 函数 `symtab_lookup` 接受变量标识符的字符串,并返回相应的符号信息。 参数 `place` 是存储该表达式求值结果的地址变量。` translate_Exp` 返回节点 `Exp` 及其子节点的 TAC 代码。 88 | 89 | image-20240104163357305 90 | 91 | 右栏中,一对括号括起来的代码代表一条具体的 TAC 指令,在两条 TAC 指令上使用加号(`+`)表示将它们连接起来。 92 | 93 | 前两个重写规则的翻译方案很简单。 对于赋值表达式的产生,我们已经通过语义分析将左值约束为标识符、数组表达式或结构体表达式。 这里我们只展示左侧是标识符时的情况,即 `Exp1 -> ID`,稍后我们将在第 5.4 节中详细讨论最后两种情况。 回想一下,赋值运算符是右结合的,所以我们应该首先计算 `Exp2`,然后将结果值赋给相应的变量。 94 | 95 | 对于算术运算,我们应该计算两个操作数,然后对它们应用相应的运算符。 在这里,我们定义了从左到右的评估顺序,因此我们先评估 `Exp1`,然后再评估 `Exp2`。 表达式的一元减法会导致负数情况,可以通过从零减去自身来简单地表示。 96 | 97 | BPL 语法中定义了 9 个条件表达式(3 个布尔值和 6 个比较)。 它们的值为 0 或 1。我们通过辅助函数 `translate_cond_Exp` 来翻译这些表达式,这将在第 5.1.2 节中进行说明。 98 | 99 | #### 5.1.2. 条件表达式 100 | 101 | 条件表达式通常用在 `if` 和 `while` 语句中,其中涉及条件跳转指令。 这些跳转指令将与条件表达式的 `IR` 代码一起生成。 我们定义了一个辅助函数 `translate_cond_Exp`,它带有两个附加参数,`lb_t`指定当条件计算为 TRUE(本质上是 1)时要跳转的位置(标签),`lb_f` 用于FALSE情况,用于翻译条件表达式。 您应该确保 `translate_cond_Exp` 的第一个参数始终是条件表达式。 这可以在翻译之前检查。 102 | 103 | 下表中的方案产生 `AND`/`OR` 运算的短路评估。 要查看效果,请考虑规则 `Exp1 AND Exp2`:当通过 `translate_cond_Exp(Exp1, lb1, lb_f) `的 IR 代码将 `Exp1` 计算为 FALSE(即 0)时,控制流直接跳转到 `lb_f` 并跳过 `code2` 。 对于 TRUE 的情况,将执行 `code2` 来计算整个 AND 表达式。 相同的机制也适用于 OR 表达式。 104 | 105 | image-20240104164523361 106 | 107 | 我们列出了 4 个条件操作的翻译方案(对于其他情况,只需替换 `EQ` token)。 事实上,由于 C 是弱类型的,非条件表达式也可以用在控制流语句中。 一个广泛使用的例子是 `while(T--){}` 块,其中循环体将对任何非负整数 T 执行 T 次,并且当 T 达到零时循环终止。 您可以考虑如何翻译这种控制流,并将其实现为编译器的额外功能。 108 | 109 | ### 5.2. 语句 110 | 111 | 下表显示了语句的翻译方案。 为了翻译控制流语句(即 `if` 和 `while`),我们利用之前定义的函数 `translate_cond_Exp`。 翻译条件表达式引入了条件跳转,而语句的翻译方案中只有无条件跳转。 112 | 113 | image-20240104164940427 114 | 115 | ### 5.3. 函数调用 116 | 117 | 在翻译函数之前需要做一件事:您应该向符号表添加一个 `read` 函数,该函数不带参数并返回一个整数值,以及一个接受单个整数参数的`write` 函数。 这两个预定义函数为 BPL 程序提供用户交互 (I/O)。 它们有特殊的翻译方案:`read` 函数调用应翻译为 `READ` 指令,`write` 为 `WRITE` 指令。 118 | 119 | 与函数调用相关的重写规则有两种,一种是带参数的,另一种是不带参数的。 内置函数 `read` 和 `write` 有自己的翻译方案。它们显示在下表的前两行中。请注意,`write` 函数仅接受一个参数,因此我们将 `Args` 符号直接重写至 `Exp`。 120 | 121 | image-20240104170500373 122 | 123 | 让我们重新审视 BPL 运行时中的参数传递顺序。 我们已经提到(第 4.2 节),参数应该以与声明相反的顺序推入堆栈。 在 `Args` 的转换方案中,我们通过传递附加的 `arg_list` 参数来完成此行为。 每次评估新参数时,其引用都会插入到该列表的头部。 在插入 `CALL` 指令之前,我们从 `arg_list` 中弹出这些引用并生成其相应的 `ARG` 指令。 在这里,我们模拟先进后出列表,因此被调用函数的参数从左到右计算,并且它们将从右到左压入运行时堆栈。 124 | 125 | 值得一提的是,C语言的求值顺序是一种未定义的行为。 函数参数由逗号表达式指定,编译器可以按任意顺序计算每个子表达式。例如,要调用 `foo(a+b, a-b, -a)`,编译器可以生成从左到右、从右到左计算的代码,甚至先计算 `a-b`,然后是 `-a`,然后再计算 `a+b`。 在提供的翻译方案中,我们为函数参数定义从左到右的求值顺序。 但是,您可以根据不同的评估顺序生成代码。 唯一重要的事情是参数应该以正确的顺序传递。 126 | 127 | ### 5.4. 派生数据类型 128 | 129 | BPL 中有两种派生日期类型:数组和结构体。 与宽度固定的整数不同,我们应该在使用派生类型的变量之前通过使用具有声明类型大小的 `DEC` 语句来动态分配内存。 一般来说,派生数据类型可以被视为元素的集合。 访问特定元素可以用 `base + offset` 的形式表示,其中 `offset` 是根据前面元素的大小计算的。 使用派生类型变量有两种重写规则:`Exp -> Exp LB Exp RB` 和 `Exp -> Exp DOT ID`,这两个规则都会被翻译成内存偏移量计算。 130 | 131 | 我们采用真正的多维数组表示,它将所有元素存储在一个连续的块中。 在 BPL 数组中,所有元素的大小都相等,并且同一较低维度中的所有数组的大小也相等。 因此我们可以通过以下方式计算元素的地址(假设数组元素的数据类型为 $T$ ): 132 | 133 | $$ 134 | ADDR(arr[i_l]\dots[i_n])=ADDR(arr)+OFFSET(arr[i_l]\dots[i_n])\times SIZE(T) 135 | $$ 136 | 137 | $OFFSET$ 函数不涉及数据大小。 它仅取决于前面元素的数量。 以 3 维数组 `arr[l][m][n]` 为例,元素 `arr[i][j][k] `的偏移量为 138 | 139 | $$ 140 | OFFSET(arr[i][i][k]) = i \times m \times n + j \times n + k 141 | $$ 142 | 143 | 上面的公式可以很容易地推广到更高维度的数组。 144 | 145 | 对于结构体变量,偏移量是通过前面元素的大小之和来计算的。 尽管我们假设所有变量都是整数,但您可以设计自己的方式来表示其他数据类型,例如字符、短数字甚至浮点数。 如果结构体变量中的字段属于不同类型,我们无法计算偏移量并将其与常量大小相乘。 寻址特定字段的公式为: 146 | 147 | $$ 148 | ADDR(st.f_i)=ADDR(st)+\sum_t^{i-1}SIZE(st.f_t) 149 | $$ 150 | 151 | 但是,您应该考虑对齐方式。 在运行时,所有结构体字段都应与 32 位边界对齐。 为了简化实现,您可以将所有基本类型分配在 4 个字节中。 152 | 153 | 还有更复杂的情况,例如访问数组元素,而数组是结构体的字段。 有了正确的数据类型表示和程序设计模式,处理这种复杂的情况并不是很困难。 由于您不需要实现派生类型变量,因此我们不会为您提供具体的翻译方案。 不过,您可以实现此功能来获得奖励分数。 154 | 155 | ### 5.5. 提示 156 | 157 | 我们建议您为中间表示定义一个单独的类(TAC 指令的集合,请参阅 §3 了解可能的实现选择)。 然后,您可以人工构建一个示例 TAC 程序并在 IR 模拟器上运行它来验证您的 IR 类。 158 | 159 | 您需要为每个语法符号 `X` 实现 `translate_X` 函数。我们已经介绍了表达式和语句的翻译方案。 您应该考虑如何处理其他情况,例如数据初始化、结构成员访问等。一旦您理解并实现了前面介绍的翻译方案,编写新方案应该很简单。 自己编写更多的测试用例总是有助于发现编译器的不足。 160 | 161 | ## 6. 项目要求 162 | 163 | ### 6.1. 基本要求 164 | 165 | 在此阶段,输入格式与之前的阶段相同,即可执行文件 bplc 接受表示 BPL 程序路径的单个命令行参数。 我们的测试用例没有词法/语法/语义错误,因此您的任务是生成保留该程序行为的 TAC-IR,而不考虑报告错误(尽管您可以自由地保留这些检查例程)。 您应该仔细阅读第 6.2 节中的假设,以避免陷入过于复杂的情况(例如以数组作为字段的结构或结构数组等)。(略) 166 | 167 | ### 6.2. 假设 168 | 169 | 以下是我们测试用例的假设,这意味着您可以通过忽略它们的违规行为来安全地实现代码生成器。 170 | 171 | - 假设 1:所有测试都没有词法/语法/语义错误(假设也没有逻辑错误); 172 | - 假设 2:只有整型原始类型变量; 173 | - 假设 3:没有全局变量,并且所有标识符都是唯一的; 174 | - 假设 4:所有函数的唯一返回数据类型是 int; 175 | - 假设 5:所有函数都是直接定义而无需声明; 176 | - 假设 6:没有结构变量或数组; 177 | - 假设 7:函数的参数绝不是结构体或数组。 178 | 179 | ### 6.3. 输入和输出 180 | 181 | 您的代码生成器应将输入 BPL 程序转换为 TAC 指令。 要展示其工作原理,请参阅以下 BPL 程序: 182 | 183 | ```c 184 | int main() { 185 | int n; 186 | n = read(); 187 | if (n > 0) write(1); 188 | else if (n < 0) write(-1); 189 | else write(0); 190 | return 0; 191 | } 192 | ``` 193 | 194 | 该代码是一个符号函数,输出 1 表示正数,-1 表示负数,0 表示零。 该程序的有效中间表示是: 195 | 196 | ```assembly 197 | FUNCTION main : 198 | READ t1 199 | v1 := t1 200 | t2 := #0 201 | IF v1 > t2 GOTO label1 202 | GOTO label2 203 | LABEL label1 : 204 | t3 := #1 205 | WRITE t3 206 | GOTO label3 207 | LABEL label2 : 208 | t4 := #0 209 | IF v1 < t4 GOTO label4 210 | GOTO label5 211 | LABEL label4 : 212 | t5 := #1 213 | t6 := #0 - t5 214 | WRITE t6 215 | GOTO label6 216 | LABEL label5 : 217 | t7 := #0 218 | WRITE t7 219 | LABEL label6 : 220 | LABEL label3 : 221 | t8 := #0 222 | RETURN t8 223 | ``` 224 | 225 | 我们的示例输出采用命名约定,变量名称遵循模式 `t_n` 或 `v_n` , `label_n` 表示标签名称。 然而,这不是唯一的方法。 您的编译器可以根据您的意愿生成任何有效的名称。 226 | 227 | 请注意,上述 TAC IR 远非高效。 例如,它将常量 0 分配给四个变量 `t2`、`t4`、`t7` 和 `t8`,但它们可以是同一个局部变量。 此外,还有像 `label6` 这样的虚拟标签。 您可以构建一个生成更高效代码的编译器。 228 | 229 | ### 6.4. 竞争分数 230 | 231 | 我们根据执行指令的数量来评估代码效率,并根据您的编译器性能分配有竞争力的分数。 232 | 233 | ### 6.5. 额外功能 234 | 235 | 我们鼓励您设计和实现自己的语言功能。 但是,为了确保生成的代码可以在 IR 模拟器中安全运行,您应该仔细设计转换方案,以便给定的 TAC 指令可以支持额外的功能。 建议的额外功能是支持循环中的 continue/break 语句。 您可以通过添加新终端轻松扩展 BPL 语法,并将结构转换为某种 GOTO 结构。 236 | 237 | 您还可以通过修改假设来实现您的编译器。(略) 238 | 239 | ### 6.6. 评分政策 240 | 241 | (略) 242 | 243 | ## 7. 提交 244 | 245 | 略 246 | 247 | # 附录 A 248 | 249 | 三地址码规范 250 | 251 | image-20240104190656308 252 | -------------------------------------------------------------------------------- /Documents/Project 4.md: -------------------------------------------------------------------------------- 1 | # 阶段 4:目标代码生成 2 | 3 | ## 1. 概述 4 | 5 | 我们终于到达了工作编译器的最后一步:目标代码生成。 实际上,我们已经在第三阶段完成了代码生成,其中我们设计了一个概念性的运行时环境,并将源代码转换为遵循该约定的三地址代码。 BPL 语言的三地址代码是一种中级中间表示 (IR),但是,更底层的东西仍未处理。 有了三地址代码,编译器将处理这些低级内容并最终生成可以在 MIPS32 机器上运行的可执行代码。 6 | 7 | 机器代码的底层细节在于三个方面: 8 | 9 | - 三地址码和机器码并不是一一对应的。 单个 TAC 指令可以翻译为多个机器代码指令,反之亦然。 所以我们必须设计我们的指令选择策略; 10 | - 我们假设三地址代码中的局部变量数量不受限制,尽管现实世界中并非如此。 例如,x86上只有8个通用寄存器,而MIPS32上有32个寄存器(程序的运行时内存也有有限的容量)来支持计算。 我们需要仔细设计寄存器分配算法,以便只有活动变量驻留在寄存器中; 11 | - 我们使用 `ARG` 和 `CALL` TAC 指令来调用带有参数的函数。 然而,大多数硬件中没有针对此任务的特殊指令。 我们应该仅使用跳转和数据移动原语来维护调用堆栈。 12 | 13 | 在这个阶段,我们将解决上述问题。 我们选择 MIPS32 作为我们的目标语言。 MIPS是一种精简指令集计算机(RISC)指令集架构(ISA),其32位版本称为MIPS32。 MIPS32 是我们编译器的理想目标语言,原因有二: 14 | 15 | - 它是精简指令集,指令编码紧凑,语义清晰; 16 | - 它提供了32个寄存器,每个寄存器都有明确的使用约定,有利于寄存器分配/赋值的设计。 17 | 18 | 为了简化您的实施,我们为您提供了入门代码,以便您可以快速开始。 起始代码定义了几个函数存根,以便您可以插入代码并立即检查结果。 提供加载功能,直接读取并翻译文本IR代码文件; 您还可以使编译器前端适应目标代码生成器。 这两种方法在我们的项目中都是可以接受的,但后者更可取,因为它为您提供了一个端到端的编译器,而且更令人兴奋。 19 | 20 | ## 2. 实验环境 21 | 22 | 生成的目标机器代码可以直接在模拟器中运行(实际上,甚至是实际的 MIPS32 机器)。 在实验室虚拟机中,我们安装了 SPIM 模拟器。 SPIM 是一个运行 MIPS32 程序的独立模拟器。 它读取并执行为 MIPS32 处理器编写的汇编语言程序,而不是二进制可执行文件。 23 | 24 | 要运行生成的 MIPS 代码(假设代码文件路径为 `test/test_a.s`),只需在终端中键入以下命令: 25 | ```bash 26 | spim -file test/test_a.s 27 | ``` 28 | 29 | 建议以 `.s`/`.asm` 扩展名结束生成的代码文件,但 SPIM 不会检查此扩展名。 有关 SPIM 的更多命令行选项和其他功能,您可以参考其官方文档。(略) 30 | 31 | ## 3. 指令选择 32 | 33 | ### 3.1. 编写 MIPS32 汇编 34 | 35 | #### 3.1.1. 基础 36 | 37 | SPIM 接受文本汇编文件并模拟其执行。 通常,汇编程序文件以 `.s`/`.asm` 扩展名结尾。 汇编程序包含多个代码(或文本)段和数据段,它们对应于 `.text` 和 `.data` 伪指令。 SPIM 还支持单行注释,以 `#` 开头并以换行符结尾。 程序员可以在数据段中声明常量或全局变量,格式如下: 38 | 39 | ```assembly 40 | name: storage_type value(s) 41 | ``` 42 | 43 | 这里,`name` 是一个标签,用于定位声明变量的内存地址,`storage_type` 是变量的数据类型,`value` 是变量的初始值。下表列出了几种常用的数据类型及其声明。 44 | 45 | image-20240104193850405 46 | 47 | #### 3.1.2. 寄存器 48 | 49 | MIPS32有32个寄存器,编号为 0∼31。 每个寄存器都有一个缩写,反映了寄存器的预期用途。 下表显示了所有 MIPS32 寄存器及其在 gcc 中的常规用法。 大多数 MIPS32 寄存器在硬件级别都是相同的,除了 `$0` 始终包含硬连线值 0。这种设计意味着使用约定不是由硬件强制执行的,而是应由软件遵循。 您可以生成不遵守这些约定的工作 MIPS 代码。 然而,由于大多数程序员、编译器、汇编器确实遵循这些约定,因此违反约定会限制生成代码的可移植性。 更糟糕的是,模拟器可能无法执行它们。 50 | 51 | image-20240104194326369 52 | 53 | 寄存器 `$0` 始终包含硬连线值 0,该值无法更改。 寄存器`$at`、`$k0` 和 `$k1` 是为汇编器和操作系统保留的,它们不应该被用户程序或编译器使用。 如果您的编译器尝试使用它们,SPIM 将在加载汇编程序时引发语法错误。 寄存器 `$v0` 和 `$v1` 用于从函数返回值。 寄存器 `$a0` - `$a3` 用于将前四个参数传递给例程(其余参数在堆栈上传递)。 54 | 55 | 寄存器 `$t0` - `$t9` 是调用者保存的寄存器,用于保存不需要在调用之间保留的临时值。 在进行过程调用之前,调用者应将这些寄存器中的值保存到主内存中。 寄存器 `$s0` - `$s7` 是被调用者保存的寄存器,它们保存应在调用之间保留的长期值。 对于被调用者保存的寄存器中的值,被调用者的工作是在真正执行被调用者的代码之前将它们保存到主内存中,并在被调用者返回之前将它们加载回寄存器。 我们将在第 5 节稍后讨论有关此约定的更多信息。 56 | 57 | 寄存器 `$gp` 是一个全局指针,指向静态数据段中 64K 内存块的中间,通常它存储一个常量地址 0x10008000。 MIPS32 指令全部编码为 32 位长度。 这些加载和存储指令无法直接访问 32 位地址,因为所有立即值最多为 16 位。 换句话说,我们无法在一条指令中访问超出 16 位范围的地址。 然而,通过 `$gp` 寄存器,我们可以使用带符号的 16 位偏移字段来访问静态数据段的前 64 KB。 例如,要将地址 `0x10010020` 处的字加载到 `$v0` 中,我们可以使用: 58 | 59 | ```assembly 60 | lw $v0, 0x8020($gp) 61 | ``` 62 | 63 | 寄存器 `$sp` 是堆栈指针,指向堆栈区域的顶部,而寄存器 `$fp` (30) 是帧指针。` jal` 指令将过程调用的返回地址写入寄存器 `$ra`,在过程完成并返回后 `jr` 可以使用该地址。 64 | 65 | 简而言之,您可以使用 `$zero` 作为常量零,分配 `$t0` - `$t9`、`$s0` - `$s7` 任意使用。 `$at`、`$k0`、`$k1` 永远不应该被分配,而其他的则应该在过程调用期间小心维护。 66 | 67 | #### 3.1.3. 数据移动 68 | 69 | MIPS32 将加载和存储原语分开。 在这种架构下,计算指令的操作数必须预先加载到寄存器中。 SPIM 支持多种加载和存储寻址模式,如下表所示。 70 | 71 | image-20240104201843666 72 | 73 | #### 3.1.4. 程序案例 74 | 75 | 在起始代码中,BPL 内置读取函数的指令为: 76 | 77 | ```assembly 78 | read: 79 | li $v0, 4 80 | la $a0, _prmpt 81 | syscall 82 | li $v0, 5 83 | syscall 84 | jr $ra 85 | ``` 86 | 87 | 这里的第一行定义了一个标签 `read`,它对应于函数标识符。 请注意,汇编代码不区分标签名称或函数名称,它们都是标签。 然后 `li` 指令将立即数 4 加载到寄存器 `$v0` 中。 `la` 指令将地址加载到 `$a0`。 这里的地址是在数据段中声明的自定义标识符 `_prmpt`,它是一串提示信息。 系统调用指令触发软件中断以调用特定的操作系统服务。 该服务号已加载到 `$v0` 中。 在本例中,系统调用服务为 4(`print_string`)。 接下来的两行执行 `read_int` 服务。 最后,该过程通过无条件跳转jr返回到返回地址寄存器 `$ra` 中存储的位置。 88 | 89 | 在上面的代码中,我们假设 `read` 函数的返回地址已经存储在 `$ra` 寄存器中,因此生成的代码可以在调用 `read` 后安全地返回到调用站点。 系统调用 `read_int` 会将其返回值存储到 `$v0` 中,因此生成的代码应该从相应的寄存器中获取该值。 这些运行时行为不是 MIPS32 规范的一部分,而是大多数现实世界编译器的约定。 尽管我们不要求您遵循这些约定,但强烈建议您这样做,因为违反它们可能会导致错误。 90 | 91 | ### 3.2. 翻译三地址码 92 | 93 | 指令选择实际上是一个模式匹配的问题。 为了将中间表示转换为机器代码,我们需要找到特定的模式,然后将它们转换为相应的指令。 此过程类似于中间代码生成过程,尽管它依赖于机器。 94 | 95 | 我们在起始代码中提供了线性 IR 定义,因此转换相当简单:您可以通过一对一映射简单地转换 TAC。下表显示了数据操作和跳转指令的映射方案。 函数 `reg(·)` 代表为变量分配的寄存器,我们稍后会详细讨论。 这个方案并不是独一无二的。 您还可以设计自己的方案以更好地优化代码。 96 | 97 | image-20240104202817543 98 | 99 | 值得一提的是,乘法、除法和分支指令不采用非零常量作为操作数,因此这些指令中涉及的立即数应首先加载到寄存器中。 100 | 101 | 这种转换方案可能会产生低效的代码。 以整数数组访问表达式 `arr[3]` 的翻译为例。 假设基指针 `arr` 已经存储在寄存器 `$t1` 中,并且要将 `arr[3]` 的值保存到 `$t2` 中,进行一对一映射翻译,可以得到以下代码: 102 | 103 | ```assembly 104 | addi $t3, $t1, 12 105 | lw $t2, 0($t3) 106 | ``` 107 | 108 | 然而,通过利用寻址模式,它们可以合并成一条指令: 109 | 110 | ```assembly 111 | lw $t2, 12($t1) 112 | ``` 113 | 114 | 上面的例子展示了我们如何使用滑动窗口进行局部优化。 通常,我们会向前查看多个 TAC 指令,看看它们是否可以合并为单个目标指令。 这种方法也称为窥孔优化。 115 | 116 | ## 4. 寄存器分配 117 | 118 | 大多数 MIPS32 指令的操作数都来自寄存器,加载/存储除外。 任何参与计算/比较的变量都应该首先加载到寄存器中。 由于寄存器的数量有限,我们需要寄存器分配算法来决定哪些值保留在寄存器中以及它们将驻留在哪些寄存器中。 119 | 120 | 最简单也是最昂贵的方法是将所有变量存储在内存中,并且仅加载下一条指令涉及的那些值。 由于所有 MIPS32 指令最多占用三个地址,因此我们可以简单地将它们分配给 `$t0` - `$t2`。 执行该指令后,我们存储回这些值。 显然,它会生成功能正确的代码,尽管它们可能非常慢。 如果您选择实现这个简单的算法,那完全没问题。 如果这样做,您可以跳过其余小节中介绍的高级算法。 121 | 122 | 下面我们将介绍两种有关寄存器分配的算法。 值得注意的是,在现实情况下,找到最佳分配是 NP 困难的,因此现代编译器只能找到该问题的近似解决方案。 123 | 124 | ### 4.1. 本地寄存器分配 125 | 126 | 寄存器分配的主要挑战是寄存器数量有限。 一般来说,变量的数量多于寄存器的数量,因此变量应该在这些寄存器之间进行交换。 频繁加载和存储变量会带来内存访问的开销,因此我们需要一种机制来正确地将寄存器分配给变量。 127 | 128 | 局部寄存器分配就是这样一种算法,其中通过启发式仅在基本块内部分配寄存器。 当控制流退出基本块时,所有分配的寄存器的值都应存储到内存中。 当程序进入基本块时,所有寄存器都被标记为空闲。 然后我们扫描基本块中的代码。 如果有变量需要加载到寄存器中,请执行以下操作: 129 | 130 | - 如果有空闲寄存器,则将变量分配给它; 131 | - 如果没有寄存器空闲,则将寄存器的内容存储(或溢出)到内存。 显然,最好选择近期不会被访问的寄存器或基本块内的寄存器。 132 | 133 | 上面的算法采用了一种启发式算法,试图最小化溢出变量的成本。 我们尝试通过贪婪地选择最后访问的变量来减少内存访问的开销。 假设 TAC 指令具有通用形式: 134 | 135 | ```assembly 136 | z := x op y 137 | ``` 138 | 139 | 其中 `x` 和 `y` 是操作数,`op` 是运算符,`z` 存储结果。 本地寄存器分配对每条 TAC 指令执行以下例程: 140 | 141 | ```C 142 | rx = Ensure(x) 143 | ry = Ensure(y) 144 | rz = Allocate(z) 145 | Emit([rz := rx op ry]) 146 | if (x is not needed after the current operation) 147 | Free(rx) 148 | if (y is not needed after the current operation) 149 | Free(ry) 150 | ``` 151 | 152 | 函数 `Free` 将寄存器标记为空闲,`Emit` 输出一条 MIPS32 指令。 另外两个辅助功能是: 153 | 154 | ```C 155 | Ensure(x): 156 | if (x is already in register r) 157 | result = r 158 | else 159 | result = Allocate(x) 160 | Emit([lw result, x]) 161 | return result 162 | ``` 163 | 164 | ```C 165 | Allocate(x): 166 | if (exists idle register r) 167 | result = r 168 | else 169 | result = register whose value’s next-use is the farthest 170 | spill result 171 | return result 172 | ``` 173 | 174 | 教科书第 8.6.3 节中描述的 `getReg` 与我们的算法类似。 教科书中的 `getReg` 函数引入了寄存器描述符和地址描述符来消除寄存器之间的数据移动,希望最大限度地减少加载/存储指令的数量。 它更有效,但也更复杂。 您可以选择实现 `getReg` 函数而不是此处描述的本地寄存器分配算法,甚至可以设计并实现您自己的策略。 175 | 176 | ### 4.2. 全局寄存器分配 177 | 178 | 本地寄存器分配中的术语“本地”代表我们只关注基本块内的变量。 但是,如果我们尝试跨多个基本块分配寄存器,则本地策略不再有效。 这个问题的主要挑战是:我们不知道程序的实际控制流,因此我们不知道寄存器中的值 `x` 是否应该溢出到内存中,因为控制流可能会跳转到一个基本的 涉及 `x` 的块,或另一个不涉及 `x` 的块。 179 | 180 | 跨基本块分配寄存器的优点是减少加载/存储操作的数量,从而提高代码效率。 一个典型的例子是,由于程序大部分时间都花在循环中,因此将最活跃的值(例如索引 `i`)保留在固定寄存器中将在块边界节省大量加载/存储指令。 181 | 182 | 在本地寄存器分配中,我们将所有活动变量存储到每个基本块末尾的内存中。 然而,在全局寄存器分配中,我们应该跨基本块确定每个变量的活跃度,这种技术称为活跃度分析。 然后,我们通过将寄存器分配问题减少到变量干扰图上的图形着色来决定哪些变量驻留在寄存器中。 183 | 184 | #### 4.2.1. 活性分析 185 | 186 | 我们首先定义什么是实时变量。 我们说变量 `x` 在特定的程序位置有效,当且仅当: 187 | 188 | 1. 如果指令 `i` 使用 `x` 的值,则 `x` 在执行 `i` 之前处于活动状态; 189 | 2. 如果 `x` 在执行指令 `i` 之后是活动的,其中 `i` 没有定义 `x`,那么 `x` 在执行 `i` 之前也是活动的; 190 | 3. 如果 `x` 在执行指令 `i` 之后处于活动状态,并且可以通过从 `i` 跳转到指令 `j`,则 `x` 在执行 `j` 之前处于活动状态; 191 | 4. 如果指令 `i` 定义了 `x` 但没有使用它,则 `x` 在执行 `i` 之前不是活动的(或死亡的)。 192 | 193 | 规则 1 定义活动变量的起源,规则 2 和规则 3 定义活动如何传播,规则 4 定义活动何时结束。 194 | 195 | 然后我们将指令 `i` 的后继(successor)定义为: 196 | 197 | 1. 如果 `i` 无条件跳转到指令 `j`,那么 $succ[i]=\{j\}$; 198 | 2. 如果 `i` 有条件跳转到指令 `j`,那么 $succ[i]=\{j, i+1\}$; 199 | 3. 如果 `i` 是返回语句,那么 $succ[i]=\emptyset$; 200 | 4. 其他情况 $succ[i]=\{i+1\}$。 201 | 202 | 然后我们将集合 $def[i]$ 定义为在指令 `i` 处定义的变量, $use[i]$ 为在 `i` 处使用/读取的变量集, $in[i]$ 为执行 `i` 之前有效的变量, $out [i]$ 作为执行 `i` 后的实时变量。 203 | 204 | 遵循这些定义,我们可以将活性分析问题形式化为数据流方程: 205 | 206 | $$ 207 | \begin{cases} 208 | in[i]=use[i]\cup(out[i]-def[i]) \\ 209 | out[i]=\bigcup_{j\in succ[i]}in[j] 210 | \end{cases} 211 | $$ 212 | 213 | 方程组可以迭代求解:一开始, $in[i] = \emptyset$ 。 然后,对于每条指令 `i`,我们根据(1)更新 `in[i]` 和 `out[i]`,直到所有集合收敛到固定大小。 实际上,根据格理论,`in[i]` 和 `out[i]` 的求值顺序并不影响收敛性。 然而,以相反的顺序(即从代码末尾到开头)评估它们可能会更快地收敛。 214 | 215 | > **实现提示** 216 | > 217 | > 为了有效地执行集合运算,一个好的做法是应用位向量。 假设通用集合中有 9 个元素,那么我们可以用 9 位来表示这样一个集合及其所有子集。 第 i 个位置上的 1 表示第 i 个元素属于该集合,而 0 表示相反。 在这种表示下,两个集合的交可以通过布尔与运算来执行,两个集合的并可以通过布尔或运算来执行,并且集合的补可以通过布尔非运算来执行。 218 | 219 | #### 4.2.2. 通过图着色分配 220 | 221 | 根据活跃度分析的结果,我们能够进行全局寄存器分配。 显然,我们应该将两个实时变量分配给不同的寄存器,否则,将引入大量加载/存储操作来访问这些实时变量。 然而,有两个例外: 222 | 223 | - 对于赋值 `x := y`,`x` 和 `y` 可以共享同一个寄存器,即使它们在赋值后都处于活动状态,因为它们是等效的; 224 | - 对于二元运算 `x := y + z`,如果在该指令之后 `x` 不再存在,而 `y` 仍然存在,则它们不应该共享同一个寄存器,否则,为 `x` 的寄存器分配新值也会覆盖 `y` 的值。 225 | 226 | 根据上面的分析,我们定义变量 `x` 和 `y` 之间的干扰为: 227 | 228 | - $\exists i$, s.t. $x\in out[i]$ 且 $y \in out [i]$; 229 | - $\exists i\neq[x:=y]$, s.t. $x\in def[i]$ 且 $y \in out [i]$。 230 | 231 | 这里,集合 $def[i]$ 和 $out[i]$ 是通过活性分析收集的,如第 4.2.1 节所述。 这个阶段最重要的事情是:如果 `x` 和 `y` 互相干扰,我们将把它们分配到不同的寄存器。 232 | 233 | 以程序中的一个变量为顶点,两个变量之间的干涉关系为边,就可以画出程序的干涉图。 假设我们将为每个变量分配一个寄存器,而有 k 个寄存器(k 种颜色)可用。 更重要的是,两个相邻的顶点不能共享相同的寄存器,或者说它们不能具有相同的颜色。 然后寄存器分配就简化为众所周知的图形着色问题。 234 | 235 | 对于固定的 k,决定图是否可以 k 着色是 NP 完全的。 为了在多项式时间内解决这个问题,我们通常采用启发式方法。 k 着色的一个简单启发式称为 Kempe 算法,它执行以下操作: 236 | 237 | 1. 如果干扰图中存在度数小于k的顶点,则将其从图中移除,然后将其压入堆栈; 238 | 2. 重复步骤1,直到没有顶点可以被删除。 如果剩下的顶点少于 k 个,则为它们分配不同的颜色,然后从堆栈中弹出这些顶点,并为每个顶点分配与其邻居不同的颜色。 否则,转至步骤 3; 239 | 3. 移除并推动一个顶点,并将其标记为“溢出”,转至步骤 1; 240 | 4. 如果弹出的顶点被标记为“溢出”,请检查其邻居的颜色。 如果它的邻居的颜色少于 k 个颜色,则只需按最后一个颜色分配它,否则,使该节点保持不着色,这意味着它应该被溢出到内存中。 241 | 242 | 步骤 1 的基本原理是,当删除这样的顶点时,如果生成的图是 k-可着色的,则原始图也必须是 k-可着色的。 对于每个顶点至少有 k 个邻居的图,仍然可以对其进行 k 着色。 但我们无法有效地计算答案,因为它是 NP 完全的。 尽管如此,Kempe 算法为我们提供了一个很好的启发式解决方案来解决图形着色问题,特别是在寄存器分配的情况下。 243 | 244 | 运行图形着色算法后,中间代码中的所有变量要么被分配寄存器,要么被标记为“溢出”。 对于溢出变量,如果通过某些计算访问它,则应将其加载到特定寄存器中; 计算完成后,将从寄存器存回内存。 要为其分配寄存器,最简单的方法是为溢出变量预先定义一些寄存器。 还有更多获得更好运行时性能的策略,可以在教科书中找到。 245 | 246 | ## 5. 过程调用约定 247 | 248 | ### 5.1. 堆栈布局 249 | 250 | 当调用函数或过程时,编译器应该考虑两个流,即控制流和数据流。 基本上,控制流转换意味着在调用过程之前将程序计数器存储在寄存器 `$ra` 中,并在过程返回之前从该寄存器恢复 PC。 这种机制可以通过 MIPS32 中的 `jal` 和 `jr` 指令轻松维护。 所以你的编译器应该关注数据流转换。 在这里,我们感兴趣的是传递参数和返回值。 251 | 252 | 从技术上讲,您可以将值存储在任何地方,除了一些不可变寄存器(即 `$zero`、`$at`),但建议您遵循使用约定(第 3.1.2 节)。 要传递参数,您应该同时使用寄存器和堆栈。 对于最多有四个参数的函数,参数的值应分别加载到 `$a0`、`$a1`、`$a2`、`$a3` 中。 第五个及以下参数将存储在堆栈中。 函数的返回值存储在 `$v0` 中。 253 | 254 | 实现过程调用最重要的内存段是栈。 在运行时,每个函数都会将其激活记录存储在堆栈中,堆栈也称为堆栈帧。 堆栈帧的布局可能因体系结构甚至编译器实现而异。下图显示了典型的堆栈框架布局。 在此布局中,`$sp` 指向堆栈的顶部,而 `$fp` 则指向被调用过程的激活记录的底部。 如果该过程需要四个以上的参数,则以下参数将存储在 `$fp` 之后。 `$fp` 和 `$sp` 之间的内存空间可以存储任何需要的信息。 255 | 256 | image-20240104213638961 257 | 258 | 图中的 Return address 是调用者函数的返回地址,而被调用者函数的返回地址则保存在 `$ra` 中。 当被调用者退出时,应该恢复调用者的返回地址。 这是因为当我们使用指令 `jal` 调用一个过程时,它会覆盖寄存器 `$ra` 的内容,因此我们需要将 `$ra` 的旧值存储到被调用过程的堆栈中,以便以后可以恢复它 。 259 | 260 | 在寄存器分配中,一些变量会从寄存器溢出到内存中。 与 `$ra` 寄存器一样,如果采用帧指针实现(即教科书中讨论的堆栈分配方法),也应该保存 `$fp` 寄存器,尽管这不是必需的。 对于局部变量,我们将它们存储在堆栈中。 对于全局变量,应该将它们溢出到可写数据段。 由于我们在项目第 4 阶段没有引入全局变量,因此您可以忽略后一种情况。 261 | 262 | 局部变量通常按照其声明顺序存储在堆栈中。 此外,数组和结构变量应该存储在堆栈中,即使它们只包含适合寄存器大小的单个字段。 263 | 264 | ### 5.2. 调用和返回序列 265 | 266 | 如果一个过程/函数 f 调用另一个过程/函数 g,那么我们称 f 为调用者,g 为被调用者。 在被调用者的过程中,一些寄存器将被覆盖。 由于它们的值可能在执行被调用者之后被调用者使用,因此它们应该在执行被调用者的代码之前溢出到内存并在执行后恢复。 那么问题来了:这些寄存器保存操作应该在哪里进行呢? 在调用者或被调用者中? 在调用者看来,它不知道被调用者将使用哪些值; 对于被调用者来说,它不知道调用后哪些值对调用者仍然有用。 因此他们只能将所有寄存器存储在他们的程序中,这导致效率低下。 267 | 268 | 解决这个问题的一般方法是将寄存器存储在调用者和被调用者中。 MIPS32 提供调用者保存的寄存器(`$t0` - `$t9`)和被调用者保存的寄存器(`$s0` - `$s8`)。 建议调用者保存在过程调用期间将写入的那些寄存器(`$t0` - `$t9` 中的部分)的内容。 另一方面,被调用者应该保存这些寄存器的内容(`$s0` - `$s8`中的部分),这在调用后仍然有用。 269 | 270 | #### 5.2.1. 调用者序列 271 | 272 | 当调用者调用另一个函数时,它应该将所有调用者保存的寄存器的值存储到堆栈中,然后将参数加载到寄存器中(或压入堆栈)。 当被调用者返回时,调用者应该恢复那些保存的寄存器值。 该例程的指令序列如下: 273 | 274 | ```assembly 275 | sw live1, offset[live1]($sp) 276 | ... 277 | sw livek, offset[livek]($sp) 278 | subu $sp, $sp, max{0, 4*(n-5)} 279 | move $a0, arg1 280 | ... 281 | move $a3, arg4 282 | sw arg5, 0($sp) 283 | ... 284 | sw argn, (4*(n-5))($sp) 285 | jal callee 286 | addi $sp, $sp, max{0, 4*(n-5)} 287 | lw live1, offset[live1]($sp) 288 | ... 289 | lw livek, offset[livek]($sp) 290 | ``` 291 | 292 | 上面的代码假设所有参数在函数调用之前都已加载到寄存器中。 在实践中,您还可以计算并传递参数。 但是,如果选择后一种策略,则应仔细维护每个变量的偏移量,因为堆栈指针 `$sp` 的值可能会在此过程中发生变化。 为了解决这个问题,你也可以选择帧指针 `$fp` 作为基地址,而不是使用 `$sp`。 293 | 294 | #### 5.2.2. 被调用者序列 295 | 296 | 调用序列位于被调用者主体的顶部,也称为序言; 另一方面,返回序列位于底部,我们称之为尾声。 297 | 298 | 序言负责设置激活记录,存储返回地址和帧指针。 然后,存储被调用者保存的寄存器,并获取参数: 299 | 300 | image-20240104215038356 301 | 302 | 在尾声中,被调用者保存的寄存器以及堆栈都被恢复: 303 | 304 | image-20240104215103661 305 | 306 | 其中 $fs_g$ 表示函数 g 的栈帧大小。 307 | 308 | 正如我们在调用者序列中建议的那样,您还可以通过帧指针而不是堆栈指针来引用堆栈。 309 | 310 | 最后我们讨论过程调用如何影响寄存器分配。 被调用者保存的寄存器 `$s0` - `$s8` 在过程调用中保留它们的值,因此调用者不需要考虑它们的分配。 重要的是调用者保存的寄存器 `$t0` - `$t9`,因为它们的值在过程调用后会丢失。 311 | 312 | 如果采用本地寄存器分配,则 `$t0` - `$t9` 中的所有值应在 `CALL` 指令之前溢出,并在过程调用后恢复。 至于全局寄存器分配,您应该避免将 `$t0` - `$t9` 分配给 `CALL` 指令中的那些变量。 如果您采用简单的寄存器分配,则可以忽略这些建议。 313 | 314 | ## 6. 项目要求 315 | 316 | ### 6.1. 基础要求 317 | 318 | (略) 319 | 320 | ### 6.2. 假设 321 | 322 | - 假设 1:中间代码在逻辑上是正确的,这意味着您可以在IR模拟器上运行它们并获得正确的输出; 323 | - 假设 2:没有结构体或数组变量,因此不需要翻译 DEC 指令; 324 | - 假设 3:所有整数常量都在 $[−2^{16}, 2^{16})$ 范围内,以便它们可以安全地由 MIPS32 立即数表示。 325 | 326 | ### 6.3. 所需任务 327 | 328 | #### 6.3.1. 寄存器分配 329 | 330 | 您的第一个任务是设计并实现寄存器分配算法。 除了一种非常简单的算法之外,我们在第 4 节中讨论了两种寄存器分配算法。 这两种算法在代码效率和实现复杂性方面有所不同。 您还可以实施自己的策略以获得更好的性能。 331 | 332 | 我们在提供的文件 `mips32.h` 中定义了寄存器描述符 (`struct RegDesc`) 和地址描述符 (`struct VarDesc`)。 您可以根据需要添加(或删除)字段。 您应该实现两个函数 `get_register` 和 `get_register_w`。 `w` 后缀表示获得的寄存器将用于加载值。 分离寄存器使用的主要原因是,覆盖寄存器会使相应的变量不再存在于该位置,因此应该将寄存器的旧值溢出到内存以保证数据一致性(如果需要)。 此外,您还应该实现溢出寄存器函数,当没有可用的寄存器用于新值时将调用该函数。 333 | 334 | #### 6.3.2. TAC 翻译 335 | 336 | 您需要完成的另一项任务是翻译一些 TAC 指令。 起始代码已经提供了一些示例。 下面的代码显示了 `LABEL` TAC 语句的翻译功能。 每个发射器函数接受 TAC 实例的结构,并返回下一个要翻译的 TAC 指令。 此模式可以在目标代码生成期间实现本地优化。 337 | 338 | ```c 339 | tac *emit_label(tac *label) { 340 | assert(_tac_kind(label) == LABEL); 341 | _mips_printf("label%d:", _tac_quadruple(label).labelno->int_val); 342 | return label->next; 343 | } 344 | ``` 345 | 346 | 这里的主要任务是翻译过程调用序列,它对应于四个 TAC 指令:`ARG`、`CALL`、`PARAM` 和 `RETURN`。 您还可以修改已实现的函数以获得更优化的代码。 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------