From 44d42d316370bd3e51834b433d1ac4208714ff17 Mon Sep 17 00:00:00 2001 From: ridethepig Date: Wed, 24 May 2023 17:05:58 +0800 Subject: [PATCH] better gep generation --- include/llir_instruction.h | 10 ++++++- src/visitor.cpp | 54 ++++++++++++++++++++++++-------------- src/visitor_llir_gen.cpp | 2 +- 3 files changed, 44 insertions(+), 22 deletions(-) diff --git a/include/llir_instruction.h b/include/llir_instruction.h index c5031f5..796d83d 100644 --- a/include/llir_instruction.h +++ b/include/llir_instruction.h @@ -56,7 +56,7 @@ public: // decltype(parent_bb->inst_list.begin()) inst_itr_in_parent; Instruction(InstTag inst_tag, TypePtr_t type, BasicBlockPtr_t parent_bb) : User("", type), tag(inst_tag), parent_bb(parent_bb) {} - virtual std::string to_string() override { + std::string tag_string() { switch (tag) { case InstTag::Add: return "add"; case InstTag::Sub: return "sub"; @@ -86,6 +86,9 @@ public: case InstTag::ExtractEle: return "ExtractEle"; } } + virtual std::string to_string() override { + return type->to_string() + " " + tag_string(); + }; }; class InstAlloca : public Instruction { @@ -200,6 +203,10 @@ public: // getelementptr , ptr {, [inrange] }* // Example: lea arr[2][3] from arr[5][4]: // &arr[2][3] = GEP [5x[4xi32]], [5x[4xi32]]* arr, i32 0, i32 2, i32 3 +// For simplicity, we want to limit the use of gep of at most 3 ops +// op0: pointer to array; +// if there is only one index, the return value has the same type as op0 +// if there is 2 index, the return value has type of arr's element class InstGEP : public Instruction { public: ValuePtr_t aim_to; @@ -216,6 +223,7 @@ public: // LOG(WARNING) << "Unexpected pointer type " << pointer->to_string(); aim_to = nullptr; } + assert(indices.size() <= 2); element_type = extract_type(pointer, indices); Add_Operand(pointer); for (auto index : indices) { diff --git a/src/visitor.cpp b/src/visitor.cpp index 5bcaa2b..dfaa86e 100644 --- a/src/visitor.cpp +++ b/src/visitor.cpp @@ -732,8 +732,8 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { return {lval}; } if (lval->type->type_tag == Type::TypeTag::PointerType) { - auto ptr_type = std::dynamic_pointer_cast(lval->type); - switch (ptr_type->pointed_type->type_tag) { + auto lval_pointed_type = shared_cast(lval->type)->pointed_type; + switch (lval_pointed_type->type_tag) { case Type::TypeTag::IntegerType: { // Int if (ctx->exp().empty()) { @@ -764,6 +764,7 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { } else { // fparam array, whose first dim is represented by a pointer +#if 0 auto pointed_type = Type::asType(lval->type)->pointed_type; auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb); auto exp_list = ctx->exp(); @@ -771,14 +772,11 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { auto exp_val = any_to_Value(visitExp(exp_list[0])); auto ptr = build_InstGEP(inst_load, {exp_val}, _state.current_bb); pointed_type = Type::asType(ptr->type)->pointed_type; - assert(Type::isType(pointed_type)); return ptr; } - // LOG(INFO) << lval->to_string() << " " << lval->type->to_string(); auto ptr = build_InstGEP(inst_load, {CONST0}, _state.current_bb); pointed_type = Type::asType(ptr->type)->pointed_type; ValuePtr_t offset = ConstantInt::make_shared(0); - // LOG(INFO) << pointed_type->to_string(); assert(Type::isType(pointed_type)); // calculate offset by hand: offset = (offset + exp[i]) * dim_size[i] @@ -809,19 +807,32 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { auto arr_ptr = build_InstGEP(ptr, {CONST0, offset}, _state.current_bb); return arr_ptr; } +#else + // for array type in fparam, say a[][5][4], the type looks like: + // alloca->pointer->array[5x4]->array[4] + auto exp_list = ctx->exp(); + auto inst_load = build_InstLoad(lval, lval_pointed_type, _state.current_bb); + ValuePtr_t ptr = inst_load; + auto exp_val = any_to_Value(visitExp(exp_list.front())); + ptr = build_InstGEP(ptr, {exp_val}, _state.current_bb); + for (int i = 1; i < exp_list.size(); ++i) { + auto exp_val = any_to_Value(visitExp(exp_list[i])); + ptr = build_InstGEP(ptr, {CONST0, exp_val}, _state.current_bb); + } + if (Type::isType(PointerType::pointedType(ptr->type))) { + ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb); + } + return ptr; +#endif } } case Type::TypeTag::ArrayType: { - if (ctx->exp().empty()) { - // passing an array to function - auto ptr = build_InstGEP(lval, {CONST0, CONST0}, _state.current_bb); - return ptr; - } // get &array[0] +#if 0 + auto exp_list = ctx->exp(); auto ptr = build_InstGEP(lval, {CONST0, CONST0}, _state.current_bb); auto pointed_type = std::dynamic_pointer_cast(ptr->type)->pointed_type; ValuePtr_t offset = ConstantInt::make_shared(0); - 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(pointed_type->type_tag == Type::TypeTag::ArrayType); @@ -834,15 +845,6 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { pointed_type = array_type->element_type; ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb); } - // for (int i = 0; i < exp_list.size() - 1; ++ i) { - // 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])); - // if (Value::isValueType(exp_val)){ - // exp_val = build_InstLoad(exp_val, pointed_type, _state.current_bb); - // } - // ptr = build_InstGEP(ptr, {CONST0, exp_val}, _state.current_bb); - // } auto exp_val = any_to_Value(visitExp(exp_list.back())); auto inst_add = build_InstBinary(InstTag::Add, offset, exp_val, _state.current_bb); offset = inst_add; // finally, we get the offset @@ -860,6 +862,18 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) { auto arr_elem_ptr = build_InstGEP(ptr, {CONST0, offset}, _state.current_bb); return arr_elem_ptr; } +#else + auto exp_list = ctx->exp(); + ValuePtr_t ptr = lval; + for (int i = 0; i < exp_list.size(); ++i) { + auto exp_val = any_to_Value(visitExp(exp_list[i])); + ptr = build_InstGEP(ptr, {CONST0, exp_val}, _state.current_bb); + } + if (Type::isType(PointerType::pointedType(ptr->type))) { + ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb); + } + return ptr; +#endif } default: panic("Unreachable"); } diff --git a/src/visitor_llir_gen.cpp b/src/visitor_llir_gen.cpp index a5702f3..ac09aed 100644 --- a/src/visitor_llir_gen.cpp +++ b/src/visitor_llir_gen.cpp @@ -313,7 +313,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list &bl case InstTag::And: case InstTag::Or: { auto inst = Value::as(_inst); - ostr << "%" << inst->ir_seqno << " = " << inst->to_string() << " "; + ostr << "%" << inst->ir_seqno << " = " << inst->tag_string() << " "; if (Value::is(inst->operand_list[0])) { auto op0 = Value::as(inst->operand_list[0]); assert(op0->ir_seqno >= 0);