Commit 793fd3dd authored by lxq's avatar lxq

beginning for stack allocation

parent 40437b6e
# Lab5 实验文档 # Lab5 实验文档
- [Lab5 实验文档](#lab5-实验文档) - [Lab5 实验文档](#lab5-实验文档)
- [0. 前言](#0-前言) - [0. 前言](#0-前言)
- [主要工作](#主要工作) - [主要工作](#主要工作)
- [1. 实验框架](#1-实验框架) - [1. 实验框架](#1-实验框架)
- [2. 实验内容](#2-实验内容) - [2. 实验内容](#2-实验内容)
- [阅读龙芯的文档](#阅读龙芯的文档) - [阅读龙芯的文档](#阅读龙芯的文档)
- [完成代码](#完成代码) - [完成代码](#完成代码)
- [3. 运行与调试](#3-运行与调试) - [3. 运行与调试](#3-运行与调试)
- [龙芯服务器的登录](#龙芯服务器的登录) - [龙芯服务器的登录](#龙芯服务器的登录)
- [汇编代码的生成](#汇编代码的生成) - [汇编代码的生成](#汇编代码的生成)
- [调试生成的汇编](#调试生成的汇编) - [调试生成的汇编](#调试生成的汇编)
- [测试](#测试) - [测试](#测试)
- [4. 提交](#4-提交) - [4. 提交](#4-提交)
- [目录结构](#目录结构) - [目录结构](#目录结构)
- [提交要求、评分标准](#提交要求评分标准) - [提交要求、评分标准](#提交要求评分标准)
- [附录:栈分配策略](#附录栈分配策略) - [附录:栈分配策略](#附录栈分配策略)
- [示例 1:计算加法并输出](#示例-1计算加法并输出) - [示例 1:计算加法并输出](#示例-1计算加法并输出)
- [示例 2:调用函数访问数组](#示例-2调用函数访问数组) - [示例 2:调用函数访问数组](#示例-2调用函数访问数组)
## 0. 前言 ## 0. 前言
...@@ -31,7 +30,6 @@ ...@@ -31,7 +30,6 @@
3. 进行寄存器分配,优化性能(选做)。 3. 进行寄存器分配,优化性能(选做)。
4. 工作总结及功能汇报展示。 4. 工作总结及功能汇报展示。
## 1. 实验框架 ## 1. 实验框架
需要在现有框架的基础上,添加 `codegen` 模块,实现 IR 到汇编的转换;如果要优化性能,可以添加寄存器分配的模块。 需要在现有框架的基础上,添加 `codegen` 模块,实现 IR 到汇编的转换;如果要优化性能,可以添加寄存器分配的模块。
...@@ -50,7 +48,6 @@ ...@@ -50,7 +48,6 @@
> 可以写一段 C 语言代码,在龙芯上用 `gcc -S` 生成汇编代码,观察汇编代码,思考如何实现。 > 可以写一段 C 语言代码,在龙芯上用 `gcc -S` 生成汇编代码,观察汇编代码,思考如何实现。
### 完成代码 ### 完成代码
可以先使用[栈分配策略](#附录栈分配策略)存储变量,优先追求代码生成的完成度。 可以先使用[栈分配策略](#附录栈分配策略)存储变量,优先追求代码生成的完成度。
...@@ -61,20 +58,18 @@ ...@@ -61,20 +58,18 @@
评测、答辩将会考虑以下两个方面: 评测、答辩将会考虑以下两个方面:
1. 代码生成的完成度(允许自由选择和组合): 1. 代码生成的完成度(允许自由选择和组合):
+ 单个 main 函数的代码的汇编代码生成,主要包括算术指令、调用 `output` 函数,正常返回。 + 单个 main 函数的代码的汇编代码生成,主要包括算术指令、调用 `output` 函数,正常返回。
+ 单个 main 函数的代码的汇编代码生成,包括比较和跳转指令、局部数组访问。 + 单个 main 函数的代码的汇编代码生成,包括比较和跳转指令、局部数组访问。
+ 多个函数的代码的汇编代码生成,包括函数调用、返回。 + 多个函数的代码的汇编代码生成,包括函数调用、返回。
+ 支持浮点数、全局变量等高级类型 + 支持浮点数、全局变量等高级类型
> 允许自由拓展 > 允许自由拓展
2. 是否完成寄存器分配: 2. 是否完成寄存器分配:
+ 不进行专门的寄存器分配算法(图着色、线性分配等),所有变量都存储在栈上(详见[附录](#附录栈分配策略))。 + 不进行专门的寄存器分配算法(图着色、线性分配等),所有变量都存储在栈上(详见[附录](#附录栈分配策略))。
+ 完成专门的寄存器分配算法 + 完成专门的寄存器分配算法
## 3. 运行与调试 ## 3. 运行与调试
...@@ -82,7 +77,6 @@ ...@@ -82,7 +77,6 @@
根据助教提供的账号,密码,采用 ssh 登录龙芯机器。 根据助教提供的账号,密码,采用 ssh 登录龙芯机器。
### 汇编代码的生成 ### 汇编代码的生成
编译过程: 编译过程:
...@@ -122,6 +116,7 @@ gdb test ...@@ -122,6 +116,7 @@ gdb test
``` ```
> gdb 常用命令: > gdb 常用命令:
>
> ``` > ```
> b 20 # 在第 20 行设置断点 > b 20 # 在第 20 行设置断点
> r # 运行程序 > r # 运行程序
...@@ -141,7 +136,6 @@ gdb test ...@@ -141,7 +136,6 @@ gdb test
评测脚本的使用说明见 [评测脚本.md](评测脚本.md) 评测脚本的使用说明见 [评测脚本.md](评测脚本.md)
## 4. 提交 ## 4. 提交
### 目录结构 ### 目录结构
...@@ -177,33 +171,31 @@ gdb test ...@@ -177,33 +171,31 @@ gdb test
如果需要,可以添加新的文件,或者修改已有文件。 如果需要,可以添加新的文件,或者修改已有文件。
### 提交要求、评分标准 ### 提交要求、评分标准
- 提交要求: - 提交要求:
需要提交实验代码、实验报告。答辩时间待定 需要提交实验代码、实验报告。答辩时间待定
- 提交方式: - 提交方式:
- 代码提交:在希冀课程平台上发布的作业中填写 GitLab 链接。 - 代码提交:在希冀课程平台上发布的作业中填写 GitLab 链接。
如果遇到在平台上提交异常的问题,请通过邮件联系助教,助教将收取截止日期之前,学生在 gitlab 仓库最近一次 commit 内容进行评测。 如果遇到在平台上提交异常的问题,请通过邮件联系助教,助教将收取截止日期之前,学生在 gitlab 仓库最近一次 commit 内容进行评测。
- 报告提交:`将 Reports/5/report.md` 导出成 pdf 文件 - 报告提交:`将 Reports/5/report.md` 导出成 pdf 文件
- 截止时间: - 截止时间:
2023 年 3 月初,具体时间待定 2023 年 3 月初,具体时间待定
- 评分标准: - 评分标准:
- 实验分数组成如下:
测试用例的通过情况 - 实验分数组成如下:
实验报告 测试用例的通过情况
答辩情况 实验报告
- 禁止执行恶意代码,违者本次实验0分处理 答辩情况
- 禁止执行恶意代码,违者本次实验0分处理
- 关于抄袭和雷同 - 关于抄袭和雷同
经过助教和老师判定属于实验抄袭或雷同情况,所有参与方一律零分,不接受任何解释和反驳。 经过助教和老师判定属于实验抄袭或雷同情况,所有参与方一律零分,不接受任何解释和反驳。
如有任何问题,可以通过邮件联系助教。 如有任何问题,可以通过邮件联系助教。
## 附录:栈分配策略 ## 附录:栈分配策略
主要思想是: 主要思想是:
...@@ -268,7 +260,6 @@ main: ...@@ -268,7 +260,6 @@ main:
在程序设置返回值之后,恢复返回地址、帧指针、栈指针的寄存器前,设置断点,可以观察到栈中的变量值: 在程序设置返回值之后,恢复返回地址、帧指针、栈指针的寄存器前,设置断点,可以观察到栈中的变量值:
> 地址以 4 字节为单位 > 地址以 4 字节为单位
``` ```
...@@ -352,7 +343,6 @@ main: ...@@ -352,7 +343,6 @@ main:
jr $ra # 跳转到返回地址 jr $ra # 跳转到返回地址
``` ```
在执行完 store 函数中的 `stptr` 后,恢复帧指针和栈指针前,栈的情况如下: 在执行完 store 函数中的 `stptr` 后,恢复帧指针和栈指针前,栈的情况如下:
> 地址以 8 字节为单位 > 地址以 8 字节为单位
......
#ifndef CODEGEN_HPP #ifndef CODEGEN_HPP
#define CODEGEN_HPP #define CODEGEN_HPP
#include "Function.h"
#include "Instruction.h"
#include "Module.h" #include "Module.h"
#include "Value.h"
#include "logging.hpp" #include "logging.hpp"
#include <map>
#define STACK_ALIGN(x) (((x / 16) + (x % 16 ? 1 : 0)) * 16)
using std::map;
using std::string; using std::string;
using std::vector; using std::vector;
...@@ -24,6 +32,70 @@ class CodeGen { ...@@ -24,6 +32,70 @@ class CodeGen {
void run(); void run();
private: private:
void IR2assem(Instruction &);
void IR2assem(ReturnInst *);
void IR2assem(LoadInst *);
void IR2assem(StoreInst *);
void IR2assem(BranchInst *) {}
void IR2assem(BinaryInst *) {}
void IR2assem(AllocaInst *) {}
void IR2assem(PhiInst *) {}
void IR2assem(CallInst *) {}
void IR2assem(GetElementPtrInst *);
void IR2assem(ZextInst *) {}
void IR2assem(FpToSiInst *) {}
void IR2assem(SiToFpInst *) {}
void stackMemAlloc();
void stackMemDealloc();
// load value `opk` to the specified register
// - for constant number, just load into reg
// - for global variables and pointers from alloca and GEP, read through
// address
// only use register a_id and t_
void value2reg(Value *, int id = 0);
// load the content in ptr to specified register.
// only use register a_id and t_
void ptrContent2reg(Value *, int id = 0);
int typeLen(Type *type) {
if (type->is_float_type())
return 4;
else if (type->is_integer_type()) {
if (static_cast<IntegerType *>(type)->get_num_bits() == 32)
return 4;
else
return 1;
} else if (type->is_pointer_type())
return 8;
else if (type->is_array_type()) {
auto arr_tp = static_cast<ArrayType *>(type);
int n = arr_tp->get_num_of_elements();
return n * typeLen(arr_tp->get_element_type());
} else
assert(false && "unexpected case while computing type-length");
}
string suffix(int len) {
switch (len) {
case 1:
return ".b";
case 2:
return ".h";
case 4:
return ".w";
case 8:
return ".d";
}
assert(false && "no such suffix");
}
std::map<Value *, unsigned int> off;
unsigned int N;
Function *cur_func;
Module *m; Module *m;
vector<string> output; vector<string> output;
}; };
......
This diff is collapsed.
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