From 1bbad18f529b6bfd10771dfe3a740a69eeec43b3 Mon Sep 17 00:00:00 2001 From: ridethepig Date: Mon, 8 May 2023 19:41:14 +0800 Subject: [PATCH] bugfix --- .vscode/launch.json | 16 +++++ include/common.h | 5 ++ include/llir_type.h | 28 +++++++++ include/llir_value.h | 99 +++++++++++++++++++++++++++--- include/visitor.h | 7 +-- scripts/compiler.py | 2 +- src/visitor.cpp | 140 ++++++++++++++++++++++++++++++++++--------- 7 files changed, 257 insertions(+), 40 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..2320521 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug", + "program": "${workspaceFolder}/build/sysy", + "args": ["testcases/functional/55_sort_test1.sy", "-S", "-o", "sss"], + "cwd": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/include/common.h b/include/common.h index e899b5e..94a26de 100644 --- a/include/common.h +++ b/include/common.h @@ -20,6 +20,11 @@ namespace antlrSysY { +template +std::ostream &operator<<(typename std::enable_if::value, std::ostream>::type &stream, const T &e) { + return stream << static_cast::type>(e); +} + class GrammarException : public std::exception { public: GrammarException() : message("Unknown Grammar Exception") {} diff --git a/include/llir_type.h b/include/llir_type.h index 38309d7..ee15283 100644 --- a/include/llir_type.h +++ b/include/llir_type.h @@ -2,6 +2,7 @@ #include "common.h" #include +#include #include namespace antlrSysY { @@ -19,6 +20,24 @@ public: TypeTag type_tag; Type(TypeTag type_tag) : type_tag(type_tag) {} virtual ~Type() = default; + virtual std::string to_string() { + switch (type_tag) { + case TypeTag::IntegerType: + return "IntegerType"; + case TypeTag::FunctionType: + return "FunctionType"; + case TypeTag::ArrayType: + return "ArrayType"; + case TypeTag::PointerType: + return "PointerType"; + case TypeTag::VectorType: + return "VectorType"; + case TypeTag::VoidType: + return "VoidType"; + case TypeTag::LabelType: + return "LabelType"; + } + } }; class IntegerType : public Type { @@ -78,6 +97,9 @@ public: } return std::dynamic_pointer_cast(array_type); } + virtual std::string to_string() override { + return "Array[" + std::to_string(element_count) + " x " + element_type->to_string() + "]"; + } }; class PointerType : public Type { @@ -85,6 +107,12 @@ public: TypePtr_t pointed_type = TypeHelper::TYPE_I32; PointerType() : Type(TypeTag::PointerType) {} PointerType(TypePtr_t pointed_type) : Type(TypeTag::PointerType), pointed_type(pointed_type) {} + static auto make_shared(TypePtr_t pointed_type) { + return std::make_shared(pointed_type); + } + virtual std::string to_string() override { + return "Pointer->" + pointed_type->to_string(); + } }; class FunctionType : public Type { diff --git a/include/llir_value.h b/include/llir_value.h index c4a2b7a..a87abec 100644 --- a/include/llir_value.h +++ b/include/llir_value.h @@ -5,6 +5,7 @@ #include #include +#include "3rdparty/easylogging++.h" #include "common.h" #include "llir_type.h" @@ -16,6 +17,17 @@ public: TypePtr_t type; Value(const std::string &name, TypePtr_t type) : name(name), type(type) {} virtual ~Value() = default; + template static bool isType(std::shared_ptr ptr) { + if (ptr.get()) { + auto &r = *ptr.get(); + return typeid(r) == typeid(TT); + } + LOG(WARNING) << "Comparing with nullptr"; + return false; + } + virtual std::string to_string() { + return name + ": " + type->to_string(); + } }; class User : public Value { @@ -34,10 +46,21 @@ class Function : public Value { public: std::vector> fparam_list; std::vector> bb_list; + // we use empty basic_block to represent lib function Function(const std::string &name, TypePtr_t ret_type) : Value(name, std::make_shared(ret_type)) {} std::shared_ptr get_type() { return std::dynamic_pointer_cast(type); } + bool is_libfunc() { + return bb_list.size() == 0; + } + virtual std::string to_string() override { + std::string params_str; + for (auto fparam : fparam_list) { + params_str += fparam->to_string() + ","; + } + return name + "(" + params_str + ") -> " + type->to_string(); + } }; class BasicBlock : public Value { @@ -82,12 +105,13 @@ public: typedef std::shared_ptr ConstantPtr_t; +// emmm, actually it is more of a Instruction type class GlobalVar : public Value { public: ConstantPtr_t init_value; bool is_const; GlobalVar(const std::string &name, ConstantPtr_t init_value, bool is_const) - : Value(name, init_value->type), init_value(init_value), is_const(is_const) {} + : Value(name, PointerType::make_shared(init_value->type)), init_value(init_value), is_const(is_const) {} static std::shared_ptr make_shared(const std::string &name, ConstantPtr_t init_value, bool is_const) { return std::make_shared(name, init_value, is_const); } @@ -129,6 +153,62 @@ public: std::vector> operand_list; Instruction(InstTag inst_tag, TypePtr_t type, std::shared_ptr parent_bb) : Value("", type), tag(inst_tag), parent_bb(parent_bb) {} + virtual std::string to_string() override { + switch (tag) { + case InstTag::Add: + return "Add"; + case InstTag::Sub: + return "Sub"; + case InstTag::Mod: + return "Mod"; + case InstTag::Mul: + return "Mul"; + case InstTag::Div: + return "Div"; + case InstTag::Lt: + return "Lt"; + case InstTag::Le: + return "Le"; + case InstTag::Ge: + return "Ge"; + case InstTag::Gt: + return "Gt"; + case InstTag::Eq: + return "Eq"; + case InstTag::Ne: + return "Ne"; + case InstTag::And: + return "And"; + case InstTag::Or: + return "Or"; + case InstTag::Br: + return "Br"; + case InstTag::Call: + return "Call"; + case InstTag::Ret: + return "Ret"; + case InstTag::Alloca: + return "Alloca"; + case InstTag::Load: + return "Load"; + case InstTag::Store: + return "Store"; + case InstTag::GEP: + return "GEP"; + case InstTag::Zext: + return "Zext"; + case InstTag::Phi: + return "Phi"; + case InstTag::MemPhi: + return "MemPhi"; + case InstTag::LoadDep: + return "LoadDep"; + case InstTag::InsertEle: + return "InsertEle"; + case InstTag::ExtractEle: + return "ExtractEle"; + } + } }; class InstAlloca : public Instruction { @@ -215,14 +295,17 @@ public: TypePtr_t element_type; InstGEP(ValuePtr_t pointer, const std::vector &indices, BasicBlockPtr_t parent_bb) : Instruction(InstTag::GEP, std::make_shared(extract_type(pointer, indices)), parent_bb) { - if (typeid(pointer) == typeid(std::shared_ptr)) { + if (Value::isType(pointer)) { aim_to = std::dynamic_pointer_cast(pointer)->aim_to; } - else { - sysy_assert(typeid(pointer) == typeid(std::shared_ptr) || - typeid(pointer) == typeid(std::shared_ptr)); + else if (Value::isType(pointer) || Value::isType(pointer)){ aim_to = pointer; } + else { + LOG(WARNING) << "Unexpected pointer type" << pointer->to_string(); + aim_to = pointer; + panic("message"); + } element_type = extract_type(pointer, indices); operand_list.push_back(pointer); operand_list.insert(operand_list.end(), indices.begin(), indices.end()); @@ -232,8 +315,9 @@ public: static TypePtr_t extract_type(ValuePtr_t pointer, const std::vector &indices) { auto pointer_type = std::dynamic_pointer_cast(pointer->type); auto pointed_type = pointer_type->pointed_type; + // ptr->array if (pointed_type->type_tag == Type::TypeTag::ArrayType) { - for (int i = 1; i < indices.size() - 1; ++i) { + for (int i = 1; i < indices.size(); ++i) { pointed_type = std::dynamic_pointer_cast(pointed_type)->element_type; } } @@ -241,7 +325,8 @@ public: return pointed_type; } else { - panic("Unmatch indices and array pointer"); + LOG(WARNING) << "not returning an int-type"; + return pointed_type; } } }; diff --git a/include/visitor.h b/include/visitor.h index b0b08c3..567e0fc 100644 --- a/include/visitor.h +++ b/include/visitor.h @@ -90,10 +90,7 @@ public: } CONST0 = std::make_shared("CONST0", 0); } - std::any visitProgram(SysyParser::ProgramContext *ctx) override { - // before visiting, we add some lib functions - return this->SysyBaseVisitor::visitProgram(ctx); - } + std::any visitProgram(SysyParser::ProgramContext *ctx) override; // std::any visitCompUnit(SysyParser::CompUnitContext *ctx) override; @@ -158,7 +155,7 @@ public: std::any visitReturnStmt(SysyParser::ReturnStmtContext *ctx) override; - // std::any visitCond(SysyParser::CondContext *ctx) override; + std::any visitCond(SysyParser::CondContext *ctx) override; // std::any visitFuncRParams(SysyParser::FuncRParamsContext *ctx) override; diff --git a/scripts/compiler.py b/scripts/compiler.py index 089a626..20dcfaa 100644 --- a/scripts/compiler.py +++ b/scripts/compiler.py @@ -145,7 +145,7 @@ class Compiler: for testcase in self.testcases: Print_C.print_subheader(f"[Compiling {self.scheme} | {testcase}]") self.sy_to_ir(frontend_instr=frontend_instr, testcase=testcase, category=category) - if self.count_error >= 10: + if self.count_error >= 5: Print_C.print_error(f"Test script stopped due to too many errors") return diff --git a/src/visitor.cpp b/src/visitor.cpp index a92d7d1..c10d38b 100644 --- a/src/visitor.cpp +++ b/src/visitor.cpp @@ -39,10 +39,80 @@ static ValuePtr_t any_to_Value(const std::any &fuck_any) { ANY2VALUE(InstBranch) ANY2VALUE(InstReturn) ANY2VALUE(InstCall) + ANY2VALUE(InstGEP) LOG(ERROR) << fuck_any.type().name(); panic("Unreachable"); } +static TypePtr_t any_to_Type(const std::any &fuck_any) { + ANY2VALUE(Type) + ANY2VALUE(ArrayType) + ANY2VALUE(FunctionType) + ANY2VALUE(IntegerType) + ANY2VALUE(PointerType) + LOG(ERROR) << fuck_any.type().name(); + panic("Unreachable"); +} + +/* +int getint(),getch(),getarray(int a[]); +void putint(int a),putch(int a),putarray(int n,int a[]); +#define starttime() _sysy_starttime(__LINE__) +#define stoptime() _sysy_stoptime(__LINE__) +__attribute((constructor)) void before_main(); +__attribute((destructor)) void after_main(); +void _sysy_starttime(int lineno); +void _sysy_stoptime(int lineno); +*/ + +std::any Visitor::visitProgram(SysyParser::ProgramContext *ctx) { + +#pragma region RegisterLibFunc + auto fparam_i32 = std::make_shared("", TypeHelper::TYPE_I32); + auto pointer_type = std::make_shared(TypeHelper::TYPE_I32); + auto fparam_ptr_i32 = std::make_shared("", pointer_type); + + auto func_getint = std::make_shared("getint", TypeHelper::TYPE_I32); + // void param + _func_tab.push_name("getint", func_getint); + + auto func_getch = std::make_shared("getch", TypeHelper::TYPE_I32); + // void param + _func_tab.push_name("getch", func_getch); + + auto func_getarray = std::make_shared("getarray", TypeHelper::TYPE_I32); + func_getarray->fparam_list.push_back(fparam_ptr_i32); + _func_tab.push_name("getarray", func_getarray); + + auto func_putint = std::make_shared("putint", TypeHelper::TYPE_VOID); + func_putint->fparam_list.push_back(fparam_i32); + _func_tab.push_name("putint", func_putint); + + auto func_putch = std::make_shared("putch", TypeHelper::TYPE_VOID); + func_putch->fparam_list = {fparam_i32}; + _func_tab.push_name("putch", func_putch); + + auto func_putarray = std::make_shared("putarray", TypeHelper::TYPE_VOID); + func_putarray->fparam_list = {fparam_ptr_i32, fparam_i32}; + _func_tab.push_name("putarray", func_putarray); + + // auto func_putf = std::make_shared("putf", TypeHelper::TYPE_VOID); + // should not be used + + auto func_starttime = std::make_shared("_sysy_starttime", TypeHelper::TYPE_VOID); + func_starttime->fparam_list = {fparam_i32}; + _func_tab.push_name("starttime", func_starttime); + + auto func_stoptime = std::make_shared("_sysy_stoptime", TypeHelper::TYPE_VOID); + func_stoptime->fparam_list = {fparam_i32}; + _func_tab.push_name("stoptime", func_stoptime); + +#pragma endregion + + SysyBaseVisitor::visitProgram(ctx); + return {}; +} + std::any Visitor::visitConstDecl(SysyParser::ConstDeclContext *ctx) { for (auto constDef : ctx->constDef()) { visitConstDef(constDef); @@ -222,7 +292,7 @@ std::any Visitor::visitInitVal(SysyParser::InitValContext *ctx) { if (_state.isGlobalIint) { auto const_value = any_to_Value(visitInitVal(init_val)); // should evaluate to const int - sysy_assert(typeid(const_value) == typeid(std::shared_ptr)); + sysy_assert(Value::isType(const_value)); cur_arr.push_back(const_value); } else { @@ -347,9 +417,9 @@ std::any Visitor::visitAddExp(SysyParser::AddExpContext *ctx) { std::any Visitor::visitMulExp(SysyParser::MulExpContext *ctx) { if (_state.isConstInt) { - auto result = std::any_cast>(visitUnaryExp(ctx->unaryExp())); + auto result = std::dynamic_pointer_cast(any_to_Value(visitUnaryExp(ctx->unaryExp()))); if (ctx->mulExp()) { - auto mul_result = std::any_cast>(visitMulExp(ctx->mulExp())); + auto mul_result = std::dynamic_pointer_cast(any_to_Value(visitMulExp(ctx->mulExp()))); if (ctx->MUL()) { result->value = mul_result->value * result->value; } @@ -392,25 +462,25 @@ std::any Visitor::visitMulExp(SysyParser::MulExpContext *ctx) { // relExp: addExp | relExp ('<' | '>' | '<=' | '>=') addExp; std::any Visitor::visitRelExp(SysyParser::RelExpContext *ctx) { auto add_exp = any_to_Value(visitAddExp(ctx->addExp())); - // should always has type I32 - sysy_assert(TypeHelper::isIntegerTypeI32(add_exp->type)); if (ctx->relExp()) { auto rel_exp = any_to_Value(visitRelExp(ctx->relExp())); sysy_assert(TypeHelper::isIntegerTypeI32(rel_exp->type)); - if (ctx->relExp()->LE()) { + if (ctx->LE()) { add_exp = build_InstBinary(InstTag::Le, rel_exp, add_exp, _state.current_bb); } - else if (ctx->relExp()->LT()) { + else if (ctx->LT()) { add_exp = build_InstBinary(InstTag::Lt, rel_exp, add_exp, _state.current_bb); } - else if (ctx->relExp()->GE()) { + else if (ctx->GE()) { add_exp = build_InstBinary(InstTag::Ge, rel_exp, add_exp, _state.current_bb); } - else if (ctx->relExp()->GT()) { + else if (ctx->GT()) { add_exp = build_InstBinary(InstTag::Gt, rel_exp, add_exp, _state.current_bb); } - else + else { + LOG(ERROR) << ctx->relExp()->getStart()->getLine() << ":" << ctx->relExp()->getText(); panic("Unreachable"); + } } return add_exp; } @@ -418,10 +488,10 @@ std::any Visitor::visitRelExp(SysyParser::RelExpContext *ctx) { // eqExp: relExp | eqExp ('==' | '!=') relExp; std::any Visitor::visitEqExp(SysyParser::EqExpContext *ctx) { auto rel_exp = any_to_Value(visitRelExp(ctx->relExp())); - sysy_assert(TypeHelper::isIntegerTypeI1(rel_exp->type)); + // sysy_assert(TypeHelper::isIntegerTypeI1(rel_exp->type)); if (ctx->eqExp()) { auto eq_exp = any_to_Value(visitEqExp(ctx->eqExp())); - sysy_assert(TypeHelper::isIntegerTypeI1(eq_exp->type)); + // sysy_assert(TypeHelper::isIntegerTypeI1(eq_exp->type)); if (ctx->EQ()) { rel_exp = build_InstBinary(InstTag::Eq, eq_exp, rel_exp, _state.current_bb); } @@ -444,7 +514,6 @@ std::any Visitor::visitLAndExp(SysyParser::LAndExpContext *ctx) { for (int i = 0; i < eq_exp_list.size(); ++i) { auto next_block = build_BasicBlock("", _state.current_func); auto eq_exp = any_to_Value(visitEqExp(eq_exp_list[i])); - sysy_assert(TypeHelper::isIntegerTypeI1(eq_exp->type)); // expect a boolean auto condition = build_InstBinary(InstTag::Ne, eq_exp, CONST0, _state.current_bb); build_InstBranch(condition, next_block, ctx->false_block, _state.current_bb); _state.current_bb = next_block; @@ -456,16 +525,26 @@ std::any Visitor::visitLAndExp(SysyParser::LAndExpContext *ctx) { // @retval: Bool // lOrExp: lAndExp ('||' lAndExp)*; std::any Visitor::visitLOrExp(SysyParser::LOrExpContext *ctx) { - auto n_and_exp = ctx->lAndExp().size(); + LOG(DEBUG) << "Eval to Cond(lOrExp); lineno=" << ctx->getStart()->getLine(); + auto and_exp_list = ctx->lAndExp(); + auto n_and_exp = and_exp_list.size(); for (int i = 0; i < n_and_exp - 1; ++i) { auto next_block = build_BasicBlock("", _state.current_func); ctx->lAndExp(i)->true_block = ctx->true_block; ctx->lAndExp(i)->false_block = next_block; - visitLAndExp(ctx->lAndExp(i)); + visitLAndExp(and_exp_list[i]); _state.current_bb = next_block; } ctx->lAndExp(n_and_exp - 1)->true_block = ctx->true_block; ctx->lAndExp(n_and_exp - 1)->false_block = ctx->false_block; + visitLAndExp(ctx->lAndExp(n_and_exp-1)); + return {}; +} + +std::any Visitor::visitCond(SysyParser::CondContext *ctx) { + _state.isCondExp = true; + visitLOrExp(ctx->lOrExp()); + _state.isCondExp = false; return {}; } @@ -551,9 +630,10 @@ std::any Visitor::visitPrimaryExp(SysyParser::PrimaryExpContext *ctx) { } else if (ctx->lVal()) { auto value = any_to_Value(visitLVal(ctx->lVal())); - auto constint = std::dynamic_pointer_cast(value); + // auto constint = std::dynamic_pointer_cast(value); // actually, it is only a type assertion - return constint->value; + // return constint->value; + return value; } else if (ctx->number()) { return visitNumber(ctx->number()); @@ -579,7 +659,7 @@ std::any Visitor::visitPrimaryExp(SysyParser::PrimaryExpContext *ctx) { } // @retval: InstLoad else { - LOG(WARNING) << "lval type is pointer"; + LOG(WARNING) << "lval type is pointer: " << lval->type->type_tag; // should be InstAlloca auto ptr_type = std::dynamic_pointer_cast(lval->type); return build_InstLoad(lval, ptr_type->pointed_type, _state.current_bb); @@ -618,10 +698,11 @@ std::any Visitor::visitIntConst(SysyParser::IntConstContext *ctx) { std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { auto name = ctx->IDENT()->getText(); - LOG(DEBUG) << "Eval to lVal " << name; + LOG(DEBUG) << "Eval to lVal " << name << "; lineno=" << ctx->getStart()->getLine(); auto _lval = _scope_tab.get_name(name); sysy_assert(_lval.has_value()); auto lval = _lval.value(); + LOG(DEBUG) << "lVal found: " << lval->to_string(); // @retval: ConstantInt if (lval->type->type_tag == Type::TypeTag::IntegerType) { return {lval}; @@ -653,18 +734,19 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { // ??? Pointer // @retval: InstLoad LOG(WARNING) << "Unexpected pointer"; - auto pointed_type = std::dynamic_pointer_cast(lval)->pointed_type; + auto pointed_type = std::dynamic_pointer_cast(lval->type)->pointed_type; auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb); return inst_load; } else { // fparam array, whose first dim is represented by a pointer - auto pointed_type = std::dynamic_pointer_cast(lval)->pointed_type; - sysy_assert(pointed_type->type_tag == Type::TypeTag::ArrayType); + auto pointed_type = std::dynamic_pointer_cast(lval->type)->pointed_type; auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb); auto ptr = build_InstGEP(inst_load, {CONST0}, _state.current_bb); pointed_type = std::dynamic_pointer_cast(ptr->type)->pointed_type; + LOG(INFO) << pointed_type->to_string(); + sysy_assert(pointed_type->type_tag == Type::TypeTag::ArrayType); ValuePtr_t offset = ConstantInt::make_shared(0); auto exp_list = ctx->exp(); // calculate offset by hand: offset = (offset + exp[i]) * dim_size[i] @@ -704,7 +786,7 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { auto exp_list = ctx->exp(); // calculate offset by hand: offset = (offset + exp[i]) * dim_size[i] for (int i = 0; i < exp_list.size() - 1; ++i) { - sysy_assert(typeid(pointed_type) == typeid(std::shared_ptr)); + sysy_assert(pointed_type->type_tag == Type::TypeTag::ArrayType); auto array_type = std::dynamic_pointer_cast(pointed_type); auto exp_val = any_to_Value(visitExp(exp_list[i])); auto dim_size = ConstantInt::make_shared(array_type->element_count); @@ -752,6 +834,7 @@ std::any Visitor::visitFuncDef(SysyParser::FuncDefContext *ctx) { if (ctx->funcFParams()) { visitFuncFParams(ctx->funcFParams()); } + LOG(DEBUG) << func_obj->to_string(); visitBlock(ctx->block()); // add return // _scope_tab.leave_scope(); @@ -769,10 +852,9 @@ std::any Visitor::visitFuncDef(SysyParser::FuncDefContext *ctx) { // Directly add to function, rather than return something... std::any Visitor::visitFuncFParams(SysyParser::FuncFParamsContext *ctx) { for (auto fparam_ctx : ctx->funcFParam()) { - auto fparam_type = std::any_cast(visitFuncFParam(fparam_ctx)); - auto fparam_name = fparam_ctx->getText(); + auto fparam_type = any_to_Type(visitFuncFParam(fparam_ctx)); + auto fparam_name = fparam_ctx->IDENT()->getText(); auto fparam = std::make_shared(fparam_name, fparam_type); - _state.current_func->fparam_list.push_back(fparam); auto alloca_ = build_InstAlloca(fparam_type, _state.current_bb); build_InstStore(fparam, alloca_, _state.current_bb); _scope_tab.push_name(fparam_name, alloca_); @@ -789,7 +871,7 @@ std::any Visitor::visitFuncFParam(SysyParser::FuncFParamContext *ctx) { } else { // array type - std::vector dim_list; // the first dim must be empty, though + std::vector dim_list = {0}; // the first dim must be empty, though for (auto exp_ctx : ctx->exp()) { _state.isConstInt = true; auto exp_val = std::dynamic_pointer_cast(any_to_Value(visitExp(exp_ctx))); @@ -833,6 +915,8 @@ std::any Visitor::visitAssignStmt(SysyParser::AssignStmtContext *ctx) { // TODO: Remove RETURN in else stmt std::any Visitor::visitIfStmt(SysyParser::IfStmtContext *ctx) { + LOG(DEBUG) << "Visiting IfStmt " + << "; lineno=" << ctx->getStart()->getLine(); auto true_block = build_BasicBlock("_then", _state.current_func); auto next_block = build_BasicBlock("_next", _state.current_func); auto false_block = next_block; @@ -857,6 +941,8 @@ std::any Visitor::visitIfStmt(SysyParser::IfStmtContext *ctx) { // TODO: backpatching? I am not sure whether it is necessary std::any Visitor::visitWhileStmt(SysyParser::WhileStmtContext *ctx) { + LOG(DEBUG) << "Visiting WhileStmt " + << "; lineno=" << ctx->getStart()->getLine(); auto while_id = std::to_string(_state.loop_stmt_count); auto cond_block = build_BasicBlock("_loop_cond_" + while_id, _state.current_func); auto body_block = build_BasicBlock("_loop_body_" + while_id, _state.current_func);