Commit 793fd3dd authored by lxq's avatar lxq

beginning for stack allocation

parent 40437b6e
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
- [示例 1:计算加法并输出](#示例-1计算加法并输出) - [示例 1:计算加法并输出](#示例-1计算加法并输出)
- [示例 2:调用函数访问数组](#示例-2调用函数访问数组) - [示例 2:调用函数访问数组](#示例-2调用函数访问数组)
## 0. 前言 ## 0. 前言
经过前四个Lab,我们的cminus compiler已经可以生成有效的llvm IR。Lab5实验目的,需要你根据 IR 生成龙芯LA64架构下的可正常运行的汇编代码。 经过前四个Lab,我们的cminus compiler已经可以生成有效的llvm IR。Lab5实验目的,需要你根据 IR 生成龙芯LA64架构下的可正常运行的汇编代码。
...@@ -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` 生成汇编代码,观察汇编代码,思考如何实现。
### 完成代码 ### 完成代码
可以先使用[栈分配策略](#附录栈分配策略)存储变量,优先追求代码生成的完成度。 可以先使用[栈分配策略](#附录栈分配策略)存储变量,优先追求代码生成的完成度。
...@@ -74,15 +71,12 @@ ...@@ -74,15 +71,12 @@
+ 不进行专门的寄存器分配算法(图着色、线性分配等),所有变量都存储在栈上(详见[附录](#附录栈分配策略))。 + 不进行专门的寄存器分配算法(图着色、线性分配等),所有变量都存储在栈上(详见[附录](#附录栈分配策略))。
+ 完成专门的寄存器分配算法 + 完成专门的寄存器分配算法
## 3. 运行与调试 ## 3. 运行与调试
### 龙芯服务器的登录 ### 龙芯服务器的登录
根据助教提供的账号,密码,采用 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,7 +171,6 @@ gdb test ...@@ -177,7 +171,6 @@ gdb test
如果需要,可以添加新的文件,或者修改已有文件。 如果需要,可以添加新的文件,或者修改已有文件。
### 提交要求、评分标准 ### 提交要求、评分标准
- 提交要求: - 提交要求:
...@@ -191,6 +184,7 @@ gdb test ...@@ -191,6 +184,7 @@ gdb test
2023 年 3 月初,具体时间待定 2023 年 3 月初,具体时间待定
- 评分标准: - 评分标准:
- 实验分数组成如下: - 实验分数组成如下:
测试用例的通过情况 测试用例的通过情况
实验报告 实验报告
...@@ -202,8 +196,6 @@ gdb test ...@@ -202,8 +196,6 @@ gdb test
如有任何问题,可以通过邮件联系助教。 如有任何问题,可以通过邮件联系助教。
## 附录:栈分配策略 ## 附录:栈分配策略
主要思想是: 主要思想是:
...@@ -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