aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2021-10-30 15:59:01 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-11-01 13:12:48 +0000
commitd18672f220ba9377d8f86fb228b7142e98b23a44 (patch)
tree02b816d5ae2affa2eb98e093a4c46975152b9e9b /gcc
parentfaa1a005e92237a0188311b48455be88126e3e68 (diff)
downloadgcc-d18672f220ba9377d8f86fb228b7142e98b23a44.zip
gcc-d18672f220ba9377d8f86fb228b7142e98b23a44.tar.gz
gcc-d18672f220ba9377d8f86fb228b7142e98b23a44.tar.bz2
Add type-resolution for enum items
This patch does the type resolution to actually create the types when we encounter enums within toplevel HIR::Items and HIR::Stmt conext's. We don't support actual creation of enums yet in this patch but this is an isolated building block. Co-authored-by: Philip Herron <philip.herron@embecosm.com> Addresses #79
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-enumitem.h149
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-stmt.h53
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h52
3 files changed, 254 insertions, 0 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-enumitem.h b/gcc/rust/typecheck/rust-hir-type-check-enumitem.h
new file mode 100644
index 0000000..1ab07b3
--- /dev/null
+++ b/gcc/rust/typecheck/rust-hir-type-check-enumitem.h
@@ -0,0 +1,149 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_TYPE_CHECK_ENUMITEM
+#define RUST_HIR_TYPE_CHECK_ENUMITEM
+
+#include "rust-hir-type-check-base.h"
+#include "rust-hir-full.h"
+#include "rust-hir-type-check-type.h"
+#include "rust-hir-type-check-expr.h"
+
+extern ::Backend *
+rust_get_backend ();
+
+namespace Rust {
+namespace Resolver {
+
+class TypeCheckEnumItem : public TypeCheckBase
+{
+ using Rust::Resolver::TypeCheckBase::visit;
+
+public:
+ static TyTy::VariantDef *Resolve (HIR::EnumItem *item,
+ int64_t last_discriminant)
+ {
+ TypeCheckEnumItem resolver (last_discriminant);
+ item->accept_vis (resolver);
+ return resolver.variant;
+ }
+
+ void visit (HIR::EnumItem &item) override
+ {
+ if (last_discriminant == INT64_MAX)
+ rust_error_at (item.get_locus (), "discriminant too big");
+
+ variant
+ = new TyTy::VariantDef (item.get_identifier (), last_discriminant + 1);
+ }
+
+ void visit (HIR::EnumItemDiscriminant &item) override
+ {
+ if (last_discriminant == INT64_MAX)
+ rust_error_at (item.get_locus (), "discriminant too big");
+
+ auto &discriminant = item.get_discriminant_expression ();
+ auto capacity_type = TypeCheckExpr::Resolve (discriminant.get (), false);
+ if (capacity_type->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+
+ TyTy::USizeType *expected_ty
+ = new TyTy::USizeType (discriminant->get_mappings ().get_hirid ());
+ context->insert_type (discriminant->get_mappings (), expected_ty);
+
+ auto unified = expected_ty->unify (capacity_type);
+ if (unified->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+
+ auto backend = rust_get_backend ();
+ auto folded_discriminant
+ = ConstFold::ConstFoldExpr::fold (discriminant.get ());
+ if (folded_discriminant == nullptr
+ || backend->is_error_expression (folded_discriminant))
+ return;
+
+ size_t specified_discriminant;
+ bool ok
+ = backend->const_size_cast (folded_discriminant, &specified_discriminant);
+ rust_assert (ok);
+
+ variant
+ = new TyTy::VariantDef (item.get_identifier (), specified_discriminant);
+ }
+
+ void visit (HIR::EnumItemTuple &item) override
+ {
+ if (last_discriminant == INT64_MAX)
+ rust_error_at (item.get_locus (), "discriminant too big");
+
+ std::vector<TyTy::StructFieldType *> fields;
+ size_t idx = 0;
+ for (auto &field : item.get_tuple_fields ())
+ {
+ TyTy::BaseType *field_type
+ = TypeCheckType::Resolve (field.get_field_type ().get ());
+ TyTy::StructFieldType *ty_field
+ = new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
+ std::to_string (idx), field_type);
+ fields.push_back (ty_field);
+ context->insert_type (field.get_mappings (),
+ ty_field->get_field_type ());
+ idx++;
+ }
+
+ variant
+ = new TyTy::VariantDef (item.get_identifier (),
+ TyTy::VariantDef::VariantType::TUPLE, fields);
+ }
+
+ void visit (HIR::EnumItemStruct &item) override
+ {
+ if (last_discriminant == INT64_MAX)
+ rust_error_at (item.get_locus (), "discriminant too big");
+
+ std::vector<TyTy::StructFieldType *> fields;
+ for (auto &field : item.get_struct_fields ())
+ {
+ TyTy::BaseType *field_type
+ = TypeCheckType::Resolve (field.get_field_type ().get ());
+ TyTy::StructFieldType *ty_field
+ = new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
+ field.get_field_name (), field_type);
+ fields.push_back (ty_field);
+ context->insert_type (field.get_mappings (),
+ ty_field->get_field_type ());
+ }
+
+ variant
+ = new TyTy::VariantDef (item.get_identifier (),
+ TyTy::VariantDef::VariantType::STRUCT, fields);
+ }
+
+private:
+ TypeCheckEnumItem (int64_t last_discriminant)
+ : TypeCheckBase (), variant (nullptr), last_discriminant (last_discriminant)
+ {}
+
+ TyTy::VariantDef *variant;
+ int64_t last_discriminant;
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_HIR_TYPE_CHECK_ENUMITEM
diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
index 2195968..7f98c46 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
@@ -23,6 +23,7 @@
#include "rust-hir-full.h"
#include "rust-hir-type-check-type.h"
#include "rust-hir-type-check-expr.h"
+#include "rust-hir-type-check-enumitem.h"
namespace Rust {
namespace Resolver {
@@ -187,6 +188,58 @@ public:
infered = type;
}
+ void visit (HIR::Enum &enum_decl) override
+ {
+ std::vector<TyTy::SubstitutionParamMapping> substitutions;
+ if (enum_decl.has_generics ())
+ {
+ for (auto &generic_param : enum_decl.get_generic_params ())
+ {
+ switch (generic_param.get ()->get_kind ())
+ {
+ case HIR::GenericParam::GenericKind::LIFETIME:
+ // Skipping Lifetime completely until better handling.
+ break;
+
+ case HIR::GenericParam::GenericKind::TYPE: {
+ auto param_type
+ = TypeResolveGenericParam::Resolve (generic_param.get ());
+ context->insert_type (generic_param->get_mappings (),
+ param_type);
+
+ substitutions.push_back (TyTy::SubstitutionParamMapping (
+ static_cast<HIR::TypeParam &> (*generic_param),
+ param_type));
+ }
+ break;
+ }
+ }
+ }
+
+ std::vector<TyTy::VariantDef *> variants;
+ int64_t discriminant_value = 0;
+ for (auto &variant : enum_decl.get_variants ())
+ {
+ TyTy::VariantDef *field_type
+ = TypeCheckEnumItem::Resolve (variant.get (), discriminant_value);
+
+ variants.push_back (field_type);
+ if (field_type->get_variant_type ()
+ == TyTy::VariantDef::VariantType::NUM)
+ discriminant_value = field_type->get_discriminant ();
+ }
+
+ TyTy::BaseType *type
+ = new TyTy::ADTType (enum_decl.get_mappings ().get_hirid (),
+ mappings->get_next_hir_id (),
+ enum_decl.get_identifier (),
+ TyTy::ADTType::ADTKind::ENUM, std::move (variants),
+ std::move (substitutions));
+
+ context->insert_type (enum_decl.get_mappings (), type);
+ infered = type;
+ }
+
void visit (HIR::StructStruct &struct_decl) override
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
index 4dae953..98f037e 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
@@ -24,6 +24,7 @@
#include "rust-hir-type-check-implitem.h"
#include "rust-hir-type-check-type.h"
#include "rust-hir-type-check-expr.h"
+#include "rust-hir-type-check-enumitem.h"
#include "rust-tyty.h"
namespace Rust {
@@ -188,6 +189,57 @@ public:
context->insert_type (struct_decl.get_mappings (), type);
}
+ void visit (HIR::Enum &enum_decl) override
+ {
+ std::vector<TyTy::SubstitutionParamMapping> substitutions;
+ if (enum_decl.has_generics ())
+ {
+ for (auto &generic_param : enum_decl.get_generic_params ())
+ {
+ switch (generic_param.get ()->get_kind ())
+ {
+ case HIR::GenericParam::GenericKind::LIFETIME:
+ // Skipping Lifetime completely until better handling.
+ break;
+
+ case HIR::GenericParam::GenericKind::TYPE: {
+ auto param_type
+ = TypeResolveGenericParam::Resolve (generic_param.get ());
+ context->insert_type (generic_param->get_mappings (),
+ param_type);
+
+ substitutions.push_back (TyTy::SubstitutionParamMapping (
+ static_cast<HIR::TypeParam &> (*generic_param),
+ param_type));
+ }
+ break;
+ }
+ }
+ }
+
+ std::vector<TyTy::VariantDef *> variants;
+ int64_t discriminant_value = 0;
+ for (auto &variant : enum_decl.get_variants ())
+ {
+ TyTy::VariantDef *field_type
+ = TypeCheckEnumItem::Resolve (variant.get (), discriminant_value);
+
+ variants.push_back (field_type);
+ if (field_type->get_variant_type ()
+ == TyTy::VariantDef::VariantType::NUM)
+ discriminant_value = field_type->get_discriminant ();
+ }
+
+ TyTy::BaseType *type
+ = new TyTy::ADTType (enum_decl.get_mappings ().get_hirid (),
+ mappings->get_next_hir_id (),
+ enum_decl.get_identifier (),
+ TyTy::ADTType::ADTKind::ENUM, std::move (variants),
+ std::move (substitutions));
+
+ context->insert_type (enum_decl.get_mappings (), type);
+ }
+
void visit (HIR::Union &union_decl) override
{
std::vector<TyTy::SubstitutionParamMapping> substitutions;