开发日志(自用)
lab2
250409
目前的问题是函数参数的 checker 忘记支持数组了,然后需要检查 parser 里函数参数是怎么构建结点的,checker 该怎么识别一个参数是不是数组
难崩,发现 parser 函数参数直接忽略数组维度了,得改一下函数参数的结点类
250410
- 已解决函数参数问题,新问题:函数名与变量名一致是否合法
- 靠北,if 和 while 的是 stmt,不是 block,我裂开,我居然直接转化为 block
[!WARNING]
之前 lab1 的测试点是怎么过的????是不是可以增加这个地方的测试点
- 已解决 if、while 的 stmt 当成 block 问题
- 已解决 initval 不支持二元 binaryexp、funccall 问题
- 已解决 bardef 不支持局部变量覆盖外部同名变量问题
[!CAUTION]
新问题:lab2 的 arr_defn4 第二个数组
- 已解决 FuncFParam 类的 no first index 初始化没实例化 dimdef 的问题
- 已解决 checkInitVal 未支持负数 unaryexp 的问题
- 已解决 checkFuncDef 因在检查 block 后才将函数插入符号表导致无法递归的问题
- 已解决数组初始化时对右值的类型检查不全面且过于繁杂的问题
- 已解决 recArrayInit 在 InitVal 每层返回填充 0 时忘记 filled_size 还要先减去 inner_filled_size 的问题
至此 lab2 测试点全部通过,等待实验报告撰写
lab3
250410
- 更正 log.md 中把日期记成 24 年的错误
250415
- 选择 zero-IR,合并模板,确定待完成事项:
- [x]
src/ir/ir.hpp
根据 AST 情况补充 IRtree 结点(参考实验文档 IR 定义表格)
- [x]
ir/ir_translator.hpp
完成IRTranslator
类及其方法,类似typechecker
- [x]
analysis/control_flow.hpp
为了支持全局变量,需要在 Module 类中添加一个成员变量来存储全局变量的信息
- [x]
analysis/cfg_builder.cpp
目前仅完成了合并RETURN
语句的功能,且还未对函数进行基本块划分,在build_single_func
中实现基本块划分
250417
- 已完成 IRtree 结点补充
250418
- 已完成除 vardef,lval 之外的 translate
250419
- 已完成 vardef,lval 的 translate 函数
- 已排除 ir_translator 相关的编译错误,成功编译
已解决 vardef,lval 的 translate 函数因 lab2 的符号表全局变量的 scope 值应是-1 而非 0 导致的错误识别全局变量问题- 随便检查了几个程序生成的中间代码都是正确的,但是全都没跑过测试
- 已实现基本块划分,但未完成基于此的优化
- 已解决
translateFuncCall
翻译时用了PARAM
传参的问题 - 已解决
translateVarDef
未初始化时忘记考虑数组的问题 - 已解决
translateAssignStmt
未分类考虑数组、全局变量,而是直接翻译 Lval 然后直接将 place 当左值的问题 - 已解决
Dec
打印时忘记给 size 数值前面加#
的问题 translateLVal
未考虑左值数组下标可以是左值的问题- 左值数组下标是左值时其 AST 结点丢失 symbol
250421
- 已解决左值数组下标是左值时其 AST 结点丢失 symbol 的问题,系
checkLValDims
函数未实现 - 已解决 Store 语句若无地址偏移不应有括号的问题
- 已解决 Deref 语句若无地址偏移不应有括号的问题
- 已解决
build_single_func
修改后 main 函数消失的问题,系每次 push 的是 curr_block 的地址而非实例,导致所有 block 都是 curr_block 最后更新后的内容 - 已解决
get_array_offset
未初始化offset
的问题 - 已解决翻译函数定义时没有 Param 的问题,系忘记给
AST::FuncFParam
类设置 symbol,进而在checkFuncDef
中未将函数形参符号挂载到语法树中,最终在translateFuncDef
直接忘记翻译 Param - 已解决
translateWhileStmt
因未设置退出逻辑导致的 while 死循环问题 - 已解决
translateIfStmt
因未设置跳转至 else block 的逻辑导致的 then block 必被执行的问题 - 已解决
translateVarDef
中处理数组初始化时忘记给地址偏移乘 4 的问题 - 已解决
translateInitVal
未正常返回数组元素的问题recArrayInit
和checkArrayInit
中新增处理std::vector<AST::NodePtr> final_array_nodes;
的逻辑,该变量将线性存储数组初始化语句右值的结点,并且会填充0
AST::VarDef
添加std::vector<AST::NodePtr> init_nodes;
,挂载final_array_nodes
,方便翻译时直接用- 删除
translateInitVal
- 已解决
translateLVal
无法区分数组地址和数组值的问题- 在
class LVal;
中新增TypePtr type;
- 在
checkLVal
中存储左值本身的类型,而非只有其符号的类型
- 在
- 已解决
checkInitVal
未进一步检查表达式的问题checkInitVal
直接删了,我是傻逼,用check
即可
- 已解决中间代码不支持 not 单元运算的问题,修改了
translateUnaryExp
- 已解决 module 未处理全局变量的问题,以及控制流未打印全局变量的问题
- 已解决非数组全局变量强制初始化为 0 的问题
- 已根据实验文档重构
translateCond
和translateUnaryExp
根据测试点一个个排查,修复了大量零碎 bug,不在此处赘述
- 已解决
translateLVal
在引用全局变量没有维度信息时未区分是否是数组的问题
至此 lab3 测试点全部通过,等待实验报告撰写
250422
已完成实验报告
lab4
250423
- 合并模板,确认事项:
- [x]
codegen/asm.hpp
完成 riscv 类定义 - [x] 寄存器分配阶段需要实现一个
RegAllocator
类,用于将虚拟寄存器分配到物理寄存器上。对于每一个函数,我们在完成寄存器分配后,可以得到一个RegMap
,将虚拟寄存器映射到物理寄存器。我们可以将其保存在Function
类中,方便在后续的汇编指令发射中使用。
- 已完成
asm.hpp
中的相关类定义
- 已完成
inst_selector.cpp
中大部分 ir node 的选择函数
250424
- 确认当前的问题
- Callee-saved 寄存器如何确定有哪些
- 需要在 asm emitter 处理
- Caller-saved 寄存器如何确定有哪些
- 需要在 call asm node 处理
- Callee-saved 寄存器如何确定有哪些
- 编译成功,只是能编译,很多细节还没处理
- 已配置 RV32 工具链
- 临时变量未成功转化为物理寄存器
- prologue 和 epilogue 位置不对,内容不对
./compiler sp25-tests/tests/lab4/array_hard.sy debug/test.s
riscv32-unknown-elf-gcc -g -o debug/test debug/test.s
qemu-riscv32 debug/test
qemu-riscv32 debug/test < debug/input.txt > debug/output.txt
qemu-riscv32 -g 1234 debug/test
riscv32-unknown-elf-gdb debug/test
target remote : 1234
250425
- 已解决
ASM::Store
create 时 rs1 和 rs2 弄反的问题 - 已解决
RegAllocator::allocate
中 reg_map 全映射到 t0 的问题,系 emplace 问题 - 已重构
RegAllocator::allocate
,采用全部压栈的朴素分配方式- 将 reg 替换位置从
ASMEmitter::emit
移至RegAllocator::allocate
- 将 reg 替换位置从
240426
- 已解决每个函数开始时未初始化
sp
的问题 - 已解决
get_defs
和get_uses
出现相同 reg 时分配了不同寄存器,reg_map 被覆盖,导致存入栈时用的是后一个分配的寄存器时 - 已解决全局变量地址固定是
sp
且没考虑 offset 的问题Function
类中添加std::unordered_map<std::string, int> tmp_offset_map;
- 已解决数组地址和数组第一个元素存储位置相同的问题
- 重构了
InstSelector::selectDec
- 重构了
- 已解决
InstSelector::selectParam
中ASM::Mv::create
参数弄反的问题 - 已解决函数返回时
ra
未正确恢复的问题,系函数结束时恢复sp
的操作被跳过了 - 已解决函数多个参数只传递了第一个参数的问题
- 重构了
InstSelector::selectArg
- 重构了
奶奶的,早知道先认真设计,想着先大致搭个框架,然后一点一点修正,结果 debug 累死,一块一块重构,成屎山了,以后不这么干了,靠
相同变量重复分配不同栈,导致far_label
测试点无法通过的问题
给 lab3 中间代码生成临时变量分配采用相同变量重复利用同一临时变量的机制
- 已解决
.text
出现在全局变量定义前导致无法修改全局变量的问题
240427
- 已解决全局变量取址出错的问题,系没有声明
.data
段
- 已解决局部大数组存栈上会报爆,系 riscv 立即数加载范围有限
- 更新了
ASM::Load
,ASM::Store
,ASM::ArithImm
的打印函数,以及ASMEmitter::emit
函数初始化sp
的内容
- 更新了
未保存 callee reg(s0~s7)- 不需要保存,全都在栈上
未保存 caller reg(a0~a7,t0~t7),看情况保存- 不需要保存,全都在栈上
等课内学了寄存器分配再继续写吧,先告一段落,最近还有更重要的事情
240428
- 已解决相同变量重复分配不同栈,导致
far_label
测试点无法通过的问题- 给中间代码生成添加了朴素的临时变量分配机制
- 已解决数独程序 Ran for more than the max allowed steps (500000)!,系超时,实际测试时有参数设置无 step 数限制
- 已解决 far_label 能算出,但是超时的问题,助教说可以直接改 config,无惩罚
- 已解决 dijkstra 不知道能不能算出,但是 debug/test.s:3487: branch to if.else.label28 too far:bne t1, t2, if.else.label28 的问题
- 将
class Branch
输出反转,借助j
进行远距离跳转 - optional:可扫描出所有 label 地址,计算偏移再决定是否要反转
- 将
- 已解决 spill 就是栈传参出错的问题,传参时先改了 sp,然后又要使用的问题,栈传参目前仍借助了 8 个 t reg,过多参数无法解决的问题
- 新增类
ASM::ArgStore
,修改InstSelector::selectCall
,修改RegAllocator::allocate
,对ArgStore
进行特殊处理,使其使用正确地址获取变量
- 新增类
最后两个都需要重构寄存器分配,交给后面更强大的我吧
完结撒花~~
还可以优化