[gcc/devel/rust/master] Port over:
Thomas Schwinge
tschwinge@gcc.gnu.org
Mon Aug 29 15:33:19 GMT 2022
https://gcc.gnu.org/g:8a9b94d8c3ac6c691fa49585756c0df234602d8b
commit 8a9b94d8c3ac6c691fa49585756c0df234602d8b
Author: Philip Herron <philip.herron@embecosm.com>
Date: Wed Jul 20 13:40:18 2022 +0100
Port over:
- cxx_bind_parameters_in_call
- addr_of_non_const_var
- adjust_temp_type
There is alot of cleanup we can do when we get more of this working but
for now its best to keep porting like this.
Diff:
---
gcc/rust/backend/rust-constexpr.cc | 134 +++++++++++++++++++++++++++++++++++++
1 file changed, 134 insertions(+)
diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc
index c1d5cad1448..aa2d4708a9b 100644
--- a/gcc/rust/backend/rust-constexpr.cc
+++ b/gcc/rust/backend/rust-constexpr.cc
@@ -47,6 +47,8 @@ static HOST_WIDE_INT
find_array_ctor_elt (tree ary, tree dindex, bool insert = false);
static int
array_index_cmp (tree key, tree index);
+inline tree
+get_nth_callarg (tree t, int n);
struct constexpr_global_ctx
{
@@ -388,6 +390,138 @@ eval_binary_expression (const constexpr_ctx *ctx, tree t, bool lval,
return fold_binary_loc (loc, code, type, lhs, rhs);
}
+/* TEMP is the constant value of a temporary object of type TYPE. Adjust
+ the type of the value to match. */
+
+static tree
+adjust_temp_type (tree type, tree temp)
+{
+ if (same_type_p (TREE_TYPE (temp), type))
+ return temp;
+
+ gcc_assert (scalarish_type_p (type));
+ /* Now we know we're dealing with a scalar, and a prvalue of non-class
+ type is cv-unqualified. */
+ return fold_convert (cv_unqualified (type), temp);
+}
+
+/* Helper function of cxx_bind_parameters_in_call. Return non-NULL
+ if *TP is address of a static variable (or part of it) currently being
+ constructed or of a heap artificial variable. */
+
+static tree
+addr_of_non_const_var (tree *tp, int *walk_subtrees, void *data)
+{
+ if (TREE_CODE (*tp) == ADDR_EXPR)
+ if (tree var = get_base_address (TREE_OPERAND (*tp, 0)))
+ if (VAR_P (var) && TREE_STATIC (var))
+ {
+ if (DECL_NAME (var) == heap_uninit_identifier
+ || DECL_NAME (var) == heap_identifier
+ || DECL_NAME (var) == heap_vec_uninit_identifier
+ || DECL_NAME (var) == heap_vec_identifier)
+ return var;
+
+ constexpr_global_ctx *global = (constexpr_global_ctx *) data;
+ if (global->values.get (var))
+ return var;
+ }
+ if (TYPE_P (*tp))
+ *walk_subtrees = false;
+ return NULL_TREE;
+}
+
+/* Subroutine of cxx_eval_call_expression.
+ We are processing a call expression (either CALL_EXPR or
+ AGGR_INIT_EXPR) in the context of CTX. Evaluate
+ all arguments and bind their values to correspondings
+ parameters, making up the NEW_CALL context. */
+
+static tree
+rs_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun,
+ bool *non_constant_p, bool *overflow_p,
+ bool *non_constant_args)
+{
+ const int nargs = call_expr_nargs (t);
+ tree parms = DECL_ARGUMENTS (fun);
+ int i;
+ /* We don't record ellipsis args below. */
+ int nparms = list_length (parms);
+ int nbinds = nargs < nparms ? nargs : nparms;
+ tree binds = make_tree_vec (nbinds);
+ for (i = 0; i < nargs; ++i)
+ {
+ tree x, arg;
+ tree type = parms ? TREE_TYPE (parms) : void_type_node;
+ if (parms && DECL_BY_REFERENCE (parms))
+ type = TREE_TYPE (type);
+ x = get_nth_callarg (t, i);
+
+ if (TREE_ADDRESSABLE (type))
+ /* Undo convert_for_arg_passing work here. */
+ x = convert_from_reference (x);
+ /* Normally we would strip a TARGET_EXPR in an initialization context
+ such as this, but here we do the elision differently: we keep the
+ TARGET_EXPR, and use its CONSTRUCTOR as the value of the parm. */
+ arg = constexpr_expression (ctx, x, /*lval=*/false, non_constant_p,
+ overflow_p);
+ /* Don't VERIFY_CONSTANT here. */
+ if (*non_constant_p && ctx->quiet)
+ break;
+ /* Just discard ellipsis args after checking their constantitude. */
+ if (!parms)
+ continue;
+
+ if (!*non_constant_p)
+ {
+ /* Make sure the binding has the same type as the parm. But
+ only for constant args. */
+ if (!TYPE_REF_P (type))
+ arg = adjust_temp_type (type, arg);
+ if (!TREE_CONSTANT (arg))
+ *non_constant_args = true;
+ else if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ /* The destructor needs to see any modifications the callee makes
+ to the argument. */
+ *non_constant_args = true;
+ /* If arg is or contains address of a heap artificial variable or
+ of a static variable being constructed, avoid caching the
+ function call, as those variables might be modified by the
+ function, or might be modified by the callers in between
+ the cached function and just read by the function. */
+ else if (!*non_constant_args
+ && rs_walk_tree (&arg, addr_of_non_const_var, ctx->global,
+ NULL))
+ *non_constant_args = true;
+
+ // /* For virtual calls, adjust the this argument, so that it is
+ // the object on which the method is called, rather than
+ // one of its bases. */
+ // if (i == 0 && DECL_VIRTUAL_P (fun))
+ // {
+ // tree addr = arg;
+ // STRIP_NOPS (addr);
+ // if (TREE_CODE (addr) == ADDR_EXPR)
+ // {
+ // tree obj = TREE_OPERAND (addr, 0);
+ // while (TREE_CODE (obj) == COMPONENT_REF
+ // && DECL_FIELD_IS_BASE (TREE_OPERAND (obj, 1))
+ // && !same_type_ignoring_top_level_qualifiers_p (
+ // TREE_TYPE (obj), DECL_CONTEXT (fun)))
+ // obj = TREE_OPERAND (obj, 0);
+ // if (obj != TREE_OPERAND (addr, 0))
+ // arg = build_fold_addr_expr_with_type (obj, TREE_TYPE
+ // (arg));
+ // }
+ // }
+ TREE_VEC_ELT (binds, i) = arg;
+ }
+ parms = TREE_CHAIN (parms);
+ }
+
+ return binds;
+}
+
// Subroutine of cxx_eval_constant_expression.
// Evaluate the call expression tree T in the context of OLD_CALL expression
// evaluation.
More information about the Gcc-cvs
mailing list