Skip to content

Commit

Permalink
Initialize members with no desginators
Browse files Browse the repository at this point in the history
  • Loading branch information
leewei05 committed Jun 20, 2024
1 parent af1f794 commit 93b4b97
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 5 deletions.
7 changes: 7 additions & 0 deletions include/type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ class RecordType : public Type {
/// @return The type id.
virtual std::string id() // NOLINT(readability-identifier-naming)
const noexcept = 0;
/// @return The type offset in the record.
virtual std::size_t offset( // NOLINT(readability-identifier-naming)
const std::string& id) const noexcept = 0;
/// @brief Checks if `id` is a member of the record type.
virtual bool IsMember(const std::string& id) const noexcept = 0;
/// @return The type of a member in struct or union. The unknown type if the
Expand All @@ -205,6 +208,8 @@ class StructType : public RecordType {

std::string id() // NOLINT(readability-identifier-naming)
const noexcept override;
std::size_t offset( // NOLINT(readability-identifier-naming)
const std::string& id) const noexcept override;
bool IsMember(const std::string& id) const noexcept override;
std::unique_ptr<Type> MemberType(
const std::string& id) const noexcept override;
Expand Down Expand Up @@ -232,6 +237,8 @@ class UnionType : public RecordType {

std::string id() // NOLINT(readability-identifier-naming)
const noexcept override;
std::size_t offset( // NOLINT(readability-identifier-naming)
const std::string& id) const noexcept override;
bool IsMember(const std::string& id) const noexcept override;
std::unique_ptr<Type> MemberType(
const std::string& id) const noexcept override;
Expand Down
35 changes: 30 additions & 5 deletions src/qbe_ir_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,14 +214,23 @@ void QbeIrGenerator::Visit(const FieldNode& field) {
}

void QbeIrGenerator::Visit(const RecordVarDeclNode& record_var_decl) {
const auto num = NextLocalNum();
const auto base_addr = NextLocalNum();
// TODO: support different data types. We have `int` type for now.
WriteInstr_("{} =l alloc4 {}", FuncScopeTemp{num},
WriteInstr_("{} =l alloc4 {}", FuncScopeTemp{base_addr},
record_var_decl.type->size());
id_to_num[record_var_decl.id] = num;
id_to_num[record_var_decl.id] = base_addr;

for (const auto& init : record_var_decl.inits) {
for (auto i = std::size_t{0}, e = record_var_decl.inits.size(); i < e; ++i) {
const auto& init = record_var_decl.inits.at(i);
init->Accept(*this);
const auto init_num = num_recorder.NumOfPrevExpr();

// res_addr = base_addr + offset
const int res_addr_num = NextLocalNum();
WriteInstr_("{} =l add {}, {}", FuncScopeTemp{res_addr_num},
FuncScopeTemp{base_addr}, i * init->type->size());
WriteInstr_("storew {}, {}", FuncScopeTemp{init_num},
FuncScopeTemp{res_addr_num});
}
}

Expand Down Expand Up @@ -779,7 +788,23 @@ void QbeIrGenerator::Visit(const PostfixArithExprNode& postfix_expr) {
FuncScopeTemp{id_to_num.at(id_expr->id)});
}

void QbeIrGenerator::Visit(const RecordMemExprNode& mem_expr) {}
void QbeIrGenerator::Visit(const RecordMemExprNode& mem_expr) {
mem_expr.expr->Accept(*this);
const auto num = num_recorder.NumOfPrevExpr();
const auto id_num = reg_num_to_id_num.at(num);
auto* record_type = dynamic_cast<RecordType*>(mem_expr.expr->type.get());
assert(record_type);

const auto res_addr_num = NextLocalNum();
WriteInstr_("{} =l add {}, {}", FuncScopeTemp{res_addr_num},
FuncScopeTemp{id_num}, record_type->offset(mem_expr.id));

const int res_num = NextLocalNum();
WriteInstr_("{} =w loadw {}", FuncScopeTemp{res_num},
FuncScopeTemp{res_addr_num});
reg_num_to_id_num[res_num] = res_addr_num;
num_recorder.Record(res_num);
}

void QbeIrGenerator::Visit(const UnaryExprNode& unary_expr) {
unary_expr.operand->Accept(*this);
Expand Down
16 changes: 16 additions & 0 deletions src/type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,17 @@ std::string StructType::id() const noexcept {
return id_;
}

std::size_t StructType::offset(const std::string& id) const noexcept {
for (auto i = std::size_t{0}, e = fields_.size(); i < e; ++i) {
const auto& field = fields_.at(i);
if (field->id == id) {
return i * field->type->size();
}
}

return -1;
}

bool StructType::IsMember(const std::string& id) const noexcept {
for (const auto& field : fields_) {
if (field->id == id) {
Expand Down Expand Up @@ -220,6 +231,11 @@ std::unique_ptr<Type> StructType::Clone() const {
return std::make_unique<StructType>(id_, std::move(cloned_fields));
}

std::size_t UnionType::offset(const std::string& id) const noexcept {
// Every member in union shares the same starting location.
return 0;
}

std::string UnionType::id() const noexcept {
return id_;
}
Expand Down
20 changes: 20 additions & 0 deletions test/codegen/struct.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
int main() {
struct ss;

struct birth {
int date;
int month;
int year;
};

struct birth bd1 = {3, 5, 1998};

__builtin_print(bd1.date);
__builtin_print(bd1.month);
__builtin_print(bd1.year);

bd1.date = bd1.date + 2;
__builtin_print(bd1.date);

return 0;
}
4 changes: 4 additions & 0 deletions test/codegen/struct.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
3
5
1998
5
25 changes: 25 additions & 0 deletions test/codegen/union.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
int main() {
union u;

union shape {
int square;
int circle;
int triangle;
};

// It's a legal case, but compilers like GCC may show warning of excessing elements.
// The value of the members is 3.
union shape s = {3, 4, 5};

// Every member shares the same starting memory address, so their value are the same.
__builtin_print(s.square);
__builtin_print(s.circle);
__builtin_print(s.triangle);

s.circle = 4;
__builtin_print(s.square);
__builtin_print(s.circle);
__builtin_print(s.triangle);

return 0;
}
6 changes: 6 additions & 0 deletions test/codegen/union.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
3
3
3
4
4
4

0 comments on commit 93b4b97

Please sign in to comment.