This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[lto] PATCH: change low-level CALL_EXPR representation


Finally! Here's the change all my previous CALL_EXPR-related hacking was in preparation for. Any comments or complaints before I commit it?

-Sandra

2006-08-10  Sandra Loosemore  <sandra@codesourcery.com>

	* gcc/gentype.c (walk_type): When walking an array, compute the
	length and store it in a local variable before walking the array
	elements, instead of recomputing the length expression each time
	through the loop.  This is necessary to handle the new CALL_EXPR
	representation where the length is stored in the first array element,
	because otherwise that operand was getting overwritten on the
	first iteration.

	* gcc/tree.c (tree_code_size): Remove tcc_vl_exp, so that this
	signals an error on variably-sized expressions.
	(tree_size): Use VL_EXP_OPERAND_LENGTH instead of the more general
	TREE_OPERAND_LENGTH.
	(tree_operand_length): New function to implement TREE_OPERAND_LENGTH.
	(make_node_stat): Remove tcc_vl_exp, so that this signals an error.
	(build_nt_call_list): Rewrite to use build_vl_exp as the primitive.
	(process_call_operands): Remove explicit loop over arguments, since
	arguments are now ordinary operands.
	(build_vl_exp_stat): New primitive constructor for tcc_vl_exp objects.
	(build_call_list): Rewrite to use build_vl_exp as the primitive.
	(build_call_valist): Likewise.
	(build_call_array): Likewise.
	(init_call_expr_iterator): Rewrite for new CALL_EXPR representation.
	(next_call_expr_arg): Likewise.
	(more_call_expr_args_p): Likewise.
	(call_expr_nargs): Delete (this is now a macro).
	(call_expr_arg): Delete.  Calls changed to use the lvalue macro
	CALL_EXPR_ARG instead.
	(call_expr_argp): Delete, since it's no longer needed by the
	CALL_EXPR_ARG macro.
	(call_expr_arglist): New function used to implement the
	CALL_EXPR_ARGS macro.  
	* gcc/tree.h (TREE_OPERAND_LENGTH): Expand to call
	tree_operand_length instead of TREE_CODE_LENGTH, to account for
	variably-sized expression nodes.
	(VL_EXP_OPERAND_LENGTH): New macro.
	(CALL_EXPR_FN): Redefine for new CALL_EXPR representation.
	(CALL_EXPR_ARGS): Likewise.
	(CALL_EXPR_ARG0, CALL_EXPR_ARG1, CALL_EXPR_ARG2): Likewise.
	(CALL_EXPR_ARG): Likewise.
	(CALL_EXPR_ARGP): New macro to point to argument array in a
	CALL_EXPR.
	(call_expr_arg_iterator): Change internal state to reflect new
	CALL_EXPR representation.
	(tree_operand_length): Declare.
	(build_vl_exp_stat): Declare.
	(build_vl_exp): New macro.
	(call_expr_nargs, call_expr_arg, call_expr_argp): Delete declarations.
	(call_expr_arglist): Declare.

	* gcc/tree.def (CALL_EXPR): Document new CALL_EXPR layout.

	* gcc/builtins.c (fold_call_expr): Remove unnecessary copy to local
	array.
	(rewrite_call_expr): Rewrite to use new build_call_array.
	(expand_builtin_memory_chk): Change call_expr_arg to CALL_EXPR_ARG.
	(maybe_emit_chk_warning): Likewise.
	(maybe_emit_sprintf_chk_warning): Likewise.
	(fold_builtin_sprintf_chk): Likewise.
	(fold_builtin_snprintf_chk): Likewise.

	* gcc/objc/objc-act.c (receiver_is_class_object): Change
	call_expr_arg to CALL_EXPR_ARG.
	* gcc/tree-ssa-ccp.c (ccp_fold_builtin): Likewise.

	* gcc/tree-ssa-pre.c (list_node_pool):  Delete, since argument lists
	no longer need special treatment.
	(pool_copy_list): Likewise.
	(temp_copy_call_expr): Delete argument list copy.
	(create_expression_by_pieces): Rewrite to avoid building temporary
	argument list.
	(create_value_expr_from): Remove explicit traversal of arguments,
	since they're now ordinary operands.
	(init_pre, fini_pre): Remove references to list_node_pool.

	* gcc/cp/cp-tree.def (AGGR_INIT_EXPR): Document new layout.

	* gcc/cp/semantics.c (simplify_aggr_init_expr): Rewrite to avoid
	building a temporary argument list.

	* gcc/java/java-tree.def (NEW_CLASS_EXPR): Document new layout.

	* gcc/doc/c-tree.texi (Expression trees): Document
	new CALL_EXPR and AGGR_INIT_EXPR layout and accessors.
	

Index: gcc/gengtype.c
===================================================================
*** gcc/gengtype.c	(revision 116048)
--- gcc/gengtype.c	(working copy)
*************** walk_type (type_p t, struct walk_type_da
*** 1743,1755 ****
  	oprintf (d->of, "%*s{\n", d->indent, "");
  	d->indent += 2;
  	oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
! 	oprintf (d->of, "%*sfor (i%d = 0; i%d != (size_t)(", d->indent, "",
! 		 loopcounter, loopcounter);
  	if (length)
  	  output_escaped_param (d, length, "length");
  	else
  	  oprintf (d->of, "%s", t->u.a.len);
! 	oprintf (d->of, "); i%d++) {\n", loopcounter);
  	d->indent += 2;
  	d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
  	d->used_length = 1;
--- 1743,1759 ----
  	oprintf (d->of, "%*s{\n", d->indent, "");
  	d->indent += 2;
  	oprintf (d->of, "%*ssize_t i%d;\n", d->indent, "", loopcounter);
! 	oprintf (d->of, "%*ssize_t l%d = (size_t)(",
! 		 d->indent, "", loopcounter);
  	if (length)
  	  output_escaped_param (d, length, "length");
  	else
  	  oprintf (d->of, "%s", t->u.a.len);
! 	oprintf (d->of, ");\n");
! 	
! 	oprintf (d->of, "%*sfor (i%d = 0; i%d != l%d; i%d++) {\n",
! 		 d->indent, "",
! 		 loopcounter, loopcounter, loopcounter, loopcounter);
  	d->indent += 2;
  	d->val = newval = xasprintf ("%s[i%d]", oldval, loopcounter);
  	d->used_length = 1;
Index: gcc/tree.c
===================================================================
*** gcc/tree.c	(revision 116048)
--- gcc/tree.c	(working copy)
*************** tree_code_size (enum tree_code code)
*** 355,361 ****
      case tcc_comparison:  /* a comparison expression */
      case tcc_unary:       /* a unary arithmetic expression */
      case tcc_binary:      /* a binary arithmetic expression */
-     case tcc_vl_exp:      /* FIXME: a function call expression */
        return (sizeof (struct tree_exp)
  	      + (TREE_CODE_LENGTH (code) - 1) * sizeof (tree));
  
--- 355,360 ----
*************** tree_size (tree node)
*** 431,442 ****
      default:
        if (TREE_CODE_CLASS (code) == tcc_vl_exp)
  	return (sizeof (struct tree_exp)
! 		+ (TREE_OPERAND_LENGTH (node) - 1) * sizeof (tree));
        else
  	return tree_code_size (code);
      }
  }
  
  /* Return a newly allocated node of code CODE.  For decl and type
     nodes, some other fields are initialized.  The rest of the node is
     initialized to zero.  This function cannot be used for PHI_NODE,
--- 430,452 ----
      default:
        if (TREE_CODE_CLASS (code) == tcc_vl_exp)
  	return (sizeof (struct tree_exp)
! 		+ (VL_EXP_OPERAND_LENGTH (node) - 1) * sizeof (tree));
        else
  	return tree_code_size (code);
      }
  }
  
+ /* Compute the number of operands in an expression node NODE.  For 
+    tcc_vl_exp nodes like CALL_EXPRs, this is stored in the node itself,
+    otherwise it is looked up from the node's code.  */
+ int tree_operand_length (tree node)
+ {
+   if (VL_EXP_CLASS_P (node))
+     return VL_EXP_OPERAND_LENGTH (node);
+   else
+     return TREE_CODE_LENGTH (TREE_CODE (node));
+ }
+ 
  /* Return a newly allocated node of code CODE.  For decl and type
     nodes, some other fields are initialized.  The rest of the node is
     initialized to zero.  This function cannot be used for PHI_NODE,
*************** make_node_stat (enum tree_code code MEM_
*** 476,482 ****
      case tcc_comparison:  /* a comparison expression */
      case tcc_unary:  /* a unary arithmetic expression */
      case tcc_binary:  /* a binary arithmetic expression */
-     case tcc_vl_exp:  /* a call expression */
        kind = e_kind;
        break;
  
--- 486,491 ----
*************** tree
*** 3195,3207 ****
  build_nt_call_list (enum tree_code code, tree fn, tree arglist)
  {
    tree t;
    gcc_assert (TREE_CODE_CLASS (code) == tcc_vl_exp);
  
!   /* FIXME: change this to use the new CALL_EXPR representation.  */
!   t = make_node (code);
    CALL_EXPR_FN (t) = fn;
    CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE;
!   CALL_EXPR_ARGS (t) = arglist;
    return t;
  }
  
--- 3204,3218 ----
  build_nt_call_list (enum tree_code code, tree fn, tree arglist)
  {
    tree t;
+   int i;
+ 
    gcc_assert (TREE_CODE_CLASS (code) == tcc_vl_exp);
  
!   t = build_vl_exp (code, list_length (arglist) + 3);
    CALL_EXPR_FN (t) = fn;
    CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE;
!   for (i = 0; arglist; arglist = TREE_CHAIN (arglist), i++)
!     CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist);
    return t;
  }
  
*************** process_call_operands (tree t)
*** 7017,7040 ****
        i = call_expr_flags (t);
        if (!(i & (ECF_CONST | ECF_PURE)))
  	side_effects = 1;
- 
-       /* FIXME: This goes away after representation change is complete.  */
-       /* And even those have side-effects if their arguments do.  */
-       else
- 	{
- 	  tree node;
- 	  call_expr_arg_iterator iter;
- 	  FOR_EACH_CALL_EXPR_ARG (node, iter, t)
- 	    if (TREE_SIDE_EFFECTS (node))
- 	      {
- 		side_effects = 1;
- 		break;
- 	      }
- 	}
      }
    TREE_SIDE_EFFECTS (t) = side_effects;
  }
  
  /* Build a CALL_EXPR-like thing of class tcc_vl_exp with code CODE and the
     indicated RETURN_TYPE and FN and a null static chain slot.
     ARGLIST is a TREE_LIST of the arguments.  */
--- 7028,7070 ----
        i = call_expr_flags (t);
        if (!(i & (ECF_CONST | ECF_PURE)))
  	side_effects = 1;
      }
    TREE_SIDE_EFFECTS (t) = side_effects;
  }
  
+ /* Build a tcc_vl_exp object with code CODE and room for LEN operands.  LEN
+    includes the implicit operand count in TREE_OPERAND 0, and so must be >= 1.
+    Except for the CODE and operand count field, other storage for the
+    object is initialized to zeros.  */
+ 
+ tree
+ build_vl_exp_stat (enum tree_code code, int len MEM_STAT_DECL)
+ {
+   tree t;
+   int length = (len-1) * sizeof (tree) + sizeof (struct tree_exp);
+ 
+   gcc_assert (TREE_CODE_CLASS (code) == tcc_vl_exp);
+   gcc_assert (len >= 1);
+ 
+ #ifdef GATHER_STATISTICS
+   tree_node_counts[(int) e_kind]++;
+   tree_node_sizes[(int) e_kind] += length;
+ #endif
+ 
+   t = ggc_alloc_zone_pass_stat (length, &tree_zone);
+ 
+   memset (t, 0, length);
+ 
+   TREE_SET_CODE (t, code);
+ 
+   /* Can't use TREE_OPERAND to store the length because if checking is
+      enabled, it will try to check the length before we store it.  :-P  */
+   t->exp.operands[0] = build_int_cst (sizetype, len);
+ 
+   return t;
+ }
+ 
+ 
  /* Build a CALL_EXPR-like thing of class tcc_vl_exp with code CODE and the
     indicated RETURN_TYPE and FN and a null static chain slot.
     ARGLIST is a TREE_LIST of the arguments.  */
*************** build_call_list (enum tree_code code, tr
*** 7044,7057 ****
  		 tree arglist)
  {
    tree t;
!   gcc_assert (TREE_CODE_CLASS (code) == tcc_vl_exp);
  
!   /* FIXME: change this to use the new CALL_EXPR representation.  */
!   t = make_node (code);
    TREE_TYPE (t) = return_type;
    CALL_EXPR_FN (t) = fn;
    CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE;
!   CALL_EXPR_ARGS (t) = arglist;
    process_call_operands (t);
    return t;
  }
--- 7074,7088 ----
  		 tree arglist)
  {
    tree t;
!   int i;
  
!   gcc_assert (TREE_CODE_CLASS (code) == tcc_vl_exp);
!   t = build_vl_exp (code, list_length (arglist) + 3);
    TREE_TYPE (t) = return_type;
    CALL_EXPR_FN (t) = fn;
    CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE;
!   for (i = 0; arglist; arglist = TREE_CHAIN (arglist), i++)
!     CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist);
    process_call_operands (t);
    return t;
  }
*************** tree
*** 7082,7093 ****
  build_call_valist (enum tree_code code, tree return_type, tree fn,
  		   int nargs, va_list args)
  {
!   /* FIXME: change this to use the new CALL_EXPR representation.  */
!   tree arglist = NULL_TREE;
    int i;
    for (i = 0; i < nargs; i++)
!     arglist = tree_cons (NULL_TREE, va_arg (args, tree), arglist);
!   return build_call_list (code, return_type, fn, nreverse (arglist));
  }
  
  /* Build a CALL_EXPR-like thing of class tcc_vl_exp with code CODE and the
--- 7113,7130 ----
  build_call_valist (enum tree_code code, tree return_type, tree fn,
  		   int nargs, va_list args)
  {
!   tree t;
    int i;
+ 
+   gcc_assert (TREE_CODE_CLASS (code) == tcc_vl_exp);
+   t = build_vl_exp (code, nargs + 3);
+   TREE_TYPE (t) = return_type;
+   CALL_EXPR_FN (t) = fn;
+   CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE;
    for (i = 0; i < nargs; i++)
!     CALL_EXPR_ARG (t, i) = va_arg (args, tree);
!   process_call_operands (t);
!   return t;
  }
  
  /* Build a CALL_EXPR-like thing of class tcc_vl_exp with code CODE and the
*************** tree
*** 7099,7112 ****
  build_call_array (enum tree_code code, tree return_type, tree fn,
  		  int nargs, tree *args)
  {
!   /* FIXME: change this to use the new CALL_EXPR representation.  */
!   tree arglist = NULL_TREE;
    int i;
    for (i = 0; i < nargs; i++)
!     arglist = tree_cons (NULL_TREE, args[i], arglist);
!   return build_call_list (code, return_type, fn, nreverse (arglist));
  }
  
  /* Returns true if it is possible to prove that the index of
     an array access REF (an ARRAY_REF expression) falls into the
     array bounds.  */
--- 7136,7156 ----
  build_call_array (enum tree_code code, tree return_type, tree fn,
  		  int nargs, tree *args)
  {
!   tree t;
    int i;
+ 
+   gcc_assert (TREE_CODE_CLASS (code) == tcc_vl_exp);
+   t = build_vl_exp (code, nargs + 3);
+   TREE_TYPE (t) = return_type;
+   CALL_EXPR_FN (t) = fn;
+   CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE;
    for (i = 0; i < nargs; i++)
!     CALL_EXPR_ARG (t, i) = args[i];
!   process_call_operands (t);
!   return t;
  }
  
+ 
  /* Returns true if it is possible to prove that the index of
     an array access REF (an ARRAY_REF expression) falls into the
     array bounds.  */
*************** stdarg_p (tree fntype)
*** 7867,7873 ****
  void
  init_call_expr_arg_iterator (tree exp, call_expr_arg_iterator *iter)
  {
!   iter->tail =  CALL_EXPR_ARGS (exp);
  }
  
  /* Initialize the abstract argument list iterator object ITER, then advance
--- 7911,7919 ----
  void
  init_call_expr_arg_iterator (tree exp, call_expr_arg_iterator *iter)
  {
!   iter->t = exp;
!   iter->n = call_expr_nargs (exp);
!   iter->i = 0;
  }
  
  /* Initialize the abstract argument list iterator object ITER, then advance
*************** tree
*** 7889,7898 ****
  next_call_expr_arg (call_expr_arg_iterator *iter)
  {
    tree result;
!   if (iter->tail == NULL_TREE)
      return NULL_TREE;
!   result = TREE_VALUE (iter->tail);
!   iter->tail = TREE_CHAIN (iter->tail);
    return result;
  }
  
--- 7935,7944 ----
  next_call_expr_arg (call_expr_arg_iterator *iter)
  {
    tree result;
!   if (iter->i >= iter->n)
      return NULL_TREE;
!   result = CALL_EXPR_ARG (iter->t, iter->i);
!   iter->i++;
    return result;
  }
  
*************** next_call_expr_arg (call_expr_arg_iterat
*** 7902,7957 ****
  bool
  more_call_expr_args_p (const call_expr_arg_iterator *iter)
  {
!   return (iter->tail != NULL_TREE);
  }
  
! /* Count the number of arguments passed in CALL_EXPR node EXP.  */
! 
! int
! call_expr_nargs (tree exp)
! {
!   call_expr_arg_iterator iter;
!   int i = 0;
!   tree arg;
!   for (arg = first_call_expr_arg (exp, &iter); arg;
!        arg = next_call_expr_arg (&iter))
!     i++;
!   return i;
! }
! 
! /* Return the Nth (zero-based) argument from CALL_EXPR node EXP.  Returns
!    NULL if there aren't that many arguments.  */
! 
  tree
! call_expr_arg (tree exp, int n)
! {
!   call_expr_arg_iterator iter;
!   tree t = NULL;
!   int i;
!   for (i = 0, t = first_call_expr_arg (exp, &iter);
!        (i < n) && t;
!        i++, t = next_call_expr_arg (&iter))
!     ;
!   return t;
! }
! 
! /* Return a pointer to the Nth (zero-based) argument from CALL_EXPR node EXP.
!    Returns NULL if there aren't that many arguments.  */
! 
! tree *
! call_expr_argp (tree exp, int n)
  {
!   tree t = CALL_EXPR_ARGS (exp);
    int i;
!   for (i = 0; i < n; i++)
!     {
!       if (!t)
! 	return NULL;
!       t = TREE_CHAIN (t);
!     }
!   if (t)
!     return &(TREE_VALUE (t));
!   return NULL;
  }
  
  #include "gt-tree.h"
--- 7948,7969 ----
  bool
  more_call_expr_args_p (const call_expr_arg_iterator *iter)
  {
!   return (iter->i < iter->n);
  }
  
! /* Build and return a TREE_LIST of arguments in the CALL_EXPR exp.
!    FIXME: don't use this function.  It exists for compatibility with
!    the old representation of CALL_EXPRs where a list was used to hold the
!    arguments.  Places that currently extract the arglist from a CALL_EXPR
!    ought to be rewritten to use the CALL_EXPR itself.  */
  tree
! call_expr_arglist (tree exp)
  {
!   tree arglist = NULL_TREE;
    int i;
!   for (i = call_expr_nargs (exp) - 1; i >= 0; i--)
!     arglist = tree_cons (NULL_TREE, CALL_EXPR_ARG (exp, i), arglist);
!   return arglist;
  }
  
  #include "gt-tree.h"
Index: gcc/tree.h
===================================================================
*** gcc/tree.h	(revision 116048)
--- gcc/tree.h	(working copy)
*************** struct tree_constructor GTY(())
*** 1413,1422 ****
  				 && integer_zerop (TREE_OPERAND (NODE, 0)))
  
  /* In ordinary expression nodes.  */
! #define TREE_OPERAND_LENGTH(NODE) TREE_CODE_LENGTH (TREE_CODE (NODE))
  #define TREE_OPERAND(NODE, I) TREE_OPERAND_CHECK (NODE, I)
  #define TREE_COMPLEXITY(NODE) (EXPR_CHECK (NODE)->exp.complexity)
  
  /* In a LOOP_EXPR node.  */
  #define LOOP_EXPR_BODY(NODE) TREE_OPERAND_CHECK_CODE (NODE, LOOP_EXPR, 0)
  
--- 1413,1428 ----
  				 && integer_zerop (TREE_OPERAND (NODE, 0)))
  
  /* In ordinary expression nodes.  */
! #define TREE_OPERAND_LENGTH(NODE) tree_operand_length (NODE)
  #define TREE_OPERAND(NODE, I) TREE_OPERAND_CHECK (NODE, I)
  #define TREE_COMPLEXITY(NODE) (EXPR_CHECK (NODE)->exp.complexity)
  
+ /* In a tcc_vl_exp node, operand 0 is an INT_CST node holding the operand
+    length.  Note that we have to bypass the use of TREE_OPERAND to access
+    that field to avoid infinite recursion in expanding the macros.  */
+ #define VL_EXP_OPERAND_LENGTH(NODE) \
+   ((int)TREE_INT_CST_LOW (VL_EXP_CHECK (NODE)->exp.operands[0]))
+ 
  /* In a LOOP_EXPR node.  */
  #define LOOP_EXPR_BODY(NODE) TREE_OPERAND_CHECK_CODE (NODE, LOOP_EXPR, 0)
  
*************** struct tree_constructor GTY(())
*** 1545,1561 ****
  
  /* CALL_EXPR accessors.
   */
! #define CALL_EXPR_FN(NODE) TREE_OPERAND (VL_EXP_CHECK (NODE), 0)
  #define CALL_EXPR_STATIC_CHAIN(NODE) TREE_OPERAND (VL_EXP_CHECK (NODE), 2)
! #define CALL_EXPR_ARGS(NODE) TREE_OPERAND (VL_EXP_CHECK (NODE), 1)
! #define CALL_EXPR_ARG0(NODE) TREE_VALUE (CALL_EXPR_ARGS (NODE))
! #define CALL_EXPR_ARG1(NODE) TREE_VALUE (TREE_CHAIN (CALL_EXPR_ARGS (NODE)))
! #define CALL_EXPR_ARG2(NODE) TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CALL_EXPR_ARGS (NODE))))
! #define CALL_EXPR_ARG(NODE, I) (*call_expr_argp ((NODE), (I)))
  
  typedef struct call_expr_arg_iterator_d GTY (())
  {
!   tree tail;
  } call_expr_arg_iterator;
  
  /* Iterate through each argument ARG of CALL_EXPR CALL, using variable ITER
--- 1551,1579 ----
  
  /* CALL_EXPR accessors.
   */
! #define CALL_EXPR_FN(NODE) TREE_OPERAND (VL_EXP_CHECK (NODE), 1)
  #define CALL_EXPR_STATIC_CHAIN(NODE) TREE_OPERAND (VL_EXP_CHECK (NODE), 2)
! #define CALL_EXPR_ARGS(NODE) call_expr_arglist (NODE)
! #define CALL_EXPR_ARG0(NODE) TREE_OPERAND (VL_EXP_CHECK (NODE), 3)
! #define CALL_EXPR_ARG1(NODE) TREE_OPERAND (VL_EXP_CHECK (NODE), 4)
! #define CALL_EXPR_ARG2(NODE) TREE_OPERAND (VL_EXP_CHECK (NODE), 5)
! #define CALL_EXPR_ARG(NODE, I) TREE_OPERAND (VL_EXP_CHECK (NODE), (I)+3)
! #define call_expr_nargs(NODE) (VL_EXP_OPERAND_LENGTH(NODE) - 3)
! 
! /* CALL_EXPR_ARGP returns a pointer to the argument vector for NODE.
!    We can't use &CALL_EXPR_ARG0 (NODE) because that will complain if
!    the argument count is zero when checking is enabled.  Instead, do
!    the pointer arithmetic to advance past the 3 fixed operands in a
!    CALL_EXPR.  That produces a valid pointer to just past the end of the
!    argument array, even if it's not valid to dereference it.  */
! #define CALL_EXPR_ARGP(NODE) \
!   (&(TREE_OPERAND (VL_EXP_CHECK (NODE), 0)) + 3)
  
  typedef struct call_expr_arg_iterator_d GTY (())
  {
!   tree t;	/* the call_expr */
!   int n;	/* argument count */
!   int i;	/* next argument index */
  } call_expr_arg_iterator;
  
  /* Iterate through each argument ARG of CALL_EXPR CALL, using variable ITER
*************** extern tree decl_assembler_name (tree);
*** 3452,3461 ****
  extern size_t tree_size (tree);
  
  /* Compute the number of bytes occupied by a tree with code CODE.  This
!    function cannot be used for TREE_VEC or PHI_NODE codes, which are of
!    variable length.  */
  extern size_t tree_code_size (enum tree_code);
  
  /* Lowest level primitive for allocating a node.
     The TREE_CODE is the only argument.  Contents are initialized
     to zero except for a few of the common fields.  */
--- 3470,3484 ----
  extern size_t tree_size (tree);
  
  /* Compute the number of bytes occupied by a tree with code CODE.  This
!    function cannot be used for TREE_VEC, PHI_NODE, or CALL_EXPR codes,
!    which are of variable length.  */
  extern size_t tree_code_size (enum tree_code);
  
+ /* Compute the number of operands in an expression node NODE.  For 
+    tcc_vl_exp nodes like CALL_EXPRs, this is stored in the node itself,
+    otherwise it is looked up from the node's code.  */
+ extern int tree_operand_length (tree);
+ 
  /* Lowest level primitive for allocating a node.
     The TREE_CODE is the only argument.  Contents are initialized
     to zero except for a few of the common fields.  */
*************** extern void annotate_with_locus (tree, l
*** 3576,3581 ****
--- 3599,3607 ----
  extern tree build_empty_stmt (void);
  extern tree build_omp_clause (enum omp_clause_code);
  
+ extern tree build_vl_exp_stat (enum tree_code, int MEM_STAT_DECL);
+ #define build_vl_exp(c,n) build_vl_exp_stat (c,n MEM_STAT_INFO)
+ 
  extern tree build_call_list (enum tree_code, tree, tree, tree);
  extern tree build_call_nary (enum tree_code, tree, tree, int, ...);
  extern tree build_call_valist (enum tree_code, tree, tree, int, va_list);
*************** extern void init_call_expr_arg_iterator 
*** 4176,4184 ****
  extern tree first_call_expr_arg (tree, call_expr_arg_iterator *);
  extern tree next_call_expr_arg (call_expr_arg_iterator *);
  extern bool more_call_expr_args_p (const call_expr_arg_iterator *);
! extern int call_expr_nargs (tree);
! extern tree call_expr_arg (tree, int);
! extern tree *call_expr_argp (tree, int);
  extern tree *nth_parm_type_ptr (tree, int);
  extern tree alloc_parm_types (int);
  extern tree vec_heap2parm_types (VEC(tree,heap) *);
--- 4202,4208 ----
  extern tree first_call_expr_arg (tree, call_expr_arg_iterator *);
  extern tree next_call_expr_arg (call_expr_arg_iterator *);
  extern bool more_call_expr_args_p (const call_expr_arg_iterator *);
! extern tree call_expr_arglist (tree);
  extern tree *nth_parm_type_ptr (tree, int);
  extern tree alloc_parm_types (int);
  extern tree vec_heap2parm_types (VEC(tree,heap) *);
Index: gcc/tree.def
===================================================================
*** gcc/tree.def	(revision 116048)
--- gcc/tree.def	(working copy)
*************** DEFTREECODE (VEC_COND_EXPR, "vec_cond_ex
*** 522,531 ****
     nodes for the function.  */
  DEFTREECODE (BIND_EXPR, "bind_expr", tcc_expression, 3)
  
! /* Function call.  Operand 0 is the function.
!    Operand 1 is the argument list, a list of expressions
!    made out of a chain of TREE_LIST nodes.
!    Operand 2 is the static chain argument, or NULL.  */
  DEFTREECODE (CALL_EXPR, "call_expr", tcc_vl_exp, 3)
  
  /* Specify a value to compute along with its corresponding cleanup.
--- 522,533 ----
     nodes for the function.  */
  DEFTREECODE (BIND_EXPR, "bind_expr", tcc_expression, 3)
  
! /* Function call.  CALL_EXPRs are represented by variably-sized expression
!    nodes.  There are at least three fixed operands.  Operand 0 is an
!    INTEGER_CST node containing the total operand count, the number of
!    arguments plus 3.  Operand 1 is the function, while operand 2 is
!    is static chain argument, or NULL.  The remaining operands are the
!    arguments to the call.  */
  DEFTREECODE (CALL_EXPR, "call_expr", tcc_vl_exp, 3)
  
  /* Specify a value to compute along with its corresponding cleanup.
Index: gcc/builtins.c
===================================================================
*** gcc/builtins.c	(revision 116048)
--- gcc/builtins.c	(working copy)
*************** fold_call_expr (tree exp, bool ignore)
*** 8886,8906 ****
        /* FIXME: Don't use a list in this interface.  */
        if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
  	return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore);
- 
- 
-       /* FIXME: When the CALL_EXPR representation changes to store the
- 	 arguments in an array instead of in a TREE_LIST, we can just pass
- 	 that array to fold_builtin_n instead of copying the arguments
- 	 to a local array.  */
        else
  	{
  	  int nargs = call_expr_nargs (exp);
  	  if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
  	    {
! 	      int i;
! 	      tree args[MAX_ARGS_TO_FOLD_BUILTIN];
! 	      for (i = 0; i < nargs; i++)
! 		args[i] = call_expr_arg (exp, i);
  	      ret = fold_builtin_n (fndecl, args, nargs, ignore);
  	      if (ret)
  		return ret;
--- 8886,8897 ----
        /* FIXME: Don't use a list in this interface.  */
        if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
  	return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore);
        else
  	{
  	  int nargs = call_expr_nargs (exp);
  	  if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
  	    {
! 	      tree *args = CALL_EXPR_ARGP (exp);
  	      ret = fold_builtin_n (fndecl, args, nargs, ignore);
  	      if (ret)
  		return ret;
*************** fold_builtin_call_valist (tree type,
*** 9052,9091 ****
  /* Construct a new CALL_EXPR using the tail of the argument list of EXP
     along with N new arguments specified as the "..." parameters.  SKIP
     is the number of arguments in EXP to be omitted.  This function is used
!    to do varargs-to-varargs transformations.
! 
!    FIXME: This needs to be rewritten when the underlying CALL_EXPR
!    representation changes not to use a TREE_LIST to hold the arguments.  */
  
  static tree
! rewrite_call_expr (tree exp, int skip, tree fn, int n, ...)
  {
!   tree arglist = CALL_EXPR_ARGS (exp);
!   int i;
!   for (i = 0; i < skip; i++)
!     arglist = TREE_CHAIN (arglist);
    if (n > 0)
      {
!       tree temp = NULL_TREE;
        va_list ap;
        va_start (ap, n);
-       /* Build TEMP backwards, then destructively reverse and concatenate
- 	 it onto ARGLIST.  */
        for (i = 0; i < n; i++)
! 	{
! 	  tree arg = va_arg (ap, tree);
! 	  temp = tree_cons (NULL_TREE, arg, temp);
! 	}
        va_end (ap);
!       for (i = 0; i < n; i++)
! 	{
! 	  tree next = TREE_CHAIN (temp);
! 	  TREE_CHAIN (temp) = arglist;
! 	  arglist = temp;
! 	  temp = next;
! 	}
      }
!   return build_function_call_expr (fn, arglist);
  }
  
  /* Validate a single argument ARG against a tree code CODE representing
--- 9043,9077 ----
  /* Construct a new CALL_EXPR using the tail of the argument list of EXP
     along with N new arguments specified as the "..." parameters.  SKIP
     is the number of arguments in EXP to be omitted.  This function is used
!    to do varargs-to-varargs transformations.  */
  
  static tree
! rewrite_call_expr (tree exp, int skip, tree fndecl, int n, ...)
  {
!   int oldnargs = call_expr_nargs (exp);
!   int nargs = oldnargs - skip + n;
!   tree fntype = TREE_TYPE (fndecl);
!   tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
!   tree *buffer;
! 
    if (n > 0)
      {
!       int i, j;
        va_list ap;
+ 
+       buffer = alloca (nargs * sizeof (tree));
        va_start (ap, n);
        for (i = 0; i < n; i++)
! 	buffer[i] = va_arg (ap, tree);
        va_end (ap);
!       for (j = skip; j < oldnargs; j++, i++)
! 	buffer[i] = CALL_EXPR_ARG (exp, j);
      }
!   else 
!     buffer = CALL_EXPR_ARGP (exp) + skip;
! 
!   return fold (build_call_array (CALL_EXPR, TREE_TYPE (exp), fn,
! 				 nargs, buffer));
  }
  
  /* Validate a single argument ARG against a tree code CODE representing
*************** expand_builtin_memory_chk (tree exp, rtx
*** 9928,9934 ****
    dest = CALL_EXPR_ARG0 (exp);
    src = CALL_EXPR_ARG1 (exp);
    len = CALL_EXPR_ARG2 (exp);
!   size = call_expr_arg (exp, 3);
  
    if (! host_integerp (size, 1))
      return NULL_RTX;
--- 9914,9920 ----
    dest = CALL_EXPR_ARG0 (exp);
    src = CALL_EXPR_ARG1 (exp);
    len = CALL_EXPR_ARG2 (exp);
!   size = CALL_EXPR_ARG (exp, 3);
  
    if (! host_integerp (size, 1))
      return NULL_RTX;
*************** maybe_emit_chk_warning (tree exp, enum b
*** 10044,10061 ****
      /* For __strcat_chk the warning will be emitted only if overflowing
         by at least strlen (dest) + 1 bytes.  */
      case BUILT_IN_STRCAT_CHK:
!       len = call_expr_arg (exp, 1);
!       size = call_expr_arg (exp, 2);
        is_strlen = 1;
        break;
      case BUILT_IN_STRNCPY_CHK:
!       len = call_expr_arg (exp, 2);
!       size = call_expr_arg (exp, 3);
        break;
      case BUILT_IN_SNPRINTF_CHK:
      case BUILT_IN_VSNPRINTF_CHK:
!       len = call_expr_arg (exp, 1);
!       size = call_expr_arg (exp, 3);
        break;
      default:
        gcc_unreachable ();
--- 10030,10047 ----
      /* For __strcat_chk the warning will be emitted only if overflowing
         by at least strlen (dest) + 1 bytes.  */
      case BUILT_IN_STRCAT_CHK:
!       len = CALL_EXPR_ARG (exp, 1);
!       size = CALL_EXPR_ARG (exp, 2);
        is_strlen = 1;
        break;
      case BUILT_IN_STRNCPY_CHK:
!       len = CALL_EXPR_ARG (exp, 2);
!       size = CALL_EXPR_ARG (exp, 3);
        break;
      case BUILT_IN_SNPRINTF_CHK:
      case BUILT_IN_VSNPRINTF_CHK:
!       len = CALL_EXPR_ARG (exp, 1);
!       size = CALL_EXPR_ARG (exp, 3);
        break;
      default:
        gcc_unreachable ();
*************** maybe_emit_sprintf_chk_warning (tree exp
*** 10098,10104 ****
    dest = CALL_EXPR_ARG0 (exp);
    flag = CALL_EXPR_ARG1 (exp);
    size = CALL_EXPR_ARG2 (exp);
!   fmt = call_expr_arg (exp, 3);
  
    if (! host_integerp (size, 1) || integer_all_onesp (size))
      return;
--- 10084,10090 ----
    dest = CALL_EXPR_ARG0 (exp);
    flag = CALL_EXPR_ARG1 (exp);
    size = CALL_EXPR_ARG2 (exp);
!   fmt = CALL_EXPR_ARG (exp, 3);
  
    if (! host_integerp (size, 1) || integer_all_onesp (size))
      return;
*************** maybe_emit_sprintf_chk_warning (tree exp
*** 10123,10129 ****
  
        if (nargs < 5)
  	return;
!       arg = call_expr_arg (exp, 4);
        if (! POINTER_TYPE_P (TREE_TYPE (arg)))
  	return;
  
--- 10109,10115 ----
  
        if (nargs < 5)
  	return;
!       arg = CALL_EXPR_ARG (exp, 4);
        if (! POINTER_TYPE_P (TREE_TYPE (arg)))
  	return;
  
*************** fold_builtin_sprintf_chk (tree exp, enum
*** 10523,10529 ****
    size = CALL_EXPR_ARG2 (exp);
    if (!validate_arg (size, INTEGER_TYPE))
      return NULL_TREE;
!   fmt = call_expr_arg (exp, 3);
    if (!validate_arg (fmt, POINTER_TYPE))
      return NULL_TREE;
  
--- 10509,10515 ----
    size = CALL_EXPR_ARG2 (exp);
    if (!validate_arg (size, INTEGER_TYPE))
      return NULL_TREE;
!   fmt = CALL_EXPR_ARG (exp, 3);
    if (!validate_arg (fmt, POINTER_TYPE))
      return NULL_TREE;
  
*************** fold_builtin_sprintf_chk (tree exp, enum
*** 10554,10560 ****
  
  	  if (nargs == 5)
  	    {
! 	      arg = call_expr_arg (exp, 4);
  	      if (validate_arg (arg, POINTER_TYPE))
  		{
  		  len = c_strlen (arg, 1);
--- 10540,10546 ----
  
  	  if (nargs == 5)
  	    {
! 	      arg = CALL_EXPR_ARG (exp, 4);
  	      if (validate_arg (arg, POINTER_TYPE))
  		{
  		  len = c_strlen (arg, 1);
*************** fold_builtin_snprintf_chk (tree exp, tre
*** 10607,10625 ****
    /* Verify the required arguments in the original call.  */
    if (call_expr_nargs (exp) < 5)
      return NULL_TREE;
!   dest = call_expr_arg (exp, 0);
    if (!validate_arg (dest, POINTER_TYPE))
      return NULL_TREE;
!   len = call_expr_arg (exp, 1);
    if (!validate_arg (len, INTEGER_TYPE))
      return NULL_TREE;
!   flag = call_expr_arg (exp, 2);
    if (!validate_arg (flag, INTEGER_TYPE))
      return NULL_TREE;
!   size = call_expr_arg (exp, 3);
    if (!validate_arg (size, INTEGER_TYPE))
      return NULL_TREE;
!   fmt = call_expr_arg (exp, 4);
    if (!validate_arg (fmt, POINTER_TYPE))
      return NULL_TREE;
  
--- 10593,10611 ----
    /* Verify the required arguments in the original call.  */
    if (call_expr_nargs (exp) < 5)
      return NULL_TREE;
!   dest = CALL_EXPR_ARG (exp, 0);
    if (!validate_arg (dest, POINTER_TYPE))
      return NULL_TREE;
!   len = CALL_EXPR_ARG (exp, 1);
    if (!validate_arg (len, INTEGER_TYPE))
      return NULL_TREE;
!   flag = CALL_EXPR_ARG (exp, 2);
    if (!validate_arg (flag, INTEGER_TYPE))
      return NULL_TREE;
!   size = CALL_EXPR_ARG (exp, 3);
    if (!validate_arg (size, INTEGER_TYPE))
      return NULL_TREE;
!   fmt = CALL_EXPR_ARG (exp, 4);
    if (!validate_arg (fmt, POINTER_TYPE))
      return NULL_TREE;
  
Index: gcc/objc/objc-act.c
===================================================================
*** gcc/objc/objc-act.c	(revision 116048)
--- gcc/objc/objc-act.c	(working copy)
*************** receiver_is_class_object (tree receiver,
*** 6127,6133 ****
        && TREE_TYPE (exp) == TREE_TYPE (objc_get_class_decl)
        && !strcmp (IDENTIFIER_POINTER (DECL_NAME (exp)), TAG_GETCLASS)
        /* We have a call to objc_get_class/objc_getClass!  */
!       && (arg = call_expr_arg (receiver, 0)))
      {
        STRIP_NOPS (arg);
        if (TREE_CODE (arg) == ADDR_EXPR
--- 6127,6133 ----
        && TREE_TYPE (exp) == TREE_TYPE (objc_get_class_decl)
        && !strcmp (IDENTIFIER_POINTER (DECL_NAME (exp)), TAG_GETCLASS)
        /* We have a call to objc_get_class/objc_getClass!  */
!       && (arg = CALL_EXPR_ARG (receiver, 0)))
      {
        STRIP_NOPS (arg);
        if (TREE_CODE (arg) == ADDR_EXPR
Index: gcc/tree-ssa-ccp.c
===================================================================
*** gcc/tree-ssa-ccp.c	(revision 116048)
--- gcc/tree-ssa-ccp.c	(working copy)
*************** ccp_fold_builtin (tree stmt, tree fn)
*** 2306,2312 ****
  					  CALL_EXPR_ARG0 (fn),
  					  CALL_EXPR_ARG1 (fn),
  					  CALL_EXPR_ARG2 (fn),
! 					  call_expr_arg (fn, 3),
  					  val[2], ignore,
  					  DECL_FUNCTION_CODE (callee));
        break;
--- 2306,2312 ----
  					  CALL_EXPR_ARG0 (fn),
  					  CALL_EXPR_ARG1 (fn),
  					  CALL_EXPR_ARG2 (fn),
! 					  CALL_EXPR_ARG (fn, 3),
  					  val[2], ignore,
  					  DECL_FUNCTION_CODE (callee));
        break;
*************** ccp_fold_builtin (tree stmt, tree fn)
*** 2327,2333 ****
  	result = fold_builtin_strncpy_chk (CALL_EXPR_ARG0 (fn),
  					   CALL_EXPR_ARG1 (fn),
  					   CALL_EXPR_ARG2 (fn),
! 					   call_expr_arg (fn, 3),
  					   val[2]);
        break;
  
--- 2327,2333 ----
  	result = fold_builtin_strncpy_chk (CALL_EXPR_ARG0 (fn),
  					   CALL_EXPR_ARG1 (fn),
  					   CALL_EXPR_ARG2 (fn),
! 					   CALL_EXPR_ARG (fn, 3),
  					   val[2]);
        break;
  
Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c	(revision 116048)
--- gcc/tree-ssa-pre.c	(working copy)
*************** static alloc_pool binary_node_pool;
*** 327,333 ****
  static alloc_pool unary_node_pool;
  static alloc_pool reference_node_pool;
  static alloc_pool comparison_node_pool;
- static alloc_pool list_node_pool;
  static alloc_pool modify_expr_node_pool;
  static bitmap_obstack grand_bitmap_obstack;
  
--- 327,332 ----
*************** fully_constant_expression (tree t)
*** 965,997 ****
    return t;
  }
  
- /* Return a copy of a chain of nodes, chained through the TREE_CHAIN field.
-    For example, this can copy a list made of TREE_LIST nodes.  
-    Allocates the nodes in list_node_pool*/
- 
- static tree
- pool_copy_list (tree list)
- {
-   tree head;
-   tree prev, next;
- 
-   if (list == 0)
-     return 0;
-   head = (tree) pool_alloc (list_node_pool);
-   
-   memcpy (head, list, tree_size (list));
-   prev = head;
-   
-   next = TREE_CHAIN (list);
-   while (next)
-     {
-       TREE_CHAIN (prev) = (tree) pool_alloc (list_node_pool);
-       memcpy (TREE_CHAIN (prev), next, tree_size (next));
-       prev = TREE_CHAIN (prev);
-       next = TREE_CHAIN (next);
-     }
-   return head;
- }
  
  /* Make a temporary copy of a CALL_EXPR object NODE.  */
  
--- 964,969 ----
*************** temp_copy_call_expr (tree node)
*** 1000,1007 ****
  {
    tree new = (tree) obstack_alloc (&temp_call_expr_obstack, tree_size (node));
    memcpy (new, node, tree_size (node));
-   /* FIXME:  Remove after CALL_EXPR representation conversion.  */
-   CALL_EXPR_ARGS (new) = pool_copy_list (CALL_EXPR_ARGS (node));
    return new;
  }
  
--- 972,977 ----
*************** create_expression_by_pieces (basic_block
*** 2320,2328 ****
        {
  	tree fn, sc;
  	tree genfn;
! 	tree genarglist;
! 	tree arg;
! 	call_expr_arg_iterator iter;
  	
  	gcc_assert (TREE_CODE (expr) == CALL_EXPR);
  	
--- 2290,2297 ----
        {
  	tree fn, sc;
  	tree genfn;
! 	int i, nargs;
! 	tree *buffer;
  	
  	gcc_assert (TREE_CODE (expr) == CALL_EXPR);
  	
*************** create_expression_by_pieces (basic_block
*** 2331,2352 ****
  	
  	genfn = find_or_generate_expression (block, fn, stmts);
  
! 	/* FIXME:  It ought to be possible to do this without consing up
! 	   a temporary list.  */
! 	genarglist = NULL;
! 	FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
  	  {
! 	    tree newarg = find_or_generate_expression (block, arg, stmts);
! 	    genarglist = tree_cons (NULL_TREE, newarg, genarglist);
  	  }
- 	genarglist = nreverse (genarglist);
  
! 	folded = fold_build_call_list (TREE_CODE (expr),
! 				       TREE_TYPE (expr),
! 				       genfn, genarglist);
  	if (sc)
  	  CALL_EXPR_STATIC_CHAIN (folded) =
  	    find_or_generate_expression (block, sc, stmts);
  	break;
        }
        break;
--- 2300,2321 ----
  	
  	genfn = find_or_generate_expression (block, fn, stmts);
  
! 	nargs = call_expr_nargs (expr);
! 	buffer = alloca (nargs * sizeof (tree));
! 
! 	for (i = 0; i < nargs; i++)
  	  {
! 	    tree arg = CALL_EXPR_ARG (expr, i);
! 	    buffer[i] = find_or_generate_expression (block, arg, stmts);
  	  }
  
! 	folded = build_call_array (TREE_CODE (expr),
! 				   TREE_TYPE (expr),
! 				   genfn, nargs, buffer);
  	if (sc)
  	  CALL_EXPR_STATIC_CHAIN (folded) =
  	    find_or_generate_expression (block, sc, stmts);
+ 	folded = fold (folded);
  	break;
        }
        break;
*************** create_value_expr_from (tree expr, basic
*** 2887,2897 ****
      pool = binary_node_pool;
    else if (TREE_CODE_CLASS (code) == tcc_comparison)
      pool = comparison_node_pool;
-   else if (TREE_CODE_CLASS (code) == tcc_exceptional)
-     {
-       gcc_assert (code == TREE_LIST);
-       pool = list_node_pool;
-     }
    else 
      gcc_assert (code == CALL_EXPR);
  
--- 2856,2861 ----
*************** create_value_expr_from (tree expr, basic
*** 2902,2950 ****
        vexpr = (tree) pool_alloc (pool);
        memcpy (vexpr, expr, tree_size (expr));
      }
-   
-   /* This case is only for TREE_LIST's that appear as part of
-      CALL_EXPR's.  Anything else is a bug, but we can't easily verify
-      this, hence this comment.  TREE_LIST is not handled by the
-      general case below is because they don't have a fixed length, or
-      operands, so you can't access purpose/value/chain through
-      TREE_OPERAND macros.  */
- 
-   /* FIXME:  This section of code should go away completely when the
-      low-level representation of CALL_EXPRs is changed not to use
-      TREE_LISTs.  */
- 
-   if (code == TREE_LIST)
-     {
-       tree op = NULL_TREE;
-       tree temp = NULL_TREE;
-       if (TREE_CHAIN (vexpr))
- 	temp = create_value_expr_from (TREE_CHAIN (vexpr), block, stmt);      
-       TREE_CHAIN (vexpr) = temp ? temp : TREE_CHAIN (vexpr);
-       
- 
-       /* Recursively value-numberize reference ops.  */
-       if (REFERENCE_CLASS_P (TREE_VALUE (vexpr)))
- 	{
- 	  tree tempop;
- 	  op = TREE_VALUE (vexpr);
- 	  tempop = create_value_expr_from (op, block, stmt);
- 	  op = tempop ? tempop : op;
- 	  
- 	  TREE_VALUE (vexpr)  = vn_lookup_or_add (op, stmt);
- 	}
-       else
- 	{
- 	  op = TREE_VALUE (vexpr);
- 	  TREE_VALUE (vexpr) = vn_lookup_or_add (TREE_VALUE (vexpr), NULL);
- 	}
-       /* This is the equivalent of inserting op into EXP_GEN like we
- 	 do below */
-       if (!is_undefined_value (op))
- 	value_insert_into_set (EXP_GEN (block), op);
- 
-       return vexpr;
-     }
  
    for (i = 0; i < TREE_OPERAND_LENGTH (expr); i++)
      {
--- 2866,2871 ----
*************** create_value_expr_from (tree expr, basic
*** 2961,2980 ****
  	  op = tempop ? tempop : op;
  	  val = vn_lookup_or_add (op, stmt);
  	}
-       /* FIXME: Delete this clause when CALL_EXPR representation changes. */
-       else if (TREE_CODE (op) == TREE_LIST)
- 	{
- 	  tree tempop;
- 	  
- 	  gcc_assert (TREE_CODE (expr) == CALL_EXPR);
- 	  tempop = create_value_expr_from (op, block, stmt);
- 	  
- 	  op = tempop ? tempop : op;
- 	  /* Unlike everywhere else, we do *not* want to replace the
- 	     TREE_LIST itself with a value number, because support
- 	     functions we call will blow up.  */
- 	  val = op;
- 	}
        else       
  	/* Create a value handle for OP and add it to VEXPR.  */
  	val = vn_lookup_or_add (op, NULL);
--- 2882,2887 ----
*************** init_pre (bool do_fre)
*** 3792,3799 ****
  				       tree_code_size (NEGATE_EXPR), 30);
    reference_node_pool = create_alloc_pool ("Reference tree nodes",
  					   tree_code_size (ARRAY_REF), 30);
-   list_node_pool = create_alloc_pool ("List tree nodes",
- 				      tree_code_size (TREE_LIST), 30);  
    comparison_node_pool = create_alloc_pool ("Comparison tree nodes",
        					    tree_code_size (EQ_EXPR), 30);
    modify_expr_node_pool = create_alloc_pool ("MODIFY_EXPR nodes",
--- 3699,3704 ----
*************** fini_pre (bool do_fre)
*** 3832,3838 ****
    free_alloc_pool (binary_node_pool);
    free_alloc_pool (reference_node_pool);
    free_alloc_pool (unary_node_pool);
-   free_alloc_pool (list_node_pool);
    free_alloc_pool (comparison_node_pool);
    free_alloc_pool (modify_expr_node_pool);
    htab_delete (phi_translate_table);
--- 3737,3742 ----
Index: gcc/cp/cp-tree.def
===================================================================
*** gcc/cp/cp-tree.def	(revision 116048)
--- gcc/cp/cp-tree.def	(working copy)
*************** DEFTREECODE (MEMBER_REF, "member_ref", t
*** 74,82 ****
     operator converts to.  Operand is expression to be converted.  */
  DEFTREECODE (TYPE_EXPR, "type_expr", tcc_expression, 1)
  
! /* For AGGR_INIT_EXPR, operand 0 is function which performs initialization,
!    operand 1 is argument list to initialization function,
!    and operand 2 is the slot which was allocated for this expression.  */
  DEFTREECODE (AGGR_INIT_EXPR, "aggr_init_expr", tcc_vl_exp, 3)
  
  /* A throw expression.  operand 0 is the expression, if there was one,
--- 74,84 ----
     operator converts to.  Operand is expression to be converted.  */
  DEFTREECODE (TYPE_EXPR, "type_expr", tcc_expression, 1)
  
! /* AGGR_INIT_EXPRs have a variably-sized representation similar to
!    that of CALL_EXPRs.  Operand 0 is an INTEGER_CST node containing the
!    operand count, operand 1 is the function which performs initialization,
!    operand 2 is the slot which was allocated for this expression, and
!    the remaining operands are the arguments to the initialization function.  */
  DEFTREECODE (AGGR_INIT_EXPR, "aggr_init_expr", tcc_vl_exp, 3)
  
  /* A throw expression.  operand 0 is the expression, if there was one,
Index: gcc/cp/semantics.c
===================================================================
*** gcc/cp/semantics.c	(revision 116048)
--- gcc/cp/semantics.c	(working copy)
*************** simplify_aggr_init_expr (tree *tp)
*** 2903,2912 ****
  {
    tree aggr_init_expr = *tp;
  
-   /* FIXME: don't cons up arglist for CALL_EXPR.  */
    /* Form an appropriate CALL_EXPR.  */
    tree fn = CALL_EXPR_FN (aggr_init_expr);
-   tree args = CALL_EXPR_ARGS (aggr_init_expr);
    tree slot = AGGR_INIT_EXPR_SLOT (aggr_init_expr);
    tree type = TREE_TYPE (slot);
  
--- 2903,2910 ----
*************** simplify_aggr_init_expr (tree *tp)
*** 2925,2947 ****
        style = arg;
      }
  
    if (style == ctor)
      {
        /* Replace the first argument to the ctor with the address of the
  	 slot.  */
-       tree addr;
- 
-       args = TREE_CHAIN (args);
        cxx_mark_addressable (slot);
!       addr = build1 (ADDR_EXPR, build_pointer_type (type), slot);
!       args = tree_cons (NULL_TREE, addr, args);
      }
! 
!   call_expr = build_call_list (CALL_EXPR,
! 			       TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
! 			       fn, args);
! 
!   if (style == arg)
      {
        /* Just mark it addressable here, and leave the rest to
  	 expand_call{,_inline}.  */
--- 2923,2943 ----
        style = arg;
      }
  
+   call_expr = build_call_array (CALL_EXPR,
+ 				TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))),
+ 				fn,
+ 				call_expr_nargs (aggr_init_expr),
+ 				CALL_EXPR_ARGP (aggr_init_expr));
+ 
    if (style == ctor)
      {
        /* Replace the first argument to the ctor with the address of the
  	 slot.  */
        cxx_mark_addressable (slot);
!       CALL_EXPR_ARG0 (call_expr) =
! 	build1 (ADDR_EXPR, build_pointer_type (type), slot);
      }
!   else if (style == arg)
      {
        /* Just mark it addressable here, and leave the rest to
  	 expand_call{,_inline}.  */
Index: gcc/java/java-tree.def
===================================================================
*** gcc/java/java-tree.def	(revision 116048)
--- gcc/java/java-tree.def	(working copy)
*************** DEFTREECODE (NEW_ARRAY_EXPR, "new_array_
*** 30,38 ****
  DEFTREECODE (NEW_ANONYMOUS_ARRAY_EXPR, "new_anonymous_array",
  	     tcc_expression, 3)
  
! /* New class creation expression.
!    Operand 0 is the name of the class to be created
!    Operand 1 is the argument list used to select a constructor.
     There is no operand 2.  That slot is used for the
     CALL_EXPR_RTL macro (see preexpand_calls).
     The type should be the one of the created class.  */
--- 30,39 ----
  DEFTREECODE (NEW_ANONYMOUS_ARRAY_EXPR, "new_anonymous_array",
  	     tcc_expression, 3)
  
! /* New class creation expression.  These have a representation similar to
!    that of CALL_EXPRs.  Operand 0 is an INTEGER_CST node containing the operand
!    count, operand 1 is the name of the class to be created.  The argument
!    list used to select a constructor follows beginning with operand 3.  
     There is no operand 2.  That slot is used for the
     CALL_EXPR_RTL macro (see preexpand_calls).
     The type should be the one of the created class.  */
Index: gcc/doc/c-tree.texi
===================================================================
*** gcc/doc/c-tree.texi	(revision 116048)
--- gcc/doc/c-tree.texi	(working copy)
*************** argument does cause side-effects.
*** 2390,2408 ****
  
  @item CALL_EXPR
  These nodes are used to represent calls to functions, including
! non-static member functions.  The first operand is a pointer to the
  function to call; it is always an expression whose type is a
! @code{POINTER_TYPE}.  The second argument is a @code{TREE_LIST}.  The
! arguments to the call appear left-to-right in the list.  The
! @code{TREE_VALUE} of each list node contains the expression
! corresponding to that argument.  (The value of @code{TREE_PURPOSE} for
! these nodes is unspecified, and should be ignored.)  For non-static
  member functions, there will be an operand corresponding to the
  @code{this} pointer.  There will always be expressions corresponding to
  all of the arguments, even if the function is declared with default
  arguments and some arguments are not explicitly provided at the call
  sites.
  
  @item STMT_EXPR
  These nodes are used to represent GCC's statement-expression extension.
  The statement-expression extension allows code like this:
--- 2390,2421 ----
  
  @item CALL_EXPR
  These nodes are used to represent calls to functions, including
! non-static member functions.  @code{CALL_EXPR}s are implemented as
! expression nodes with a variable number of operands.  Rather than using
! @code{TREE_OPERAND} to extract them, it is preferable to use the
! specialized accessor macros and functions that operate specifically on
! @code{CALL_EXPR} nodes.
! 
! @code{CALL_EXPR_FN} returns a pointer to the
  function to call; it is always an expression whose type is a
! @code{POINTER_TYPE}.
! 
! The number of arguments to the call is returned by @code{call_expr_nargs},
! while the arguments themselves can be accessed with the 
! @code{CALL_EXPR_ARG} macro (along with @code{CALL_EXPR_ARG0},
! @code{CALL_EXPR_ARG1}, and so on.)  The arguments are
! zero-indexed and numbered left-to-right.
! For non-static
  member functions, there will be an operand corresponding to the
  @code{this} pointer.  There will always be expressions corresponding to
  all of the arguments, even if the function is declared with default
  arguments and some arguments are not explicitly provided at the call
  sites.
  
+ @code{CALL_EXPR}s also have a @code{CALL_EXPR_STATIC_CHAIN} operand that
+ is used to implement nested functions.  This operand is otherwise null.
+ 
+ 
  @item STMT_EXPR
  These nodes are used to represent GCC's statement-expression extension.
  The statement-expression extension allows code like this:
*************** cleanups.
*** 2529,2543 ****
  An @code{AGGR_INIT_EXPR} represents the initialization as the return
  value of a function call, or as the result of a constructor.  An
  @code{AGGR_INIT_EXPR} will only appear as a full-expression, or as the
! second operand of a @code{TARGET_EXPR}.  The first operand to the
! @code{AGGR_INIT_EXPR} is the address of a function to call, just as in
! a @code{CALL_EXPR}.  The second operand are the arguments to pass that
! function, as a @code{TREE_LIST}, again in a manner similar to that of
! a @code{CALL_EXPR}.
  
  If @code{AGGR_INIT_VIA_CTOR_P} holds of the @code{AGGR_INIT_EXPR}, then
! the initialization is via a constructor call.  The address of the third
! operand of the @code{AGGR_INIT_EXPR}, which is always a @code{VAR_DECL},
  is taken, and this value replaces the first argument in the argument
  list.
  
--- 2542,2555 ----
  An @code{AGGR_INIT_EXPR} represents the initialization as the return
  value of a function call, or as the result of a constructor.  An
  @code{AGGR_INIT_EXPR} will only appear as a full-expression, or as the
! second operand of a @code{TARGET_EXPR}.  @code{AGGR_INIT_EXPR}s have
! a representation similar to that of @code{CALL_EXPR}s, and the
! @code{CALL_EXPR_FN} and @code{CALL_EXPR_ARG} macros can be used to access
! the function to call and the arguments to pass, just as in a @code{CALL_EXPR}.
  
  If @code{AGGR_INIT_VIA_CTOR_P} holds of the @code{AGGR_INIT_EXPR}, then
! the initialization is via a constructor call.  The address of the
! @code{AGGR_INIT_EXPR_SLOT} operand, which is always a @code{VAR_DECL},
  is taken, and this value replaces the first argument in the argument
  list.
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]