public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] rust-constexpr.cc: add more cases to eval_constant_expression()
@ 2022-08-29 15:33 Thomas Schwinge
0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-08-29 15:33 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:f21f475feca30d0c9fb74dfe3bb65a6d88d5311c
commit f21f475feca30d0c9fb74dfe3bb65a6d88d5311c
Author: Faisal Abbas <90.abbasfaisal@gmail.com>
Date: Thu Jul 28 18:54:48 2022 +0100
rust-constexpr.cc: add more cases to eval_constant_expression()
Following cases have been added in this changeset:
- LOOP_EXPR
- WHILE_STMT
- FOR_STMT
These need following supporting functions which are also ported:
- eval_loop_expr
- returns
- breaks
- continues
- switches
Diff:
---
gcc/rust/backend/rust-constexpr.cc | 154 +++++++++++++++++++++++++++++++++++++
gcc/rust/backend/rust-tree.h | 24 ++++++
2 files changed, 178 insertions(+)
diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc
index 9449d599884..cac28d6870f 100644
--- a/gcc/rust/backend/rust-constexpr.cc
+++ b/gcc/rust/backend/rust-constexpr.cc
@@ -493,6 +493,10 @@ static tree
eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval,
bool *non_constant_p, bool *overflow_p);
+static tree
+eval_loop_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
+ bool *overflow_p, tree *jump_target);
+
/* Variables and functions to manage constexpr call expansion context.
These do not need to be marked for PCH or GC. */
@@ -731,6 +735,12 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
}
break;
+ case LOOP_EXPR:
+ case WHILE_STMT:
+ case FOR_STMT:
+ eval_loop_expr (ctx, t, non_constant_p, overflow_p, jump_target);
+ break;
+
case BIT_FIELD_REF:
r = eval_bit_field_ref (ctx, t, lval, non_constant_p, overflow_p);
break;
@@ -774,6 +784,7 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval,
r = eval_conditional_expression (ctx, t, lval, non_constant_p, overflow_p,
jump_target);
break;
+
default:
break;
}
@@ -2760,6 +2771,149 @@ eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool lval,
return error_mark_node;
}
+/* Predicates for the meaning of *jump_target. */
+
+static bool
+returns (tree *jump_target)
+{
+ return *jump_target
+ && (TREE_CODE (*jump_target) == RETURN_EXPR
+ || (TREE_CODE (*jump_target) == LABEL_DECL
+ && LABEL_DECL_CDTOR (*jump_target)));
+}
+
+static bool
+breaks (tree *jump_target)
+{
+ return *jump_target
+ && ((TREE_CODE (*jump_target) == LABEL_DECL
+ && LABEL_DECL_BREAK (*jump_target))
+ || TREE_CODE (*jump_target) == BREAK_STMT
+ || TREE_CODE (*jump_target) == EXIT_EXPR);
+}
+
+static bool
+continues (tree *jump_target)
+{
+ return *jump_target
+ && ((TREE_CODE (*jump_target) == LABEL_DECL
+ && LABEL_DECL_CONTINUE (*jump_target))
+ || TREE_CODE (*jump_target) == CONTINUE_STMT);
+}
+
+static bool
+switches (tree *jump_target)
+{
+ return *jump_target && TREE_CODE (*jump_target) == INTEGER_CST;
+}
+
+/* Evaluate a LOOP_EXPR for side-effects. Handles break and return
+ semantics; continue semantics are covered by cxx_eval_statement_list. */
+
+static tree
+eval_loop_expr (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
+ bool *overflow_p, tree *jump_target)
+{
+ constexpr_ctx new_ctx = *ctx;
+ tree local_target;
+ if (!jump_target)
+ {
+ local_target = NULL_TREE;
+ jump_target = &local_target;
+ }
+
+ tree body, cond = NULL_TREE, expr = NULL_TREE;
+ int count = 0;
+ switch (TREE_CODE (t))
+ {
+ case LOOP_EXPR:
+ body = LOOP_EXPR_BODY (t);
+ break;
+ case WHILE_STMT:
+ body = WHILE_BODY (t);
+ cond = WHILE_COND (t);
+ count = -1;
+ break;
+ case FOR_STMT:
+ if (FOR_INIT_STMT (t))
+ eval_constant_expression (ctx, FOR_INIT_STMT (t), /*lval*/ false,
+ non_constant_p, overflow_p, jump_target);
+ if (*non_constant_p)
+ return NULL_TREE;
+ body = FOR_BODY (t);
+ cond = FOR_COND (t);
+ expr = FOR_EXPR (t);
+ count = -1;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ auto_vec<tree, 10> save_exprs;
+ new_ctx.save_exprs = &save_exprs;
+ do
+ {
+ if (count != -1)
+ {
+ if (body)
+ eval_constant_expression (&new_ctx, body, /*lval*/ false,
+ non_constant_p, overflow_p, jump_target);
+ if (breaks (jump_target))
+ {
+ *jump_target = NULL_TREE;
+ break;
+ }
+
+ if (TREE_CODE (t) != LOOP_EXPR && continues (jump_target))
+ *jump_target = NULL_TREE;
+
+ if (expr)
+ eval_constant_expression (&new_ctx, expr, /*lval*/ false,
+ non_constant_p, overflow_p, jump_target);
+ }
+
+ if (cond)
+ {
+ tree res = eval_constant_expression (&new_ctx, cond, /*lval*/ false,
+ non_constant_p, overflow_p,
+ jump_target);
+ if (res)
+ {
+ if (verify_constant (res, ctx->quiet, non_constant_p, overflow_p))
+ break;
+ if (integer_zerop (res))
+ break;
+ }
+ else
+ gcc_assert (*jump_target);
+ }
+
+ /* Forget saved values of SAVE_EXPRs and TARGET_EXPRs. */
+ for (tree save_expr : save_exprs)
+ ctx->global->values.remove (save_expr);
+ save_exprs.truncate (0);
+
+ if (++count >= constexpr_loop_limit)
+ {
+ if (!ctx->quiet)
+ error_at (rs_expr_loc_or_input_loc (t),
+ "%<constexpr%> loop iteration count exceeds limit of %d "
+ "(use %<-fconstexpr-loop-limit=%> to increase the limit)",
+ constexpr_loop_limit);
+ *non_constant_p = true;
+ break;
+ }
+ }
+ while (!returns (jump_target) && !breaks (jump_target)
+ && !continues (jump_target) && (!switches (jump_target) || count == 0)
+ && !*non_constant_p);
+
+ /* Forget saved values of SAVE_EXPRs and TARGET_EXPRs. */
+ for (tree save_expr : save_exprs)
+ ctx->global->values.remove (save_expr);
+
+ return NULL_TREE;
+}
+
// #include "gt-rust-rust-constexpr.h"
} // namespace Compile
diff --git a/gcc/rust/backend/rust-tree.h b/gcc/rust/backend/rust-tree.h
index 01de727320f..f9623a2848a 100644
--- a/gcc/rust/backend/rust-tree.h
+++ b/gcc/rust/backend/rust-tree.h
@@ -1240,6 +1240,10 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
#define DECL_FUNCTION_MEMBER_P(NODE) \
(DECL_NONSTATIC_MEMBER_FUNCTION_P (NODE) || DECL_STATIC_FUNCTION_P (NODE))
+/* Nonzero if NODE is the target for genericization of 'return' stmts
+ in constructors/destructors of targetm.cxx.cdtor_returns_this targets. */
+#define LABEL_DECL_CDTOR(NODE) DECL_LANG_FLAG_2 (LABEL_DECL_CHECK (NODE))
+
#if defined ENABLE_TREE_CHECKING
#define LANG_DECL_MIN_CHECK(NODE) \
@@ -1334,6 +1338,26 @@ extern GTY (()) tree cp_global_trees[CPTI_MAX];
#define DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P(NODE) \
(TREE_LANG_FLAG_2 (VAR_DECL_CHECK (NODE)))
+/* WHILE_STMT accessors. These give access to the condition of the
+ while statement and the body of the while statement, respectively. */
+#define WHILE_COND(NODE) TREE_OPERAND (WHILE_STMT_CHECK (NODE), 0)
+#define WHILE_BODY(NODE) TREE_OPERAND (WHILE_STMT_CHECK (NODE), 1)
+
+/* FOR_STMT accessors. These give access to the init statement,
+ condition, update expression, and body of the for statement,
+ respectively. */
+#define FOR_INIT_STMT(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 0)
+#define FOR_COND(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 1)
+#define FOR_EXPR(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 2)
+#define FOR_BODY(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 3)
+#define FOR_SCOPE(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 4)
+
+/* Nonzero if NODE is the target for genericization of 'break' stmts. */
+#define LABEL_DECL_BREAK(NODE) DECL_LANG_FLAG_0 (LABEL_DECL_CHECK (NODE))
+
+/* Nonzero if NODE is the target for genericization of 'continue' stmts. */
+#define LABEL_DECL_CONTINUE(NODE) DECL_LANG_FLAG_1 (LABEL_DECL_CHECK (NODE))
+
// Above macros are copied from gcc/c-family/c-common.h
// Below macros are copied from gcc/cp/name-lookup.cc
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-08-29 15:33 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-29 15:33 [gcc/devel/rust/master] rust-constexpr.cc: add more cases to eval_constant_expression() Thomas Schwinge
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).