better gep generation
This commit is contained in:
parent
67a32e446e
commit
44d42d3163
@ -56,7 +56,7 @@ public:
|
|||||||
// decltype(parent_bb->inst_list.begin()) inst_itr_in_parent;
|
// decltype(parent_bb->inst_list.begin()) inst_itr_in_parent;
|
||||||
Instruction(InstTag inst_tag, TypePtr_t type, BasicBlockPtr_t parent_bb)
|
Instruction(InstTag inst_tag, TypePtr_t type, BasicBlockPtr_t parent_bb)
|
||||||
: User("", type), tag(inst_tag), parent_bb(parent_bb) {}
|
: User("", type), tag(inst_tag), parent_bb(parent_bb) {}
|
||||||
virtual std::string to_string() override {
|
std::string tag_string() {
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case InstTag::Add: return "add";
|
case InstTag::Add: return "add";
|
||||||
case InstTag::Sub: return "sub";
|
case InstTag::Sub: return "sub";
|
||||||
@ -86,6 +86,9 @@ public:
|
|||||||
case InstTag::ExtractEle: return "ExtractEle";
|
case InstTag::ExtractEle: return "ExtractEle";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
virtual std::string to_string() override {
|
||||||
|
return type->to_string() + " " + tag_string();
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class InstAlloca : public Instruction {
|
class InstAlloca : public Instruction {
|
||||||
@ -200,6 +203,10 @@ public:
|
|||||||
// getelementptr <ty>, ptr <ptrval>{, [inrange] <ty> <idx>}*
|
// getelementptr <ty>, ptr <ptrval>{, [inrange] <ty> <idx>}*
|
||||||
// Example: lea arr[2][3] from arr[5][4]:
|
// Example: lea arr[2][3] from arr[5][4]:
|
||||||
// &arr[2][3] = GEP [5x[4xi32]], [5x[4xi32]]* arr, i32 0, i32 2, i32 3
|
// &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 {
|
class InstGEP : public Instruction {
|
||||||
public:
|
public:
|
||||||
ValuePtr_t aim_to;
|
ValuePtr_t aim_to;
|
||||||
@ -216,6 +223,7 @@ public:
|
|||||||
// LOG(WARNING) << "Unexpected pointer type " << pointer->to_string();
|
// LOG(WARNING) << "Unexpected pointer type " << pointer->to_string();
|
||||||
aim_to = nullptr;
|
aim_to = nullptr;
|
||||||
}
|
}
|
||||||
|
assert(indices.size() <= 2);
|
||||||
element_type = extract_type(pointer, indices);
|
element_type = extract_type(pointer, indices);
|
||||||
Add_Operand(pointer);
|
Add_Operand(pointer);
|
||||||
for (auto index : indices) {
|
for (auto index : indices) {
|
||||||
|
|||||||
@ -732,8 +732,8 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
|
|||||||
return {lval};
|
return {lval};
|
||||||
}
|
}
|
||||||
if (lval->type->type_tag == Type::TypeTag::PointerType) {
|
if (lval->type->type_tag == Type::TypeTag::PointerType) {
|
||||||
auto ptr_type = std::dynamic_pointer_cast<PointerType>(lval->type);
|
auto lval_pointed_type = shared_cast<PointerType>(lval->type)->pointed_type;
|
||||||
switch (ptr_type->pointed_type->type_tag) {
|
switch (lval_pointed_type->type_tag) {
|
||||||
case Type::TypeTag::IntegerType: {
|
case Type::TypeTag::IntegerType: {
|
||||||
// Int
|
// Int
|
||||||
if (ctx->exp().empty()) {
|
if (ctx->exp().empty()) {
|
||||||
@ -764,6 +764,7 @@ std::any Visitor::visitLVal(SysyParser::LValContext *ctx) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// fparam array, whose first dim is represented by a pointer
|
// fparam array, whose first dim is represented by a pointer
|
||||||
|
#if 0
|
||||||
auto pointed_type = Type::asType<PointerType>(lval->type)->pointed_type;
|
auto pointed_type = Type::asType<PointerType>(lval->type)->pointed_type;
|
||||||
auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb);
|
auto inst_load = build_InstLoad(lval, pointed_type, _state.current_bb);
|
||||||
auto exp_list = ctx->exp();
|
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 exp_val = any_to_Value(visitExp(exp_list[0]));
|
||||||
auto ptr = build_InstGEP(inst_load, {exp_val}, _state.current_bb);
|
auto ptr = build_InstGEP(inst_load, {exp_val}, _state.current_bb);
|
||||||
pointed_type = Type::asType<PointerType>(ptr->type)->pointed_type;
|
pointed_type = Type::asType<PointerType>(ptr->type)->pointed_type;
|
||||||
assert(Type::isType<IntegerType>(pointed_type));
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
// LOG(INFO) << lval->to_string() << " " << lval->type->to_string();
|
|
||||||
auto ptr = build_InstGEP(inst_load, {CONST0}, _state.current_bb);
|
auto ptr = build_InstGEP(inst_load, {CONST0}, _state.current_bb);
|
||||||
pointed_type = Type::asType<PointerType>(ptr->type)->pointed_type;
|
pointed_type = Type::asType<PointerType>(ptr->type)->pointed_type;
|
||||||
ValuePtr_t offset = ConstantInt::make_shared(0);
|
ValuePtr_t offset = ConstantInt::make_shared(0);
|
||||||
// LOG(INFO) << pointed_type->to_string();
|
|
||||||
assert(Type::isType<ArrayType>(pointed_type));
|
assert(Type::isType<ArrayType>(pointed_type));
|
||||||
|
|
||||||
// calculate offset by hand: offset = (offset + exp[i]) * dim_size[i]
|
// 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);
|
auto arr_ptr = build_InstGEP(ptr, {CONST0, offset}, _state.current_bb);
|
||||||
return arr_ptr;
|
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<ArrayType>(PointerType::pointedType(ptr->type))) {
|
||||||
|
ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb);
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case Type::TypeTag::ArrayType: {
|
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]
|
// get &array[0]
|
||||||
|
#if 0
|
||||||
|
auto exp_list = ctx->exp();
|
||||||
auto ptr = build_InstGEP(lval, {CONST0, CONST0}, _state.current_bb);
|
auto ptr = build_InstGEP(lval, {CONST0, CONST0}, _state.current_bb);
|
||||||
auto pointed_type = std::dynamic_pointer_cast<PointerType>(ptr->type)->pointed_type;
|
auto pointed_type = std::dynamic_pointer_cast<PointerType>(ptr->type)->pointed_type;
|
||||||
ValuePtr_t offset = ConstantInt::make_shared(0);
|
ValuePtr_t offset = ConstantInt::make_shared(0);
|
||||||
auto exp_list = ctx->exp();
|
|
||||||
// calculate offset by hand: offset = (offset + exp[i]) * dim_size[i]
|
// calculate offset by hand: offset = (offset + exp[i]) * dim_size[i]
|
||||||
for (int i = 0; i < exp_list.size() - 1; ++i) {
|
for (int i = 0; i < exp_list.size() - 1; ++i) {
|
||||||
sysy_assert(pointed_type->type_tag == Type::TypeTag::ArrayType);
|
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;
|
pointed_type = array_type->element_type;
|
||||||
ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb);
|
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<ArrayType>(pointed_type);
|
|
||||||
// auto exp_val = any_to_Value(visitExp(exp_list[i]));
|
|
||||||
// if (Value::isValueType<PointerType>(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 exp_val = any_to_Value(visitExp(exp_list.back()));
|
||||||
auto inst_add = build_InstBinary(InstTag::Add, offset, exp_val, _state.current_bb);
|
auto inst_add = build_InstBinary(InstTag::Add, offset, exp_val, _state.current_bb);
|
||||||
offset = inst_add; // finally, we get the offset
|
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);
|
auto arr_elem_ptr = build_InstGEP(ptr, {CONST0, offset}, _state.current_bb);
|
||||||
return arr_elem_ptr;
|
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<ArrayType>(PointerType::pointedType(ptr->type))) {
|
||||||
|
ptr = build_InstGEP(ptr, {CONST0, CONST0}, _state.current_bb);
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
default: panic("Unreachable");
|
default: panic("Unreachable");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -313,7 +313,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
|
|||||||
case InstTag::And:
|
case InstTag::And:
|
||||||
case InstTag::Or: {
|
case InstTag::Or: {
|
||||||
auto inst = Value::as<InstBinary>(_inst);
|
auto inst = Value::as<InstBinary>(_inst);
|
||||||
ostr << "%" << inst->ir_seqno << " = " << inst->to_string() << " ";
|
ostr << "%" << inst->ir_seqno << " = " << inst->tag_string() << " ";
|
||||||
if (Value::is<Instruction>(inst->operand_list[0])) {
|
if (Value::is<Instruction>(inst->operand_list[0])) {
|
||||||
auto op0 = Value::as<Instruction>(inst->operand_list[0]);
|
auto op0 = Value::as<Instruction>(inst->operand_list[0]);
|
||||||
assert(op0->ir_seqno >= 0);
|
assert(op0->ir_seqno >= 0);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user