Commit 2dd8c34b authored by 李晓奇's avatar 李晓奇

Fetch lab3

parents 4dfb6145 a27f5a5e
---
Language: Cpp
BasedOnStyle: LLVM
AllowAllParametersOfDeclarationOnNextLine: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: false
BinPackParameters: false
BreakConstructorInitializers: BeforeComma
ColumnLimit: 120
CommentPragmas: '^(!|NOLINT)'
ConstructorInitializerAllOnOneLineOrOnePerLine: true
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 1
IndentCaseLabels: false
AllowShortCaseLabelsOnASingleLine: true
IndentWidth: 4
KeepEmptyLinesAtTheStartOfBlocks: false
PenaltyReturnTypeOnItsOwnLine: 200
SpacesBeforeTrailingComments: 1
TabWidth: 4
UseTab: Never
...
......@@ -22,22 +22,22 @@
本次实验的目的是让大家熟悉 Lab3 所需要的相关知识: LLVM IR、 LightIR(LLVM IR 的轻量级 C++ 接口)和 Visitor Pattern(访问者模式)。
在开始实验之前,请根据之前的[编译实验环境搭建](http://202.38.79.174/compiler_staff/2022fall-environment/-/blob/master/README.md)确保LLVM的版本为10.0.1,且PATH环境变量配置正确。可以通过`lli --version`命令是否可以输出10.0.1的版本信息来验证(其它版本不一定兼容)。
本次实验设置的目的是为 Lab3 进行知识的准备与热身, coding 的工程量不大,但是需要一定的阅读、学习、理解。因此本次的实验报告相比之下内容要求会稍微多一些,以避免大家在 Lab3 时手足无措。
这里助教提供了简单的[C++简介](Documentations/common/simple_cpp.md),对C++基本特性不熟悉的同学可以先阅读该文档。
这里助教提供了简单的[C++简介](../../Documentations/common/simple_cpp.md),对C++基本特性不熟悉的同学可以先阅读该文档。
### 主要工作
1. 第一部分: 了解 LLVM IR。通过 clang 生成的 .ll ,了解 LLVM IR 与 c 代码的对应关系,**完成1.3**
2. 第二部分: 了解 LightIR。通过助教提供的 c++ 例子,了解 LightIR 的 c++ 接口及实现,**完成2.3**
3. 第三部分: 理解 Visitor Pattern 。**完成3.1**
4. 实验报告:在 [report.md](./Reports/2-ir-gen-warmup/report.md)**回答3个问题**
4. 实验报告:在 [report.md](../../Reports/2-ir-gen-warmup/report.md)**回答3个问题**
## 1. LLVM IR 部分
### 1.1 LLVM IR 介绍
根据[维基百科](https://zh.wikipedia.org/zh-cn/LLVM)的介绍,LLVM是一个自由软件项目,它是一种编译器基础设施,以C++写成,包含一系列模块化的编译器组件和工具链,用来开发编译器前端和后端。IR的全称是Intermediate Representation,即中间表示。LLVM IR是一种类似于汇编的底层语言。
LLVM IR的具体指令可以参考 [Reference Manual](http://llvm.org/docs/LangRef.html)。由于其手册过于复杂,助教筛选了后续实验中将要用到的子集,总结为了 [Light IR 手册](../common/LightIR.md#ir-%E6%A0%BC%E5%BC%8F)。如果有感兴趣的同学可以阅读原手册作为拓展。
LLVM IR的具体指令可以参考 [Reference Manual](https://llvm.org/docs/LangRef.html)。由于其手册过于复杂,助教筛选了后续实验中将要用到的子集,总结为了 [Light IR 手册](../common/LightIR.md#ir-%E6%A0%BC%E5%BC%8F)。如果有感兴趣的同学可以阅读原手册作为拓展。
作为一开始的参考,你可以先阅读其中 `IR格式``IR指令` 两节,后续有需要再反复参考。实验的最后,你需要在 [report.md](./Reports/2-ir-gen-warmup/report.md)**回答问题1**
作为一开始的参考,你可以先阅读其中 `IR格式``IR指令` 两节,后续有需要再反复参考。实验的最后,你需要在 [report.md](../../Reports/2-ir-gen-warmup/report.md)**回答问题1**
### 1.2 gcd 例子: 利用 clang 生成的 .ll
阅读 [tests/2-ir-gen-warmup/ta_gcd/gcd_array.c](../../tests/2-ir-gen-warmup/ta_gcd/gcd_array.c)
......@@ -67,14 +67,14 @@ lab3 部分会要求大家通过 `LightIR` 根据 `AST` 构建生成 LLVM IR。
该程序的编译与运行请参考 4.2 节。
### 2.3 你的提交2: 利用 LightIR + cpp 编写生成 .ll 的程序
你需要在 `tests/2-ir-gen-warmup/stu_cpp/` 目录中,编写 [assign_generator.cpp](../../tests/2-ir-gen-warmup/stu_cpp/assign_generator.cpp)[fun_generator.cpp](../../tests/2-ir-gen-warmup/stu_cpp/fun_generator.cpp)[if_generator.cpp](../../tests/2-ir-gen-warmup/stu_cpp/if_generator.cpp)[while_generator.cpp](../../tests/2-ir-gen-warmup/stu_cpp/while_generator.cpp),以生成与 1.3 节的四个 c 程序相同逻辑功能的 `.ll` 文件。你需要完成 [report.md](./Reports/2-ir-gen-warmup/report.md) 中的**问题2**
你需要在 `tests/2-ir-gen-warmup/stu_cpp/` 目录中,编写 [assign_generator.cpp](../../tests/2-ir-gen-warmup/stu_cpp/assign_generator.cpp)[fun_generator.cpp](../../tests/2-ir-gen-warmup/stu_cpp/fun_generator.cpp)[if_generator.cpp](../../tests/2-ir-gen-warmup/stu_cpp/if_generator.cpp)[while_generator.cpp](../../tests/2-ir-gen-warmup/stu_cpp/while_generator.cpp),以生成与 1.3 节的四个 c 程序相同逻辑功能的 `.ll` 文件。你需要完成 [report.md](../../Reports/2-ir-gen-warmup/report.md) 中的**问题2**
## 3. Lab3 的准备
### 3.1 了解 Visitor Pattern
Visitor Pattern(访问者模式)是一种在 LLVM 项目源码中被广泛使用的设计模式。在遍历某个数据结构(比如树)时,如果我们需要对每个节点做一些额外的特定操作, Visitor Pattern 就是个不错的思路。
Visitor Pattern 是为了解决**稳定的数据结构****易变的操作耦合问题**而产生的一种设计模式。解决方法就是在被访问的类里面加一个对外提供接待访问者的接口,其关键在于在数据基础类里面有一个方法接受访问者,将自身引用传入访问者。这里举一个应用实例来帮助理解访问者模式: 您在朋友家做客,您是访问者;朋友接受您的访问,您通过朋友的描述,然后对朋友的描述做出一个判断,这就是访问者模式。
有关 Visitor Pattern 的含义、模式和特点,有梯子的同学可参考 [维基百科](https://en.wikipedia.org/wiki/Visitor_pattern#C++_example)。其中较为重要的一点原则在于, C++ 中对函数重载特性的支持。
`tests/2-ir-gen-warmup/calculator` 中,助教编写了一个利用访问者模式,产生计算算数表达式的中间代码的程序。该程序首先对算数表达式进行语法分析生成语法树,再使用访问者模式来遍历语法树,产生中间代码。在 [calc_ast.hpp](../../tests/2-ir-gen-warmup/calculator/calc_ast.hpp) 中,我们定义了语法树的不同节点类型。在 [calc_builder.cpp](../../tests/2-ir-gen-warmup/calculator/calc_builder.cpp) 中,我们使用 LightIR 编写了不同的 `visit` 函数。根据节点类型的不同,编译器会在多种 `visit` 函数中,选择对应的实现进行调用。请认真阅读这两个文件和其它相关代码,理解语法树是如何通过访问者模式被遍历的,并在 [report.md](./Reports/2-ir-gen-warmup/report.md)**回答问题3**
`tests/2-ir-gen-warmup/calculator` 中,助教编写了一个利用访问者模式,产生计算算数表达式的中间代码的程序。该程序首先对算数表达式进行语法分析生成语法树,再使用访问者模式来遍历语法树,产生中间代码。在 [calc_ast.hpp](../../tests/2-ir-gen-warmup/calculator/calc_ast.hpp) 中,我们定义了语法树的不同节点类型。在 [calc_builder.cpp](../../tests/2-ir-gen-warmup/calculator/calc_builder.cpp) 中,我们使用 LightIR 编写了不同的 `visit` 函数。根据节点类型的不同,编译器会在多种 `visit` 函数中,选择对应的实现进行调用。请认真阅读这两个文件和其它相关代码,理解语法树是如何通过访问者模式被遍历的,并在 [report.md](../../Reports/2-ir-gen-warmup/report.md)**回答问题3**
该程序使用方法如下:
......@@ -123,7 +123,7 @@ $ ./result
   │   ├── fun.c
   │   ├── if.c
   │   └── while.c
   ├── CMakeLists.txt <- 你在2.3节需要去掉注释(我们不收,你要改
   ├── CMakeLists.txt <- 你在2.3节需要去掉注释(你要交
   ├── stu_cpp <- lab2 所需提交的 cpp 目录(你要交)
   │   ├── assign_generator.cpp
   │   ├── fun_generator.cpp
......@@ -164,7 +164,7 @@ $ ./result
* 需要完成 `./tests/2-ir-gen-warmup/stu_cpp` 目录下的4个文件
* 需要在 `./Reports/2-ir-gen-warmup/` 目录下撰写实验报告
* 实验报告内容包括:
* 实验要求、3个问题、实验难点、实验反馈(具体参考 [report.md](./Reports/2-ir-gen-warmup/report.md))
* 实验要求、3个问题、实验难点、实验反馈(具体参考 [report.md](../../Reports/2-ir-gen-warmup/report.md))
* 本次实验报告**参与**评分标准.
* git 提交规范:
* 不破坏目录结构( `report.md` 如果需要放图片,请放在 `./Reports/2-ir-gen-warmup/figs/` 下)
......
# Lab3 实验文档
- [Lab3 实验文档](#lab3-实验文档)
- [0. 前言](#0-前言)
- [主要工作](#主要工作)
- [1. 实验框架](#1-实验框架)
- [2. 运行与调试](#2-运行与调试)
- [2.1 构建并运行 cminusfc](#21-构建并运行-cminusfc)
- [2.2 测试](#22-测试)
- [2.3 日志工具](#23-日志工具)
- [2.4 一些建议](#24-一些建议)
- [3. 实验要求](#3-实验要求)
- [3.1 目录结构](#31-目录结构)
- [3.2 提交要求和评分标准](#32-提交要求和评分标准)
## 0. 前言
Lab3 实验建立在 Lab2 的基础上,带领大家进一步理解源代码到 IR 的生成过程。同前置实验一样,需要你使用 `LightIR` 框架自动产生 `cminus-f` 语言的LLVM IR。经过 Lab2 的练手,相信你已经初步掌握了 LightIR 的使用,并且对于 LLVM IR 也有了一定的理解。
在本次实验中,你的**核心任务**是使用访问者模式来实现 IR 的自动生成。完成这一阶段后,调用 clang 从 IR 进一步生成可执行文件,这样一个初级的 cminus-f 编译器就完成了。
### 主要工作
1. 阅读[cminus-f 的语义规则](../common/cminusf.md),我们将按照语义实现程度进行评分
2. 阅读[LightIR 核心类介绍](../common/LightIR.md)
3. 阅读[实验框架](#1-实验框架),理解如何使用框架以及注意事项
4. 修改 `src/cminusfc/cminusf_builder.cpp` 来实现 IR 自动产生的算法,使得它能正确编译任何合法的 cminus-f 程序。
5.`report.md` 中解释你的设计,遇到的困难和解决方案
**友情提示**
1. 助教们在 `cminusf_builder.cpp` 中提供了基础实现,比如`CminusfBuilder::visit(ASTFunDeclaration &node)` 等函数。这些函数为示例代码,请你在开始实验前先**仔细阅读学习**文件中的这些代码片段,理解其含义和作用。
2. 助教们在 `cminusf_builder.cpp` 提供的部分函数是不完整的,无法通过所有测试用例。需要你补充代码的地方已经用 `TODO` 标出。我们提供的`cminusf_builder.cpp` 只可以满足测试用例 `lv0_1` 中的 `return.cminus`。虽然`eval.py`会显示其他一些测试用例也是`success`,但它对应的`.ll`文件是不正确的,不要因其显示 `success` 忽略了对应的代码补充,那会影响你后面较复杂样例的正确性。
3. 简要阅读 `cminusf_builder.hpp` 和其他头文件中定义的函数和变量,理解项目框架也会为你的实验提供很大的帮助。
4. 请独立完成实验,不要抄袭他人代码。
## 1. 实验框架
本次实验使用了由C++编写的 LightIR 来生成 LLVM IR。为了便于大家进行实验,该框架自动完成了语法树到 C++ 上的抽象语法树的转换。
我们可以使用[访问者模式](../2-ir-gen-warmup/README.md#31-%E4%BA%86%E8%A7%A3-visitor-pattern)来设计抽象语法树
中的算法。大家可以参考[lab2的样例](../../tests/2-ir-gen-warmup/calculator/calc_builder.cpp)[打印抽象语法树的算法](../../src/common/ast.cpp#L394-737)
以及运行 `test_ast` 来理解访问者模式下算法的执行流程。
`include/cminusf_builder.hpp` 中,我们还定义了一个用于存储作用域的类`Scope`。它的作用是辅助我们在遍历语法树时,管理不同作用域中的变量。它提供了以下接口:
```cpp
// 进入一个新的作用域
void enter();
// 退出一个作用域
void exit();
// 往当前作用域插入新的名字->值映射
bool push(std::string name, Value *val);
// 根据名字,寻找到值
Value* find(std::string name);
// 判断当前是否在全局作用域内
bool in_global();
```
你需要根据语义合理调用`enter``exit`,并且在变量声明和使用时正确调用`push``find`。在类`CminusfBuilder`中,有一个`Scope`类型的成员变量`scope`,它在初始化时已经将`input``output`等函数加入了作用域中。因此,你们在进行名字查找时不需要顾虑是否需要对特殊函数进行特殊操作。
## 2. 运行与调试
### 2.1 构建并运行 cminusfc
```sh
mkdir build && cd build
make clean
make -j
# 安装库 libcminus_io.a 至系统目录
# docker 实验环境下
make install
# 其他非 docker 实验环境且非 root 用户需要 sudo make install
```
编译后会产生 `cminusfc` 程序,它能将cminus文件输出为LLVM IR,也可以利用 clang 将 IR 编译成二进制可执行文件。程序逻辑写在`src/cminusfc/cminusfc.cpp`中。
当需要对 `.cminus` 文件测试时,可以这样使用:
```sh
# 假设 cminusfc 的路径在你的$PATH中
# 1. 利用构建好的 Module 生成 test.ll
# 注意,如果调用了外部函数,如 input, output 等,则无法使用lli运行
cminusfc test.cminus -emit-llvm
# 假设libcminus_io.a的路径在$LD_LIBRARY_PATH中,clang的路径在$PATH中
# 1. 利用构建好的 Module 生成 test.ll
# 2. 调用 clang 来编译 IR 并链接上静态链接库 libcminus_io.a,生成二进制文件 test
cminusfc test.cminus
```
### 2.2 测试
自动测试脚本和所有测试样例都是公开的,它在 `tests/3-ir-gen` 目录下,使用方法如下:
```sh
# 在 tests/3-ir-gen 目录下运行:
./eval.py
```
测试结果会输出到同文件夹的 `eval_result` 下。
### 2.3 日志工具
分析输出日志是进行程序调试的好方法,为方便大家进行实验,助教们提供了一个轻量级的日志分析工具 `logging` ,可分等级打印调试信息,更详细的说明请阅读[使用文档](../common/logging.md)
### 2.4 一些建议
1. 请比较通过你编写的编译器产生的 IR 和通过 clang 产生的IR来找出可能的问题或发现新的思路
2. 可以使用 logging 工具来打印调试信息
3. 可以使用 GDB 等软件进行动态分析,可以单步调试来检查错误的原因
## 3. 实验要求
### 3.1 目录结构
```
.
├── CMakeLists.txt
├── Documentations
│   ├── ...
│   ├── common
│   | ├── LightIR.md <- LightIR 相关文档
│   | ├── logging.md <- logging 工具相关文档
│   |   └── cminusf.md <- cminus-f 的语法和语义文档
│   └── 3-ir-gen
│      └── README.md <- lab3 实验文档说明(你在这里)
├── include <- 实验所需的头文件
│   ├── ...
│   ├── lightir/*
│   ├── cminusf_builder.hpp
| └── ast.hpp
├── Reports
│   ├── ...
│   └── 3-ir-gen
│   ├── report.md <- lab3 所需提交的实验报告,请详细说明你们的设计(需要上交)
│   └── contribution.md <- lab3 所需提交的队员贡献信息(需要上交)
├── src
│   ├── ...
│   └── cminusfc
│   ├── cminusfc.cpp <- cminusfc 的主程序文件
│   └── cminusf_builder.cpp <- lab3 需要修改的文件,你们要在该文件中用访问者模式实现自动 IR 生成的算法(需要上交)
└── tests
├── ...
└── 3-ir-gen
   ├── testcases <- 助教提供的测试样例
├── answers <- 助教提供的测试样例
   └── eval.py <- 助教提供的测试脚本
```
### 3.2 提交要求和评分标准
* 提交要求
本实验的提交要求分为两部分: 实验部分的文件和报告,git提交的规范性。
* 实验部分:
* 需要完善 `src/cminusfc/cminusf_builder.cpp`
* 需要在 `Reports/3-ir-gen/` 目录下撰写实验报告 `report.md`
* 实验报告内容主要包括实验要求、实现难点、实验反馈等(具体参考[repord.md](../../Reports/3-ir-gen/report.md)
* 本次实验收取 `src/cminusfc/cminusf_builder.cpp` 文件和 `Reports/3-ir-gen` 目录
* git提交规范:
* 请勿破坏目录结构,特别是`CMakeLists.txt`文件
* 如果需要在报告文档 [repord.md](../../Reports/3-ir-gen/report.md) 中插入图片,请放在目录 `Reports/3-ir-gen/figs/` 下)
* 请勿上传构建过程中生成的临时文件
* (不强制)git commit message 请提供简洁有效信息,可以参考学习 [Augular git commit 格式规范](https://blog.csdn.net/bbbbbubble/article/details/108456965)
* 提交方式:
* 代码提交:本次实验需要在希冀课程平台上发布的作业[Lab3-代码提交](http://cscourse.ustc.edu.cn/assignment/index.jsp?courseID=17&assignID=54)提交自己仓库的 gitlab 链接(注:由于平台限制,请提交http协议格式的仓库链接。例:学号为 PB011001 的同学,Lab3 的实验仓库地址为`http://202.38.79.174/PB011001/2022fall-compiler_cminus.git`),我们会收集最后一次提交的评测分数,作为最终代码得分。
* 报告提交:`将 Reports/3-ir-gen/report.md` 导出成 pdf 文件单独提交到[Lab3-报告提交](http://cscourse.ustc.edu.cn/assignment/index.jsp?courseID=17&assignID=54)
* 提交异常:如果遇到在平台上提交异常的问题,请通过邮件联系助教,助教将收取截止日期之前,学生在 gitlab 仓库最近一次 commit 内容进行评测。
* 评分标准:
* 实验分数组成如下:
* cminusf 程序测试 (75分)
* `report.md`(25分)
* 禁止执行恶意代码,违者本次实验0分处理
* 迟交规定
* `Soft Deadline` : 2022/11/07 23:59:59 (北京标准时间,UTC+8)
* `Hard Deadline` : 2022/11/14 23:59:59 (北京标准时间,UTC+8)
* 迟交需要邮件通知TA:
* 邮箱: `lq_2019@mail.ustc.edu.cn` 抄送 `edwardzcn@mail.ustc.edu.cn`
* 邮件主题: lab3迟交-学号-姓名
* 内容: 包括迟交原因、最后版本commitID、迟交时间等
* 迟交分数
* x为迟交天数(对于`Soft Deadline`而言),grade为满分
``` bash
final_grade = grade, x = 0
final_grade = grade * (0.9)^x, 0 < x <= 7
final_grade = 0, x > 7
```
* 关于抄袭和雷同
经过助教和老师判定属于实验抄袭或雷同情况,所有参与方一律零分,不接受任何解释和反驳。
如有任何问题,可以通过邮件联系助教,也欢迎在论坛提意见进行批判指正。
......@@ -10,6 +10,9 @@
* [lab2](./Documentations/2-ir-gen-warmup/)
+ DDL:2022-10-23 23:59:59 (UTC+8)
* [lab2](./Documentations/3-ir-gen/)
+ DDL:2022-11-07 23:59:59 (UTC+8)
## FAQ: How to merge upstream remote branches
In brief, you need another alias for upstream repository (we assume you are now in your local copy of forked repository on Gitlab):
......
......@@ -30,6 +30,7 @@ PB20111654 李晓奇
### assign.c
<<<<<<< HEAD
![](figures/assign.png)
### fun.c
......@@ -69,6 +70,10 @@ PB20111654 李晓奇
1->2->3->4->5->7->8->9->11->14->16->12->15->10->13->6
> 个人感觉这个过程像是根据分析树构建语法树。过程中通过val保存一次visit调用的结果,只有在涉及到翻译的节点,即加减乘除运算时才做输出。
=======
序列请按如下格式指明(序号为问题 3.1 中的编号):
3->2->5->1
>>>>>>> a27f5a5e24257d52caf0259ffdba533a4bcdf252
## 实验难点
......
# lab3 实验报告
学号 姓名
## 实验要求
## 实验难点
实验中遇到哪些挑战
## 实验设计
请写明为了顺利完成本次实验,加入了哪些亮点设计,并对这些设计进行解释。
可能的阐述方向有:
1. 如何设计全局变量
2. 遇到的难点以及解决方案
3. 如何降低生成 IR 中的冗余
4. ...
### 实验总结
此次实验有什么收获
### 实验反馈 (可选 不计入评分)
对本次实验的建议
#ifndef _CMINUSF_BUILDER_HPP_
#define _CMINUSF_BUILDER_HPP_
#include "BasicBlock.h"
#include "Constant.h"
#include "Function.h"
#include "IRBuilder.h"
#include "Module.h"
#include "Type.h"
#include "ast.hpp"
#include <map>
#include <memory>
class Scope {
public:
// enter a new scope
void enter() { inner.push_back({}); }
// exit a scope
void exit() { inner.pop_back(); }
bool in_global() { return inner.size() == 1; }
// push a name to scope
// return true if successful
// return false if this name already exits
bool push(std::string name, Value *val) {
auto result = inner[inner.size() - 1].insert({name, val});
return result.second;
}
Value *find(std::string name) {
for (auto s = inner.rbegin(); s != inner.rend(); s++) {
auto iter = s->find(name);
if (iter != s->end()) {
return iter->second;
}
}
return nullptr;
}
private:
std::vector<std::map<std::string, Value *>> inner;
};
class CminusfBuilder : public ASTVisitor {
public:
CminusfBuilder() {
module = std::unique_ptr<Module>(new Module("Cminus code"));
builder = std::make_unique<IRBuilder>(nullptr, module.get());
auto TyVoid = Type::get_void_type(module.get());
auto TyInt32 = Type::get_int32_type(module.get());
auto TyFloat = Type::get_float_type(module.get());
auto input_type = FunctionType::get(TyInt32, {});
auto input_fun = Function::create(input_type, "input", module.get());
std::vector<Type *> output_params;
output_params.push_back(TyInt32);
auto output_type = FunctionType::get(TyVoid, output_params);
auto output_fun = Function::create(output_type, "output", module.get());
std::vector<Type *> output_float_params;
output_float_params.push_back(TyFloat);
auto output_float_type = FunctionType::get(TyVoid, output_float_params);
auto output_float_fun = Function::create(output_float_type, "outputFloat", module.get());
auto neg_idx_except_type = FunctionType::get(TyVoid, {});
auto neg_idx_except_fun = Function::create(neg_idx_except_type, "neg_idx_except", module.get());
scope.enter();
scope.push("input", input_fun);
scope.push("output", output_fun);
scope.push("outputFloat", output_float_fun);
scope.push("neg_idx_except", neg_idx_except_fun);
}
std::unique_ptr<Module> getModule() { return std::move(module); }
private:
virtual void visit(ASTProgram &) override final;
virtual void visit(ASTNum &) override final;
virtual void visit(ASTVarDeclaration &) override final;
virtual void visit(ASTFunDeclaration &) override final;
virtual void visit(ASTParam &) override final;
virtual void visit(ASTCompoundStmt &) override final;
virtual void visit(ASTExpressionStmt &) override final;
virtual void visit(ASTSelectionStmt &) override final;
virtual void visit(ASTIterationStmt &) override final;
virtual void visit(ASTReturnStmt &) override final;
virtual void visit(ASTAssignExpression &) override final;
virtual void visit(ASTSimpleExpression &) override final;
virtual void visit(ASTAdditiveExpression &) override final;
virtual void visit(ASTVar &) override final;
virtual void visit(ASTTerm &) override final;
virtual void visit(ASTCall &) override final;
std::unique_ptr<IRBuilder> builder;
Scope scope;
std::unique_ptr<Module> module;
};
#endif
......@@ -2,3 +2,4 @@ add_subdirectory(parser)
add_subdirectory(common)
add_subdirectory(io)
add_subdirectory(lightir)
add_subdirectory(cminusfc)
\ No newline at end of file
add_executable(
cminusfc
cminusfc.cpp
cminusf_builder.cpp
)
target_link_libraries(
cminusfc
IR_lib
common
syntax
)
install(
TARGETS cminusfc
RUNTIME DESTINATION bin
)
/*
* 声明:本代码为 2020 秋 中国科大编译原理(李诚)课程实验参考实现。
* 请不要以任何方式,将本代码上传到可以公开访问的站点或仓库
*/
#include "cminusf_builder.hpp"
#define CONST_FP(num) ConstantFP::get((float)num, module.get())
#define CONST_INT(num) ConstantInt::get(num, module.get())
// TODO: Global Variable Declarations
// You can define global variables here
// to store state. You can expand these
// definitions if you need to.
// function that is being built
Function *cur_fun = nullptr;
// types
Type *VOID_T;
Type *INT1_T;
Type *INT32_T;
Type *INT32PTR_T;
Type *FLOAT_T;
Type *FLOATPTR_T;
/*
* use CMinusfBuilder::Scope to construct scopes
* scope.enter: enter a new scope
* scope.exit: exit current scope
* scope.push: add a new binding to current scope
* scope.find: find and return the value bound to the name
*/
void CminusfBuilder::visit(ASTProgram &node) {
VOID_T = Type::get_void_type(module.get());
INT1_T = Type::get_int1_type(module.get());
INT32_T = Type::get_int32_type(module.get());
INT32PTR_T = Type::get_int32_ptr_type(module.get());
FLOAT_T = Type::get_float_type(module.get());
FLOATPTR_T = Type::get_float_ptr_type(module.get());
for (auto decl : node.declarations) {
decl->accept(*this);
}
}
void CminusfBuilder::visit(ASTNum &node) {
//!TODO: This function is empty now.
// Add some code here.
}
void CminusfBuilder::visit(ASTVarDeclaration &node) {
//!TODO: This function is empty now.
// Add some code here.
}
void CminusfBuilder::visit(ASTFunDeclaration &node) {
FunctionType *fun_type;
Type *ret_type;
std::vector<Type *> param_types;
if (node.type == TYPE_INT)
ret_type = INT32_T;
else if (node.type == TYPE_FLOAT)
ret_type = FLOAT_T;
else
ret_type = VOID_T;
for (auto &param : node.params) {
//!TODO: Please accomplish param_types.
}
fun_type = FunctionType::get(ret_type, param_types);
auto fun = Function::create(fun_type, node.id, module.get());
scope.push(node.id, fun);
cur_fun = fun;
auto funBB = BasicBlock::create(module.get(), "entry", fun);
builder->set_insert_point(funBB);
scope.enter();
std::vector<Value *> args;
for (auto arg = fun->arg_begin(); arg != fun->arg_end(); arg++) {
args.push_back(*arg);
}
for (int i = 0; i < node.params.size(); ++i) {
//!TODO: You need to deal with params
// and store them in the scope.
}
node.compound_stmt->accept(*this);
if (builder->get_insert_block()->get_terminator() == nullptr)
{
if (cur_fun->get_return_type()->is_void_type())
builder->create_void_ret();
else if (cur_fun->get_return_type()->is_float_type())
builder->create_ret(CONST_FP(0.));
else
builder->create_ret(CONST_INT(0));
}
scope.exit();
}
void CminusfBuilder::visit(ASTParam &node) {
//!TODO: This function is empty now.
// Add some code here.
}
void CminusfBuilder::visit(ASTCompoundStmt &node) {
//!TODO: This function is not complete.
// You may need to add some code here
// to deal with complex statements.
for (auto &decl : node.local_declarations) {
decl->accept(*this);
}
for (auto &stmt : node.statement_list) {
stmt->accept(*this);
if (builder->get_insert_block()->get_terminator() != nullptr)
break;
}
}
void CminusfBuilder::visit(ASTExpressionStmt &node) {
//!TODO: This function is empty now.
// Add some code here.
}
void CminusfBuilder::visit(ASTSelectionStmt &node) {
//!TODO: This function is empty now.
// Add some code here.
}
void CminusfBuilder::visit(ASTIterationStmt &node) {
//!TODO: This function is empty now.
// Add some code here.
}
void CminusfBuilder::visit(ASTReturnStmt &node) {
if (node.expression == nullptr) {
builder->create_void_ret();
} else {
//!TODO: The given code is incomplete.
// You need to solve other return cases (e.g. return an integer).
}
}
void CminusfBuilder::visit(ASTVar &node) {
//!TODO: This function is empty now.
// Add some code here.
}
void CminusfBuilder::visit(ASTAssignExpression &node) {
//!TODO: This function is empty now.
// Add some code here.
}
void CminusfBuilder::visit(ASTSimpleExpression &node) {
//!TODO: This function is empty now.
// Add some code here.
}
void CminusfBuilder::visit(ASTAdditiveExpression &node) {
//!TODO: This function is empty now.
// Add some code here.
}
void CminusfBuilder::visit(ASTTerm &node) {
//!TODO: This function is empty now.
// Add some code here.
}
void CminusfBuilder::visit(ASTCall &node) {
//!TODO: This function is empty now.
// Add some code here.
}
#include "cminusf_builder.hpp"
#include <fstream>
#include <iostream>
#include <memory>
using namespace std::literals::string_literals;
void print_help(std::string exe_name) {
std::cout << "Usage: " << exe_name <<
" [ -h | --help ] [ -o <target-file> ] [ -emit-llvm ] <input-file>" << std::endl;
}
int main(int argc, char **argv) {
std::string target_path;
std::string input_path;
bool mem2reg = false;
bool const_propagation = false;
bool activevars = false;
bool loop_inv_hoist = false;
bool loop_search = false;
bool emit = false;
for (int i = 1; i < argc; ++i) {
if (argv[i] == "-h"s || argv[i] == "--help"s) {
print_help(argv[0]);
return 0;
} else if (argv[i] == "-o"s) {
if (target_path.empty() && i + 1 < argc) {
target_path = argv[i + 1];
i += 1;
} else {
print_help(argv[0]);
return 0;
}
} else if (argv[i] == "-emit-llvm"s) {
emit = true;
} else if (argv[i] == "-mem2reg"s) {
mem2reg = true;
} else if (argv[i] == "-loop-search"s) {
loop_search = true;
} else if (argv[i] == "-loop-inv-hoist"s) {
loop_inv_hoist = true;
} else if (argv[i] == "-const-propagation"s) {
const_propagation = true;
} else if (argv[i] == "-active-vars"s) {
activevars = true;
} else {
if (input_path.empty()) {
input_path = argv[i];
} else {
print_help(argv[0]);
return 0;
}
}
}
if (input_path.empty()) {
print_help(argv[0]);
return 0;
}
if (target_path.empty()) {
auto pos = input_path.rfind('.');
if (pos == std::string::npos) {
std::cerr << argv[0] << ": input file " << input_path << " has unknown filetype!" << std::endl;
return -1;
} else {
if (input_path.substr(pos) != ".cminus") {
std::cerr << argv[0] << ": input file " << input_path << " has unknown filetype!" << std::endl;
return -1;
}
if (emit) {
target_path = input_path.substr(0, pos);
} else {
target_path = input_path.substr(0, pos);
}
}
}
auto s = parse(input_path.c_str());
auto a = AST(s);
CminusfBuilder builder;
a.run_visitor(builder);
auto m = builder.getModule();
auto IR = m->print();
std::ofstream output_stream;
auto output_file = target_path + ".ll";
output_stream.open(output_file, std::ios::out);
output_stream << "; ModuleID = 'cminus'\n";
output_stream << "source_filename = \"" + input_path + "\"\n\n";
output_stream << IR;
output_stream.close();
if (!emit) {
std::string lib_path = argv[0];
lib_path.erase(lib_path.rfind('/')) += "/libcminus_io.a";
auto command_string = "clang -O0 -w "s + target_path + ".ll -o " + target_path + " " + lib_path;
int re_code0 = std::system(command_string.c_str());
command_string = "rm "s + target_path + ".ll";
int re_code1 = std::system(command_string.c_str());
if (re_code0 == 0 && re_code1 == 0)
return 0;
else
return 1;
}
return 0;
}
3
1
4
1
5
9
2
6
5
3
5
8
9
7
9
3
2
3
8
4
6
2
6
4
3
3
8
3
2
7
9
5
0
2
8
8
4
1
9
7
1
6
9
3
9
9
3
7
5
1
0
5
8
2
0
9
7
4
9
4
4
5
9
2
3
0
7
8
1
6
4
0
6
2
8
6
2
0
8
9
9
8
6
2
8
0
3
4
8
2
5
3
4
2
1
1
7
0
6
7
9
8
2
1
4
8
0
8
6
5
1
3
2
8
2
3
0
6
6
4
7
0
9
3
8
4
4
6
0
9
5
5
0
5
8
2
2
3
1
7
2
5
3
5
9
4
0
8
1
2
8
4
8
1
1
1
7
4
5
0
2
8
4
1
0
2
7
0
1
9
3
8
5
2
1
1
0
5
5
5
9
6
4
4
6
2
2
9
4
8
9
5
4
9
3
0
3
8
1
9
6
4
4
2
8
8
1
0
9
7
5
6
6
5
9
3
3
4
4
6
1
2
8
4
7
5
6
4
8
2
3
3
7
8
6
7
8
3
1
6
5
2
7
1
2
0
1
9
0
9
1
4
5
6
4
8
5
6
6
9
2
3
4
6
0
3
4
8
6
1
0
4
5
4
3
2
6
6
4
8
2
1
3
3
9
3
6
0
7
2
6
0
2
4
9
1
4
1
2
7
3
7
2
4
5
8
7
0
0
6
6
0
6
3
1
5
5
8
8
1
7
4
8
8
1
5
2
0
9
2
0
9
6
2
8
2
9
2
5
4
0
9
1
7
1
5
3
6
4
3
6
7
8
9
2
5
9
0
3
6
0
0
1
1
3
3
0
5
3
0
5
4
8
8
2
0
4
6
6
5
2
1
3
8
4
1
4
6
9
5
1
9
4
1
5
1
1
6
0
9
4
3
3
0
5
7
2
7
0
3
6
5
7
5
9
5
9
1
9
5
3
0
9
2
1
8
6
1
1
7
3
8
1
9
3
2
6
1
1
7
9
3
1
0
5
1
1
8
5
4
8
0
7
4
4
6
2
3
7
9
9
6
2
7
4
9
5
6
7
3
5
1
8
8
5
7
5
2
7
2
4
8
9
1
2
2
7
9
3
8
1
8
3
0
1
1
9
4
9
1
2
9
8
3
3
6
7
3
3
6
2
4
4
0
6
5
6
6
4
3
0
8
6
0
2
1
3
9
4
9
4
6
3
9
5
2
2
4
7
3
7
1
9
0
7
0
2
1
7
9
8
6
0
9
4
3
7
0
2
7
7
0
5
3
9
2
1
7
1
7
6
2
9
3
1
7
6
7
5
2
3
8
4
6
7
4
8
1
8
4
6
7
6
6
9
4
0
5
1
3
2
0
0
0
5
6
8
1
2
7
1
4
5
2
6
3
5
6
0
8
2
7
7
8
5
7
7
1
3
4
2
7
5
7
7
8
9
6
0
9
1
7
3
6
3
7
1
7
8
7
2
1
4
6
8
4
4
0
9
0
1
2
2
4
9
5
3
4
3
0
1
4
6
5
4
9
5
8
5
3
7
1
0
5
0
7
9
2
2
7
9
6
8
9
2
5
8
9
2
3
5
4
2
0
1
9
9
5
6
1
1
2
1
2
9
0
2
1
9
6
0
8
6
4
0
3
4
4
1
8
1
5
9
8
1
3
6
2
9
7
7
4
7
7
1
3
0
9
9
6
0
5
1
8
7
0
7
2
1
1
3
4
9
9
9
9
9
9
8
3
7
2
9
7
8
0
4
9
9
5
1
0
5
9
7
3
1
7
3
2
8
1
6
0
9
6
3
1
8
5
#!/usr/bin/env python3
import subprocess
# 17
lv0_1 = {
"return": (3, False),
"decl_int": (2, False),
"decl_float": (2, False),
"decl_int_array": (2, False),
"decl_float_array": (2, False),
"input": (2, True),
"output_float": (2, False),
"output_int": (2, False),
}
# 18
lv0_2 = {
"num_add_int": (0.5, False),
"num_sub_int": (0.5, False),
"num_mul_int": (0.5, False),
"num_div_int": (0.5, False),
"num_add_float": (0.5, False),
"num_sub_float": (0.5, False),
"num_mul_float": (0.5, False),
"num_div_float": (0.5, False),
"num_add_mixed": (0.5, False),
"num_sub_mixed": (0.5, False),
"num_mul_mixed": (0.5, False),
"num_div_mixed": (0.5, False),
"num_comp1": (1.5, False),
"num_le_int": (0.5, False),
"num_lt_int": (0.5, False),
"num_ge_int": (0.5, False),
"num_gt_int": (0.5, False),
"num_eq_int": (0.5, False),
"num_neq_int": (0.5, False),
"num_le_float": (0.5, False),
"num_lt_float": (0.5, False),
"num_ge_float": (0.5, False),
"num_gt_float": (0.5, False),
"num_eq_float": (0.5, False),
"num_neq_float": (0.5, False),
"num_le_mixed": (0.5, False),
"num_lt_mixed": (0.5, False),
"num_ge_mixed": (0.5, False),
"num_gt_mixed": (0.5, False),
"num_eq_mixed": (0.5, False),
"num_neq_mixed": (0.5, False),
"num_comp2": (1.5, False),
}
# 31
lv1 = {
"assign_int_var_local": (1, False),
"assign_int_array_local": (2, False),
"assign_int_var_global": (1, False),
"assign_int_array_global": (2, False),
"assign_float_var_local": (1, False),
"assign_float_array_local": (2, False),
"assign_float_var_global": (1, False),
"assign_float_array_global": (2, False),
"assign_cmp": (1, False),
"innout": (1, True),
"idx_float": (1, False),
"negidx_int": (1, False),
"negidx_float": (1, False),
"negidx_intfuncall": (1, False),
"negidx_floatfuncall": (1, False),
"negidx_voidfuncall": (1, False),
"selection1": (1.5, False),
"selection2": (1.5, False),
"selection3": (1.5, False),
"iteration1": (1.5, False),
"iteration2": (1.5, False),
"scope": (1.5, False),
"transfer_float_to_int": (1, False),
"transfer_int_to_float": (1, False),
}
# 23
lv2 = {
"funcall_chain": (2, False),
"assign_chain": (2, False),
"funcall_var": (2, False),
"funcall_int_array": (2, False),
"funcall_float_array": (2, False),
"funcall_array_array": (2, False),
"return_in_middle1": (2, False),
"return_in_middle2": (2, False),
"funcall_type_mismatch1": (2, False),
"funcall_type_mismatch2": (2, False),
"return_type_mismatch1": (1.5, False),
"return_type_mismatch2": (1.5, False),
}
# 11
lv3 = {
"complex1": (3, False),
"complex2": (3, True),
"complex3": (2, True),
"complex4": (3, False),
}
suite = [
("lv0_1", lv0_1, 0),
("lv0_2", lv0_2, 0),
("lv1", lv1, 0),
("lv2", lv2, 0),
("lv3", lv3, 0)
]
def eval():
f = open("eval_result", 'w')
EXE_PATH = "../../build/cminusfc"
TEST_BASE_PATH = "./testcases/"
ANSWER_BASE_PATH = "./answers/"
total_points = 0
for level in suite:
lv_points = 0
has_bonus = True
level_name = level[0]
bonus = level[2]
cases = level[1]
f.write('===========%s START========\n' % level_name)
for case in cases:
f.write('%s:' % case)
TEST_PATH = TEST_BASE_PATH + level_name + "/" + case
ANSWER_PATH = ANSWER_BASE_PATH + level_name + "/" + case
score = cases[case][0]
need_input = cases[case][1]
COMMAND = [TEST_PATH]
try:
result = subprocess.run([EXE_PATH, TEST_PATH + ".cminus"], stderr=subprocess.PIPE, timeout=1)
except Exception as _:
f.write('\tFail\n')
continue
if result.returncode == 0:
input_option = None
if need_input:
with open(ANSWER_PATH + ".in", "rb") as fin:
input_option = fin.read()
try:
result = subprocess.run(COMMAND, input=input_option, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=1)
with open(ANSWER_PATH + ".out", "rb") as fout:
if result.stdout == fout.read():
f.write('\tSuccess\n')
lv_points += score
else:
f.write('\tFail\n')
has_bonus = False
except Exception as _:
f.write('\tFail\n')
has_bonus = False
finally:
subprocess.call(["rm", "-rf", TEST_PATH, TEST_PATH + ".o"])
else:
f.write('\tFail\n')
has_bonus = False
if has_bonus:
lv_points += bonus
total_points += lv_points
f.write('points of %s is: %d\n' % (level_name, lv_points))
f.write('===========%s END========\n\n' % level_name)
f.write('total points: %d\n' % total_points)
if __name__ == "__main__":
eval()
void main(void) {
float a;
return;
}
void main(void) {
float a[10];
return;
}
void main(void) {
int a;
return;
}
void main(void) {
int a[10];
return;
}
void main(void) {
input();
return;
}
void main(void) {
outputFloat(123.4);
return;
}
void main(void) {
output(1234);
return;
}
void main(void) {
output(100.0 + 23.4);
return;
}
void main(void) {
output(1000 + 234);
return;
}
void main(void) {
output(1000 + 23.4);
return;
}
void main(void) {
outputFloat(9 + 1.2 / (2 * 2 + 5 - 6) * 3.2 - 55);
return;
}
void main(void) {
output((1 > 2.) < 3);
output((1 > 2) < ((3 == 4) >= 0));
output(((3 == 4.) >= 0) <= (4 != 4));
output(((1 > 2) < ((3 == 4) >= 0)) <= (4. != 4));
return;
}
void main(void) {
output(24.68 / 2.);
return;
}
void main(void) {
output(2468 / 2);
return;
}
void main(void) {
output(24.68 / 2);
return;
}
void main(void) {
output(1. == 2.);
output(2. == 2.);
output(3. == 2.);
return;
}
void main(void) {
output(1 == 2);
output(2 == 2);
output(3 == 2);
return;
}
void main(void) {
output(1. == 2);
output(2. == 2);
output(3 == 2.);
return;
}
void main(void) {
output(1. >= 2.);
output(2. >= 2.);
output(3. >= 2.);
return;
}
void main(void) {
output(1 >= 2);
output(2 >= 2);
output(3 >= 2);
return;
}
void main(void) {
output(1. >= 2);
output(2. >= 2);
output(3 >= 2.);
return;
}
void main(void) {
output(1. > 2.);
output(2. > 2.);
output(3. > 2.);
return;
}
void main(void) {
output(1 > 2);
output(2 > 2);
output(3 > 2);
return;
}
void main(void) {
output(1. > 2);
output(2. > 2);
output(3 > 2.);
return;
}
void main(void) {
output(1. <= 2.);
output(2. <= 2.);
output(3. <= 2.);
return;
}
void main(void) {
output(1 <= 2);
output(2 <= 2);
output(3 <= 2);
return;
}
void main(void) {
output(1. <= 2);
output(2. <= 2);
output(3 <= 2.);
return;
}
void main(void) {
output(1. < 2.);
output(2. < 2.);
output(3. < 2.);
return;
}
void main(void) {
output(1 < 2);
output(2 < 2);
output(3 < 2);
return;
}
void main(void) {
output(1. < 2);
output(2 < 2.);
output(3. < 2);
return;
}
void main(void) {
output(2. * 61.7);
return;
}
void main(void) {
output(2 * 617);
return;
}
void main(void) {
output(2 * 61.7);
return;
}
void main(void) {
output(1. != 2.);
output(2. != 2.);
output(3. != 2.);
return;
}
void main(void) {
output(1 != 2);
output(2 != 2);
output(3 != 2);
return;
}
void main(void) {
output(1. != 2);
output(2 != 2.);
output(3 != 2.);
return;
}
void main(void) {
output(200.0 - 7.66);
return;
}
void main(void) {
output(2000 - 766);
return;
}
void main(void) {
output(2000 - 76.6);
return;
}
void main(void) {
int a;
int b;
int c;
a = 1 < 3;
b = 2 == 4;
c = 3 > 5;
output(a);
output(b);
output(c);
return;
}
float b[10];
void main(void) {
b[3] = 1234.0;
outputFloat(b[3]);
return;
}
void main(void) {
float b[10];
b[3] = 1234.0;
outputFloat(b[3]);
return;
}
float b;
void main(void) {
b = 1234.0;
outputFloat(b);
return;
}
void main(void) {
float b;
b = 1234.0;
outputFloat(b);
return;
}
int a[10];
void main(void) {
a[3] = 1234;
output(a[3]);
return;
}
void main(void) {
int a[10];
a[3] = 1234;
output(a[3]);
return;
}
int a;
void main(void) {
a = 1234;
output(a);
return;
}
void main(void) {
int a;
a = 1234;
output(a);
return;
}
void main(void) {
int a[10];
a[0] = 1024;
output(a[0.1]);
return;
}
void main(void) {
int a;
a = input();
output(a);
return;
}
void main(void) {
int i;
i = 10;
while (i) {
output(i);
i = i - 1;
}
return;
}
void main(void) {
int i;
i = 10;
while (i > 0) {
output(i);
i = i - 1;
}
return;
}
void main(void) {
int a[10];
a[2.-3];
return;
}
float test(void) {
int a[10];
a[2-3];
return 2.;
}
void main(void) {
test();
return;
}
void main(void) {
int a[10];
a[2-3];
return;
}
int test(void) {
int a[10];
a[2-3];
return 2;
}
void main(void) {
test();
return;
}
void test(void) {
int a[10];
a[2-3];
return;
}
void main(void) {
test();
return;
}
void main(void) {
int a;
a = 3;
output(a);
{
int a;
a = 11;
output(a);
}
output(a);
return;
}
void main(void) {
int a;
a = 2;
if (a)
output(42);
output(24);
return;
}
void main(void) {
if (2 > 1)
output(42);
output(24);
if (1 > 2) {
output (1234);
}
return;
}
void main(void) {
if (2 > 1) {
output(42);
} else
output(1234);
output(24);
if (2 < 1)
output(42);
else {
output(1234);
}
return;
}
void main(void){
int a;
a = 1.0;
output(a);
return;
}
void main(void){
float a;
a = 1;
outputFloat(a);
return;
}
void main(void) {
int a;
int b;
int c;
a = b = c = 3;
output(a);
output(b);
output(c);
return;
}
void g(int b[]) {
output(b[3]);
return;
}
void f(int c[]) {
output(c[3]);
g(c);
return;
}
void main(void) {
int a[10];
a[3] = 1024;
f(a);
return;
}
int addone(int a) {
return a + 1;
}
void main(void) {
int result;
result = addone(addone(addone(addone(1230))));
output(result);
return;
}
void test(float a[]) {
output(a[3]);
return;
}
void main(void) {
float a[10];
a[3] = 3.14;
test(a);
return;
}
void test(int a[]) {
output(a[3]);
return;
}
void main(void) {
int a[10];
a[3] = 10;
test(a);
return;
}
void f(int a) {
output(a);
return;
}
void main(void) {
float a;
a = 10;
f(a);
return;
}
void f(float a) {
outputFloat(a);
return;
}
void main(void) {
int a;
a = 4.5;
f(a);
return;
}
void test(int a) {
output(a);
return;
}
void main(void) {
int a;
a = 10;
test(a);
return;
}
int result(void){
int i;
if (1) {
i = 1;
return 0;
} else {
i = 2;
}
output(3);
return 3;
}
void main(void) {
output(result());
return;
}
int result(void){
int i;
i = 10;
while (i > 0) {
return 0;
}
output(4);
return 1;
}
void main(void) {
output(result());
return;
}
int f(void) {
return 233.3;
}
void main(void) {
output(f());
return;
}
float f(void) {
return 7;
}
void main(void) {
outputFloat(f());
return;
}
/*
This code is adopted from Dik T. Winter at CWI
It computes pi to 800 decimal digits
*/
int mod(int a, int b) {
return a - a / b * b;
}
void printfour(int input) {
int a;
int b;
int c;
int d;
input = mod(input, 10000);
d = mod(input, 10);
input = input / 10;
c = mod(input, 10);
input = input / 10;
b = mod(input, 10);
input = input / 10;
a = input;
output(a);
output(b);
output(c);
output(d);
return;
}
void main(void) {
int r[2801];
int i;
int k;
int b;
int d;
int c;
c = 0;
d = 1234;
{
int mod;
mod = 0;
while (mod < 2800) {
r[mod] = 2000;
mod = mod + 1;
}
}
k = 2800;
while (k) {
int d;
d = 0;
i = k;
while (i != 0) {
d = d + r[i] * 10000;
b = 2 * i - 1;
r[i] = mod(d, b);
d = d / b;
i = i - 1;
if (i != 0) {
d = d * i;
}
}
printfour(c + d / 10000);
c = mod(d, 10000);
k = k - 14;
}
return;
}
/* this is the sample program in C- in the book "Compiler Construction" */
/* A program to perform selection sort on a 10 element array. */
float x[10];
int minloc (float a[], float low, int high )
{
int i;
int x;
int k;
k = low;
x = a[low];
i = low + 1;
while (i < high) {
if (a[i] < x) {
x = a[i];
k = i;
}
i = i + 1;
}
return k;
}
void sort(float a[], int low, float high)
{
int i;
int k;
i = low;
while (i < high - 1)
{
int t;
k = minloc(a, i, high);
t = a[k];
a[k] = a[i];
a[i] = t;
i = i + 1;
}
return;
}
void main(void)
{
int i;
i = 0;
while ( i < 10) {
x[i] = input();
i = i + 1;
}
sort(x, 0, 10);
i = 0;
while (i < 10) {
output(x[i]);
i = i + 1;
}
return;
}
int gcd (int u, int v) {
if (v == 0) return u;
else return gcd(v, u - u / v * v);
}
void main(void) {
int x;
int y;
int temp;
x = input();
y = input();
if (x < y) {
temp = x;
x = y;
y = temp;
}
temp = gcd(x, y);
output(temp);
return;
}
float get(float a[], int x, int y, int row) {
return a[x * row + y];
}
float abs(float x) {
if (x > 0)
return x;
else
return 0 - x;
}
float isZero(float t) {
return abs(t) < 0.000001;
}
int gauss(float vars[], float equ[], int var) {
int i;
int j;
int k;
int varone;
int maxr;
int col;
float temp;
varone = var + 1;
i = 0;
while (i < var) {
vars[i] = 0;
i = i + 1;
}
col = 0;
k = 0;
while (k < var) {
maxr = k;
i = k + 1;
while (i < var) {
if (abs(get(equ, i, col, varone)) > abs(get(equ, maxr, col, varone)))
maxr = i;
i = i + 1;
}
if (maxr != k) {
j = k;
while (j < varone) {
temp = get(equ, k, j, varone);
equ[k * varone + j] = get(equ, maxr, j, varone);
equ[maxr * varone + j] = temp;
j = j + 1;
}
}
if (isZero(get(equ, k, col, varone))) {
k = k - 1;
} else {
i = k + 1;
while (i < var) {
if (1 - isZero(get(equ, i, col, varone))) {
temp = get(equ, i, col, varone) / get(equ, k, col, varone);
j = col;
while (j < varone) {
equ[i * varone + j] = equ[i * varone + j] - get(equ, k, j, varone) * temp;
j = j + 1;
}
}
i = i + 1;
}
}
k = k + 1;
col = col + 1;
}
i = var - 1;
while (i >= 0) {
temp = get(equ, i, var, varone);
j = i + 1;
while (j < var) {
if (1 - isZero(get(equ, i, j, varone)))
temp = temp - get(equ, i, j, varone) * vars[j];
j = j + 1;
}
vars[i] = temp / get(equ, i, i, varone);
i = i - 1;
}
return 0;
}
void main(void) {
int num;
float vars[3];
float equ[12];
equ[0] = 1; equ[1] = 2; equ[2] = 1; equ[3] = 1;
equ[1 * 4 + 0] = 2; equ[1 * 4 + 1] = 3; equ[1 * 4 + 2] = 4; equ[1 * 4 + 3] = 3;
equ[2 * 4 + 0] = 1; equ[2 * 4 + 1] = 1; equ[2 * 4 + 2] = 0 - 2; equ[2 * 4 + 3] = 0;
gauss(vars, equ, 3);
num = 0;
while (num < 3) {
outputFloat(vars[num]);
num = num + 1;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment