From d7dae72839ee40e2dad105b81b4fb225d2898798 Mon Sep 17 00:00:00 2001 From: LiXiaoQi Date: Wed, 26 Oct 2022 17:17:46 +0800 Subject: [PATCH] backup on halfway --- .clang-format | 4 +- Reports/3-ir-gen/report.md | 61 +++- include/ast.hpp | 78 +++-- include/cminusf_builder.hpp | 2 + src/cminusfc/cminusf_builder.cpp | 342 +++++++++++++++++++++- src/cminusfc/cminusfc.cpp | 6 +- src/common/ast.cpp | 212 +++++--------- src/common/syntax_tree.c | 113 ++++--- tests/3-ir-gen/.gitignore | 2 + tests/3-ir-gen/testcases/lv0_1/.gitignore | 11 + tests/3-ir-gen/testcases/lv0_2/.gitignore | 35 +++ 11 files changed, 599 insertions(+), 267 deletions(-) create mode 100644 tests/3-ir-gen/.gitignore create mode 100644 tests/3-ir-gen/testcases/lv0_1/.gitignore create mode 100644 tests/3-ir-gen/testcases/lv0_2/.gitignore diff --git a/.clang-format b/.clang-format index b7c58b7..db13e1d 100644 --- a/.clang-format +++ b/.clang-format @@ -15,8 +15,8 @@ IncludeCategories: Priority: 2 - Regex: '.*' Priority: 1 -IndentCaseLabels: false -AllowShortCaseLabelsOnASingleLine: true +IndentCaseLabels: true +AllowShortCaseLabelsOnASingleLine: false IndentWidth: 4 KeepEmptyLinesAtTheStartOfBlocks: false PenaltyReturnTypeOnItsOwnLine: 200 diff --git a/Reports/3-ir-gen/report.md b/Reports/3-ir-gen/report.md index b557e09..e68bd7d 100644 --- a/Reports/3-ir-gen/report.md +++ b/Reports/3-ir-gen/report.md @@ -1,10 +1,67 @@ # 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指针?这个关乎地址的计算、类型转换…… + + 答案在于:中间代码是如何生成的? + + 按我的理解, + + - 在翻译为中间代码时,函数内部声明的只能是数组,计算地址时会得到指针。 + + - 在传递给函数时,只能传递数组,但是传递为指针。 ## 实验设计 diff --git a/include/ast.hpp b/include/ast.hpp index 41de619..ae6d12d 100644 --- a/include/ast.hpp +++ b/include/ast.hpp @@ -2,17 +2,13 @@ #define _SYNTAX_TREE_HPP_ extern "C" { #include "syntax_tree.h" - extern syntax_tree *parse(const char *input); +extern syntax_tree *parse(const char *input); } -#include #include #include +#include -enum CminusType { - TYPE_INT, - TYPE_FLOAT, - TYPE_VOID -}; +enum CminusType { TYPE_INT, TYPE_FLOAT, TYPE_VOID }; enum RelOp { // <= @@ -64,23 +60,24 @@ struct ASTVar; struct ASTAssignExpression; struct ASTSimpleExpression; struct ASTAdditiveExpression; -struct ASTTerm ; +struct ASTTerm; struct ASTCall; class ASTVisitor; class AST { -public: + public: AST() = delete; AST(syntax_tree *); AST(AST &&tree) { root = tree.root; tree.root = nullptr; }; - ASTProgram* get_root() { return root.get(); } - void run_visitor(ASTVisitor& visitor); -private: - ASTNode* transform_node_iter(syntax_tree_node *); + ASTProgram *get_root() { return root.get(); } + void run_visitor(ASTVisitor &visitor); + + private: + ASTNode *transform_node_iter(syntax_tree_node *); std::shared_ptr root = nullptr; }; @@ -90,21 +87,20 @@ struct ASTNode { struct ASTProgram : ASTNode { virtual void accept(ASTVisitor &) override final; - std::vector> - declarations; + std::vector> declarations; }; -struct ASTDeclaration: ASTNode { +struct ASTDeclaration : ASTNode { virtual void accept(ASTVisitor &) override; CminusType type; std::string id; }; -struct ASTFactor: ASTNode { +struct ASTFactor : ASTNode { virtual void accept(ASTVisitor &) override; }; -struct ASTNum: ASTFactor { +struct ASTNum : ASTFactor { virtual void accept(ASTVisitor &) override final; CminusType type; union { @@ -113,19 +109,19 @@ struct ASTNum: ASTFactor { }; }; -struct ASTVarDeclaration: ASTDeclaration { +struct ASTVarDeclaration : ASTDeclaration { virtual void accept(ASTVisitor &) override final; CminusType type; std::shared_ptr num; }; -struct ASTFunDeclaration: ASTDeclaration { +struct ASTFunDeclaration : ASTDeclaration { virtual void accept(ASTVisitor &) override final; std::vector> params; std::shared_ptr compound_stmt; }; -struct ASTParam: ASTNode { +struct ASTParam : ASTNode { virtual void accept(ASTVisitor &) override final; CminusType type; std::string id; @@ -137,62 +133,62 @@ struct ASTStatement : ASTNode { virtual void accept(ASTVisitor &) override; }; -struct ASTCompoundStmt: ASTStatement { - virtual void accept(ASTVisitor&) override final; +struct ASTCompoundStmt : ASTStatement { + virtual void accept(ASTVisitor &) override final; std::vector> local_declarations; std::vector> statement_list; }; -struct ASTExpressionStmt: ASTStatement { +struct ASTExpressionStmt : ASTStatement { virtual void accept(ASTVisitor &) override final; - std::shared_ptr expression; + std::shared_ptr expression; }; -struct ASTSelectionStmt: ASTStatement { +struct ASTSelectionStmt : ASTStatement { virtual void accept(ASTVisitor &) override final; - std::shared_ptr expression; + std::shared_ptr expression; std::shared_ptr if_statement; // should be nullptr if no else structure exists std::shared_ptr else_statement; }; -struct ASTIterationStmt: ASTStatement { +struct ASTIterationStmt : ASTStatement { virtual void accept(ASTVisitor &) override final; - std::shared_ptr expression; + std::shared_ptr expression; std::shared_ptr statement; }; -struct ASTReturnStmt: ASTStatement { +struct ASTReturnStmt : ASTStatement { virtual void accept(ASTVisitor &) override final; // should be nullptr if return void - std::shared_ptr expression; + std::shared_ptr expression; }; -struct ASTExpression: ASTFactor { +struct ASTExpression : ASTFactor { virtual void accept(ASTVisitor &) override; }; -struct ASTAssignExpression: ASTExpression { +struct ASTAssignExpression : ASTExpression { virtual void accept(ASTVisitor &) override final; std::shared_ptr var; std::shared_ptr expression; }; -struct ASTSimpleExpression: ASTExpression { +struct ASTSimpleExpression : ASTExpression { virtual void accept(ASTVisitor &) override final; std::shared_ptr additive_expression_l; std::shared_ptr additive_expression_r; RelOp op; }; -struct ASTVar: ASTFactor { +struct ASTVar : ASTFactor { virtual void accept(ASTVisitor &) override final; std::string id; // nullptr if var is of int type std::shared_ptr expression; }; -struct ASTAdditiveExpression: ASTNode { +struct ASTAdditiveExpression : ASTNode { virtual void accept(ASTVisitor &) override final; std::shared_ptr additive_expression; AddOp op; @@ -206,14 +202,14 @@ struct ASTTerm : ASTNode { std::shared_ptr factor; }; -struct ASTCall: ASTFactor { +struct ASTCall : ASTFactor { virtual void accept(ASTVisitor &) override final; std::string id; std::vector> args; }; class ASTVisitor { -public: + public: virtual void visit(ASTProgram &) = 0; virtual void visit(ASTNum &) = 0; virtual void visit(ASTVarDeclaration &) = 0; @@ -233,7 +229,7 @@ public: }; class ASTPrinter : public ASTVisitor { -public: + public: virtual void visit(ASTProgram &) override final; virtual void visit(ASTNum &) override final; virtual void visit(ASTVarDeclaration &) override final; @@ -252,8 +248,8 @@ public: virtual void visit(ASTCall &) override final; void add_depth() { depth += 2; } void remove_depth() { depth -= 2; } -private: + + private: int depth = 0; }; #endif - diff --git a/include/cminusf_builder.hpp b/include/cminusf_builder.hpp index 750dc3a..4a20f7d 100644 --- a/include/cminusf_builder.hpp +++ b/include/cminusf_builder.hpp @@ -96,6 +96,8 @@ class CminusfBuilder : public ASTVisitor { virtual void visit(ASTTerm &) override final; virtual void visit(ASTCall &) override final; + bool type_cast(Value *&, Value *&, std::string = "computation"); + std::unique_ptr builder; Scope scope; std::unique_ptr module; diff --git a/src/cminusfc/cminusf_builder.cpp b/src/cminusfc/cminusf_builder.cpp index e4278b2..fa4990d 100644 --- a/src/cminusfc/cminusf_builder.cpp +++ b/src/cminusfc/cminusf_builder.cpp @@ -5,15 +5,18 @@ #include "cminusf_builder.hpp" +#include "logging.hpp" + #define CONST_FP(num) ConstantFP::get((float)num, module.get()) #define CONST_INT(num) ConstantInt::get(num, module.get()) - -// TODO: Global Variable Declarations +// TODO: Global Variable Declarations // You can define global variables here // to store state. You can expand these // definitions if you need to. +// the latest return value +Value *cur_value = nullptr; // function that is being built Function *cur_fun = nullptr; @@ -33,6 +36,28 @@ Type *FLOATPTR_T; * scope.find: find and return the value bound to the name */ +void error_exit(std::string s) { + LOG_ERROR << s; + std::abort(); +} + +// This function makes sure that +// 1. 2 values have same type +// 2. type is either int or float +// 3. return true if there is float +bool CminusfBuilder::type_cast(Value *&lvalue, Value *&rvalue, std::string util) { + if (not Type::is_eq_type(lvalue->get_type(), rvalue->get_type())) { + if (Type::is_eq_type(lvalue->get_type(), INT32_T) and Type::is_eq_type(rvalue->get_type(), FLOAT_T)) + lvalue = builder->create_sitofp(lvalue, FLOAT_T); + else if (Type::is_eq_type(rvalue->get_type(), INT32_T) and Type::is_eq_type(lvalue->get_type(), FLOAT_T)) + rvalue = builder->create_sitofp(rvalue, FLOAT_T); + } + // now 2 value is the same type, but we only support computing between int and float + if (not Type::is_eq_type(lvalue->get_type(), INT32_T) or not Type::is_eq_type(lvalue->get_type(), FLOAT_T)) + error_exit("not supported cross-type " + util); + return Type::is_eq_type(lvalue->get_type(), FLOAT_T); +} + void CminusfBuilder::visit(ASTProgram &node) { VOID_T = Type::get_void_type(module.get()); INT1_T = Type::get_int1_type(module.get()); @@ -46,16 +71,73 @@ void CminusfBuilder::visit(ASTProgram &node) { } } +// Done void CminusfBuilder::visit(ASTNum &node) { //!TODO: This function is empty now. // Add some code here. + // + switch (node.type) { + case TYPE_INT: + cur_value = CONST_INT(node.i_val); + return; + case TYPE_FLOAT: + cur_value = CONST_FP(node.f_val); + return; + default: + error_exit("ASTNum is not int or float"); + } } +// Done void CminusfBuilder::visit(ASTVarDeclaration &node) { //!TODO: This function is empty now. // Add some code here. + if (node.num) { + // declares an array + // + // get array size + node.num->accept(*this); + // + // type cast + if (Type::is_eq_type(cur_value->get_type(), FLOAT_T)) + cur_value = builder->create_fptosi(cur_value, INT32_T); + int size = static_cast(cur_value)->get_value(); + if (size <= 0) + error_exit("array size[" + std::to_string(size) + "] <= 0"); + + switch (node.type) { + case TYPE_INT: { + auto I32Array_T = Type::get_array_type(INT32_T, size); + cur_value = builder->create_alloca(I32Array_T); + break; + } + + case TYPE_FLOAT: { + auto FloatArray_T = Type::get_array_type(FLOAT_T, size); + cur_value = builder->create_alloca(FloatArray_T); + break; + } + default: + error_exit("Variable type(not array) is not int or float"); + } + + } else { + switch (node.type) { + case TYPE_INT: + cur_value = builder->create_alloca(INT32_T); + break; + case TYPE_FLOAT: + cur_value = builder->create_alloca(FLOAT_T); + break; + default: + error_exit("Variable type(not array) is not int or float"); + } + } + if (not scope.push(node.id, cur_value)) + error_exit("variable redefined: " + node.id); } +// Done void CminusfBuilder::visit(ASTFunDeclaration &node) { FunctionType *fun_type; Type *ret_type; @@ -69,32 +151,46 @@ void CminusfBuilder::visit(ASTFunDeclaration &node) { for (auto ¶m : node.params) { //!TODO: Please accomplish param_types. - - - + // + // First make function BB, which needs this param type, + // then set_insert_point, we can call accept to gen code, + switch (param->type) { + case TYPE_INT: + param_types.push_back(param->isarray ? INT32PTR_T : INT32_T); + break; + case TYPE_FLOAT: + param_types.push_back(param->isarray ? FLOATPTR_T : FLOAT_T); + break; + case TYPE_VOID: + if (not param_types.empty()) + error_exit("function parameters weird"); + break; + } } fun_type = FunctionType::get(ret_type, param_types); auto fun = Function::create(fun_type, node.id, module.get()); - scope.push(node.id, fun); cur_fun = fun; + scope.push(node.id, fun); + auto funBB = BasicBlock::create(module.get(), "entry", fun); builder->set_insert_point(funBB); scope.enter(); + std::vector args; for (auto arg = fun->arg_begin(); arg != fun->arg_end(); arg++) { args.push_back(*arg); } + for (int i = 0; i < node.params.size(); ++i) { //!TODO: You need to deal with params // and store them in the scope. - - - + cur_value = args[i]; + node.params[i]->accept(*this); } node.compound_stmt->accept(*this); - if (builder->get_insert_block()->get_terminator() == nullptr) - { + // default return value + if (builder->get_insert_block()->get_terminator() == nullptr) { if (cur_fun->get_return_type()->is_void_type()) builder->create_void_ret(); else if (cur_fun->get_return_type()->is_float_type()) @@ -105,16 +201,28 @@ void CminusfBuilder::visit(ASTFunDeclaration &node) { scope.exit(); } +// Done void CminusfBuilder::visit(ASTParam &node) { //!TODO: This function is empty now. - // Add some code here. + // If the parameter is int|float, copy and store them + switch (node.type) { + case TYPE_INT: { + scope.push(node.id, cur_value); + break; + } + case TYPE_FLOAT: { + scope.push(node.id, cur_value); + break; + } + case TYPE_VOID: + break; + } } void CminusfBuilder::visit(ASTCompoundStmt &node) { //!TODO: This function is not complete. // You may need to add some code here - // to deal with complex statements. - + // to deal with complex statements. for (auto &decl : node.local_declarations) { decl->accept(*this); @@ -142,43 +250,245 @@ void CminusfBuilder::visit(ASTIterationStmt &node) { // Add some code here. } +// Jobs: +// - call accept() +// - gen return code void CminusfBuilder::visit(ASTReturnStmt &node) { if (node.expression == nullptr) { builder->create_void_ret(); } else { //!TODO: The given code is incomplete. // You need to solve other return cases (e.g. return an integer). - - + // + node.expression->accept(*this); + builder->create_ret(cur_value); } } void CminusfBuilder::visit(ASTVar &node) { //!TODO: This function is empty now. // Add some code here. + // + // Goal: calculate address + // 1. get base + // 2. get bias if there is, and cast it if needed. + + auto memory = scope.find(node.id); + Value *addr; + if (memory == nullptr) { + LOG_ERROR << node.id << " not declared!"; + std::abort(); + } + if (node.expression) { // a[1] = 1; + node.expression->accept(*this); + if (not Type::is_eq_type(cur_value->get_type(), INT32_T)) { + if (Type::is_eq_type(cur_value->get_type(), FLOAT_T)) + cur_value = builder->create_fptosi(cur_value, INT32_T); + else { + LOG_ERROR << "unexpected type!"; + std::abort(); + } + } + + addr = builder->create_gep(memory, {cur_value}); + + } else { // a = 1; + addr = memory; + } + cur_value = addr; } void CminusfBuilder::visit(ASTAssignExpression &node) { //!TODO: This function is empty now. // Add some code here. + // + // 1. For assignment, both side should have a vaule, + // the left side has an addr, right side have the correspond value + // 2. Type cast!!! + // + // + // This accept() should update `cur_value` to the left value + node.var->accept(*this); + auto left = cur_value; + // This accept() should update `cur_value` to the right value + node.expression->accept(*this); + + // type cast + auto type = scope.find(node.var->id)->get_type(); + if (not Type::is_eq_type(type, cur_value->get_type())) { + if (type->is_pointer_type()) + cur_value = builder->create_fptosi(cur_value, INT32_T); + else if (type->is_float_type()) + cur_value = builder->create_sitofp(cur_value, FLOAT_T); + else { + LOG(ERROR) << "Bad assignment!"; + std::abort(); + } + } + // gen code + builder->create_store(left, cur_value); } +// Done void CminusfBuilder::visit(ASTSimpleExpression &node) { //!TODO: This function is empty now. // Add some code here. + // + node.additive_expression_l->accept(*this); + if (node.additive_expression_r) { + auto lvalue = cur_value; + node.additive_expression_r->accept(*this); + auto rvalue = cur_value; + // type cast + bool float_cmp = type_cast(lvalue, rvalue, "cmp"); + switch (node.op) { + case OP_LE: { + if (float_cmp) + cur_value = builder->create_fcmp_le(lvalue, rvalue); + else + cur_value = builder->create_icmp_le(lvalue, rvalue); + break; + } + case OP_LT: { + if (float_cmp) + cur_value = builder->create_fcmp_lt(lvalue, rvalue); + else + cur_value = builder->create_icmp_lt(lvalue, rvalue); + break; + } + case OP_GT: { + if (float_cmp) + cur_value = builder->create_fcmp_gt(lvalue, rvalue); + else + cur_value = builder->create_icmp_gt(lvalue, rvalue); + break; + } + case OP_GE: { + if (float_cmp) + cur_value = builder->create_fcmp_ge(lvalue, rvalue); + else + cur_value = builder->create_icmp_ge(lvalue, rvalue); + break; + } + case OP_EQ: { + if (float_cmp) + cur_value = builder->create_fcmp_eq(lvalue, rvalue); + else + cur_value = builder->create_icmp_eq(lvalue, rvalue); + break; + } + case OP_NEQ: { + if (float_cmp) + cur_value = builder->create_fcmp_ne(lvalue, rvalue); + else + cur_value = builder->create_icmp_ne(lvalue, rvalue); + break; + } + } + } } +// Done void CminusfBuilder::visit(ASTAdditiveExpression &node) { //!TODO: This function is empty now. // Add some code here. + // + node.term->accept(*this); + if (node.additive_expression) { + auto lvalue = cur_value; + node.additive_expression->accept(*this); + auto rvalue = cur_value; + // type cast + bool float_type = type_cast(lvalue, rvalue, "addop"); + // now left and right is the same type + switch (node.op) { + case OP_PLUS: { + if (float_type) + cur_value = builder->create_fadd(lvalue, rvalue); + else + cur_value = builder->create_iadd(lvalue, rvalue); + break; + } + case OP_MINUS: { + if (float_type) + cur_value = builder->create_fsub(lvalue, rvalue); + else + cur_value = builder->create_isub(lvalue, rvalue); + break; + } + } + } } +// Done void CminusfBuilder::visit(ASTTerm &node) { //!TODO: This function is empty now. // Add some code here. + node.factor->accept(*this); + if (node.term) { + auto lvalue = cur_value; + node.term->accept(*this); + auto rvalue = cur_value; + // type cast + bool float_type = type_cast(lvalue, rvalue, "mulop"); + // now left and right is the same type + switch (node.op) { + case OP_MUL: { + if (float_type) + cur_value = builder->create_fmul(lvalue, rvalue); + else + cur_value = builder->create_imul(lvalue, rvalue); + break; + } + case OP_DIV: { + if (float_type) + cur_value = builder->create_fdiv(lvalue, rvalue); + else + cur_value = builder->create_isdiv(lvalue, rvalue); + break; + } + } + } } +// Done void CminusfBuilder::visit(ASTCall &node) { //!TODO: This function is empty now. // Add some code here. + Function *func = static_cast(scope.find(node.id)); + std::vector args; + if (func == nullptr) + error_exit("function " + node.id + " not declared"); + if (node.args.size() != func->get_num_of_args()) + error_exit("expect " + std::to_string(func->get_num_of_args()) + " params, but " + + std::to_string(node.args.size()) + " is given"); + for (int i = 0; i != node.args.size(); ++i) { + Type *param_type = func->get_function_type()->get_param_type(i); + node.args[i]->accept(*this); + + // type cast + if (not Type::is_eq_type(param_type, cur_value->get_type())) { + if (param_type->is_pointer_type()) { + if (not Type::is_eq_type(param_type->get_pointer_element_type(), + cur_value->get_type()->get_array_element_type())) + error_exit("expected right pointer type"); + // int[] to int* or float[] to flot* + cur_value = builder->create_gep(cur_value, {0, 0}); + } else if (param_type->is_integer_type() or param_type->is_float_type()) { + // need type cast between int and float + if (Type::is_eq_type(cur_value->get_type(), INT32_T)) + cur_value = builder->create_sitofp(cur_value, FLOAT_T); + else if (Type::is_eq_type(cur_value->get_type(), FLOAT_T)) + cur_value = builder->create_fptosi(cur_value, INT32_T); + else + error_exit("unexpected type cast!"); + + } else + error_exit("unexpected case when casting arguments for function call" + node.id); + } + + // now cur_value fits the param type + args.push_back(cur_value); + } + cur_value = builder->create_call(func, args); } diff --git a/src/cminusfc/cminusfc.cpp b/src/cminusfc/cminusfc.cpp index 09dbe05..ec0d73d 100644 --- a/src/cminusfc/cminusfc.cpp +++ b/src/cminusfc/cminusfc.cpp @@ -1,4 +1,5 @@ #include "cminusf_builder.hpp" + #include #include #include @@ -6,11 +7,10 @@ using namespace std::literals::string_literals; void print_help(std::string exe_name) { - std::cout << "Usage: " << exe_name << - " [ -h | --help ] [ -o ] [ -emit-llvm ] " << std::endl; + std::cout << "Usage: " << exe_name << " [ -h | --help ] [ -o ] [ -emit-llvm ] " + << std::endl; } - int main(int argc, char **argv) { std::string target_path; std::string input_path; diff --git a/src/common/ast.cpp b/src/common/ast.cpp index 4243968..263c468 100644 --- a/src/common/ast.cpp +++ b/src/common/ast.cpp @@ -1,31 +1,28 @@ #include "ast.hpp" + #include -#include #include -#define _AST_NODE_ERROR_ \ - std::cerr << "Abort due to node cast error."\ - "Contact with TAs to solve your problem."\ - << std::endl;\ +#include +#define _AST_NODE_ERROR_ \ + std::cerr << "Abort due to node cast error." \ + "Contact with TAs to solve your problem." \ + << std::endl; \ std::abort(); #define _STR_EQ(a, b) (strcmp((a), (b)) == 0) -void AST::run_visitor(ASTVisitor &visitor) { - root->accept(visitor); -} +void AST::run_visitor(ASTVisitor &visitor) { root->accept(visitor); } -AST::AST(syntax_tree* s) { +AST::AST(syntax_tree *s) { if (s == nullptr) { std::cerr << "empty input tree!" << std::endl; std::abort(); } auto node = transform_node_iter(s->root); del_syntax_tree(s); - root = std::shared_ptr( - static_cast(node)); + root = std::shared_ptr(static_cast(node)); } -ASTNode * -AST::transform_node_iter(syntax_tree_node *n) { +ASTNode *AST::transform_node_iter(syntax_tree_node *n) { if (_STR_EQ(n->name, "program")) { auto node = new ASTProgram(); @@ -39,11 +36,9 @@ AST::transform_node_iter(syntax_tree_node *n) { s.push(list_ptr->children[0]); while (!s.empty()) { - auto child_node = static_cast( - transform_node_iter(s.top())); + auto child_node = static_cast(transform_node_iter(s.top())); - auto child_node_shared = - std::shared_ptr(child_node); + auto child_node_shared = std::shared_ptr(child_node); node->declarations.push_back(child_node_shared); s.pop(); } @@ -57,7 +52,7 @@ AST::transform_node_iter(syntax_tree_node *n) { node->type = TYPE_INT; else node->type = TYPE_FLOAT; - + if (n->children_num == 3) { node->id = n->children[1]->name; } else if (n->children_num == 6) { @@ -97,19 +92,15 @@ AST::transform_node_iter(syntax_tree_node *n) { s.push(list_ptr->children[0]); while (!s.empty()) { - auto child_node = static_cast( - transform_node_iter(s.top())); + auto child_node = static_cast(transform_node_iter(s.top())); - auto child_node_shared = - std::shared_ptr(child_node); + auto child_node_shared = std::shared_ptr(child_node); node->params.push_back(child_node_shared); s.pop(); } } - auto stmt_node = - static_cast( - transform_node_iter(n->children[5])); + auto stmt_node = static_cast(transform_node_iter(n->children[5])); node->compound_stmt = std::shared_ptr(stmt_node); return node; } else if (_STR_EQ(n->name, "param")) { @@ -134,16 +125,14 @@ AST::transform_node_iter(syntax_tree_node *n) { } while (!s.empty()) { - auto decl_node = - static_cast( - transform_node_iter(s.top())); + auto decl_node = static_cast(transform_node_iter(s.top())); auto decl_node_ptr = std::shared_ptr(decl_node); node->local_declarations.push_back(decl_node_ptr); s.pop(); } } - if (n->children[2]->children_num == 2) { + if (n->children[2]->children_num == 2) { // flatten statement-list auto list_ptr = n->children[2]; std::stack s; @@ -153,9 +142,7 @@ AST::transform_node_iter(syntax_tree_node *n) { } while (!s.empty()) { - auto stmt_node = - static_cast( - transform_node_iter(s.top())); + auto stmt_node = static_cast(transform_node_iter(s.top())); auto stmt_node_ptr = std::shared_ptr(stmt_node); node->statement_list.push_back(stmt_node_ptr); s.pop(); @@ -167,9 +154,7 @@ AST::transform_node_iter(syntax_tree_node *n) { } else if (_STR_EQ(n->name, "expression-stmt")) { auto node = new ASTExpressionStmt(); if (n->children_num == 2) { - auto expr_node = - static_cast( - transform_node_iter(n->children[0])); + auto expr_node = static_cast(transform_node_iter(n->children[0])); auto expr_node_ptr = std::shared_ptr(expr_node); node->expression = expr_node_ptr; @@ -178,24 +163,18 @@ AST::transform_node_iter(syntax_tree_node *n) { } else if (_STR_EQ(n->name, "selection-stmt")) { auto node = new ASTSelectionStmt(); - auto expr_node = - static_cast( - transform_node_iter(n->children[2])); + auto expr_node = static_cast(transform_node_iter(n->children[2])); auto expr_node_ptr = std::shared_ptr(expr_node); node->expression = expr_node_ptr; - auto if_stmt_node = - static_cast( - transform_node_iter(n->children[4])); + auto if_stmt_node = static_cast(transform_node_iter(n->children[4])); auto if_stmt_node_ptr = std::shared_ptr(if_stmt_node); node->if_statement = if_stmt_node_ptr; // check whether this selection statement contains // else structure if (n->children_num == 7) { - auto else_stmt_node = - static_cast( - transform_node_iter(n->children[6])); + auto else_stmt_node = static_cast(transform_node_iter(n->children[6])); auto else_stmt_node_ptr = std::shared_ptr(else_stmt_node); node->else_statement = else_stmt_node_ptr; } @@ -204,15 +183,11 @@ AST::transform_node_iter(syntax_tree_node *n) { } else if (_STR_EQ(n->name, "iteration-stmt")) { auto node = new ASTIterationStmt(); - auto expr_node = - static_cast( - transform_node_iter(n->children[2])); + auto expr_node = static_cast(transform_node_iter(n->children[2])); auto expr_node_ptr = std::shared_ptr(expr_node); node->expression = expr_node_ptr; - auto stmt_node = - static_cast( - transform_node_iter(n->children[4])); + auto stmt_node = static_cast(transform_node_iter(n->children[4])); auto stmt_node_ptr = std::shared_ptr(stmt_node); node->statement = stmt_node_ptr; @@ -220,11 +195,8 @@ AST::transform_node_iter(syntax_tree_node *n) { } else if (_STR_EQ(n->name, "return-stmt")) { auto node = new ASTReturnStmt(); if (n->children_num == 3) { - auto expr_node = - static_cast( - transform_node_iter(n->children[1])); - node->expression = - std::shared_ptr(expr_node); + auto expr_node = static_cast(transform_node_iter(n->children[1])); + node->expression = std::shared_ptr(expr_node); } return node; } else if (_STR_EQ(n->name, "expression")) { @@ -234,36 +206,25 @@ AST::transform_node_iter(syntax_tree_node *n) { } auto node = new ASTAssignExpression(); - auto var_node = - static_cast( - transform_node_iter(n->children[0])); + auto var_node = static_cast(transform_node_iter(n->children[0])); node->var = std::shared_ptr(var_node); - auto expr_node = - static_cast( - transform_node_iter(n->children[2])); - node->expression = - std::shared_ptr(expr_node); + auto expr_node = static_cast(transform_node_iter(n->children[2])); + node->expression = std::shared_ptr(expr_node); return node; } else if (_STR_EQ(n->name, "var")) { auto node = new ASTVar(); node->id = n->children[0]->name; if (n->children_num == 4) { - auto expr_node = - static_cast( - transform_node_iter(n->children[2])); - node->expression = - std::shared_ptr(expr_node); + auto expr_node = static_cast(transform_node_iter(n->children[2])); + node->expression = std::shared_ptr(expr_node); } return node; } else if (_STR_EQ(n->name, "simple-expression")) { auto node = new ASTSimpleExpression(); - auto expr_node_1 = - static_cast( - transform_node_iter(n->children[0])); - node->additive_expression_l = - std::shared_ptr(expr_node_1); + auto expr_node_1 = static_cast(transform_node_iter(n->children[0])); + node->additive_expression_l = std::shared_ptr(expr_node_1); if (n->children_num == 3) { auto op_name = n->children[1]->children[0]->name; @@ -280,21 +241,15 @@ AST::transform_node_iter(syntax_tree_node *n) { else if (_STR_EQ(op_name, "!=")) node->op = OP_NEQ; - auto expr_node_2 = - static_cast( - transform_node_iter(n->children[2])); - node->additive_expression_r = - std::shared_ptr(expr_node_2); + auto expr_node_2 = static_cast(transform_node_iter(n->children[2])); + node->additive_expression_r = std::shared_ptr(expr_node_2); } return node; } else if (_STR_EQ(n->name, "additive-expression")) { auto node = new ASTAdditiveExpression(); if (n->children_num == 3) { - auto add_expr_node = - static_cast( - transform_node_iter(n->children[0])); - node->additive_expression = - std::shared_ptr(add_expr_node); + auto add_expr_node = static_cast(transform_node_iter(n->children[0])); + node->additive_expression = std::shared_ptr(add_expr_node); auto op_name = n->children[1]->children[0]->name; if (_STR_EQ(op_name, "+")) @@ -302,25 +257,18 @@ AST::transform_node_iter(syntax_tree_node *n) { else if (_STR_EQ(op_name, "-")) node->op = OP_MINUS; - auto term_node = - static_cast( - transform_node_iter(n->children[2])); + auto term_node = static_cast(transform_node_iter(n->children[2])); node->term = std::shared_ptr(term_node); } else { - auto term_node = - static_cast( - transform_node_iter(n->children[0])); + auto term_node = static_cast(transform_node_iter(n->children[0])); node->term = std::shared_ptr(term_node); } return node; } else if (_STR_EQ(n->name, "term")) { auto node = new ASTTerm(); if (n->children_num == 3) { - auto term_node = - static_cast( - transform_node_iter(n->children[0])); - node->term = - std::shared_ptr(term_node); + auto term_node = static_cast(transform_node_iter(n->children[0])); + node->term = std::shared_ptr(term_node); auto op_name = n->children[1]->children[0]->name; if (_STR_EQ(op_name, "*")) @@ -328,14 +276,10 @@ AST::transform_node_iter(syntax_tree_node *n) { else if (_STR_EQ(op_name, "/")) node->op = OP_DIV; - auto factor_node = - static_cast( - transform_node_iter(n->children[2])); + auto factor_node = static_cast(transform_node_iter(n->children[2])); node->factor = std::shared_ptr(factor_node); } else { - auto factor_node = - static_cast( - transform_node_iter(n->children[0])); + auto factor_node = static_cast(transform_node_iter(n->children[0])); node->factor = std::shared_ptr(factor_node); } return node; @@ -344,9 +288,7 @@ AST::transform_node_iter(syntax_tree_node *n) { if (n->children_num == 3) i = 1; auto name = n->children[i]->name; - if (_STR_EQ(name, "expression") || - _STR_EQ(name, "var") || - _STR_EQ(name, "call")) + if (_STR_EQ(name, "expression") || _STR_EQ(name, "var") || _STR_EQ(name, "call")) return transform_node_iter(n->children[i]); else { auto num_node = new ASTNum(); @@ -375,11 +317,8 @@ AST::transform_node_iter(syntax_tree_node *n) { s.push(list_ptr->children[0]); while (!s.empty()) { - auto expr_node = - static_cast( - transform_node_iter(s.top())); - auto expr_node_ptr = - std::shared_ptr(expr_node); + auto expr_node = static_cast(transform_node_iter(s.top())); + auto expr_node_ptr = std::shared_ptr(expr_node); node->args.push_back(expr_node_ptr); s.pop(); } @@ -409,29 +348,25 @@ void ASTTerm::accept(ASTVisitor &visitor) { visitor.visit(*this); } void ASTCall::accept(ASTVisitor &visitor) { visitor.visit(*this); } void ASTFactor::accept(ASTVisitor &visitor) { - auto expr = - dynamic_cast(this); + auto expr = dynamic_cast(this); if (expr) { expr->accept(visitor); return; } - auto var = - dynamic_cast(this); + auto var = dynamic_cast(this); if (var) { var->accept(visitor); return; } - auto call = - dynamic_cast(this); + auto call = dynamic_cast(this); if (call) { call->accept(visitor); return; } - auto num = - dynamic_cast(this); + auto num = dynamic_cast(this); if (num) { num->accept(visitor); return; @@ -441,14 +376,12 @@ void ASTFactor::accept(ASTVisitor &visitor) { } void ASTDeclaration::accept(ASTVisitor &visitor) { - auto var_decl = - dynamic_cast(this); + auto var_decl = dynamic_cast(this); if (var_decl) { var_decl->accept(visitor); return; } - auto fun_decl = - dynamic_cast(this); + auto fun_decl = dynamic_cast(this); if (fun_decl) { fun_decl->accept(visitor); return; @@ -457,36 +390,31 @@ void ASTDeclaration::accept(ASTVisitor &visitor) { } void ASTStatement::accept(ASTVisitor &visitor) { - auto comp_stmt = - dynamic_cast(this); + auto comp_stmt = dynamic_cast(this); if (comp_stmt) { comp_stmt->accept(visitor); return; } - auto expr_stmt = - dynamic_cast(this); + auto expr_stmt = dynamic_cast(this); if (expr_stmt) { expr_stmt->accept(visitor); return; } - auto sele_stmt = - dynamic_cast(this); + auto sele_stmt = dynamic_cast(this); if (sele_stmt) { sele_stmt->accept(visitor); return; } - auto iter_stmt = - dynamic_cast(this); + auto iter_stmt = dynamic_cast(this); if (iter_stmt) { iter_stmt->accept(visitor); return; } - auto ret_stmt = - dynamic_cast(this); + auto ret_stmt = dynamic_cast(this); if (ret_stmt) { ret_stmt->accept(visitor); return; @@ -495,15 +423,13 @@ void ASTStatement::accept(ASTVisitor &visitor) { } void ASTExpression::accept(ASTVisitor &visitor) { - auto simple_expr = - dynamic_cast(this); + auto simple_expr = dynamic_cast(this); if (simple_expr) { simple_expr->accept(visitor); return; } - auto assign_expr = - dynamic_cast(this); + auto assign_expr = dynamic_cast(this); if (assign_expr) { assign_expr->accept(visitor); return; @@ -511,15 +437,14 @@ void ASTExpression::accept(ASTVisitor &visitor) { _AST_NODE_ERROR_ } -#define _DEBUG_PRINT_N_(N) {\ - std::cout << std::string(N, '-');\ -} +#define _DEBUG_PRINT_N_(N) \ + { std::cout << std::string(N, '-'); } void ASTPrinter::visit(ASTProgram &node) { _DEBUG_PRINT_N_(depth); std::cout << "program" << std::endl; add_depth(); - for (auto decl: node.declarations) { + for (auto decl : node.declarations) { decl->accept(*this); } remove_depth(); @@ -534,7 +459,6 @@ void ASTPrinter::visit(ASTNum &node) { } else { _AST_NODE_ERROR_ } - } void ASTPrinter::visit(ASTVarDeclaration &node) { @@ -554,7 +478,7 @@ void ASTPrinter::visit(ASTFunDeclaration &node) { _DEBUG_PRINT_N_(depth); std::cout << "fun-declaration: " << node.id << std::endl; add_depth(); - for (auto param: node.params) { + for (auto param : node.params) { param->accept(*this); } @@ -574,11 +498,11 @@ void ASTPrinter::visit(ASTCompoundStmt &node) { _DEBUG_PRINT_N_(depth); std::cout << "compound-stmt" << std::endl; add_depth(); - for (auto decl: node.local_declarations) { + for (auto decl : node.local_declarations) { decl->accept(*this); } - for (auto stmt: node.statement_list) { + for (auto stmt : node.statement_list) { stmt->accept(*this); } remove_depth(); @@ -600,7 +524,7 @@ void ASTPrinter::visit(ASTSelectionStmt &node) { node.expression->accept(*this); node.if_statement->accept(*this); if (node.else_statement != nullptr) - node.else_statement->accept(*this); + node.else_statement->accept(*this); remove_depth(); } @@ -730,7 +654,7 @@ void ASTPrinter::visit(ASTCall &node) { _DEBUG_PRINT_N_(depth); std::cout << "call: " << node.id << "()" << std::endl; add_depth(); - for (auto arg: node.args) { + for (auto arg : node.args) { arg->accept(*this); } remove_depth(); diff --git a/src/common/syntax_tree.c b/src/common/syntax_tree.c index 0ac6e6b..6a58d74 100644 --- a/src/common/syntax_tree.c +++ b/src/common/syntax_tree.c @@ -1,77 +1,72 @@ +#include "syntax_tree.h" + #include #include -#include "syntax_tree.h" - -syntax_tree_node * new_syntax_tree_node(const char * name) -{ - syntax_tree_node * new_node = (syntax_tree_node *)malloc(sizeof(syntax_tree_node)); - if (name) - strncpy(new_node->name, name, SYNTAX_TREE_NODE_NAME_MAX); - else - new_node->name[0] = '\0'; - new_node->children_num = 0; - return new_node; +syntax_tree_node *new_syntax_tree_node(const char *name) { + syntax_tree_node *new_node = (syntax_tree_node *)malloc(sizeof(syntax_tree_node)); + if (name) + strncpy(new_node->name, name, SYNTAX_TREE_NODE_NAME_MAX); + else + new_node->name[0] = '\0'; + new_node->children_num = 0; + return new_node; } -int syntax_tree_add_child(syntax_tree_node * parent, syntax_tree_node * child) -{ - if (!parent || !child) return -1; - parent->children[parent->children_num++] = child; - return parent->children_num; +int syntax_tree_add_child(syntax_tree_node *parent, syntax_tree_node *child) { + if (!parent || !child) + return -1; + parent->children[parent->children_num++] = child; + return parent->children_num; } -void del_syntax_tree_node(syntax_tree_node * node, int recursive) -{ - if (!node) return; +void del_syntax_tree_node(syntax_tree_node *node, int recursive) { + if (!node) + return; - int i; - if (recursive) { - for (i = 0; i < node->children_num; i++) { - del_syntax_tree_node(node->children[i], 1); - } - } - free(node); + int i; + if (recursive) { + for (i = 0; i < node->children_num; i++) { + del_syntax_tree_node(node->children[i], 1); + } + } + free(node); } -syntax_tree * new_syntax_tree() -{ - return (syntax_tree *)malloc(sizeof(syntax_tree)); -} +syntax_tree *new_syntax_tree() { return (syntax_tree *)malloc(sizeof(syntax_tree)); } -void del_syntax_tree(syntax_tree * tree) -{ - if (!tree) return; +void del_syntax_tree(syntax_tree *tree) { + if (!tree) + return; - if (tree->root) { - del_syntax_tree_node(tree->root, 1); - } - free(tree); + if (tree->root) { + del_syntax_tree_node(tree->root, 1); + } + free(tree); } -void print_syntax_tree_node(FILE * fout, syntax_tree_node * node, int level) -{ - // assume fout valid now - - // check if "node" empty pointer - if (!node) return; - - // print myself - int i; - for (i = 0; i < level; i++) { - fprintf(fout, "| "); - } - fprintf(fout, ">--%s %s\n", (node->children_num ? "+" : "*"), node->name); +void print_syntax_tree_node(FILE *fout, syntax_tree_node *node, int level) { + // assume fout valid now - for (i = 0; i < node->children_num; i++) { - print_syntax_tree_node(fout, node->children[i], level + 1); - } -} + // check if "node" empty pointer + if (!node) + return; + + // print myself + int i; + for (i = 0; i < level; i++) { + fprintf(fout, "| "); + } + fprintf(fout, ">--%s %s\n", (node->children_num ? "+" : "*"), node->name); -void print_syntax_tree(FILE * fout, syntax_tree * tree) -{ - if (!fout) return; - - print_syntax_tree_node(fout, tree->root, 0); + for (i = 0; i < node->children_num; i++) { + print_syntax_tree_node(fout, node->children[i], level + 1); + } } +void print_syntax_tree(FILE *fout, syntax_tree *tree) { + if (!fout) + return; + + print_syntax_tree_node(fout, tree->root, 0); +} diff --git a/tests/3-ir-gen/.gitignore b/tests/3-ir-gen/.gitignore new file mode 100644 index 0000000..7f5e6cc --- /dev/null +++ b/tests/3-ir-gen/.gitignore @@ -0,0 +1,2 @@ +eval_result + diff --git a/tests/3-ir-gen/testcases/lv0_1/.gitignore b/tests/3-ir-gen/testcases/lv0_1/.gitignore new file mode 100644 index 0000000..38169b5 --- /dev/null +++ b/tests/3-ir-gen/testcases/lv0_1/.gitignore @@ -0,0 +1,11 @@ +*.ll +clean.sh +decl_float_array +decl_float +decl_int_array +decl_int +input +output_float +output_int +return + diff --git a/tests/3-ir-gen/testcases/lv0_2/.gitignore b/tests/3-ir-gen/testcases/lv0_2/.gitignore new file mode 100644 index 0000000..116c231 --- /dev/null +++ b/tests/3-ir-gen/testcases/lv0_2/.gitignore @@ -0,0 +1,35 @@ +*.ll +clean.sh +num_add_float +num_add_int +num_add_mixed +num_comp1 +num_comp2 +num_div_float +num_div_int +num_div_mixed +num_eq_float +num_eq_int +num_eq_mixed +num_ge_float +num_ge_int +num_ge_mixed +num_gt_float +num_gt_int +num_gt_mixed +num_le_float +num_le_int +num_le_mixed +num_lt_float +num_lt_int +num_lt_mixed +num_mul_float +num_mul_int +num_mul_mixed +num_neq_float +num_neq_int +num_neq_mixed +num_sub_float +num_sub_int +num_sub_mixed + -- GitLab