aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/Make-lang.in3
-rw-r--r--gcc/rust/backend/rust-compile-context.h16
-rw-r--r--gcc/rust/backend/rust-compile-expr.h18
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h47
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h21
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.h5
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc9
-rw-r--r--gcc/rust/rust-backend.h8
-rw-r--r--gcc/rust/rust-gcc.cc46
-rw-r--r--gcc/rust/rust-session-manager.cc4
-rw-r--r--gcc/rust/typecheck/rust-hir-const-fold-base.h235
-rw-r--r--gcc/rust/typecheck/rust-hir-const-fold-ctx.h53
-rw-r--r--gcc/rust/typecheck/rust-hir-const-fold.cc74
-rw-r--r--gcc/rust/typecheck/rust-hir-const-fold.h364
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h52
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.h3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h54
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc27
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h10
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc13
-rw-r--r--gcc/rust/typecheck/rust-tyty.h10
-rw-r--r--gcc/testsuite/rust.test/compile/arrays3.rs6
-rw-r--r--gcc/testsuite/rust.test/compile/arrays4.rs6
-rw-r--r--gcc/testsuite/rust.test/xfail_compile/arrays2.rs4
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 }
}