diff options
Diffstat (limited to 'gcc')
25 files changed, 942 insertions, 149 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 428e852..9ba5457 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -79,7 +79,8 @@ GRS_OBJS = \ rust/rust-hir-type-check.o \ rust/rust-tyty.o \ rust/rust-tyctx.o \ - rust/rust-hir-liveness.o \ + rust/rust-hir-const-fold.o \ + rust/rust-hir-liveness.o \ $(END) # removed object files from here diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 8866575..226cec6 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -27,6 +27,7 @@ #include "rust-compile-tyty.h" #include "rust-ast-full.h" #include "rust-hir-full.h" +#include "rust-hir-const-fold-ctx.h" namespace Rust { namespace Compile { @@ -43,7 +44,8 @@ public: Context (::Backend *backend) : backend (backend), resolver (Resolver::Resolver::get ()), tyctx (Resolver::TypeCheckContext::get ()), - mappings (Analysis::Mappings::get ()) + mappings (Analysis::Mappings::get ()), + const_ctx (ConstFold::Context::get ()) { // insert the builtins auto builtins = resolver->get_builtin_types (); @@ -104,6 +106,7 @@ public: Resolver::Resolver *get_resolver () { return resolver; } Resolver::TypeCheckContext *get_tyctx () { return tyctx; } Analysis::Mappings *get_mappings () { return mappings; } + ConstFold::Context *get_const_ctx () { return const_ctx; } void push_block (Bblock *scope) { @@ -260,6 +263,7 @@ private: Resolver::Resolver *resolver; Resolver::TypeCheckContext *tyctx; Analysis::Mappings *mappings; + ConstFold::Context *const_ctx; // state std::vector<fncontext> fn_stack; @@ -420,16 +424,10 @@ public: void visit (TyTy::ArrayType &type) override { - mpz_t ival; - mpz_init_set_ui (ival, type.get_capacity ()); - - Btype *capacity_type = ctx->get_backend ()->integer_type (true, 32); - Bexpression *length - = ctx->get_backend ()->integer_constant_expression (capacity_type, ival); - Btype *element_type = TyTyResolveCompile::compile (ctx, type.get_element_type ()); - translated = ctx->get_backend ()->array_type (element_type, length); + translated + = ctx->get_backend ()->array_type (element_type, type.get_capacity ()); } void visit (TyTy::BoolType &type) override diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index f98ebc6..59ae815 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -275,7 +275,12 @@ public: return; } - Btype *array_type = TyTyResolveCompile::compile (ctx, tyty); + rust_assert (tyty->get_kind () == TyTy::TypeKind::ARRAY); + TyTy::ArrayType *array_tyty = static_cast<TyTy::ArrayType *> (tyty); + capacity_expr = array_tyty->get_capacity (); + + Btype *array_type = TyTyResolveCompile::compile (ctx, array_tyty); + rust_assert (array_type != nullptr); expr.get_internal_elements ()->accept_vis (*this); std::vector<unsigned long> indexes; @@ -302,7 +307,11 @@ public: Bexpression *translated_expr = CompileExpr::Compile (elems.get_elem_to_copy (), ctx); - for (size_t i = 0; i < elems.get_num_elements (); ++i) + size_t capacity; + bool ok = ctx->get_backend ()->const_size_cast (capacity_expr, &capacity); + rust_assert (ok); + + for (size_t i = 0; i < capacity; ++i) constructor.push_back (translated_expr); } @@ -786,9 +795,12 @@ public: } private: - CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} + CompileExpr (Context *ctx) + : HIRCompileBase (ctx), translated (nullptr), capacity_expr (nullptr) + {} Bexpression *translated; + Bexpression *capacity_expr; std::vector<Bexpression *> constructor; }; diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index c59412f..33fc45b 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -27,42 +27,6 @@ namespace Rust { namespace HIR { -class ArrayCapacityConstant : public ASTLoweringBase -{ - using Rust::HIR::ASTLoweringBase::visit; - -public: - static bool fold (AST::Expr *expr, size_t *folded_result) - { - ArrayCapacityConstant folder; - expr->accept_vis (folder); - *folded_result = folder.result; - return folder.ok; - } - - void visit (AST::LiteralExpr &expr) override - { - switch (expr.get_lit_type ()) - { - case AST::Literal::LitType::INT: { - ok = true; - std::stringstream ss (expr.as_string ()); - ss >> result; - } - break; - - default: - return; - } - } - -private: - ArrayCapacityConstant () : ok (false), result (-1) {} - - bool ok; - size_t result; -}; // namespace Resolver - class ASTLowerPathInExpression : public ASTLoweringBase { using Rust::HIR::ASTLoweringBase::visit; @@ -332,18 +296,9 @@ public: HIR::Expr *num_copies = ASTLoweringExpr::translate (elems.get_num_copies ().get ()); - size_t folded; - if (!ArrayCapacityConstant::fold (elems.get_num_copies ().get (), &folded)) - { - rust_fatal_error (elems.get_num_copies ()->get_locus_slow (), - "failed to fold capacity constant"); - return; - } - translated_array_elems = new HIR::ArrayElemsCopied (std::unique_ptr<HIR::Expr> (element), - std::unique_ptr<HIR::Expr> (num_copies), - folded); + std::unique_ptr<HIR::Expr> (num_copies)); } void visit (AST::LiteralExpr &expr) override diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 1748c6a..100c527 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -825,8 +825,6 @@ public: virtual void accept_vis (HIRVisitor &vis) = 0; - virtual size_t get_num_elements () const = 0; - protected: // pure virtual clone implementation virtual ArrayElems *clone_array_elems_impl () const = 0; @@ -870,7 +868,7 @@ public: void accept_vis (HIRVisitor &vis) override; - size_t get_num_elements () const override { return values.size (); } + size_t get_num_elements () const { return values.size (); } void iterate (std::function<bool (Expr *)> cb) { @@ -893,25 +891,19 @@ class ArrayElemsCopied : public ArrayElems { std::unique_ptr<Expr> elem_to_copy; std::unique_ptr<Expr> num_copies; - size_t folded_copy_amount; - - // TODO: should this store location data? public: // Constructor requires pointers for polymorphism ArrayElemsCopied (std::unique_ptr<Expr> copied_elem, - std::unique_ptr<Expr> copy_amount, - size_t folded_copy_amount) + std::unique_ptr<Expr> copy_amount) : elem_to_copy (std::move (copied_elem)), - num_copies (std::move (copy_amount)), - folded_copy_amount (folded_copy_amount) + num_copies (std::move (copy_amount)) {} // Copy constructor required due to unique_ptr - uses custom clone ArrayElemsCopied (ArrayElemsCopied const &other) : elem_to_copy (other.elem_to_copy->clone_expr ()), - num_copies (other.num_copies->clone_expr ()), - folded_copy_amount (other.folded_copy_amount) + num_copies (other.num_copies->clone_expr ()) {} // Overloaded assignment operator for deep copying @@ -919,7 +911,6 @@ public: { elem_to_copy = other.elem_to_copy->clone_expr (); num_copies = other.num_copies->clone_expr (); - folded_copy_amount = other.folded_copy_amount; return *this; } @@ -932,10 +923,10 @@ public: void accept_vis (HIRVisitor &vis) override; - size_t get_num_elements () const override { return folded_copy_amount; } - Expr *get_elem_to_copy () { return elem_to_copy.get (); } + Expr *get_num_copies_expr () { return num_copies.get (); } + protected: ArrayElemsCopied *clone_array_elems_impl () const override { diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h index 35e04a8..b999c41 100644 --- a/gcc/rust/resolve/rust-ast-resolve-type.h +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -217,10 +217,7 @@ public: } } - void visit (AST::ArrayType &type) override - { - type.get_elem_type ()->accept_vis (*this); - } + void visit (AST::ArrayType &type) override; void visit (AST::ReferenceType &type) override { diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index aac55e2..41c6938 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -589,5 +589,14 @@ ResolvePath::resolve_path (AST::PathInExpression *expr) } } +// rust-ast-resolve-type.h + +void +ResolveType::visit (AST::ArrayType &type) +{ + type.get_elem_type ()->accept_vis (*this); + ResolveExpr::go (type.get_size_expr ().get (), type.get_node_id ()); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h index 7c0ac6e..e71d81e 100644 --- a/gcc/rust/rust-backend.h +++ b/gcc/rust/rust-backend.h @@ -93,6 +93,11 @@ public: virtual void debug (Bvariable *) = 0; virtual void debug (Blabel *) = 0; + // const folder helpers + virtual bool const_size_cast (Bexpression *, size_t *) = 0; + virtual std::string const_size_val_to_string (Bexpression *) = 0; + virtual bool const_values_equal (Bexpression *, Bexpression *) = 0; + // Types. // Produce an error type. Actually the backend could probably just @@ -283,6 +288,9 @@ public: // going without crashing. virtual Bexpression *error_expression () = 0; + // return whether this is error_mark_node + virtual bool is_error_expression (Bexpression *) = 0; + // Create a nil pointer expression. virtual Bexpression *nil_pointer_expression () = 0; diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index b23d141..ed89c94 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -167,7 +167,6 @@ public: void debug (Blabel *t) { debug_tree (t->get_tree ()); }; // Types. - Btype *error_type () { return this->make_type (error_mark_node); } Btype *void_type () { return this->make_type (void_type_node); } @@ -176,6 +175,46 @@ public: Btype *char_type () { return this->make_type (char_type_node); } + bool const_size_cast (Bexpression *expr, size_t *result) + { + rust_assert (TREE_CONSTANT (expr->get_tree ())); + + unsigned char buf[sizeof (size_t) + 1]; + memset (buf, 0, sizeof (buf)); + + int ret = native_encode_expr (expr->get_tree (), buf, sizeof (buf), 0); + if (ret <= 0) + return false; + + size_t *tmp = (size_t *) buf; + *result = *tmp; + return true; + } + + std::string const_size_val_to_string (Bexpression *expr) + { + rust_assert (TREE_CONSTANT (expr->get_tree ())); + + unsigned char buf[sizeof (size_t) + 1]; + memset (buf, 0, sizeof (buf)); + + int ret = native_encode_expr (expr->get_tree (), buf, sizeof (buf), 0); + rust_assert (ret > 0); + + size_t *ptr = (size_t *) buf; + return std::to_string (*ptr); + } + + bool const_values_equal (Bexpression *a, Bexpression *b) + { + return operand_equal_p (a->get_tree (), b->get_tree (), + OEP_ONLY_CONST | OEP_PURE_SAME); + // printf ("comparing!\n"); + // debug_tree (a->get_tree ()); + // debug_tree (b->get_tree ()); + // printf ("ok = %s\n", ok ? "true" : "false"); + } + Btype *wchar_type () { // i think this is meant to be 32 bit from @@ -250,6 +289,11 @@ public: return this->make_expression (error_mark_node); } + bool is_error_expression (Bexpression *expr) + { + return expr->get_tree () == error_mark_node; + } + Bexpression *nil_pointer_expression () { return this->make_expression (null_pointer_node); diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 74e6852..da788b5 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -52,6 +52,7 @@ #include "rust-hir-scan-deadcode.h" #include "rust-tycheck-dump.h" #include "rust-ast-resolve-unused.h" +#include "rust-hir-const-fold.h" #include "rust-compile.h" extern Linemap * @@ -325,6 +326,9 @@ Session::init () // setup backend to GCC GIMPLE backend = rust_get_backend (); + + // the constant folder uses gcc + ConstFold::Context::init (backend); } /* Initialise default options. Actually called before handle_option, unlike init diff --git a/gcc/rust/typecheck/rust-hir-const-fold-base.h b/gcc/rust/typecheck/rust-hir-const-fold-base.h new file mode 100644 index 0000000..bcb59ef --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-const-fold-base.h @@ -0,0 +1,235 @@ +// 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_CONST_FOLD_BASE_H +#define RUST_HIR_CONST_FOLD_BASE_H + +#include "rust-diagnostics.h" +#include "rust-hir-visitor.h" +#include "rust-hir-map.h" +#include "rust-hir-type-check.h" +#include "rust-name-resolver.h" +#include "rust-hir-const-fold-ctx.h" + +namespace Rust { +namespace ConstFold { + +// base class to allow derivatives to overload as needed +class ConstFoldBase : public HIR::HIRVisitor +{ +public: + virtual ~ConstFoldBase () {} + + virtual void visit (HIR::Token &) override {} + virtual void visit (HIR::DelimTokenTree &) override {} + virtual void visit (HIR::AttrInputMetaItemContainer &) override {} + virtual void visit (HIR::IdentifierExpr &) override {} + virtual void visit (HIR::Lifetime &) override {} + virtual void visit (HIR::LifetimeParam &) override {} + virtual void visit (HIR::PathInExpression &) override {} + virtual void visit (HIR::TypePathSegment &) override {} + virtual void visit (HIR::TypePathSegmentGeneric &) override {} + virtual void visit (HIR::TypePathSegmentFunction &) override {} + virtual void visit (HIR::TypePath &) override {} + virtual void visit (HIR::QualifiedPathInExpression &) override {} + virtual void visit (HIR::QualifiedPathInType &) override {} + + virtual void visit (HIR::LiteralExpr &) override {} + virtual void visit (HIR::AttrInputLiteral &) override {} + virtual void visit (HIR::MetaItemLitExpr &) override {} + virtual void visit (HIR::MetaItemPathLit &) override {} + virtual void visit (HIR::BorrowExpr &) override {} + virtual void visit (HIR::DereferenceExpr &) override {} + virtual void visit (HIR::ErrorPropagationExpr &) override {} + virtual void visit (HIR::NegationExpr &) override {} + virtual void visit (HIR::ArithmeticOrLogicalExpr &) override {} + virtual void visit (HIR::ComparisonExpr &) override {} + virtual void visit (HIR::LazyBooleanExpr &) override {} + virtual void visit (HIR::TypeCastExpr &) override {} + virtual void visit (HIR::AssignmentExpr &) override {} + + virtual void visit (HIR::GroupedExpr &) override {} + + virtual void visit (HIR::ArrayElemsValues &) override {} + virtual void visit (HIR::ArrayElemsCopied &) override {} + virtual void visit (HIR::ArrayExpr &) override {} + virtual void visit (HIR::ArrayIndexExpr &) override {} + virtual void visit (HIR::TupleExpr &) override {} + virtual void visit (HIR::TupleIndexExpr &) override {} + virtual void visit (HIR::StructExprStruct &) override {} + + virtual void visit (HIR::StructExprFieldIdentifier &) override {} + virtual void visit (HIR::StructExprFieldIdentifierValue &) override {} + + virtual void visit (HIR::StructExprFieldIndexValue &) override {} + virtual void visit (HIR::StructExprStructFields &) override {} + virtual void visit (HIR::StructExprStructBase &) override {} + virtual void visit (HIR::StructExprTuple &) override {} + virtual void visit (HIR::StructExprUnit &) override {} + + virtual void visit (HIR::EnumExprFieldIdentifier &) override {} + virtual void visit (HIR::EnumExprFieldIdentifierValue &) override {} + + virtual void visit (HIR::EnumExprFieldIndexValue &) override {} + virtual void visit (HIR::EnumExprStruct &) override {} + virtual void visit (HIR::EnumExprTuple &) override {} + virtual void visit (HIR::EnumExprFieldless &) override {} + virtual void visit (HIR::CallExpr &) override {} + virtual void visit (HIR::MethodCallExpr &) override {} + virtual void visit (HIR::FieldAccessExpr &) override {} + virtual void visit (HIR::ClosureExprInner &) override {} + virtual void visit (HIR::BlockExpr &) override {} + virtual void visit (HIR::ClosureExprInnerTyped &) override {} + virtual void visit (HIR::ContinueExpr &) override {} + virtual void visit (HIR::BreakExpr &) override {} + virtual void visit (HIR::RangeFromToExpr &) override {} + virtual void visit (HIR::RangeFromExpr &) override {} + virtual void visit (HIR::RangeToExpr &) override {} + virtual void visit (HIR::RangeFullExpr &) override {} + virtual void visit (HIR::RangeFromToInclExpr &) override {} + virtual void visit (HIR::RangeToInclExpr &) override {} + virtual void visit (HIR::ReturnExpr &) override {} + virtual void visit (HIR::UnsafeBlockExpr &) override {} + virtual void visit (HIR::LoopExpr &) override {} + virtual void visit (HIR::WhileLoopExpr &) override {} + virtual void visit (HIR::WhileLetLoopExpr &) override {} + virtual void visit (HIR::ForLoopExpr &) override {} + virtual void visit (HIR::IfExpr &) override {} + virtual void visit (HIR::IfExprConseqElse &) override {} + virtual void visit (HIR::IfExprConseqIf &) override {} + virtual void visit (HIR::IfExprConseqIfLet &) override {} + virtual void visit (HIR::IfLetExpr &) override {} + virtual void visit (HIR::IfLetExprConseqElse &) override {} + virtual void visit (HIR::IfLetExprConseqIf &) override {} + virtual void visit (HIR::IfLetExprConseqIfLet &) override {} + + virtual void visit (HIR::MatchExpr &) override {} + virtual void visit (HIR::AwaitExpr &) override {} + virtual void visit (HIR::AsyncBlockExpr &) override {} + + virtual void visit (HIR::TypeParam &) override {} + + virtual void visit (HIR::LifetimeWhereClauseItem &) override {} + virtual void visit (HIR::TypeBoundWhereClauseItem &) override {} + virtual void visit (HIR::Method &) override {} + virtual void visit (HIR::ModuleBodied &) override {} + virtual void visit (HIR::ModuleNoBody &) override {} + virtual void visit (HIR::ExternCrate &) override {} + + virtual void visit (HIR::UseTreeGlob &) override {} + virtual void visit (HIR::UseTreeList &) override {} + virtual void visit (HIR::UseTreeRebind &) override {} + virtual void visit (HIR::UseDeclaration &) override {} + virtual void visit (HIR::Function &) override {} + virtual void visit (HIR::TypeAlias &) override {} + virtual void visit (HIR::StructStruct &) override {} + virtual void visit (HIR::TupleStruct &) override {} + virtual void visit (HIR::EnumItem &) override {} + virtual void visit (HIR::EnumItemTuple &) override {} + virtual void visit (HIR::EnumItemStruct &) override {} + virtual void visit (HIR::EnumItemDiscriminant &) override {} + virtual void visit (HIR::Enum &) override {} + virtual void visit (HIR::Union &) override {} + virtual void visit (HIR::ConstantItem &) override {} + virtual void visit (HIR::StaticItem &) override {} + virtual void visit (HIR::TraitItemFunc &) override {} + virtual void visit (HIR::TraitItemMethod &) override {} + virtual void visit (HIR::TraitItemConst &) override {} + virtual void visit (HIR::TraitItemType &) override {} + virtual void visit (HIR::Trait &) override {} + virtual void visit (HIR::InherentImpl &) override {} + virtual void visit (HIR::TraitImpl &) override {} + + virtual void visit (HIR::ExternalStaticItem &) override {} + virtual void visit (HIR::ExternalFunctionItem &) override {} + virtual void visit (HIR::ExternBlock &) override {} + + virtual void visit (HIR::MacroMatchFragment &) override {} + virtual void visit (HIR::MacroMatchRepetition &) override {} + virtual void visit (HIR::MacroMatcher &) override {} + virtual void visit (HIR::MacroRulesDefinition &) override {} + virtual void visit (HIR::MacroInvocation &) override {} + virtual void visit (HIR::MetaItemPath &) override {} + virtual void visit (HIR::MetaItemSeq &) override {} + virtual void visit (HIR::MetaWord &) override {} + virtual void visit (HIR::MetaNameValueStr &) override {} + virtual void visit (HIR::MetaListPaths &) override {} + virtual void visit (HIR::MetaListNameValueStr &) override {} + + virtual void visit (HIR::LiteralPattern &) override {} + virtual void visit (HIR::IdentifierPattern &) override {} + virtual void visit (HIR::WildcardPattern &) override {} + + virtual void visit (HIR::RangePatternBoundLiteral &) override {} + virtual void visit (HIR::RangePatternBoundPath &) override {} + virtual void visit (HIR::RangePatternBoundQualPath &) override {} + virtual void visit (HIR::RangePattern &) override {} + virtual void visit (HIR::ReferencePattern &) override {} + + virtual void visit (HIR::StructPatternFieldTuplePat &) override {} + virtual void visit (HIR::StructPatternFieldIdentPat &) override {} + virtual void visit (HIR::StructPatternFieldIdent &) override {} + virtual void visit (HIR::StructPattern &) override {} + + virtual void visit (HIR::TupleStructItemsNoRange &) override {} + virtual void visit (HIR::TupleStructItemsRange &) override {} + virtual void visit (HIR::TupleStructPattern &) override {} + + virtual void visit (HIR::TuplePatternItemsMultiple &) override {} + virtual void visit (HIR::TuplePatternItemsRanged &) override {} + virtual void visit (HIR::TuplePattern &) override {} + virtual void visit (HIR::GroupedPattern &) override {} + virtual void visit (HIR::SlicePattern &) override {} + + virtual void visit (HIR::EmptyStmt &) override {} + virtual void visit (HIR::LetStmt &) override {} + virtual void visit (HIR::ExprStmtWithoutBlock &) override {} + virtual void visit (HIR::ExprStmtWithBlock &) override {} + + virtual void visit (HIR::TraitBound &) override {} + virtual void visit (HIR::ImplTraitType &) override {} + virtual void visit (HIR::TraitObjectType &) override {} + virtual void visit (HIR::ParenthesisedType &) override {} + virtual void visit (HIR::ImplTraitTypeOneBound &) override {} + virtual void visit (HIR::TraitObjectTypeOneBound &) override {} + virtual void visit (HIR::TupleType &) override {} + virtual void visit (HIR::NeverType &) override {} + virtual void visit (HIR::RawPointerType &) override {} + virtual void visit (HIR::ReferenceType &) override {} + virtual void visit (HIR::ArrayType &) override {} + virtual void visit (HIR::SliceType &) override {} + virtual void visit (HIR::InferredType &) override {} + virtual void visit (HIR::BareFunctionType &) override {} + +protected: + ConstFoldBase () + : mappings (Analysis::Mappings::get ()), + resolver (Resolver::Resolver::get ()), + tyctx (Resolver::TypeCheckContext::get ()), ctx (Context::get ()) + {} + + Analysis::Mappings *mappings; + Resolver::Resolver *resolver; + Resolver::TypeCheckContext *tyctx; + Context *ctx; +}; + +} // namespace ConstFold +} // namespace Rust + +#endif // RUST_HIR_CONST_FOLD_BASE_H diff --git a/gcc/rust/typecheck/rust-hir-const-fold-ctx.h b/gcc/rust/typecheck/rust-hir-const-fold-ctx.h new file mode 100644 index 0000000..7ec296c --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-const-fold-ctx.h @@ -0,0 +1,53 @@ +// 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_CONST_FOLD_CTX_H +#define RUST_HIR_CONST_FOLD_CTX_H + +#include "rust-backend.h" +#include "rust-hir-map.h" + +namespace Rust { +namespace ConstFold { + +class Context +{ +public: + ~Context () {} + + static void init (::Backend *backend); + + static Context *get (); + + ::Backend *get_backend () { return backend; } + + bool lookup_const (HirId id, Bexpression **expr); + + void insert_const (HirId, Bexpression *expr); + +private: + Context (::Backend *backend); + + ::Backend *backend; + std::map<HirId, Bexpression *> ctx; +}; + +} // namespace ConstFold +} // namespace Rust + +#endif // RUST_HIR_CONST_FOLD_CTX_H diff --git a/gcc/rust/typecheck/rust-hir-const-fold.cc b/gcc/rust/typecheck/rust-hir-const-fold.cc new file mode 100644 index 0000000..ecad200 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-const-fold.cc @@ -0,0 +1,74 @@ +// 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/>. + +#include "rust-hir-const-fold-ctx.h" +#include "rust-hir-const-fold.h" + +namespace Rust { +namespace ConstFold { + +static Context *context = nullptr; + +Context::Context (::Backend *backend) : backend (backend) {} + +void +Context::init (::Backend *backend) +{ + rust_assert (context == nullptr); + context = new Context (backend); +} + +Context * +Context::get () +{ + rust_assert (context != nullptr); + return context; +} + +bool +Context::lookup_const (HirId id, Bexpression **expr) +{ + auto it = ctx.find (id); + if (it == ctx.end ()) + return false; + + *expr = it->second; + return true; +} + +void +Context::insert_const (HirId id, Bexpression *expr) +{ + rust_assert (ctx.find (id) == ctx.end ()); + ctx[id] = expr; +} + +// rust-hir-const-fold.h + +void +ConstFoldItem::visit (HIR::ConstantItem &item) +{ + auto folded_expr = ConstFoldExpr::fold (item.get_expr ()); + if (folded_expr == nullptr) + return; + + folded = folded_expr; +} + +} // namespace ConstFold +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-const-fold.h b/gcc/rust/typecheck/rust-hir-const-fold.h new file mode 100644 index 0000000..f6cd6ea --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-const-fold.h @@ -0,0 +1,364 @@ +// 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_CONST_FOLD_H +#define RUST_HIR_CONST_FOLD_H + +#include "rust-hir-const-fold-base.h" +#include "rust-tyty-visitor.h" + +namespace Rust { +namespace ConstFold { + +class ConstFoldType : public TyTy::TyVisitor +{ +public: + static Btype *fold (TyTy::BaseType *type, ::Backend *backend) + { + ConstFoldType folder (backend); + type->accept_vis (folder); + return folder.translated; + }; + + void visit (TyTy::ErrorType &) override { gcc_unreachable (); } + + void visit (TyTy::InferType &) override { gcc_unreachable (); } + + void visit (TyTy::ADTType &) override { gcc_unreachable (); } + + void visit (TyTy::ArrayType &) override { gcc_unreachable (); } + + void visit (TyTy::ReferenceType &) override { gcc_unreachable (); } + + void visit (TyTy::ParamType &) override { gcc_unreachable (); } + + void visit (TyTy::FnPtr &) override { gcc_unreachable (); } + + void visit (TyTy::FnType &) override { gcc_unreachable (); } + + void visit (TyTy::TupleType &type) override + { + if (type.num_fields () == 0) + translated = backend->void_type (); + else + gcc_unreachable (); + } + + void visit (TyTy::BoolType &) override + { + translated = backend->named_type ("bool", backend->bool_type (), + Linemap::predeclared_location ()); + } + + void visit (TyTy::IntType &type) override + { + switch (type.get_int_kind ()) + { + case TyTy::IntType::I8: + translated + = backend->named_type ("i8", backend->integer_type (false, 8), + Linemap::predeclared_location ()); + return; + + case TyTy::IntType::I16: + translated + = backend->named_type ("i16", backend->integer_type (false, 16), + Linemap::predeclared_location ()); + return; + + case TyTy::IntType::I32: + translated + = backend->named_type ("i32", backend->integer_type (false, 32), + Linemap::predeclared_location ()); + return; + + case TyTy::IntType::I64: + translated + = backend->named_type ("i64", backend->integer_type (false, 64), + Linemap::predeclared_location ()); + return; + + case TyTy::IntType::I128: + translated + = backend->named_type ("i128", backend->integer_type (false, 128), + Linemap::predeclared_location ()); + return; + } + gcc_unreachable (); + } + + void visit (TyTy::UintType &type) override + { + switch (type.get_uint_kind ()) + { + case TyTy::UintType::U8: + translated = backend->named_type ("u8", backend->integer_type (true, 8), + Linemap::predeclared_location ()); + return; + + case TyTy::UintType::U16: + translated + = backend->named_type ("u16", backend->integer_type (true, 16), + Linemap::predeclared_location ()); + return; + + case TyTy::UintType::U32: + translated + = backend->named_type ("u32", backend->integer_type (true, 32), + Linemap::predeclared_location ()); + return; + + case TyTy::UintType::U64: + translated + = backend->named_type ("u64", backend->integer_type (true, 64), + Linemap::predeclared_location ()); + return; + + case TyTy::UintType::U128: + translated + = backend->named_type ("u128", backend->integer_type (true, 128), + Linemap::predeclared_location ()); + return; + } + gcc_unreachable (); + } + + void visit (TyTy::FloatType &type) override + { + switch (type.get_float_kind ()) + { + case TyTy::FloatType::F32: + translated = backend->named_type ("f32", backend->float_type (32), + Linemap::predeclared_location ()); + return; + + case TyTy::FloatType::F64: + translated = backend->named_type ("f64", backend->float_type (64), + Linemap::predeclared_location ()); + return; + } + + gcc_unreachable (); + } + + void visit (TyTy::USizeType &) override + { + translated = backend->named_type ( + "usize", backend->integer_type (true, backend->get_pointer_size ()), + Linemap::predeclared_location ()); + } + + void visit (TyTy::ISizeType &) override + { + translated = backend->named_type ( + "isize", backend->integer_type (false, backend->get_pointer_size ()), + Linemap::predeclared_location ()); + } + + void visit (TyTy::CharType &) override + { + translated = backend->named_type ("char", backend->wchar_type (), + Linemap::predeclared_location ()); + } + + void visit (TyTy::StrType &) override + { + Btype *raw_str = backend->raw_str_type (); + translated + = backend->named_type ("str", raw_str, Linemap::predeclared_location ()); + } + +private: + ConstFoldType (::Backend *backend) + : backend (backend), translated (backend->error_type ()) + {} + + ::Backend *backend; + ::Btype *translated; +}; + +class ConstFoldItem : public ConstFoldBase +{ + using ConstFoldBase::visit; + +public: + static Bexpression *fold (HIR::Item &item) + { + ConstFoldItem folder; + item.accept_vis (folder); + if (folder.ctx->get_backend ()->is_error_expression (folder.folded)) + { + rust_error_at (item.get_locus_slow (), "non const value"); + return nullptr; + } + + folder.ctx->insert_const (item.get_mappings ().get_hirid (), folder.folded); + return folder.folded; + }; + + void visit (HIR::ConstantItem &item) override; + +private: + ConstFoldItem () + : ConstFoldBase (), folded (ctx->get_backend ()->error_expression ()) + {} + + Bexpression *folded; +}; + +class ConstFoldExpr : public ConstFoldBase +{ + using ConstFoldBase::visit; + +public: + static Bexpression *fold (HIR::Expr *expr) + { + ConstFoldExpr folder; + expr->accept_vis (folder); + if (folder.ctx->get_backend ()->is_error_expression (folder.folded)) + { + rust_error_at (expr->get_locus_slow (), "non const value"); + return nullptr; + } + + folder.ctx->insert_const (expr->get_mappings ().get_hirid (), + folder.folded); + return folder.folded; + }; + + void visit (HIR::IdentifierExpr &expr) override + { + NodeId ast_node_id = expr.get_mappings ().get_nodeid (); + + // then lookup the reference_node_id + NodeId ref_node_id = UNKNOWN_NODEID; + if (resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + { + // these ref_node_ids will resolve to a pattern declaration but we are + // interested in the definition that this refers to get the parent id + Resolver::Definition def; + if (!resolver->lookup_definition (ref_node_id, &def)) + { + rust_error_at (expr.get_locus (), + "unknown reference for resolved name"); + return; + } + ref_node_id = def.parent; + } + + if (ref_node_id == UNKNOWN_NODEID) + { + rust_error_at (expr.get_locus (), "unresolved node: %s", + expr.as_string ().c_str ()); + return; + } + + // node back to HIR + HirId ref; + if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), + ref_node_id, &ref)) + { + rust_error_at (expr.get_locus (), "reverse lookup failure"); + return; + } + + // lookup constant + ctx->lookup_const (ref, &folded); + } + + void visit (HIR::LiteralExpr &expr) override + { + auto literal_value = expr.get_literal (); + switch (expr.get_lit_type ()) + { + case HIR::Literal::INT: { + mpz_t ival; + if (mpz_init_set_str (ival, literal_value->as_string ().c_str (), 10) + != 0) + { + rust_fatal_error (expr.get_locus (), "bad number in literal"); + return; + } + + TyTy::BaseType *tyty = nullptr; + if (!tyctx->lookup_type (expr.get_mappings ().get_hirid (), &tyty)) + { + rust_fatal_error (expr.get_locus (), + "did not resolve type for this literal expr"); + return; + } + + Btype *type = ConstFoldType::fold (tyty, ctx->get_backend ()); + folded + = ctx->get_backend ()->integer_constant_expression (type, ival); + } + return; + + /* handle other literals */ + + default: + gcc_unreachable (); + return; + } + + gcc_unreachable (); + } + + void visit (HIR::ArithmeticOrLogicalExpr &expr) override + { + auto lhs = ConstFoldExpr::fold (expr.get_lhs ()); + if (lhs == nullptr) + return; + + auto rhs = ConstFoldExpr::fold (expr.get_rhs ()); + if (rhs == nullptr) + return; + + auto op = expr.get_expr_type (); + auto location = expr.get_locus (); + + folded + = ctx->get_backend ()->arithmetic_or_logical_expression (op, lhs, rhs, + location); + } + + void visit (HIR::NegationExpr &expr) override + { + auto negated_expr = ConstFoldExpr::fold (expr.get_expr ()); + if (negated_expr == nullptr) + return; + + auto op = expr.get_expr_type (); + auto location = expr.get_locus (); + + folded + = ctx->get_backend ()->negation_expression (op, negated_expr, location); + } + +private: + ConstFoldExpr () + : ConstFoldBase (), folded (ctx->get_backend ()->error_expression ()) + {} + + Bexpression *folded; +}; + +} // namespace ConstFold +} // namespace Rust + +#endif // RUST_HIR_CONST_FOLD_H diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 6b6eed0..787b37d 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -27,6 +27,7 @@ #include "rust-hir-method-resolve.h" #include "rust-hir-path-probe.h" #include "rust-substitution-mapper.h" +#include "rust-hir-const-fold.h" namespace Rust { namespace Resolver { @@ -676,21 +677,23 @@ public: return; } - TyTy::ArrayType *array_type = (TyTy::ArrayType *) infered; + TyTy::ArrayType *array_type = static_cast<TyTy::ArrayType *> (infered); infered = array_type->get_element_type ()->clone (); } void visit (HIR::ArrayExpr &expr) override { HIR::ArrayElems *elements = expr.get_internal_elements (); - size_t num_elems = elements->get_num_elements (); - // Check the type of array elements elements->accept_vis (*this); - rust_assert (infered_array_elems != nullptr); + if (infered_array_elems == nullptr) + return; + if (folded_array_capacity == nullptr) + return; infered - = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), num_elems, + = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), + folded_array_capacity, TyTy::TyVar (infered_array_elems->get_ref ())); } @@ -712,10 +715,40 @@ public: { infered_array_elems->append_reference (elem->get_ref ()); } + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, UNKNOWN_NODEID, + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + std::string capacity_str = std::to_string (elems.get_num_elements ()); + HIR::LiteralExpr implicit_literal_capacity ( + mapping, capacity_str, HIR::Literal::LitType::INT, + PrimitiveCoreType::CORETYPE_USIZE, Location ()); + + // mark the type for this implicit node + context->insert_type (mapping, new TyTy::USizeType (mapping.get_hirid ())); + + folded_array_capacity + = ConstFold::ConstFoldExpr::fold (&implicit_literal_capacity); } void visit (HIR::ArrayElemsCopied &elems) override { + auto capacity_type + = TypeCheckExpr::Resolve (elems.get_num_copies_expr (), false); + + TyTy::USizeType *expected_ty = new TyTy::USizeType ( + elems.get_num_copies_expr ()->get_mappings ().get_hirid ()); + context->insert_type (elems.get_num_copies_expr ()->get_mappings (), + expected_ty); + + auto unified = expected_ty->unify (capacity_type); + if (unified->get_kind () == TyTy::TypeKind::ERROR) + return; + + folded_array_capacity + = ConstFold::ConstFoldExpr::fold (elems.get_num_copies_expr ()); + infered_array_elems = TypeCheckExpr::Resolve (elems.get_elem_to_copy (), false); } @@ -973,7 +1006,7 @@ public: private: TypeCheckExpr (bool inside_loop) : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr), - inside_loop (inside_loop) + folded_array_capacity (nullptr), inside_loop (inside_loop) {} TyTy::BaseType *resolve_root_path (HIR::PathInExpression &expr) @@ -1057,6 +1090,8 @@ private: return (type->get_kind () == TyTy::TypeKind::INT) || (type->get_kind () == TyTy::TypeKind::UINT) || (type->get_kind () == TyTy::TypeKind::FLOAT) + || (type->get_kind () == TyTy::TypeKind::USIZE) + || (type->get_kind () == TyTy::TypeKind::ISIZE) || (type->get_kind () == TyTy::TypeKind::INFER && (((TyTy::InferType *) type)->get_infer_kind () == TyTy::InferType::INTEGRAL)) @@ -1070,6 +1105,8 @@ private: case ArithmeticOrLogicalOperator::BITWISE_XOR: return (type->get_kind () == TyTy::TypeKind::INT) || (type->get_kind () == TyTy::TypeKind::UINT) + || (type->get_kind () == TyTy::TypeKind::USIZE) + || (type->get_kind () == TyTy::TypeKind::ISIZE) || (type->get_kind () == TyTy::TypeKind::BOOL) || (type->get_kind () == TyTy::TypeKind::INFER && (((TyTy::InferType *) type)->get_infer_kind () @@ -1080,6 +1117,8 @@ private: case ArithmeticOrLogicalOperator::RIGHT_SHIFT: return (type->get_kind () == TyTy::TypeKind::INT) || (type->get_kind () == TyTy::TypeKind::UINT) + || (type->get_kind () == TyTy::TypeKind::USIZE) + || (type->get_kind () == TyTy::TypeKind::ISIZE) || (type->get_kind () == TyTy::TypeKind::INFER && (((TyTy::InferType *) type)->get_infer_kind () == TyTy::InferType::INTEGRAL)); @@ -1093,6 +1132,7 @@ private: /* The return value of visit(ArrayElemsValues&) and visit(ArrayElemsCopied&) Stores the type of array elements, if `expr` is ArrayExpr. */ TyTy::BaseType *infered_array_elems; + Bexpression *folded_array_capacity; bool inside_loop; }; // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index 7e9e862..7426a75 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -48,6 +48,9 @@ public: = TypeCheckExpr::Resolve (constant.get_expr (), false); context->insert_type (constant.get_mappings (), type->unify (expr_type)); + + // notify the constant folder of this + ConstFold::ConstFoldItem::fold (constant); } void visit (HIR::Function &function) override diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index 8b23920..d1d5681 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -140,6 +140,9 @@ public: = TypeCheckExpr::Resolve (constant.get_expr (), false); context->insert_type (constant.get_mappings (), type->unify (expr_type)); + + // notify the constant folder of this + ConstFold::ConstFoldItem::fold (constant); } void visit (HIR::Function &function) override diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index 5c21d5a..74e3ed3 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -26,45 +26,6 @@ namespace Rust { namespace Resolver { -class ArrayCapacityConstant : public TypeCheckBase -{ - using Rust::Resolver::TypeCheckBase::visit; - -public: - static bool fold (HIR::Expr *expr, size_t *folded_result) - { - ArrayCapacityConstant folder; - expr->accept_vis (folder); - *folded_result = folder.result; - return folder.ok; - } - - virtual ~ArrayCapacityConstant () {} - - void visit (HIR::LiteralExpr &expr) override - { - auto literal_value = expr.get_literal (); - switch (expr.get_lit_type ()) - { - case HIR::Literal::LitType::INT: { - ok = true; - std::stringstream ss (literal_value->as_string ()); - ss >> result; - } - break; - - default: - return; - } - } - -private: - ArrayCapacityConstant () : TypeCheckBase (), ok (false), result (-1) {} - - bool ok; - size_t result; -}; // namespace Resolver - class TypeCheckResolveGenericArguments : public TypeCheckBase { using Rust::Resolver::TypeCheckBase::visit; @@ -218,20 +179,7 @@ public: } } - void visit (HIR::ArrayType &type) override - { - size_t capacity; - if (!ArrayCapacityConstant::fold (type.get_size_expr (), &capacity)) - { - rust_error_at (type.get_size_expr ()->get_locus_slow (), - "non-constant value"); - return; - } - - TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ()); - translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (), - capacity, TyTy::TyVar (base->get_ref ())); - } + void visit (HIR::ArrayType &type) override; void visit (HIR::ReferenceType &type) override { diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index c8394c8..8f635bc 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -23,6 +23,7 @@ #include "rust-hir-type-check-expr.h" #include "rust-hir-type-check-struct-field.h" #include "rust-hir-inherent-impl-overlap.h" +#include "rust-hir-const-fold.h" extern bool saw_errors (void); @@ -392,5 +393,31 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) } } +// rust-hir-type-check-type.h + +void +TypeCheckType::visit (HIR::ArrayType &type) +{ + auto capacity_type = TypeCheckExpr::Resolve (type.get_size_expr (), false); + if (capacity_type->get_kind () == TyTy::TypeKind::ERROR) + return; + + TyTy::USizeType *expected_ty + = new TyTy::USizeType (type.get_size_expr ()->get_mappings ().get_hirid ()); + context->insert_type (type.get_size_expr ()->get_mappings (), expected_ty); + + auto unified = expected_ty->unify (capacity_type); + if (unified->get_kind () == TyTy::TypeKind::ERROR) + return; + + auto capacity = ConstFold::ConstFoldExpr::fold (type.get_size_expr ()); + if (capacity == nullptr) + return; + + TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ()); + translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (), capacity, + TyTy::TyVar (base->get_ref ())); +} + } // namespace Resolver } // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 03fe0d8..c5d2ced 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -25,6 +25,9 @@ #include "rust-hir-map.h" #include "rust-hir-type-check.h" +extern ::Backend * +rust_get_backend (); + namespace Rust { namespace TyTy { @@ -706,11 +709,12 @@ public: return; } + auto backend = rust_get_backend (); + // need to check the base types and capacity - if (type.get_capacity () != base->get_capacity ()) + if (!backend->const_values_equal (type.get_capacity (), + base->get_capacity ())) { - Location locus = mappings->lookup_location (type.get_ref ()); - rust_error_at (locus, "mismatch in array capacity"); BaseRules::visit (type); return; } diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 8378cf2..88743cb 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -26,6 +26,9 @@ #include "rust-hir-map.h" #include "rust-substitution-mapper.h" +extern ::Backend * +rust_get_backend (); + namespace Rust { namespace TyTy { @@ -801,8 +804,14 @@ ArrayType::accept_vis (TyVisitor &vis) std::string ArrayType::as_string () const { - return "[" + get_element_type ()->as_string () + ":" - + std::to_string (capacity) + "]"; + return "[" + get_element_type ()->as_string () + ":" + capacity_string () + + "]"; +} + +std::string +ArrayType::capacity_string () const +{ + return rust_get_backend ()->const_size_val_to_string (get_capacity ()); } BaseType * diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 2f343c1..e139bfd 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -19,6 +19,7 @@ #ifndef RUST_TYTY #define RUST_TYTY +#include "rust-backend.h" #include "rust-hir-map.h" #include "rust-hir-full.h" @@ -870,13 +871,13 @@ private: class ArrayType : public BaseType { public: - ArrayType (HirId ref, size_t capacity, TyVar base, + ArrayType (HirId ref, Bexpression *capacity, TyVar base, std::set<HirId> refs = std::set<HirId> ()) : BaseType (ref, ref, TypeKind::ARRAY, refs), capacity (capacity), element_type (base) {} - ArrayType (HirId ref, HirId ty_ref, size_t capacity, TyVar base, + ArrayType (HirId ref, HirId ty_ref, Bexpression *capacity, TyVar base, std::set<HirId> refs = std::set<HirId> ()) : BaseType (ref, ty_ref, TypeKind::ARRAY, refs), capacity (capacity), element_type (base) @@ -893,7 +894,8 @@ public: bool is_equal (const BaseType &other) const override; - size_t get_capacity () const { return capacity; } + Bexpression *get_capacity () const { return capacity; } + std::string capacity_string () const; BaseType *get_element_type () const; @@ -905,7 +907,7 @@ public: } private: - size_t capacity; + Bexpression *capacity; TyVar element_type; }; diff --git a/gcc/testsuite/rust.test/compile/arrays3.rs b/gcc/testsuite/rust.test/compile/arrays3.rs new file mode 100644 index 0000000..372d969 --- /dev/null +++ b/gcc/testsuite/rust.test/compile/arrays3.rs @@ -0,0 +1,6 @@ +const TEST: usize = 6; + +fn main() { + let a: [_; 12] = [123; TEST * 2]; + // { dg-warning "unused name" "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/rust.test/compile/arrays4.rs b/gcc/testsuite/rust.test/compile/arrays4.rs new file mode 100644 index 0000000..ac317fe --- /dev/null +++ b/gcc/testsuite/rust.test/compile/arrays4.rs @@ -0,0 +1,6 @@ +const TEST: usize = 4; + +fn main() { + let a: [_; TEST + 1 + 2] = [123; 7]; + // { dg-warning "unused name" "" { target *-*-* } .-1 } +} diff --git a/gcc/testsuite/rust.test/xfail_compile/arrays2.rs b/gcc/testsuite/rust.test/xfail_compile/arrays2.rs index 31ae1e2..e355080 100644 --- a/gcc/testsuite/rust.test/xfail_compile/arrays2.rs +++ b/gcc/testsuite/rust.test/xfail_compile/arrays2.rs @@ -1,4 +1,4 @@ fn main() { - let array: [i32; 5] = [1, 2, 3]; // { dg-error "mismatch in array capacity" } - // { dg-error "expected ..i32:5.. got ..i32:3.." "" { target { *-*-* } } .-1 } + let array: [i32; 5] = [1, 2, 3]; + // { dg-error "expected ..i32:5.. got ..i32:3.." "" { target { *-*-* } } .-1 } } |