Skip to content

Commit

Permalink
Return constant reference on query of member type
Browse files Browse the repository at this point in the history
Since the `MemberType` function is a query function, it should not have
to clone the type. Note that the function is no longer `noexcept` after
the change. Originally, it returned the `unknown` type when the `id` was
not a member of the record. However, since we cannot make up such an
unknown type as a temporary object and return its reference (undefined
behavior), we have to throw an exception. This is acceptable because the
type checker should already ensure that the member exists, thus querying
with a non-existing `id` indicates some internal errors.
  • Loading branch information
Lai-YT authored and leewei05 committed Jul 6, 2024
1 parent d787d64 commit 1f48b64
Show file tree
Hide file tree
Showing 4 changed files with 13 additions and 18 deletions.
13 changes: 5 additions & 8 deletions include/type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,9 @@ class RecordType : public Type {
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
/// `id` is not a member of the record type.
virtual std::unique_ptr<Type> MemberType(
const std::string& id) const noexcept = 0;
/// @return The type of a member in struct or union.
/// @throw `std::runtime_error` if the `id` is not a member of the record.
virtual const Type& MemberType(const std::string& id) const = 0;
/// @note Every member in union shares the same index 0.
/// @return The index of a member in struct or union.
/// @throw `std::runtime_error` if the `id` is not a member of the record.
Expand Down Expand Up @@ -227,8 +226,7 @@ class StructType : public RecordType {
}
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;
const Type& MemberType(const std::string& id) const override;
std::size_t MemberIndex(const std::string& id) const override;
std::size_t OffsetOf(const std::string& id) const override;
std::size_t OffsetOf(std::size_t index) const override;
Expand Down Expand Up @@ -260,8 +258,7 @@ class UnionType : public RecordType {
}
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;
const Type& MemberType(const std::string& id) const override;
std::size_t MemberIndex(const std::string& id) const override;
std::size_t OffsetOf(const std::string& id) const override;
std::size_t OffsetOf(std::size_t index) const override;
Expand Down
2 changes: 1 addition & 1 deletion src/llvm_ir_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ void LLVMIRGenerator::Visit(const RecordMemExprNode& mem_expr) {
auto res_addr = builder_.CreateStructGEP(
llvm_type, base_addr, record_type->MemberIndex(mem_expr.id));
auto res_val = builder_.CreateLoad(
builder_helper_.GetLLVMType(*(record_type->MemberType(mem_expr.id))),
builder_helper_.GetLLVMType(record_type->MemberType(mem_expr.id)),
res_addr);
val_to_id_addr[res_val] = res_addr;
val_recorder.Record(res_val);
Expand Down
14 changes: 6 additions & 8 deletions src/type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,15 +171,14 @@ bool StructType::IsMember(const std::string& id) const noexcept {
return false;
}

std::unique_ptr<Type> StructType::MemberType(
const std::string& id) const noexcept {
const Type& StructType::MemberType(const std::string& id) const {
for (const auto& field : fields_) {
if (field->id == id) {
return field->type->Clone();
return *field->type;
}
}

return std::make_unique<PrimType>(PrimitiveType::kUnknown);
throw std::runtime_error{"member not found in struct!"};
}

std::size_t StructType::MemberIndex(const std::string& id) const {
Expand Down Expand Up @@ -277,15 +276,14 @@ bool UnionType::IsMember(const std::string& id) const noexcept {
return false;
}

std::unique_ptr<Type> UnionType::MemberType(
const std::string& id) const noexcept {
const Type& UnionType::MemberType(const std::string& id) const {
for (const auto& field : fields_) {
if (field->id == id) {
return field->type->Clone();
return *field->type;
}
}

return std::make_unique<PrimType>(PrimitiveType::kUnknown);
throw std::runtime_error{"member not found in union!"};
}

std::size_t UnionType::MemberIndex(const std::string& id) const {
Expand Down
2 changes: 1 addition & 1 deletion src/type_checker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ void TypeChecker::Visit(RecordMemExprNode& mem_expr) {
if (auto* record_type =
dynamic_cast<RecordType*>((mem_expr.expr->type).get())) {
if (record_type->IsMember(mem_expr.id)) {
mem_expr.type = record_type->MemberType(mem_expr.id);
mem_expr.type = record_type->MemberType(mem_expr.id).Clone();
} else {
assert(false);
// TODO: Throw error if mem_expr.id is not a symbol's member.
Expand Down

0 comments on commit 1f48b64

Please sign in to comment.