Commit 793fd3dd authored by lxq's avatar lxq

beginning for stack allocation

parent 40437b6e
......@@ -19,7 +19,6 @@
- [示例 1:计算加法并输出](#示例-1计算加法并输出)
- [示例 2:调用函数访问数组](#示例-2调用函数访问数组)
## 0. 前言
经过前四个Lab,我们的cminus compiler已经可以生成有效的llvm IR。Lab5实验目的,需要你根据 IR 生成龙芯LA64架构下的可正常运行的汇编代码。
......@@ -31,7 +30,6 @@
3. 进行寄存器分配,优化性能(选做)。
4. 工作总结及功能汇报展示。
## 1. 实验框架
需要在现有框架的基础上,添加 `codegen` 模块,实现 IR 到汇编的转换;如果要优化性能,可以添加寄存器分配的模块。
......@@ -50,7 +48,6 @@
> 可以写一段 C 语言代码,在龙芯上用 `gcc -S` 生成汇编代码,观察汇编代码,思考如何实现。
### 完成代码
可以先使用[栈分配策略](#附录栈分配策略)存储变量,优先追求代码生成的完成度。
......@@ -74,15 +71,12 @@
+ 不进行专门的寄存器分配算法(图着色、线性分配等),所有变量都存储在栈上(详见[附录](#附录栈分配策略))。
+ 完成专门的寄存器分配算法
## 3. 运行与调试
### 龙芯服务器的登录
根据助教提供的账号,密码,采用 ssh 登录龙芯机器。
### 汇编代码的生成
编译过程:
......@@ -122,6 +116,7 @@ gdb test
```
> gdb 常用命令:
>
> ```
> b 20 # 在第 20 行设置断点
> r # 运行程序
......@@ -141,7 +136,6 @@ gdb test
评测脚本的使用说明见 [评测脚本.md](评测脚本.md)
## 4. 提交
### 目录结构
......@@ -177,7 +171,6 @@ gdb test
如果需要,可以添加新的文件,或者修改已有文件。
### 提交要求、评分标准
- 提交要求:
......@@ -191,6 +184,7 @@ gdb test
2023 年 3 月初,具体时间待定
- 评分标准:
- 实验分数组成如下:
测试用例的通过情况
实验报告
......@@ -202,8 +196,6 @@ gdb test
如有任何问题,可以通过邮件联系助教。
## 附录:栈分配策略
主要思想是:
......@@ -268,7 +260,6 @@ main:
在程序设置返回值之后,恢复返回地址、帧指针、栈指针的寄存器前,设置断点,可以观察到栈中的变量值:
> 地址以 4 字节为单位
```
......@@ -352,7 +343,6 @@ main:
jr $ra # 跳转到返回地址
```
在执行完 store 函数中的 `stptr` 后,恢复帧指针和栈指针前,栈的情况如下:
> 地址以 8 字节为单位
......
#ifndef CODEGEN_HPP
#define CODEGEN_HPP
#include "Function.h"
#include "Instruction.h"
#include "Module.h"
#include "Value.h"
#include "logging.hpp"
#include <map>
#define STACK_ALIGN(x) (((x / 16) + (x % 16 ? 1 : 0)) * 16)
using std::map;
using std::string;
using std::vector;
......@@ -24,6 +32,70 @@ class CodeGen {
void run();
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;
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