# lab3 实验报告 PB20111654 李晓奇 ## 实验要求 ## 实验难点 1. syntax_tree和ast的区别、为什需要ast? 阅读AST的构造函数,`AST(syntax_tree *)` 实际上这部分在上个实验就有看calc_ast的代码,但是印象不深刻。。 2. 访问者模式究竟有什么用? 比如这样一系列函数调用: ```cpp ASTPrinter::visit(ASTProgram &) { //... for (auto decl : node.declarations) { decl->accept(*this); } //... } ASTVarDeclaration::accept(ASTVisitor &) { //... auto var_decl = dynamic_cast(this); if (var_decl) { var_decl->accept(visitor); return; } //... } void ASTVarDeclaration::accept(ASTVisitor &visitor) { visitor.visit(*this); } ``` 假设就是vardeclaration,直接调用(在`ASTPrinter::visit`内)`visit(dynamic_cast(this))`不是一样的吗? 参考[攻略](https://www.jianshu.com/p/1f1049d0a0f4),接受一点,感觉还是不太明白,但是不影响写实验。因为经过反复的阅读,我已经知道了我们要实现的`CminusfBuilder`是一个访问者类! 3. 无从下手! 从变量开始! 自底向上做自然多了,不然像在摸黑拧魔方。 4. 如何获得返回值? 加入一个全局变量保存语句的返回值。 5. 数组or指针?这个关乎地址的计算、类型转换…… 答案在于:中间代码是如何生成的? 按我的理解, - 在翻译为中间代码时,函数内部声明的只能是数组,计算地址时会得到指针。 - 在传递给函数时,只能传递数组,但是传递为指针。 6. 记录遇到的坑 - 形如这种产生式子`term→term mulop factor ∣ factor`,我为了图方便先求了`factor`,在根据`term`的有调用`accept()`,但是这样会导致左右操作数颠倒。 - 我对于类型转换的控制比较严格,没考虑到的一率abort,因此很快发现了漏掉了bool类型的转换。 - 接上条,一些类型转换的bug:`i32`到`i1`也是需要转换的,开始做的时候还没意识到这些(主要是没意识到`i1`的存在)。 - **核心问题**:函数调用是值传递,比如`f(a)`,这里在中间代码看来,a返回的是一个指针,需要load出来再传过去。 但是对于字面量,又不需这样提取数据。可以使用`dynamic_cast`尝试解决。 但是出现了加减乘除时,这个又不能动态类型转换。 换句话说,访问`ASTCall`时,需要依次调用args的`accept()`,但是这个args!!!!expression应该返回的就是值才对。问题出现在变量的访问那里。 这个在访问`ASTVar`时解决掉:加入全局变量`LV`表式当前处理的是左值,所以要返回对应的地址,否则返回load出来的右值。 ```cpp struct ASTCall : ASTFactor { virtual void accept(ASTVisitor &) override final; std::string id; std::vector> args; }; ``` - 全局变量要特殊对待 - 数组下标为负时要调用`neg_idx_except()`,这个函数的call后边也要加上br - 神奇,bool变量不能比较,所以在比较、计算的时候要做类型转换 - store的顺序颠倒了!! - GEP和Load的翻译有问题。 定位问题:源操作数不是array类型! 那一定要看声明时push进scope的是什么,发现声明的数组类型其实也是指针类型(指向数组的指针),并不是数组?? 但后来发现,原来问题出在调用GEP,我直接吧0传入了,“胡闹吗这不是”。 - 不要乱给lable命名,因为lable的命名不会自动(针对自定义)去重。 - 发现ifelse语句忘了无条件跳转了…… - 返现布尔表达式必须使用i1类型,类型要求真的太严格了!! - 知道了为什么clang生成的中间代码,会把实参声明一遍再拷贝了。 在我看来方便编译器代码的生成,因为重新声明,push给scope的值是指针类型而不是纯值,这在后边访问Var中有用。 ## 实验设计 请写明为了顺利完成本次实验,加入了哪些亮点设计,并对这些设计进行解释。 可能的阐述方向有: 1. 如何设计全局变量 2. 遇到的难点以及解决方案 3. 如何降低生成 IR 中的冗余 4. ... ### 实验总结 此次实验有什么收获 不管多困难,先开始。~~因为更多的困难在动手前是永远想不到的~~。 ### 实验反馈 (可选 不计入评分) 对本次实验的建议