aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2022-01-13 22:01:59 +0000
committerPhilip Herron <philip.herron@embecosm.com>2022-01-14 12:32:40 +0000
commit52780af6602763fac6297f7983878b38e0188bb9 (patch)
tree41a8d89d018f527b3f20159da1279f67aac71f40 /gcc
parent06c2a74f557ec98896c9f71ba666bd969c4735d2 (diff)
downloadgcc-52780af6602763fac6297f7983878b38e0188bb9.zip
gcc-52780af6602763fac6297f7983878b38e0188bb9.tar.gz
gcc-52780af6602763fac6297f7983878b38e0188bb9.tar.bz2
Redesign constant folding from the typechecking pass to the backend
In Rust the ArrayType has a constant capacity constraint, this means it allows for bounds checking at compile time as no variable length arrays are allowed. In order to typecheck this case we had a constant folding pass as part of the typechecking system which generated gcc tree's for the IR and enforced the constant checking along the way. Also after doing some testing GCC with optimizations turned on is capable of constant folding/propogating the compilation unit fully. Which meant we need a method of doing with regardless of optimization level to be able to be on par with what the Rust language expects we need a full proof method. Turns out the CPP front-end already does this via its constexpr mechanism to ensure that these _do_ fold correclty. Another major reason to do this change is that the original const fold pass was a striped down copy of what the backend is _already_ doing which is creating a duplication of the code generation pass. With this all unified into the code generation pass all we need to do is port over gcc/cp/constexpr.c to enforce the const rules fully but at the GCC tree level not at the typed HIR level. Now that we have unified the pass when we hit a const function we can simply emit a normal GCC function and outside of const expressions GCC will simply emit a normal CallExpr and depending on optimization level fully optimize this. If we are in a ConstDecl we will follow the rust-constexpr.cc and fold the values or error_mark_node with an apropriate error. By reusing the CPP constexpr code we _know_ it works so reusing it as much as possible is a good idea in general for this front-end. Addresses #799
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/Make-lang.in4
-rw-r--r--gcc/rust/backend/rust-compile-base.h8
-rw-r--r--gcc/rust/backend/rust-compile-context.h6
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc235
-rw-r--r--gcc/rust/backend/rust-compile-expr.h81
-rw-r--r--gcc/rust/backend/rust-compile-item.h11
-rw-r--r--gcc/rust/backend/rust-compile-pattern.cc33
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc23
-rw-r--r--gcc/rust/backend/rust-compile-stmt.h4
-rw-r--r--gcc/rust/backend/rust-compile-type.cc14
-rw-r--r--gcc/rust/backend/rust-compile-type.h5
-rw-r--r--gcc/rust/backend/rust-compile.cc76
-rw-r--r--gcc/rust/backend/rust-constexpr.cc428
-rw-r--r--gcc/rust/backend/rust-constexpr.h (renamed from gcc/rust/typecheck/rust-hir-const-fold-ctx.h)39
-rw-r--r--gcc/rust/rust-backend.h5
-rw-r--r--gcc/rust/rust-gcc.cc42
-rw-r--r--gcc/rust/rust-session-manager.cc4
-rw-r--r--gcc/rust/typecheck/rust-hir-const-fold-base.h54
-rw-r--r--gcc/rust/typecheck/rust-hir-const-fold.cc138
-rw-r--r--gcc/rust/typecheck/rust-hir-const-fold.h499
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-enumitem.h20
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h149
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.h3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-stmt.h5
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.cc23
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc23
-rw-r--r--gcc/rust/typecheck/rust-tyty-cast.h16
-rw-r--r--gcc/rust/typecheck/rust-tyty-cmp.h7
-rw-r--r--gcc/rust/typecheck/rust-tyty-coercion.h16
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h16
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc15
-rw-r--r--gcc/rust/typecheck/rust-tyty.h54
-rw-r--r--gcc/testsuite/rust/compile/arrays2.rs3
-rw-r--r--gcc/testsuite/rust/execute/torture/const_fold1.rs13
35 files changed, 1013 insertions, 1062 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 3554982..dcb2d2c 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -85,7 +85,6 @@ GRS_OBJS = \
rust/rust-tyty-bounds.o \
rust/rust-hir-type-check-util.o \
rust/rust-hir-trait-resolve.o \
- rust/rust-hir-const-fold.o \
rust/rust-hir-type-check-type.o \
rust/rust-hir-type-check-struct.o \
rust/rust-hir-address-taken.o \
@@ -98,6 +97,7 @@ GRS_OBJS = \
rust/rust-base62.o \
rust/rust-compile-expr.o \
rust/rust-compile-type.o \
+ rust/rust-constexpr.o \
$(END)
# removed object files from here
@@ -107,7 +107,7 @@ RUST_ALL_OBJS = $(GRS_OBJS) $(RUST_TARGET_OBJS)
rust_OBJS = $(RUST_ALL_OBJS) rust/rustspec.o
# The compiler itself is called rust1 (formerly grs1)
-rust1$(exeext): $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
+rust1$(exeext): $(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(RUST_ALL_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h
index b3ae1f6..2169ea5 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -44,8 +44,9 @@ protected:
bool compile_locals_for_block (Resolver::Rib &rib, tree fndecl,
std::vector<Bvariable *> &locals);
- tree coercion_site (tree compiled_ref, TyTy::BaseType *actual,
- TyTy::BaseType *expected, Location locus);
+ tree coercion_site (tree rvalue, TyTy::BaseType *actual,
+ TyTy::BaseType *expected, Location lvalue_locus,
+ Location rvalue_locus);
tree coerce_to_dyn_object (tree compiled_ref, const TyTy::BaseType *actual,
const TyTy::BaseType *expected,
@@ -57,6 +58,9 @@ protected:
std::vector<std::pair<Resolver::TraitReference *, HIR::ImplBlock *>>
&receiver_bounds,
const TyTy::BaseType *receiver, const TyTy::BaseType *root, Location locus);
+
+ bool verify_array_capacities (tree ltype, tree rtype, Location ltype_locus,
+ Location rtype_locus);
};
} // namespace Compile
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index 43c23dd..9be9801 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -27,7 +27,6 @@
#include "rust-compile-tyty.h"
#include "rust-ast-full.h"
#include "rust-hir-full.h"
-#include "rust-hir-const-fold-ctx.h"
#include "rust-mangle.h"
namespace Rust {
@@ -45,8 +44,7 @@ public:
Context (::Backend *backend)
: backend (backend), resolver (Resolver::Resolver::get ()),
tyctx (Resolver::TypeCheckContext::get ()),
- mappings (Analysis::Mappings::get ()),
- const_ctx (ConstFold::Context::get ()), mangler (Mangler ())
+ mappings (Analysis::Mappings::get ()), mangler (Mangler ())
{
// insert the builtins
auto builtins = resolver->get_builtin_types ();
@@ -110,7 +108,6 @@ 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 (tree scope)
{
@@ -315,7 +312,6 @@ private:
Resolver::Resolver *resolver;
Resolver::TypeCheckContext *tyctx;
Analysis::Mappings *mappings;
- ConstFold::Context *const_ctx;
std::set<HirId> builtin_range;
Mangler mangler;
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 9b04bbf..33237e5 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -25,10 +25,12 @@
#include "rust-hir-type-bounds.h"
#include "rust-hir-dot-operator.h"
#include "rust-compile-pattern.h"
+#include "rust-constexpr.h"
#include "fold-const.h"
#include "realmpfr.h"
#include "convert.h"
+#include "print-tree.h"
namespace Rust {
namespace Compile {
@@ -381,7 +383,11 @@ CompileExpr::visit (HIR::CallExpr &expr)
rust_assert (ok);
// coerce it if required
- rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ());
+ Location lvalue_locus
+ = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ());
+ Location rvalue_locus = argument->get_locus ();
+ rvalue = coercion_site (rvalue, actual, expected, lvalue_locus,
+ rvalue_locus);
// add it to the list
arguments.push_back (rvalue);
@@ -477,7 +483,11 @@ CompileExpr::visit (HIR::CallExpr &expr)
rust_assert (ok);
// coerce it if required
- rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ());
+ Location lvalue_locus
+ = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ());
+ Location rvalue_locus = argument->get_locus ();
+ rvalue
+ = coercion_site (rvalue, actual, expected, lvalue_locus, rvalue_locus);
// add it to the list
args.push_back (rvalue);
@@ -604,7 +614,11 @@ CompileExpr::visit (HIR::MethodCallExpr &expr)
rust_assert (ok);
// coerce it if required
- rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ());
+ Location lvalue_locus
+ = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ());
+ Location rvalue_locus = argument->get_locus ();
+ rvalue
+ = coercion_site (rvalue, actual, expected, lvalue_locus, rvalue_locus);
// add it to the list
args.push_back (rvalue);
@@ -1093,5 +1107,220 @@ CompileExpr::type_cast_expression (tree type_to_cast_to, tree expr_tree,
expr_tree);
}
+void
+CompileExpr::visit (HIR::ArrayExpr &expr)
+{
+ TyTy::BaseType *tyty = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
+ &tyty))
+ {
+ rust_fatal_error (expr.get_locus (),
+ "did not resolve type for this array expr");
+ return;
+ }
+
+ tree array_type = TyTyResolveCompile::compile (ctx, tyty);
+ if (TREE_CODE (array_type) != ARRAY_TYPE)
+ {
+ translated = error_mark_node;
+ return;
+ }
+
+ rust_assert (tyty->get_kind () == TyTy::TypeKind::ARRAY);
+ const TyTy::ArrayType &array_tyty
+ = static_cast<const TyTy::ArrayType &> (*tyty);
+
+ HIR::ArrayElems &elements = *expr.get_internal_elements ();
+ switch (elements.get_array_expr_type ())
+ {
+ case HIR::ArrayElems::ArrayExprType::VALUES: {
+ HIR::ArrayElemsValues &elems
+ = static_cast<HIR::ArrayElemsValues &> (elements);
+ translated
+ = array_value_expr (expr.get_locus (), array_tyty, array_type, elems);
+ }
+ return;
+
+ case HIR::ArrayElems::ArrayExprType::COPIED:
+ HIR::ArrayElemsCopied &elems
+ = static_cast<HIR::ArrayElemsCopied &> (elements);
+ translated
+ = array_copied_expr (expr.get_locus (), array_tyty, array_type, elems);
+ }
+}
+
+tree
+CompileExpr::array_value_expr (Location expr_locus,
+ const TyTy::ArrayType &array_tyty,
+ tree array_type, HIR::ArrayElemsValues &elems)
+{
+ std::vector<unsigned long> indexes;
+ std::vector<tree> constructor;
+ size_t i = 0;
+ for (auto &elem : elems.get_values ())
+ {
+ tree translated_expr = CompileExpr::Compile (elem.get (), ctx);
+ constructor.push_back (translated_expr);
+ indexes.push_back (i++);
+ }
+
+ return ctx->get_backend ()->array_constructor_expression (array_type, indexes,
+ constructor,
+ expr_locus);
+}
+
+tree
+CompileExpr::array_copied_expr (Location expr_locus,
+ const TyTy::ArrayType &array_tyty,
+ tree array_type, HIR::ArrayElemsCopied &elems)
+{
+ // see gcc/cp/typeck2.c:1369-1401
+ gcc_assert (TREE_CODE (array_type) == ARRAY_TYPE);
+ tree domain = TYPE_DOMAIN (array_type);
+ if (!domain)
+ return error_mark_node;
+
+ if (!TREE_CONSTANT (TYPE_MAX_VALUE (domain)))
+ {
+ rust_error_at (expr_locus, "non const capacity domain %qT", array_type);
+ return error_mark_node;
+ }
+
+ tree capacity_expr = CompileExpr::Compile (elems.get_num_copies_expr (), ctx);
+ if (!TREE_CONSTANT (capacity_expr))
+ {
+ rust_error_at (expr_locus, "non const num copies %qT", array_type);
+ return error_mark_node;
+ }
+
+ // get the compiled value
+ tree translated_expr = CompileExpr::Compile (elems.get_elem_to_copy (), ctx);
+
+ tree max_domain = TYPE_MAX_VALUE (domain);
+ tree min_domain = TYPE_MIN_VALUE (domain);
+
+ auto max = wi::to_offset (max_domain);
+ auto min = wi::to_offset (min_domain);
+ auto precision = TYPE_PRECISION (TREE_TYPE (domain));
+ auto sign = TYPE_SIGN (TREE_TYPE (domain));
+ unsigned HOST_WIDE_INT len
+ = wi::ext (max - min + 1, precision, sign).to_uhwi ();
+
+ // create the constructor
+ size_t idx = 0;
+ std::vector<unsigned long> indexes;
+ std::vector<tree> constructor;
+ for (unsigned HOST_WIDE_INT i = 0; i < len; i++)
+ {
+ constructor.push_back (translated_expr);
+ indexes.push_back (idx++);
+ }
+
+ return ctx->get_backend ()->array_constructor_expression (array_type, indexes,
+ constructor,
+ expr_locus);
+}
+
+// tree
+// CompileExpr::array_copied_expr (Location expr_locus, tree array_type,
+// HIR::ArrayElemsCopied &elems)
+// {
+// // create tmp for the result
+// fncontext fnctx = ctx->peek_fn ();
+// Location start_location = expr_locus;
+// Location end_location = expr_locus;
+// tree fndecl = fnctx.fndecl;
+// tree enclosing_scope = ctx->peek_enclosing_scope ();
+
+// bool is_address_taken = false;
+// tree result_var_stmt = nullptr;
+// Bvariable *result
+// = ctx->get_backend ()->temporary_variable (fnctx.fndecl,
+// enclosing_scope,
+// array_type, NULL,
+// is_address_taken, expr_locus,
+// &result_var_stmt);
+// ctx->add_statement (result_var_stmt);
+
+// // get the compiled value
+// tree translated_expr = CompileExpr::Compile (elems.get_elem_to_copy (),
+// ctx);
+
+// // lets assign each index in the array
+// TyTy::BaseType *capacity_tyty = nullptr;
+// HirId capacity_ty_id
+// = elems.get_num_copies_expr ()->get_mappings ().get_hirid ();
+// bool ok = ctx->get_tyctx ()->lookup_type (capacity_ty_id,
+// &capacity_tyty); rust_assert (ok); tree capacity_type =
+// TyTyResolveCompile::compile (ctx, capacity_tyty); tree capacity_expr =
+// CompileExpr::Compile (elems.get_num_copies_expr (), ctx);
+
+// // create a loop for this with assignments to array_index exprs
+// tree index_type = capacity_type;
+// Bvariable *idx
+// = ctx->get_backend ()->temporary_variable (fnctx.fndecl,
+// enclosing_scope,
+// index_type, NULL,
+// is_address_taken, expr_locus,
+// &result_var_stmt);
+// ctx->add_statement (result_var_stmt);
+
+// // set index to zero
+// tree index_lvalue = error_mark_node;
+// tree zero = build_int_cst (index_type, 0);
+// tree index_assignment
+// = ctx->get_backend ()->assignment_statement (fnctx.fndecl,
+// index_lvalue,
+// zero, expr_locus);
+// ctx->add_statement (index_assignment);
+
+// // BEGIN loop block
+// tree loop_body = ctx->get_backend ()->block (fndecl, enclosing_scope, {},
+// start_location, end_location);
+// ctx->push_block (loop_body);
+
+// // loop predicate
+// tree loop_predicate
+// = fold_build2_loc (expr_locus.gcc_location (), GE_EXPR,
+// boolean_type_node,
+// ctx->get_backend ()->var_expression (idx, expr_locus),
+// capacity_expr);
+// tree exit_expr = fold_build1_loc (expr_locus.gcc_location (), EXIT_EXPR,
+// void_type_node, loop_predicate);
+// tree break_stmt
+// = ctx->get_backend ()->expression_statement (fnctx.fndecl, exit_expr);
+// ctx->add_statement (break_stmt);
+
+// // increment index
+// tree increment
+// = fold_build2_loc (expr_locus.gcc_location (), POSTINCREMENT_EXPR,
+// index_type,
+// ctx->get_backend ()->var_expression (idx, expr_locus),
+// build_int_cst (index_type, 1));
+
+// // create index_assess
+// tree index_access = ctx->get_backend ()->array_index_expression (
+// ctx->get_backend ()->var_expression (result, expr_locus), increment,
+// expr_locus);
+
+// // create assignment to index_access
+// tree array_assignment
+// = ctx->get_backend ()->assignment_statement (fnctx.fndecl,
+// index_access,
+// translated_expr, expr_locus);
+// ctx->add_statement (array_assignment);
+
+// // END loop block
+// ctx->pop_block ();
+
+// tree loop_expr = ctx->get_backend ()->loop_expression (loop_body,
+// expr_locus); tree loop_stmt
+// = ctx->get_backend ()->expression_statement (fnctx.fndecl, loop_expr);
+// ctx->add_statement (loop_stmt);
+
+// // result is the tmp
+// return ctx->get_backend ()->var_expression (result, expr_locus);
+// }
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 2f44621..b5047d0 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -290,7 +290,9 @@ public:
expr.get_rhs ()->get_mappings ().get_hirid (), &actual);
rust_assert (ok);
- rvalue = coercion_site (rvalue, actual, expected, expr.get_locus ());
+ rvalue
+ = coercion_site (rvalue, actual, expected, expr.get_lhs ()->get_locus (),
+ expr.get_rhs ()->get_locus ());
tree assignment
= ctx->get_backend ()->assignment_statement (fn.fndecl, lvalue, rvalue,
@@ -332,56 +334,7 @@ public:
expr.get_locus ());
}
- void visit (HIR::ArrayExpr &expr) override
- {
- TyTy::BaseType *tyty = nullptr;
- if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
- &tyty))
- {
- rust_fatal_error (expr.get_locus (),
- "did not resolve type for this array expr");
- return;
- }
-
- rust_assert (tyty->get_kind () == TyTy::TypeKind::ARRAY);
- TyTy::ArrayType *array_tyty = static_cast<TyTy::ArrayType *> (tyty);
- capacity_expr = array_tyty->get_capacity ();
-
- tree array_type = TyTyResolveCompile::compile (ctx, array_tyty);
- rust_assert (array_type != nullptr);
-
- expr.get_internal_elements ()->accept_vis (*this);
- std::vector<unsigned long> indexes;
- for (size_t i = 0; i < constructor.size (); i++)
- indexes.push_back (i);
-
- translated
- = ctx->get_backend ()->array_constructor_expression (array_type, indexes,
- constructor,
- expr.get_locus ());
- }
-
- void visit (HIR::ArrayElemsValues &elems) override
- {
- for (auto &elem : elems.get_values ())
- {
- tree translated_expr = CompileExpr::Compile (elem.get (), ctx);
- constructor.push_back (translated_expr);
- }
- }
-
- void visit (HIR::ArrayElemsCopied &elems) override
- {
- tree translated_expr
- = CompileExpr::Compile (elems.get_elem_to_copy (), ctx);
-
- 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);
- }
+ void visit (HIR::ArrayExpr &expr) override;
void visit (HIR::ArithmeticOrLogicalExpr &expr) override;
@@ -605,14 +558,18 @@ public:
std::vector<tree> arguments;
for (size_t i = 0; i < struct_expr.get_fields ().size (); i++)
{
- auto &argument = struct_expr.get_fields ().at (i);
- auto rvalue = CompileStructExprField::Compile (argument.get (), ctx);
-
// assignments are coercion sites so lets convert the rvalue if
// necessary
auto respective_field = variant->get_field_at_index (i);
auto expected = respective_field->get_field_type ();
+ // process arguments
+ auto &argument = struct_expr.get_fields ().at (i);
+ auto lvalue_locus
+ = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ());
+ auto rvalue_locus = argument->get_locus ();
+ auto rvalue = CompileStructExprField::Compile (argument.get (), ctx);
+
TyTy::BaseType *actual = nullptr;
bool ok = ctx->get_tyctx ()->lookup_type (
argument->get_mappings ().get_hirid (), &actual);
@@ -621,8 +578,8 @@ public:
// compile/torture/struct_base_init_1.rs
if (ok)
{
- rvalue = coercion_site (rvalue, actual, expected,
- argument->get_locus ());
+ rvalue = coercion_site (rvalue, actual, expected, lvalue_locus,
+ rvalue_locus);
}
// add it to the list
@@ -998,15 +955,19 @@ protected:
tree type_cast_expression (tree type_to_cast_to, tree expr, Location locus);
+ tree array_value_expr (Location expr_locus, const TyTy::ArrayType &array_tyty,
+ tree array_type, HIR::ArrayElemsValues &elems);
+
+ tree array_copied_expr (Location expr_locus,
+ const TyTy::ArrayType &array_tyty, tree array_type,
+ HIR::ArrayElemsCopied &elems);
+
private:
CompileExpr (Context *ctx)
- : HIRCompileBase (ctx), translated (error_mark_node),
- capacity_expr (nullptr)
+ : HIRCompileBase (ctx), translated (error_mark_node)
{}
tree translated;
- tree capacity_expr;
- std::vector<tree> constructor;
};
} // namespace Compile
diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h
index 5af9ab3..6174950 100644
--- a/gcc/rust/backend/rust-compile-item.h
+++ b/gcc/rust/backend/rust-compile-item.h
@@ -27,6 +27,7 @@
#include "rust-compile-expr.h"
#include "rust-compile-fnparam.h"
#include "rust-compile-extern.h"
+#include "rust-constexpr.h"
namespace Rust {
namespace Compile {
@@ -97,7 +98,10 @@ public:
rust_assert (ok);
tree type = TyTyResolveCompile::compile (ctx, resolved_type);
+ tree const_type = build_qualified_type (type, TYPE_QUAL_CONST);
+
tree value = CompileExpr::Compile (constant.get_expr (), ctx);
+ tree folded_expr = ConstCtx::fold (value);
const Resolver::CanonicalPath *canonical_path = nullptr;
ok = ctx->get_mappings ()->lookup_canonical_path (
@@ -107,7 +111,8 @@ public:
std::string ident = canonical_path->get ();
tree const_expr
- = ctx->get_backend ()->named_constant_expression (type, ident, value,
+ = ctx->get_backend ()->named_constant_expression (const_type, ident,
+ folded_expr,
constant.get_locus ());
ctx->push_const (const_expr);
@@ -183,6 +188,10 @@ public:
if (is_main_fn || function.has_visibility ())
flags |= Backend::function_is_visible;
+ // is it a const function?
+ if (function.get_qualifiers ().is_const ())
+ flags |= Backend::function_read_only;
+
const Resolver::CanonicalPath *canonical_path = nullptr;
bool ok = ctx->get_mappings ()->lookup_canonical_path (
function.get_mappings ().get_crate_num (),
diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc
index 27ee487..ffda652 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -17,6 +17,8 @@
// <http://www.gnu.org/licenses/>.
#include "rust-compile-pattern.h"
+#include "rust-compile-expr.h"
+#include "rust-constexpr.h"
namespace Rust {
namespace Compile {
@@ -46,20 +48,33 @@ CompilePatternCaseLabelExpr::visit (HIR::PathInExpression &pattern)
ok = adt->lookup_variant_by_id (variant_id, &variant);
rust_assert (ok);
- mpz_t disciminantl;
- if (variant->get_variant_type () == TyTy::VariantDef::VariantType::NUM)
+ tree case_low = error_mark_node;
+ if (variant->is_specified_discriminant_node ())
{
- mpz_init_set_ui (disciminantl, variant->get_discriminant ());
+ auto discrim_node = variant->get_discriminant_node ();
+ auto &discrim_expr = discrim_node->get_discriminant_expression ();
+
+ tree discrim_expr_node = CompileExpr::Compile (discrim_expr.get (), ctx);
+ tree folded_discrim_expr = ConstCtx::fold (discrim_expr_node);
+ case_low = folded_discrim_expr;
}
else
{
- HirId variant_id = variant->get_id ();
- mpz_init_set_ui (disciminantl, variant_id);
- }
+ mpz_t disciminantl;
+ if (variant->get_variant_type () == TyTy::VariantDef::VariantType::NUM)
+ {
+ mpz_init_set_ui (disciminantl, variant->get_discriminant ());
+ }
+ else
+ {
+ HirId variant_id = variant->get_id ();
+ mpz_init_set_ui (disciminantl, variant_id);
+ }
- tree t = TyTyResolveCompile::get_implicit_enumeral_node_type (ctx);
- tree case_low
- = double_int_to_tree (t, mpz_get_double_int (t, disciminantl, true));
+ tree t = TyTyResolveCompile::get_implicit_enumeral_node_type (ctx);
+ case_low
+ = double_int_to_tree (t, mpz_get_double_int (t, disciminantl, true));
+ }
case_label_expr
= build_case_label (case_low, NULL_TREE, associated_case_label);
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index 07133b9..c1d0778 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -95,11 +95,24 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
tree compiled_adt_type = TyTyResolveCompile::compile (ctx, adt);
// make the ctor for the union
- mpz_t val;
- mpz_init_set_ui (val, variant->get_discriminant ());
- tree t = TyTyResolveCompile::get_implicit_enumeral_node_type (ctx);
- tree qualifier
- = double_int_to_tree (t, mpz_get_double_int (t, val, true));
+ tree qualifier = error_mark_node;
+ if (variant->is_specified_discriminant_node ())
+ {
+ auto discrim_node = variant->get_discriminant_node ();
+ auto &discrim_expr = discrim_node->get_discriminant_expression ();
+
+ tree discrim_expr_node
+ = CompileExpr::Compile (discrim_expr.get (), ctx);
+ tree folded_discrim_expr = ConstCtx::fold (discrim_expr_node);
+ qualifier = folded_discrim_expr;
+ }
+ else
+ {
+ mpz_t val;
+ mpz_init_set_ui (val, variant->get_discriminant ());
+ tree t = TyTyResolveCompile::get_implicit_enumeral_node_type (ctx);
+ qualifier = double_int_to_tree (t, mpz_get_double_int (t, val, true));
+ }
return ctx->get_backend ()->constructor_expression (compiled_adt_type,
true, {qualifier},
diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h
index f3ee69d..3e73cce 100644
--- a/gcc/rust/backend/rust-compile-stmt.h
+++ b/gcc/rust/backend/rust-compile-stmt.h
@@ -112,8 +112,10 @@ public:
stmt.get_init_expr ()->get_mappings ().get_hirid (), &actual);
rust_assert (ok);
+ Location lvalue_locus = stmt.get_pattern ()->get_locus ();
+ Location rvalue_locus = stmt.get_init_expr ()->get_locus ();
TyTy::BaseType *expected = ty;
- init = coercion_site (init, actual, expected, stmt.get_locus ());
+ init = coercion_site (init, actual, expected, lvalue_locus, rvalue_locus);
auto fnctx = ctx->peek_fn ();
if (ty->is_unit ())
diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc
index c147a51..d7a8ae5 100644
--- a/gcc/rust/backend/rust-compile-type.cc
+++ b/gcc/rust/backend/rust-compile-type.cc
@@ -17,8 +17,11 @@
// <http://www.gnu.org/licenses/>.
#include "rust-compile-type.h"
+#include "rust-compile-expr.h"
+#include "rust-constexpr.h"
#include "tree.h"
+#include "print-tree.h"
namespace Rust {
namespace Compile {
@@ -63,13 +66,15 @@ TyTyResolveCompile::get_implicit_enumeral_node_type (Context *ctx)
void
TyTyResolveCompile::visit (const TyTy::ErrorType &)
{
- gcc_unreachable ();
+ translated = error_mark_node;
}
+
void
TyTyResolveCompile::visit (const TyTy::InferType &)
{
- gcc_unreachable ();
+ translated = error_mark_node;
}
+
void
TyTyResolveCompile::visit (const TyTy::ClosureType &)
{
@@ -332,8 +337,11 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type)
{
tree element_type
= TyTyResolveCompile::compile (ctx, type.get_element_type ());
+ tree capacity_expr = CompileExpr::Compile (&type.get_capacity_expr (), ctx);
+ tree folded_capacity_expr = ConstCtx::fold (capacity_expr);
+
translated
- = ctx->get_backend ()->array_type (element_type, type.get_capacity ());
+ = ctx->get_backend ()->array_type (element_type, folded_capacity_expr);
}
void
diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h
index 1e05e5d..4d9c780 100644
--- a/gcc/rust/backend/rust-compile-type.h
+++ b/gcc/rust/backend/rust-compile-type.h
@@ -63,13 +63,14 @@ public:
private:
TyTyResolveCompile (Context *ctx, bool trait_object_mode)
- : ctx (ctx), trait_object_mode (trait_object_mode), translated (nullptr),
- recursion_count (0)
+ : ctx (ctx), trait_object_mode (trait_object_mode),
+ translated (error_mark_node), recursion_count (0)
{}
Context *ctx;
bool trait_object_mode;
tree translated;
+
size_t recursion_count;
static const size_t kDefaultRecusionLimit = 5;
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index 610e3aa..b12860d 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -288,21 +288,33 @@ HIRCompileBase::compile_locals_for_block (Resolver::Rib &rib, tree fndecl,
}
tree
-HIRCompileBase::coercion_site (tree compiled_ref, TyTy::BaseType *actual,
- TyTy::BaseType *expected, Location locus)
+HIRCompileBase::coercion_site (tree rvalue, TyTy::BaseType *actual,
+ TyTy::BaseType *expected, Location lvalue_locus,
+ Location rvalue_locus)
{
auto root_actual_kind = actual->get_root ()->get_kind ();
auto root_expected_kind = expected->get_root ()->get_kind ();
- if (root_expected_kind == TyTy::TypeKind::DYNAMIC
- && root_actual_kind != TyTy::TypeKind::DYNAMIC)
+ if (root_expected_kind == TyTy::TypeKind::ARRAY
+ && root_actual_kind == TyTy::TypeKind::ARRAY)
+ {
+ tree tree_rval_type
+ = TyTyResolveCompile::compile (ctx, actual->get_root ());
+ tree tree_lval_type
+ = TyTyResolveCompile::compile (ctx, expected->get_root ());
+ if (!verify_array_capacities (tree_lval_type, tree_rval_type,
+ lvalue_locus, rvalue_locus))
+ return error_mark_node;
+ }
+ else if (root_expected_kind == TyTy::TypeKind::DYNAMIC
+ && root_actual_kind != TyTy::TypeKind::DYNAMIC)
{
const TyTy::DynamicObjectType *dyn
= static_cast<const TyTy::DynamicObjectType *> (expected->get_root ());
- return coerce_to_dyn_object (compiled_ref, actual, expected, dyn, locus);
+ return coerce_to_dyn_object (rvalue, actual, expected, dyn, rvalue_locus);
}
- return compiled_ref;
+ return rvalue;
}
tree
@@ -530,5 +542,57 @@ HIRCompileBase::compute_address_for_trait_item (
true, locus);
}
+bool
+HIRCompileBase::verify_array_capacities (tree ltype, tree rtype,
+ Location lvalue_locus,
+ Location rvalue_locus)
+{
+ rust_assert (ltype != NULL_TREE);
+ rust_assert (rtype != NULL_TREE);
+
+ // lets just return ok as other errors have already occurred
+ if (ltype == error_mark_node || rtype == error_mark_node)
+ return true;
+
+ tree ltype_domain = TYPE_DOMAIN (ltype);
+ if (!ltype_domain)
+ return false;
+
+ if (!TREE_CONSTANT (TYPE_MAX_VALUE (ltype_domain)))
+ return false;
+
+ auto ltype_length
+ = wi::ext (wi::to_offset (TYPE_MAX_VALUE (ltype_domain))
+ - wi::to_offset (TYPE_MIN_VALUE (ltype_domain)) + 1,
+ TYPE_PRECISION (TREE_TYPE (ltype_domain)),
+ TYPE_SIGN (TREE_TYPE (ltype_domain)))
+ .to_uhwi ();
+
+ tree rtype_domain = TYPE_DOMAIN (rtype);
+ if (!rtype_domain)
+ return false;
+
+ if (!TREE_CONSTANT (TYPE_MAX_VALUE (rtype_domain)))
+ return false;
+
+ auto rtype_length
+ = wi::ext (wi::to_offset (TYPE_MAX_VALUE (rtype_domain))
+ - wi::to_offset (TYPE_MIN_VALUE (rtype_domain)) + 1,
+ TYPE_PRECISION (TREE_TYPE (rtype_domain)),
+ TYPE_SIGN (TREE_TYPE (rtype_domain)))
+ .to_uhwi ();
+
+ if (ltype_length != rtype_length)
+ {
+ rust_error_at (rvalue_locus,
+ "expected an array with a fixed size of %lu "
+ "elements, found one with %lu elements",
+ ltype_length, rtype_length);
+ return false;
+ }
+
+ return true;
+}
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc
new file mode 100644
index 0000000..293f110
--- /dev/null
+++ b/gcc/rust/backend/rust-constexpr.cc
@@ -0,0 +1,428 @@
+// 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-constexpr.h"
+#include "rust-location.h"
+#include "rust-diagnostics.h"
+
+#include "fold-const.h"
+#include "realmpfr.h"
+#include "convert.h"
+#include "print-tree.h"
+#include "gimplify.h"
+#include "tree-iterator.h"
+
+/* Returns true if NODE is a pointer. */
+#define TYPE_PTR_P(NODE) (TREE_CODE (NODE) == POINTER_TYPE)
+
+/* Returns true if NODE is a reference. */
+#define TYPE_REF_P(NODE) (TREE_CODE (NODE) == REFERENCE_TYPE)
+
+/* Returns true if NODE is a pointer or a reference. */
+#define INDIRECT_TYPE_P(NODE) (TYPE_PTR_P (NODE) || TYPE_REF_P (NODE))
+
+/* [basic.fundamental]
+
+ Types bool, char, wchar_t, and the signed and unsigned integer types
+ are collectively called integral types.
+
+ Note that INTEGRAL_TYPE_P, as defined in tree.h, allows enumeration
+ types as well, which is incorrect in C++. Keep these checks in
+ ascending code order. */
+#define RS_INTEGRAL_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == BOOLEAN_TYPE || TREE_CODE (TYPE) == INTEGER_TYPE)
+
+/* [basic.fundamental]
+
+ Integral and floating types are collectively called arithmetic
+ types.
+
+ As a GNU extension, we also accept complex types.
+
+ Keep these checks in ascending code order. */
+#define ARITHMETIC_TYPE_P(TYPE) \
+ (RS_INTEGRAL_TYPE_P (TYPE) || TREE_CODE (TYPE) == REAL_TYPE \
+ || TREE_CODE (TYPE) == COMPLEX_TYPE)
+
+/* True iff TYPE is cv decltype(nullptr). */
+#define NULLPTR_TYPE_P(TYPE) (TREE_CODE (TYPE) == NULLPTR_TYPE)
+
+/* [basic.types]
+
+ Arithmetic types, enumeration types, pointer types,
+ pointer-to-member types, and std::nullptr_t are collectively called
+ scalar types.
+
+ Keep these checks in ascending code order. */
+#define SCALAR_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == ENUMERAL_TYPE || ARITHMETIC_TYPE_P (TYPE) \
+ || TYPE_PTR_P (TYPE) || NULLPTR_TYPE_P (TYPE))
+
+namespace Rust {
+namespace Compile {
+
+static tree
+constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p,
+ bool unshare_p);
+tree
+decl_constant_value (tree decl, bool unshare_p);
+
+static void
+non_const_var_error (location_t loc, tree r);
+
+static tree
+get_function_named_in_call (tree t);
+
+ConstCtx::ConstCtx () : constexpr_ops_count (0) {}
+
+tree
+ConstCtx::fold (tree expr)
+{
+ tree folded = ConstCtx ().constexpr_expression (expr);
+ rust_assert (folded != NULL_TREE);
+ return folded;
+}
+
+tree
+ConstCtx::constexpr_expression (tree t)
+{
+ location_t loc = EXPR_LOCATION (t);
+ if (CONSTANT_CLASS_P (t))
+ {
+ if (TREE_OVERFLOW (t))
+ {
+ rust_error_at (Location (loc), "overflow in constant expression");
+ return t;
+ }
+
+ if (TREE_CODE (t) == INTEGER_CST && TYPE_PTR_P (TREE_TYPE (t))
+ && !integer_zerop (t))
+ {
+ // FIXME check does this actually work to print out tree types
+ rust_error_at (Location (loc),
+ "value %qE of type %qT is not a constant expression",
+ t, TREE_TYPE (t));
+ return t;
+ }
+
+ return t;
+ }
+
+ // Avoid excessively long constexpr evaluations
+ if (++constexpr_ops_count >= constexpr_ops_limit)
+ {
+ rust_error_at (
+ Location (loc),
+ "%<constexpr%> evaluation operation count exceeds limit of "
+ "%wd (use %<-fconstexpr-ops-limit=%> to increase the limit)",
+ constexpr_ops_limit);
+
+ return t;
+ }
+
+ tree r = t;
+ tree_code tcode = TREE_CODE (t);
+ switch (tcode)
+ {
+ case CONST_DECL: {
+ r = decl_constant_value (t, /*unshare_p=*/false);
+ if (TREE_CODE (r) == TARGET_EXPR
+ && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR)
+ r = TARGET_EXPR_INITIAL (r);
+ if (DECL_P (r))
+ {
+ non_const_var_error (loc, r);
+ return r;
+ }
+ }
+ break;
+
+ case POINTER_PLUS_EXPR:
+ case POINTER_DIFF_EXPR:
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ case TRUNC_MOD_EXPR:
+ case CEIL_MOD_EXPR:
+ case ROUND_MOD_EXPR:
+ case RDIV_EXPR:
+ case EXACT_DIV_EXPR:
+ case MIN_EXPR:
+ case MAX_EXPR:
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ case LROTATE_EXPR:
+ case RROTATE_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case BIT_AND_EXPR:
+ case TRUTH_XOR_EXPR:
+ case LT_EXPR:
+ case LE_EXPR:
+ case GT_EXPR:
+ case GE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ case SPACESHIP_EXPR:
+ case UNORDERED_EXPR:
+ case ORDERED_EXPR:
+ case UNLT_EXPR:
+ case UNLE_EXPR:
+ case UNGT_EXPR:
+ case UNGE_EXPR:
+ case UNEQ_EXPR:
+ case LTGT_EXPR:
+ case RANGE_EXPR:
+ case COMPLEX_EXPR:
+ r = eval_binary_expression (t);
+ break;
+
+ case CALL_EXPR:
+ r = eval_call_expression (t);
+ break;
+
+ case RETURN_EXPR:
+ rust_assert (TREE_OPERAND (t, 0) != NULL_TREE);
+ r = constexpr_expression (TREE_OPERAND (t, 0));
+ break;
+
+ case MODIFY_EXPR:
+ r = eval_store_expression (t);
+ break;
+
+ default:
+ break;
+ }
+
+ return r;
+}
+
+tree
+ConstCtx::eval_store_expression (tree t)
+{
+ tree init = TREE_OPERAND (t, 1);
+ if (TREE_CLOBBER_P (init))
+ /* Just ignore clobbers. */
+ return void_node;
+
+ /* First we figure out where we're storing to. */
+ tree target = TREE_OPERAND (t, 0);
+
+ tree type = TREE_TYPE (target);
+ bool preeval = SCALAR_TYPE_P (type) || TREE_CODE (t) == MODIFY_EXPR;
+ if (preeval)
+ {
+ /* Evaluate the value to be stored without knowing what object it will be
+ stored in, so that any side-effects happen first. */
+ init = ConstCtx::fold (init);
+ }
+
+ bool evaluated = false;
+ tree object = NULL_TREE;
+ for (tree probe = target; object == NULL_TREE;)
+ {
+ switch (TREE_CODE (probe))
+ {
+ default:
+ if (evaluated)
+ object = probe;
+ else
+ {
+ probe = constexpr_expression (probe);
+ evaluated = true;
+ }
+ break;
+ }
+ }
+
+ return init;
+}
+
+/* Subroutine of cxx_eval_constant_expression.
+ Like cxx_eval_unary_expression, except for binary expressions. */
+
+tree
+ConstCtx::eval_binary_expression (tree t)
+{
+ tree orig_lhs = TREE_OPERAND (t, 0);
+ tree orig_rhs = TREE_OPERAND (t, 1);
+ tree lhs, rhs;
+
+ lhs = constexpr_expression (orig_lhs);
+ rhs = constexpr_expression (orig_rhs);
+
+ location_t loc = EXPR_LOCATION (t);
+ enum tree_code code = TREE_CODE (t);
+ tree type = TREE_TYPE (t);
+
+ return fold_binary_loc (loc, code, type, lhs, rhs);
+}
+
+// Subroutine of cxx_eval_constant_expression.
+// Evaluate the call expression tree T in the context of OLD_CALL expression
+// evaluation.
+tree
+ConstCtx::eval_call_expression (tree t)
+{
+ tree fun = get_function_named_in_call (t);
+ return constexpr_fn_retval (DECL_SAVED_TREE (fun));
+}
+
+// Subroutine of check_constexpr_fundef. BODY is the body of a function
+// declared to be constexpr, or a sub-statement thereof. Returns the
+// return value if suitable, error_mark_node for a statement not allowed in
+// a constexpr function, or NULL_TREE if no return value was found.
+tree
+ConstCtx::constexpr_fn_retval (tree body)
+{
+ switch (TREE_CODE (body))
+ {
+ case STATEMENT_LIST: {
+ tree expr = NULL_TREE;
+ for (tree stmt : tsi_range (body))
+ {
+ tree s = constexpr_fn_retval (stmt);
+ if (s == error_mark_node)
+ return error_mark_node;
+ else if (s == NULL_TREE)
+ /* Keep iterating. */;
+ else if (expr)
+ /* Multiple return statements. */
+ return error_mark_node;
+ else
+ expr = s;
+ }
+ return expr;
+ }
+
+ case RETURN_EXPR:
+ return constexpr_expression (body);
+
+ case DECL_EXPR: {
+ tree decl = DECL_EXPR_DECL (body);
+ if (TREE_CODE (decl) == USING_DECL
+ /* Accept __func__, __FUNCTION__, and __PRETTY_FUNCTION__. */
+ || DECL_ARTIFICIAL (decl))
+ return NULL_TREE;
+ return error_mark_node;
+ }
+
+ case CLEANUP_POINT_EXPR:
+ return constexpr_fn_retval (TREE_OPERAND (body, 0));
+
+ case BIND_EXPR: {
+ tree b = BIND_EXPR_BODY (body);
+ return constexpr_fn_retval (b);
+ }
+ break;
+
+ default:
+ return error_mark_node;
+ }
+ return error_mark_node;
+}
+
+// Taken from cp/constexpr.c
+//
+// If DECL is a scalar enumeration constant or variable with a
+// constant initializer, return the initializer (or, its initializers,
+// recursively); otherwise, return DECL. If STRICT_P, the
+// initializer is only returned if DECL is a
+// constant-expression. If RETURN_AGGREGATE_CST_OK_P, it is ok to
+// return an aggregate constant. If UNSHARE_P, return an unshared
+// copy of the initializer.
+static tree
+constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p,
+ bool unshare_p)
+{
+ while (TREE_CODE (decl) == CONST_DECL)
+ {
+ tree init;
+ /* If DECL is a static data member in a template
+ specialization, we must instantiate it here. The
+ initializer for the static data member is not processed
+ until needed; we need it now. */
+
+ init = DECL_INITIAL (decl);
+ if (init == error_mark_node)
+ {
+ if (TREE_CODE (decl) == CONST_DECL)
+ /* Treat the error as a constant to avoid cascading errors on
+ excessively recursive template instantiation (c++/9335). */
+ return init;
+ else
+ return decl;
+ }
+
+ decl = init;
+ }
+ return unshare_p ? unshare_expr (decl) : decl;
+}
+
+// A more relaxed version of decl_really_constant_value, used by the
+// common C/C++ code.
+tree
+decl_constant_value (tree decl, bool unshare_p)
+{
+ return constant_value_1 (decl, /*strict_p=*/false,
+ /*return_aggregate_cst_ok_p=*/true,
+ /*unshare_p=*/unshare_p);
+}
+
+static void
+non_const_var_error (location_t loc, tree r)
+{
+ error_at (loc,
+ "the value of %qD is not usable in a constant "
+ "expression",
+ r);
+ /* Avoid error cascade. */
+ if (DECL_INITIAL (r) == error_mark_node)
+ return;
+
+ // more in cp/constexpr.c
+}
+
+static tree
+get_callee (tree call)
+{
+ if (call == NULL_TREE)
+ return call;
+ else if (TREE_CODE (call) == CALL_EXPR)
+ return CALL_EXPR_FN (call);
+
+ return NULL_TREE;
+}
+
+// We have an expression tree T that represents a call, either CALL_EXPR
+// or AGGR_INIT_EXPR. If the call is lexically to a named function,
+// return the _DECL for that function.
+static tree
+get_function_named_in_call (tree t)
+{
+ tree fun = get_callee (t);
+ if (fun && TREE_CODE (fun) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (fun, 0)) == FUNCTION_DECL)
+ fun = TREE_OPERAND (fun, 0);
+ return fun;
+}
+
+} // namespace Compile
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-const-fold-ctx.h b/gcc/rust/backend/rust-constexpr.h
index a3f5a16..40d9159 100644
--- a/gcc/rust/typecheck/rust-hir-const-fold-ctx.h
+++ b/gcc/rust/backend/rust-constexpr.h
@@ -1,5 +1,3 @@
-// Copyright (C) 2020-2021 Free Software Foundation, Inc.
-
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
@@ -16,38 +14,33 @@
// 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
+#ifndef RUST_CONSTEXPR
+#define RUST_CONSTEXPR
-#include "rust-backend.h"
-#include "rust-hir-map.h"
+#include "rust-system.h"
+#include "tree.h"
namespace Rust {
-namespace ConstFold {
+namespace Compile {
-class Context
+class ConstCtx
{
public:
- ~Context () {}
-
- static void init (::Backend *backend);
-
- static Context *get ();
-
- ::Backend *get_backend () { return backend; }
-
- bool lookup_const (HirId id, tree *expr);
+ static tree fold (tree);
- void insert_const (HirId, tree expr);
+ tree constexpr_expression (tree);
+ tree eval_binary_expression (tree);
+ tree eval_call_expression (tree);
+ tree constexpr_fn_retval (tree);
+ tree eval_store_expression (tree);
private:
- Context (::Backend *backend);
+ ConstCtx ();
- ::Backend *backend;
- std::map<HirId, tree> ctx;
+ HOST_WIDE_INT constexpr_ops_count;
};
-} // namespace ConstFold
+} // namespace Compile
} // namespace Rust
-#endif // RUST_HIR_CONST_FOLD_CTX_H
+#endif // RUST_CONSTEXPR
diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h
index 43a81f2..98aaae9 100644
--- a/gcc/rust/rust-backend.h
+++ b/gcc/rust/rust-backend.h
@@ -74,11 +74,6 @@ public:
virtual void debug (tree) = 0;
virtual void debug (Bvariable *) = 0;
- // const folder helpers
- virtual bool const_size_cast (tree, size_t *) = 0;
- virtual std::string const_size_val_to_string (tree) = 0;
- virtual bool const_values_equal (tree, tree) = 0;
-
static Rust::ABI get_abi_from_string (const std::string &abi, Location locus)
{
if (abi.compare ("rust") == 0)
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index 43716d9..1fdba7a 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -137,45 +137,6 @@ public:
tree char_type () { return char_type_node; }
- bool const_size_cast (tree expr, size_t *result)
- {
- rust_assert (TREE_CONSTANT (expr));
-
- unsigned char buf[sizeof (size_t) + 1];
- memset (buf, 0, sizeof (buf));
-
- int ret = native_encode_expr (expr, 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 (tree expr)
- {
- rust_assert (TREE_CONSTANT (expr));
-
- unsigned char buf[sizeof (size_t) + 1];
- memset (buf, 0, sizeof (buf));
-
- int ret = native_encode_expr (expr, buf, sizeof (buf), 0);
- rust_assert (ret > 0);
-
- size_t *ptr = (size_t *) buf;
- return std::to_string (*ptr);
- }
-
- bool const_values_equal (tree a, tree b)
- {
- return operand_equal_p (a, b, 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");
- }
-
tree wchar_type ()
{
tree wchar = make_unsigned_type (32);
@@ -1672,6 +1633,9 @@ Gcc_backend::arithmetic_or_logical_expression (ArithmeticOrLogicalOperator op,
/* Construct a new tree and build an expression from it. */
auto new_tree = fold_build2_loc (location.gcc_location (), tree_code,
tree_type, left_tree, right_tree);
+ TREE_CONSTANT (new_tree)
+ = TREE_CONSTANT (left_tree) && TREE_CONSTANT (right_tree);
+
if (floating_point && extended_type != NULL_TREE)
new_tree = convert (original_type, new_tree);
return new_tree;
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index b844e3b..dccaffe 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -52,7 +52,6 @@
#include "rust-lint-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 *
@@ -330,9 +329,6 @@ Session::init ()
// set the default crate name
options.set_crate_name (kDefaultCrateName);
-
- // 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
deleted file mode 100644
index 2ab4450..0000000
--- a/gcc/rust/typecheck/rust-hir-const-fold-base.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (C) 2020-2021 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::HIRFullVisitorBase
-{
-public:
- virtual ~ConstFoldBase () {}
-
-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.cc b/gcc/rust/typecheck/rust-hir-const-fold.cc
deleted file mode 100644
index 1545c1a..0000000
--- a/gcc/rust/typecheck/rust-hir-const-fold.cc
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (C) 2020-2021 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, tree *expr)
-{
- auto it = ctx.find (id);
- if (it == ctx.end ())
- return false;
-
- *expr = it->second;
- return true;
-}
-
-void
-Context::insert_const (HirId id, tree 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 ());
-
- folded = folded_expr;
-}
-
-void
-ConstFoldArrayElems::visit (HIR::ArrayElemsValues &elems)
-{
- unsigned long index = 0;
- std::vector<unsigned long> indices;
- std::vector<tree> values;
-
- 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 array elems values");
- return;
- }
-
- tree type = ConstFoldType::fold (tyty, ctx->get_backend ());
-
- for (auto &value : elems.get_values ())
- {
- indices.push_back (index++);
- values.push_back (ConstFoldExpr::fold (value.get ()));
- }
-
- folded
- = ctx->get_backend ()->array_constructor_expression (type, indices, values,
- expr.get_locus ());
-}
-
-void
-ConstFoldArrayElems::visit (HIR::ArrayElemsCopied &elems)
-{
- std::vector<unsigned long> indices;
- std::vector<tree> values;
-
- 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 array elems");
- return;
- }
-
- tree type = ConstFoldType::fold (tyty, ctx->get_backend ());
- tree elem = ConstFoldExpr::fold (elems.get_elem_to_copy ());
-
- // num copies expr was already folded in rust-hir-type-check-expr; lookup the
- // earlier result
- tree num_copies_expr = ctx->get_backend ()->error_expression ();
- ctx->lookup_const (elems.get_num_copies_expr ()->get_mappings ().get_hirid (),
- &num_copies_expr);
-
- size_t copies;
- bool ok = ctx->get_backend ()->const_size_cast (num_copies_expr, &copies);
- rust_assert (ok);
-
- for (size_t i = 0; i < copies; i++)
- {
- indices.push_back (i);
- values.push_back (elem);
- }
-
- folded
- = ctx->get_backend ()->array_constructor_expression (type, indices, values,
- expr.get_locus ());
-}
-
-} // namespace ConstFold
-} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-const-fold.h b/gcc/rust/typecheck/rust-hir-const-fold.h
deleted file mode 100644
index 1907816..0000000
--- a/gcc/rust/typecheck/rust-hir-const-fold.h
+++ /dev/null
@@ -1,499 +0,0 @@
-// Copyright (C) 2020-2021 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 tree 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 &type) override
- {
- tree element_ty = ConstFoldType::fold (type.get_element_type (), backend);
- translated = backend->array_type (element_ty, type.get_capacity ());
- }
-
- void visit (TyTy::ReferenceType &type) override
- {
- tree base_compiled_type = ConstFoldType::fold (type.get_base (), backend);
- if (type.is_mutable ())
- {
- translated = backend->reference_type (base_compiled_type);
- }
- else
- {
- auto base = backend->immutable_type (base_compiled_type);
- translated = backend->reference_type (base);
- }
- }
-
- void visit (TyTy::PointerType &type) override
- {
- tree base_compiled_type = ConstFoldType::fold (type.get_base (), backend);
- if (type.is_mutable ())
- {
- translated = backend->pointer_type (base_compiled_type);
- }
- else
- {
- auto base = backend->immutable_type (base_compiled_type);
- translated = backend->pointer_type (base);
- }
- }
-
- void visit (TyTy::ParamType &) override { gcc_unreachable (); }
-
- void visit (TyTy::FnPtr &) override { gcc_unreachable (); }
-
- void visit (TyTy::FnType &) override { gcc_unreachable (); }
-
- void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); }
-
- void visit (TyTy::ProjectionType &) override { gcc_unreachable (); }
-
- void visit (TyTy::TupleType &type) override
- {
- if (type.num_fields () == 0)
- translated = backend->unit_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
- {
- tree raw_str = backend->raw_str_type ();
- translated
- = backend->named_type ("str", raw_str, Linemap::predeclared_location ());
- }
-
- void visit (TyTy::NeverType &) override { gcc_unreachable (); }
-
- void visit (TyTy::DynamicObjectType &) override { gcc_unreachable (); }
-
- void visit (TyTy::ClosureType &) override { gcc_unreachable (); }
-
-private:
- ConstFoldType (::Backend *backend)
- : backend (backend), translated (backend->error_type ())
- {}
-
- ::Backend *backend;
- ::tree translated;
-};
-
-class ConstFoldItem : public ConstFoldBase
-{
- using ConstFoldBase::visit;
-
-public:
- static tree 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 (), "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 ())
- {}
-
- tree folded;
-};
-
-class ConstFoldArrayElems : public ConstFoldBase
-{
- using ConstFoldBase::visit;
-
-public:
- static tree fold (HIR::ArrayExpr &expr)
- {
- ConstFoldArrayElems folder (expr);
- HIR::ArrayElems *elems = expr.get_internal_elements ();
- elems->accept_vis (folder);
- return folder.folded;
- }
-
- void visit (HIR::ArrayElemsValues &elems) override;
- void visit (HIR::ArrayElemsCopied &elems) override;
-
-private:
- ConstFoldArrayElems (HIR::ArrayExpr &expr)
- : ConstFoldBase (), folded (ctx->get_backend ()->error_expression ()),
- expr (expr)
- {}
-
- tree folded;
- HIR::ArrayExpr &expr;
-};
-
-class ConstFoldExpr : public ConstFoldBase
-{
- using ConstFoldBase::visit;
-
-public:
- static tree 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 (), "non const value");
- return folder.ctx->get_backend ()->error_expression ();
- }
-
- 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;
- }
-
- tree type = ConstFoldType::fold (tyty, ctx->get_backend ());
- folded
- = ctx->get_backend ()->integer_constant_expression (type, ival);
- }
- return;
-
- case HIR::Literal::BOOL: {
- bool bval = literal_value.as_string ().compare ("true") == 0;
- folded = ctx->get_backend ()->boolean_constant_expression (bval);
- }
- return;
-
- case HIR::Literal::FLOAT: {
- mpfr_t fval;
- if (mpfr_init_set_str (fval, literal_value.as_string ().c_str (), 10,
- MPFR_RNDN)
- != 0)
- {
- rust_fatal_error (expr.get_locus (),
- "bad floating-point 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;
- }
-
- tree type = ConstFoldType::fold (tyty, ctx->get_backend ());
- folded = ctx->get_backend ()->float_constant_expression (type, fval);
- }
- return;
-
- /* handle other literals */
-
- default:
- gcc_unreachable ();
- return;
- }
-
- gcc_unreachable ();
- }
-
- void visit (HIR::ArrayExpr &expr) override
- {
- folded = ConstFoldArrayElems::fold (expr);
- }
-
- void visit (HIR::ArithmeticOrLogicalExpr &expr) override
- {
- auto lhs = ConstFoldExpr::fold (expr.get_lhs ());
- auto rhs = ConstFoldExpr::fold (expr.get_rhs ());
-
- 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 ().get ());
-
- auto op = expr.get_expr_type ();
- auto location = expr.get_locus ();
-
- folded
- = ctx->get_backend ()->negation_expression (op, negated_expr, location);
- }
-
- void visit (HIR::ArrayIndexExpr &expr) override
- {
- tree array = ConstFoldExpr::fold (expr.get_array_expr ());
- tree index = ConstFoldExpr::fold (expr.get_index_expr ());
-
- folded = ctx->get_backend ()->array_index_expression (array, index,
- expr.get_locus ());
- }
-
- void visit (HIR::BorrowExpr &expr) override
- {
- tree main_expr = ConstFoldExpr::fold (expr.get_expr ().get ());
-
- folded
- = ctx->get_backend ()->address_expression (main_expr, expr.get_locus ());
- }
-
- void visit (HIR::DereferenceExpr &expr) override
- {
- tree main_expr = ConstFoldExpr::fold (expr.get_expr ().get ());
-
- 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 TupleExpr");
- return;
- }
-
- tree expected_type = ConstFoldType::fold (tyty, ctx->get_backend ());
- bool known_valid = true;
- folded = ctx->get_backend ()->indirect_expression (expected_type, main_expr,
- known_valid,
- expr.get_locus ());
- }
-
- void visit (HIR::GroupedExpr &expr) override
- {
- folded = ConstFoldExpr::fold (expr.get_expr_in_parens ().get ());
- }
-
-private:
- ConstFoldExpr ()
- : ConstFoldBase (), folded (ctx->get_backend ()->error_expression ())
- {}
-
- tree folded;
-};
-
-} // namespace ConstFold
-} // namespace Rust
-
-#endif // RUST_HIR_CONST_FOLD_H
diff --git a/gcc/rust/typecheck/rust-hir-type-check-enumitem.h b/gcc/rust/typecheck/rust-hir-type-check-enumitem.h
index 4df7df6..f770bed 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-enumitem.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-enumitem.h
@@ -63,28 +63,16 @@ public:
if (capacity_type->get_kind () == TyTy::TypeKind::ERROR)
return;
- TyTy::USizeType *expected_ty
- = new TyTy::USizeType (discriminant->get_mappings ().get_hirid ());
+ TyTy::ISizeType *expected_ty
+ = new TyTy::ISizeType (discriminant->get_mappings ().get_hirid ());
context->insert_type (discriminant->get_mappings (), expected_ty);
auto unified = expected_ty->unify (capacity_type);
if (unified->get_kind () == TyTy::TypeKind::ERROR)
return;
- auto backend = rust_get_backend ();
- auto folded_discriminant
- = ConstFold::ConstFoldExpr::fold (discriminant.get ());
- if (backend->is_error_expression (folded_discriminant))
- return;
-
- size_t specified_discriminant;
- bool ok
- = backend->const_size_cast (folded_discriminant, &specified_discriminant);
- rust_assert (ok);
-
- variant
- = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
- item.get_identifier (), specified_discriminant);
+ variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
+ item.get_identifier (), &item);
}
void visit (HIR::EnumItemTuple &item) override
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index b636e29..1ac4946 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -27,7 +27,6 @@
#include "rust-hir-type-check-struct-field.h"
#include "rust-hir-path-probe.h"
#include "rust-substitution-mapper.h"
-#include "rust-hir-const-fold.h"
#include "rust-hir-trait-resolve.h"
#include "rust-hir-type-bounds.h"
#include "rust-hir-dot-operator.h"
@@ -728,17 +727,17 @@ public:
It is a constant, but for fold it to get a tree. */
std::string capacity_str
= std::to_string (expr.get_literal ().as_string ().size ());
- HIR::LiteralExpr literal_capacity (capacity_mapping, capacity_str,
- HIR::Literal::LitType::INT,
- PrimitiveCoreType::CORETYPE_USIZE,
- expr.get_locus ());
+ HIR::LiteralExpr *literal_capacity
+ = new HIR::LiteralExpr (capacity_mapping, capacity_str,
+ HIR::Literal::LitType::INT,
+ PrimitiveCoreType::CORETYPE_USIZE,
+ expr.get_locus ());
// mark the type for this implicit node
- context->insert_type (capacity_mapping,
- new TyTy::USizeType (
- capacity_mapping.get_hirid ()));
-
- tree capacity = ConstFold::ConstFoldExpr::fold (&literal_capacity);
+ TyTy::BaseType *expected_ty = nullptr;
+ ok = context->lookup_builtin ("usize", &expected_ty);
+ rust_assert (ok);
+ context->insert_type (capacity_mapping, expected_ty);
Analysis::NodeMapping array_mapping (crate_num, UNKNOWN_NODEID,
mappings->get_next_hir_id (
@@ -746,7 +745,8 @@ public:
UNKNOWN_LOCAL_DEFID);
TyTy::ArrayType *array
- = new TyTy::ArrayType (array_mapping.get_hirid (), capacity,
+ = new TyTy::ArrayType (array_mapping.get_hirid (),
+ *literal_capacity,
TyTy::TyVar (u8->get_ref ()));
context->insert_type (array_mapping, array);
@@ -979,77 +979,75 @@ public:
void visit (HIR::ArrayExpr &expr) override
{
- HIR::ArrayElems *elements = expr.get_internal_elements ();
- root_array_expr_locus = expr.get_locus ();
-
- elements->accept_vis (*this);
- if (infered_array_elems == nullptr)
- return;
- if (folded_array_capacity == nullptr)
- return;
+ HIR::ArrayElems &elements = *expr.get_internal_elements ();
- infered
- = new TyTy::ArrayType (expr.get_mappings ().get_hirid (),
- folded_array_capacity,
- TyTy::TyVar (infered_array_elems->get_ref ()));
- }
-
- void visit (HIR::ArrayElemsValues &elems) override
- {
- std::vector<TyTy::BaseType *> types;
-
- for (auto &elem : elems.get_values ())
+ HIR::Expr *capacity_expr = nullptr;
+ TyTy::BaseType *element_type = nullptr;
+ switch (elements.get_array_expr_type ())
{
- types.push_back (TypeCheckExpr::Resolve (elem.get (), false));
- }
+ case HIR::ArrayElems::ArrayExprType::COPIED: {
+ HIR::ArrayElemsCopied &elems
+ = static_cast<HIR::ArrayElemsCopied &> (elements);
+ element_type
+ = TypeCheckExpr::Resolve (elems.get_elem_to_copy (), false);
- infered_array_elems
- = TyTy::TyVar::get_implicit_infer_var (root_array_expr_locus).get_tyty ();
+ auto capacity_type
+ = TypeCheckExpr::Resolve (elems.get_num_copies_expr (), false);
- for (auto &type : types)
- {
- infered_array_elems = infered_array_elems->unify (type);
- }
- for (auto &elem : types)
- {
- infered_array_elems->append_reference (elem->get_ref ());
- }
+ TyTy::BaseType *expected_ty = nullptr;
+ bool ok = context->lookup_builtin ("usize", &expected_ty);
+ rust_assert (ok);
+ context->insert_type (elems.get_num_copies_expr ()->get_mappings (),
+ expected_ty);
- 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 ());
+ auto unified = expected_ty->unify (capacity_type);
+ if (unified->get_kind () == TyTy::TypeKind::ERROR)
+ return;
- // mark the type for this implicit node
- context->insert_type (mapping, new TyTy::USizeType (mapping.get_hirid ()));
+ capacity_expr = elems.get_num_copies_expr ();
+ }
+ break;
- folded_array_capacity
- = ConstFold::ConstFoldExpr::fold (&implicit_literal_capacity);
- }
+ case HIR::ArrayElems::ArrayExprType::VALUES: {
+ HIR::ArrayElemsValues &elems
+ = static_cast<HIR::ArrayElemsValues &> (elements);
- void visit (HIR::ArrayElemsCopied &elems) override
- {
- auto capacity_type
- = TypeCheckExpr::Resolve (elems.get_num_copies_expr (), false);
+ std::vector<TyTy::BaseType *> types;
+ for (auto &elem : elems.get_values ())
+ {
+ types.push_back (TypeCheckExpr::Resolve (elem.get (), 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);
+ element_type = TyTy::TyVar::get_implicit_infer_var (expr.get_locus ())
+ .get_tyty ();
+ for (auto &type : types)
+ {
+ element_type = element_type->unify (type);
+ }
- auto unified = expected_ty->unify (capacity_type);
- if (unified->get_kind () == TyTy::TypeKind::ERROR)
- return;
+ 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 ());
+ capacity_expr
+ = new HIR::LiteralExpr (mapping, capacity_str,
+ HIR::Literal::LitType::INT,
+ PrimitiveCoreType::CORETYPE_USIZE,
+ Location ());
- folded_array_capacity
- = ConstFold::ConstFoldExpr::fold (elems.get_num_copies_expr ());
+ // mark the type for this implicit node
+ TyTy::BaseType *expected_ty = nullptr;
+ bool ok = context->lookup_builtin ("usize", &expected_ty);
+ rust_assert (ok);
+ context->insert_type (mapping, expected_ty);
+ }
+ break;
+ }
- infered_array_elems
- = TypeCheckExpr::Resolve (elems.get_elem_to_copy (), false);
+ infered
+ = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), *capacity_expr,
+ TyTy::TyVar (element_type->get_ref ()));
}
// empty struct
@@ -1547,8 +1545,7 @@ protected:
private:
TypeCheckExpr (bool inside_loop)
- : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr),
- folded_array_capacity (nullptr), inside_loop (inside_loop)
+ : TypeCheckBase (), infered (nullptr), inside_loop (inside_loop)
{}
// Beware: currently returns Tyty::ErrorType or nullptr in case of error.
@@ -1617,14 +1614,8 @@ private:
/* The return value of TypeCheckExpr::Resolve */
TyTy::BaseType *infered;
- /* The return value of visit(ArrayElemsValues&) and visit(ArrayElemsCopied&)
- Stores the type of array elements, if `expr` is ArrayExpr. */
- TyTy::BaseType *infered_array_elems;
- tree folded_array_capacity;
- Location root_array_expr_locus;
-
bool inside_loop;
-}; // namespace Resolver
+};
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
index a860608..25b592c 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
@@ -170,9 +170,6 @@ 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-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
index fb0e047..22b6f3f 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
@@ -64,9 +64,6 @@ public:
infered = type->unify (expr_type);
context->insert_type (constant.get_mappings (), infered);
-
- // notify the constant folder of this
- ConstFold::ConstFoldItem::fold (constant);
}
void visit (HIR::LetStmt &stmt) override
@@ -98,7 +95,7 @@ public:
if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
return;
- context->insert_type (stmt.get_mappings (), unified_ty);
+ context->insert_type (stmt.get_mappings (), specified_ty);
}
else
{
diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
index 7b1dfc9..3733e429 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h
@@ -315,9 +315,6 @@ 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.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index cfe9652..93f46e6 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -18,6 +18,7 @@
#include "rust-hir-type-check-type.h"
#include "rust-hir-trait-resolve.h"
+#include "rust-hir-type-check-expr.h"
namespace Rust {
namespace Resolver {
@@ -575,5 +576,27 @@ TypeCheckType::visit (HIR::TraitObjectType &type)
std::move (specified_bounds));
}
+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::BaseType *expected_ty = nullptr;
+ bool ok = context->lookup_builtin ("usize", &expected_ty);
+ rust_assert (ok);
+ 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;
+
+ TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ());
+ translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (),
+ *type.get_size_expr (),
+ TyTy::TyVar (base->get_ref ()));
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index d2da20e..ccde21a 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -23,7 +23,6 @@
#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);
@@ -135,28 +134,6 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
}
-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 ());
-
- TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ());
- translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (), capacity,
- TyTy::TyVar (base->get_ref ()));
-}
-
// rust-hir-trait-ref.h
TraitItemReference::TraitItemReference (
diff --git a/gcc/rust/typecheck/rust-tyty-cast.h b/gcc/rust/typecheck/rust-tyty-cast.h
index 07fedd0..6036a75 100644
--- a/gcc/rust/typecheck/rust-tyty-cast.h
+++ b/gcc/rust/typecheck/rust-tyty-cast.h
@@ -806,19 +806,9 @@ public:
return;
}
- auto backend = rust_get_backend ();
-
- // need to check the base types and capacity
- if (!backend->const_values_equal (type.get_capacity (),
- base->get_capacity ()))
- {
- BaseCastRules::visit (type);
- return;
- }
-
- resolved
- = new ArrayType (type.get_ref (), type.get_ty_ref (),
- type.get_capacity (), TyVar (base_resolved->get_ref ()));
+ resolved = new ArrayType (type.get_ref (), type.get_ty_ref (),
+ type.get_capacity_expr (),
+ TyVar (base_resolved->get_ref ()));
}
private:
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index 291e590..6347530 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -851,13 +851,6 @@ public:
void visit (const ArrayType &type) override
{
- // need to check the base types and capacity
- if (type.get_capacity () != base->get_capacity ())
- {
- BaseCmp::visit (type);
- return;
- }
-
// check base type
const BaseType *base_element = base->get_element_type ();
const BaseType *other_element = type.get_element_type ();
diff --git a/gcc/rust/typecheck/rust-tyty-coercion.h b/gcc/rust/typecheck/rust-tyty-coercion.h
index b483130..25f6810 100644
--- a/gcc/rust/typecheck/rust-tyty-coercion.h
+++ b/gcc/rust/typecheck/rust-tyty-coercion.h
@@ -824,19 +824,9 @@ public:
return;
}
- auto backend = rust_get_backend ();
-
- // need to check the base types and capacity
- if (!backend->const_values_equal (type.get_capacity (),
- base->get_capacity ()))
- {
- BaseCoercionRules::visit (type);
- return;
- }
-
- resolved
- = new ArrayType (type.get_ref (), type.get_ty_ref (),
- type.get_capacity (), TyVar (base_resolved->get_ref ()));
+ resolved = new ArrayType (type.get_ref (), type.get_ty_ref (),
+ type.get_capacity_expr (),
+ TyVar (base_resolved->get_ref ()));
}
private:
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
index 5dc2d2f..450a93f 100644
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ b/gcc/rust/typecheck/rust-tyty-rules.h
@@ -841,19 +841,9 @@ public:
return;
}
- auto backend = rust_get_backend ();
-
- // need to check the base types and capacity
- if (!backend->const_values_equal (type.get_capacity (),
- base->get_capacity ()))
- {
- BaseRules::visit (type);
- return;
- }
-
- resolved
- = new ArrayType (type.get_ref (), type.get_ty_ref (),
- type.get_capacity (), TyVar (base_resolved->get_ref ()));
+ resolved = new ArrayType (type.get_ref (), type.get_ty_ref (),
+ type.get_capacity_expr (),
+ TyVar (base_resolved->get_ref ()));
}
private:
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index f141a41..679187b 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -1335,14 +1335,7 @@ ArrayType::accept_vis (TyConstVisitor &vis) const
std::string
ArrayType::as_string () const
{
- 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 ());
+ return "[" + get_element_type ()->as_string () + ":" + "CAPACITY" + "]";
}
BaseType *
@@ -1381,8 +1374,6 @@ ArrayType::is_equal (const BaseType &other) const
return false;
auto other2 = static_cast<const ArrayType &> (other);
- if (get_capacity () != other2.get_capacity ())
- return false;
auto this_element_type = get_element_type ();
auto other_element_type = other2.get_element_type ();
@@ -1399,8 +1390,8 @@ ArrayType::get_element_type () const
BaseType *
ArrayType::clone () const
{
- return new ArrayType (get_ref (), get_ty_ref (), get_capacity (),
- element_type, get_combined_refs ());
+ return new ArrayType (get_ref (), get_ty_ref (), capacity_expr, element_type,
+ get_combined_refs ());
}
void
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 40c06a5..bdf85a9 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -19,12 +19,12 @@
#ifndef RUST_TYTY
#define RUST_TYTY
-#include "rust-backend.h"
#include "rust-hir-map.h"
#include "rust-hir-full.h"
#include "rust-diagnostics.h"
#include "rust-abi.h"
#include "rust-common.h"
+#include "tree.h"
namespace Rust {
@@ -1034,7 +1034,16 @@ public:
}
VariantDef (HirId id, std::string identifier, int discriminant)
- : id (id), identifier (identifier), discriminant (discriminant)
+ : id (id), identifier (identifier), discriminant (discriminant),
+ discriminant_node (nullptr)
+ {
+ type = VariantType::NUM;
+ fields = {};
+ }
+
+ VariantDef (HirId id, std::string identifier,
+ HIR::EnumItemDiscriminant *discriminant)
+ : id (id), identifier (identifier), discriminant_node (discriminant)
{
type = VariantType::NUM;
fields = {};
@@ -1042,7 +1051,8 @@ public:
VariantDef (HirId id, std::string identifier, VariantType type,
std::vector<StructFieldType *> fields)
- : id (id), identifier (identifier), type (type), fields (fields)
+ : id (id), identifier (identifier), type (type), fields (fields),
+ discriminant_node (nullptr)
{
discriminant = 0;
rust_assert (type == VariantType::TUPLE || type == VariantType::STRUCT);
@@ -1073,7 +1083,12 @@ public:
bool is_dataless_variant () const { return type == VariantType::NUM; }
std::string get_identifier () const { return identifier; }
- int get_discriminant () const { return discriminant; }
+
+ int get_discriminant () const
+ {
+ rust_assert (!is_specified_discriminant_node ());
+ return discriminant;
+ }
size_t num_fields () const { return fields.size (); }
StructFieldType *get_field_at_index (size_t index)
@@ -1109,6 +1124,17 @@ public:
return false;
}
+ bool is_specified_discriminant_node () const
+ {
+ return discriminant_node != nullptr;
+ }
+
+ HIR::EnumItemDiscriminant *get_discriminant_node () const
+ {
+ rust_assert (is_specified_discriminant_node ());
+ return discriminant_node;
+ }
+
std::string as_string () const
{
if (type == VariantType::NUM)
@@ -1166,6 +1192,7 @@ private:
VariantType type;
int discriminant; /* Either discriminant or fields are valid. */
std::vector<StructFieldType *> fields;
+ HIR::EnumItemDiscriminant *discriminant_node;
};
class ADTType : public BaseType, public SubstitutionRef
@@ -1595,16 +1622,16 @@ private:
class ArrayType : public BaseType
{
public:
- ArrayType (HirId ref, tree capacity, TyVar base,
+ ArrayType (HirId ref, HIR::Expr &capacity_expr, TyVar base,
std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::ARRAY, refs), capacity (capacity),
- element_type (base)
+ : BaseType (ref, ref, TypeKind::ARRAY, refs), element_type (base),
+ capacity_expr (capacity_expr)
{}
- ArrayType (HirId ref, HirId ty_ref, tree capacity, TyVar base,
+ ArrayType (HirId ref, HirId ty_ref, HIR::Expr &capacity_expr, TyVar base,
std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::ARRAY, refs), capacity (capacity),
- element_type (base)
+ : BaseType (ref, ty_ref, TypeKind::ARRAY, refs), element_type (base),
+ capacity_expr (capacity_expr)
{}
void accept_vis (TyVisitor &vis) override;
@@ -1622,9 +1649,6 @@ public:
bool is_equal (const BaseType &other) const override;
- tree get_capacity () const { return capacity; }
- std::string capacity_string () const;
-
BaseType *get_element_type () const;
BaseType *clone () const final override;
@@ -1634,9 +1658,11 @@ public:
return get_element_type ()->is_concrete ();
}
+ HIR::Expr &get_capacity_expr () const { return capacity_expr; }
+
private:
- tree capacity;
TyVar element_type;
+ HIR::Expr &capacity_expr;
};
class BoolType : public BaseType
diff --git a/gcc/testsuite/rust/compile/arrays2.rs b/gcc/testsuite/rust/compile/arrays2.rs
index 9c788db..c96f4f7d 100644
--- a/gcc/testsuite/rust/compile/arrays2.rs
+++ b/gcc/testsuite/rust/compile/arrays2.rs
@@ -1,4 +1,5 @@
+// { dg-additional-options "-w" }
fn main() {
let array: [i32; 5] = [1, 2, 3];
- // { dg-error "expected ..i32:5.. got ..i32:3.." "" { target *-*-* } .-1 }
+ // { dg-error "expected an array with a fixed size of 5 elements, found one with 3 elements" "" { target *-*-* } .-1 }
}
diff --git a/gcc/testsuite/rust/execute/torture/const_fold1.rs b/gcc/testsuite/rust/execute/torture/const_fold1.rs
new file mode 100644
index 0000000..3cd6c0c
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/const_fold1.rs
@@ -0,0 +1,13 @@
+// { dg-additional-options "-w" }
+const fn const_fn() -> usize {
+ 4
+}
+
+const FN_TEST: usize = const_fn();
+
+const TEST: usize = 2 + FN_TEST;
+
+fn main() -> i32 {
+ let a: [_; 12] = [5; TEST * 2];
+ a[6] - 5
+}