[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