aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-04-20 15:19:33 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-04-20 18:56:53 +0100
commit393b783549e1247dfed5b86f098fb10d1eaf6659 (patch)
tree628921f4b47bc83ab588fa3f7109ddfd7702bfd6 /gcc
parentee5afc03f94e8a76c1b1b9306849cd932d5d9090 (diff)
downloadgcc-393b783549e1247dfed5b86f098fb10d1eaf6659.zip
gcc-393b783549e1247dfed5b86f098fb10d1eaf6659.tar.gz
gcc-393b783549e1247dfed5b86f098fb10d1eaf6659.tar.bz2
Reuse fold-const.c from GCC to enforce const array capacities
Rust allows for constant eval for cases like array capacity, the initial version of this code forced the programmer to only use literals which was not correct but got the type system off the ground. This now takes advantage of the GCC backend object to offer 3 helpers. 1. check for constant Bexpression* are equal 2. extract a size_t constant value from the Bexpression* 3. to string the Bexpression constant We can get away with the extraction of the value here because we know its going to be a usize for array capacity but some thought is needed if these methods are to be reused in other cases. There is a new ConstFold namespace which should be extensible for const functions later on and const generics. Fixes: #296
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 }
}