Skip to content

开发日志(自用)

:material-circle-edit-outline: 约 2437 个字 :material-clock-time-two-outline: 预计阅读时间 8 分钟

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 未正常返回数组元素的问题
    • recArrayInitcheckArrayInit 中新增处理 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 的问题
  • 已根据实验文档重构 translateCondtranslateUnaryExp

根据测试点一个个排查,修复了大量零碎 bug,不在此处赘述

  • 已解决 translateLVal 在引用全局变量没有维度信息时未区分是否是数组的问题

至此 lab3 测试点全部通过,等待实验报告撰写

image-20250421221240222

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 处理
  • 编译成功,只是能编译,很多细节还没处理
  • 已配置 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

240426

  • 已解决每个函数开始时未初始化 sp 的问题
  • 已解决 get_defsget_uses 出现相同 reg 时分配了不同寄存器,reg_map 被覆盖,导致存入栈时用的是后一个分配的寄存器时
  • 已解决全局变量地址固定是 sp 且没考虑 offset 的问题
    • Function 类中添加 std::unordered_map<std::string, int> tmp_offset_map;
  • 已解决数组地址和数组第一个元素存储位置相同的问题
    • 重构了 InstSelector::selectDec
  • 已解决 InstSelector::selectParamASM::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),看情况保存
    • 不需要保存,全都在栈上

等课内学了寄存器分配再继续写吧,先告一段落,最近还有更重要的事情

image-20250427214410694

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 进行特殊处理,使其使用正确地址获取变量

image-20250428123359285

最后两个都需要重构寄存器分配,交给后面更强大的我吧

image-20250428135740957

完结撒花~~

还可以优化