public inbox for gcc-cvs@sourceware.org help / color / mirror / Atom feed
From: Thomas Schwinge <tschwinge@gcc.gnu.org> To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] rust-constexpr.cc: add more cases to eval_constant_expression() Date: Mon, 29 Aug 2022 15:33:44 +0000 (GMT) [thread overview] Message-ID: <20220829153344.C8B623856DDC@sourceware.org> (raw) 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
reply other threads:[~2022-08-29 15:33 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20220829153344.C8B623856DDC@sourceware.org \ --to=tschwinge@gcc.gnu.org \ --cc=gcc-cvs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
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).