[tuples] implementation of GS_CALL
Aldy Hernandez
aldyh@redhat.com
Fri Jun 1 01:41:00 GMT 2007
Hi Diego.
I thought I was going to have more time to finish everything related to
CALLs, but there's a wife screaming something about packing before the
last possible minute. Yay vacation!
Here are the accessors and constructors for GS_CALL (relevant pretty
printer code is missing). I actually hacked them so I could work on
gimplify_modify_expr_to_mem* which needed them. The functions
gimplify_modify_expr_to_mem{cpy,memset} have also been rewritten.
In the process, gimplify_statement_list() got a rewrite. Could you
please take a look at the "FIXME tuples" here? I'm not sure whether the
tsi_delink is needed. And I'm also not sure I'm recursiving into
gimplify_expr with the correct arguments.
[I've been using the following as a stress test:
void f(int a) {
struct {int b[a];} c, d;
init(&c);
d = c;
}
You'll find all sorts of interesting tidbits wrt unimplemented
gimplify_call_expr.
]
I'm committing the patch below. Please take a look at the FIXMEs below
if you can. Otherwise, I'm sure it can wait two weeks :).
Now where did I put that Margarita?
Aldy
* gimple-ir.c (gs_build_call): New.
* gimple-ir.h (GS_CALL_LHS): New.
(GS_CALL_FN): New.
(GS_CALL_CHAIN): New.
(GS_CALL_NARGS): New.
(GS_CALL_ARG): New.
(gs_call_lhs): New.
(gs_call_fn): New.
(gs_call_chain): New.
(gs_call_nargs): New.
(gs_call_arg): New.
* gimplify.c (gimplify_modify_expr_to_memcpy): Enable and rewrite for
tuples.
(gimplify_modify_expr_to_memset): Same.
(gimplify_expr): Enable STATEMENT_LIST case.
Index: gimple-ir.c
===================================================================
--- gimple-ir.c (revision 125165)
+++ gimple-ir.c (working copy)
@@ -50,6 +50,35 @@ gs_build_return (bool result_decl_p, tre
return p;
}
+/* Construct a GS_CALL statement.
+
+ FUNC is the function decl.
+ NARGS is the number of arguments.
+ The ... are the arguments. */
+
+gimple
+gs_build_call (tree func, int nargs, ...)
+{
+ va_list ap;
+ gimple p;
+ int i;
+
+ p = ggc_alloc_cleared (sizeof (struct gimple_statement_call) +
+ sizeof (tree) * nargs - 1);
+
+ GS_CODE (p) = GS_CALL;
+ GS_SUBCODE_FLAGS (p) = 0;
+ GS_CALL_NARGS (p) = nargs;
+ GS_CALL_FN (p) = func;
+
+ va_start (ap, nargs);
+ for (i = 0; i < nargs; ++i)
+ GS_CALL_ARG (p, i) = va_arg (ap, tree);
+ va_end (ap);
+
+ return p;
+}
+
/* Construct a GS_ASSIGN statement. */
gimple
Index: gimple-ir.h
===================================================================
--- gimple-ir.h (revision 125165)
+++ gimple-ir.h (working copy)
@@ -323,6 +323,7 @@ union gimple_statement_d GTY ((desc ("gi
extern gimple gs_build_return (bool, tree);
extern gimple gs_build_assign (tree, tree);
+extern gimple gs_build_call (tree, int, ...);
extern enum gimple_statement_structure_enum gimple_statement_structure (gimple);
extern void gs_add (gimple, gs_seq);
extern enum gimple_statement_structure_enum gss_for_assign (enum tree_code);
@@ -405,6 +406,43 @@ gs_assign_operand_rhs (gimple gs)
#define GS_ASSIGN_UNARY_MEM_RHS(G) \
GS_CHECK ((G), GS_ASSIGN)->gs_assign_unary_mem.op[1]
+/* GS_CALL accessors. */
+#define GS_CALL_LHS(G) (*gs_call_lhs ((G)))
+#define GS_CALL_FN(G) (*gs_call_fn ((G)))
+#define GS_CALL_CHAIN(G) (*gs_call_chain ((G)))
+#define GS_CALL_NARGS(G) (*gs_call_nargs ((G)))
+#define GS_CALL_ARG(G, N) (*gs_call_arg ((G), (N)))
+
+static inline tree *
+gs_call_lhs (gimple gs)
+{
+ return &GS_CHECK (gs, GS_CALL)->gs_call.lhs;
+}
+
+static inline tree *
+gs_call_fn (gimple gs)
+{
+ return &GS_CHECK (gs, GS_CALL)->gs_call.fn;
+}
+
+static inline tree *
+gs_call_chain (gimple gs)
+{
+ return &GS_CHECK (gs, GS_CALL)->gs_call.fn;
+}
+
+static inline unsigned long *
+gs_call_nargs (gimple gs)
+{
+ return &GS_CHECK (gs, GS_CALL)->gs_call.nargs;
+}
+
+static inline tree *
+gs_call_arg (gimple gs, unsigned int n)
+{
+ return &GS_CHECK (gs, GS_CALL)->gs_call.args[n];
+}
+
/* GS_RETURN accessors. */
static inline tree *
gs_return_operand_retval (gimple gs)
Index: gimplify.c
===================================================================
--- gimplify.c (revision 125167)
+++ gimplify.c (working copy)
@@ -2589,30 +2589,36 @@ gimplify_cond_expr (tree *expr_p, gs_seq
/* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
a call to __builtin_memcpy. */
-#if 0
-/* FIXME tuples */
static enum gimplify_status
-gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value)
+gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
+ gs_seq seq_p)
{
tree t, to, to_ptr, from, from_ptr;
+ gimple gs;
to = GENERIC_TREE_OPERAND (*expr_p, 0);
from = GENERIC_TREE_OPERAND (*expr_p, 1);
from_ptr = build_fold_addr_expr (from);
-
to_ptr = build_fold_addr_expr (to);
t = implicit_built_in_decls[BUILT_IN_MEMCPY];
- t = build_call_expr (t, 3, to_ptr, from_ptr, size);
+
+ gs = gs_build_call (t, 3, to_ptr, from_ptr, size);
if (want_value)
{
- t = build1 (NOP_EXPR, TREE_TYPE (to_ptr), t);
- t = build1 (INDIRECT_REF, TREE_TYPE (to), t);
+ /* tmp = memcpy() */
+ t = create_tmp_var (TREE_TYPE (to_ptr), NULL);
+ GS_CALL_LHS (gs) = t;
+ gs_add (gs, seq_p);
+
+ *expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
+ return GS_ALL_DONE;
}
- *expr_p = t;
- return GS_OK;
+ gs_add (gs, seq_p);
+ *expr_p = NULL;
+ return GS_ALL_DONE;
}
/* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
@@ -2620,26 +2626,34 @@ gimplify_modify_expr_to_memcpy (tree *ex
a CONSTRUCTOR with an empty element list. */
static enum gimplify_status
-gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value)
+gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
+ gs_seq seq_p)
{
tree t, to, to_ptr;
+ gimple gs;
to = GENERIC_TREE_OPERAND (*expr_p, 0);
to_ptr = build_fold_addr_expr (to);
t = implicit_built_in_decls[BUILT_IN_MEMSET];
- t = build_call_expr (t, 3, to_ptr, integer_zero_node, size);
+
+ gs = gs_build_call (t, 3, to_ptr, integer_zero_node, size);
if (want_value)
{
- t = build1 (NOP_EXPR, TREE_TYPE (to_ptr), t);
- t = build1 (INDIRECT_REF, TREE_TYPE (to), t);
+ /* tmp = memset() */
+ t = create_tmp_var (TREE_TYPE (to_ptr), NULL);
+ GS_CALL_LHS (gs) = t;
+ gs_add (gs, seq_p);
+
+ *expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
+ return GS_ALL_DONE;
}
- *expr_p = t;
- return GS_OK;
+ gs_add (gs, seq_p);
+ *expr_p = NULL;
+ return GS_ALL_DONE;
}
-#endif
/* A subroutine of gimplify_init_ctor_preeval. Called via walk_tree,
determine, cautiously, if a CONSTRUCTOR overlaps the lhs of an
@@ -3662,6 +3676,7 @@ gimplify_modify_expr (tree *expr_p, gs_s
want_value);
if (ret != GS_UNHANDLED)
return ret;
+#endif
/* If we've got a variable sized assignment between two lvalues (i.e. does
not involve a call), then we can make things a bit more straightforward
@@ -3672,14 +3687,14 @@ gimplify_modify_expr (tree *expr_p, gs_s
tree size = TREE_OPERAND (*from_p, 1);
if (TREE_CODE (from) == CONSTRUCTOR)
- return gimplify_modify_expr_to_memset (expr_p, size, want_value);
+ return gimplify_modify_expr_to_memset (expr_p, size, want_value, pre_p);
if (is_gimple_addressable (from))
{
*from_p = from;
- return gimplify_modify_expr_to_memcpy (expr_p, size, want_value);
+ return gimplify_modify_expr_to_memcpy (expr_p, size, want_value,
+ pre_p);
}
}
-#endif
/* Transform partial stores to non-addressable complex variables into
total stores. This allows us to use real instead of virtual operands
@@ -3836,13 +3851,11 @@ gimplify_compound_expr (tree *expr_p, gs
}
#endif
-/* Gimplifies a statement list. These may be created either by an
- enlightened front-end, or by shortcut_cond_expr. */
+/* Gimplifies a statement list onto a sequence. These may be created either
+ by an enlightened front-end, or by shortcut_cond_expr. */
-#if 0
-/* FIXME tuples */
static enum gimplify_status
-gimplify_statement_list (tree *expr_p, tree *pre_p)
+gimplify_statement_list (tree *expr_p, gs_seq pre_p)
{
tree temp = voidify_wrapper_expr (*expr_p, NULL);
@@ -3850,36 +3863,23 @@ gimplify_statement_list (tree *expr_p, t
while (!tsi_end_p (i))
{
- tree t;
-
-#if 0
-/* FIXME tuples */
- gimplify_stmt (tsi_stmt_ptr (i));
-#endif
- gcc_unreachable();
-
- t = tsi_stmt (i);
- if (t == NULL)
- tsi_delink (&i);
- else if (TREE_CODE (t) == STATEMENT_LIST)
- {
- tsi_link_before (&i, t, TSI_SAME_STMT);
- tsi_delink (&i);
- }
- else
- tsi_next (&i);
- }
+ gimplify_stmt (tsi_stmt_ptr (i), pre_p);
+ /* FIXME tuples: We probably don't need to delink. GC will take care of
+ this. */
+ tsi_delink (&i); }
if (temp)
{
- append_to_statement_list (*expr_p, pre_p);
+ gimplify_expr (expr_p, pre_p, NULL, false,
+
+ /* FIXME tuples: I'm not sure of either of these. */
+ is_gimple_val, fb_rvalue);
+
*expr_p = temp;
- return GS_OK;
}
return GS_ALL_DONE;
}
-#endif
/* Gimplify a SAVE_EXPR node. EXPR_P points to the expression to
gimplify. After gimplification, EXPR_P will point to a new temporary
@@ -5892,11 +5892,7 @@ gimplify_expr (tree *expr_p, gs_seq pre_
break;
case STATEMENT_LIST:
-#if 0
-/* FIXME tuples */
ret = gimplify_statement_list (expr_p, pre_p);
-#endif
- gcc_unreachable();
break;
case WITH_SIZE_EXPR:
More information about the Gcc-patches
mailing list