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]

va_list: i960


Thrice-cursed is he who once thought an array type va_list
was a good idea.  

Follows the changes needed for i960, and some other generic changes
needed to make array type va_list work right.  Noteworthy in the
patches is the need to propogate MEM_ALIAS_SET through store_multiple.

One of the features of the va_arg reorg is that all of the prologue
spills and all of the va_arg dereferences can be put into the same
alias set, which should cure the semi-annual problems with stores
and loads failing to be considered aliasing.


r~

PS: This one I got to actually test on a simulator!  ;-)
	* i960.c (i960_setup_incoming_varargs): Use get_varargs_alias_set
	for the register spill block.
	(i960_build_va_list): New.
	(i960_va_start): New.
	(i960_va_arg): New.
	* i960.h (BUILD_VA_LIST_TYPE): New.
	(EXPAND_BUILTIN_VA_START): New.
	(EXPAND_BUILTIN_VA_ARG): New.
	* i960.md (store_multiple): Use change_address on individul mems.

Index: config/i960/i960.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/i960/i960.c,v
retrieving revision 1.11
diff -c -p -d -r1.11 i960.c
*** i960.c	1999/07/09 18:57:11	1.11
--- i960.c	1999/07/27 05:26:35
***************
*** 1,5 ****
  /* Subroutines used for code generation on intel 80960.
!    Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
     Contributed by Steven McGeady, Intel Corp.
     Additional Work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson
     Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support.
--- 1,6 ----
  /* Subroutines used for code generation on intel 80960.
!    Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999
!    Free Software Foundation, Inc.
     Contributed by Steven McGeady, Intel Corp.
     Additional Work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson
     Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support.
*************** i960_setup_incoming_varargs (cum, mode, 
*** 2623,2636 ****
        emit_label (label);
  
        /* ??? Note that we unnecessarily store one extra register for stdarg
! 	 fns.  We could optimize this, but it's kept as for now.  */
        regblock = gen_rtx (MEM, BLKmode,
  			  plus_constant (arg_pointer_rtx,
  					 first_reg * 4));
        move_block_from_reg (first_reg, regblock,
  			   NPARM_REGS - first_reg,
  			   (NPARM_REGS - first_reg) * UNITS_PER_WORD);
      }
  }
  
  /* Calculate the final size of the reg parm stack space for the current
--- 2624,2729 ----
        emit_label (label);
  
        /* ??? Note that we unnecessarily store one extra register for stdarg
! 	 fns.  We could optimize this, but it's kept as-is for now.  */
        regblock = gen_rtx (MEM, BLKmode,
  			  plus_constant (arg_pointer_rtx,
  					 first_reg * 4));
+       MEM_ALIAS_SET (regblock) = get_varargs_alias_set ();
        move_block_from_reg (first_reg, regblock,
  			   NPARM_REGS - first_reg,
  			   (NPARM_REGS - first_reg) * UNITS_PER_WORD);
      }
+ }
+ 
+ /* Define the `__builtin_va_list' type for the ABI.  */
+ 
+ tree
+ i960_build_va_list ()
+ {
+   return build_array_type (unsigned_type_node,
+ 			   build_index_type (size_one_node));
+ }
+ 
+ /* Implement `va_start' for varargs and stdarg.  */
+ 
+ void
+ i960_va_start (stdarg_p, valist, nextarg)
+      int stdarg_p ATTRIBUTE_UNUSED;
+      tree valist;
+      rtx nextarg ATTRIBUTE_UNUSED;
+ {
+   tree d, s, t;
+ 
+   s = make_tree (unsigned_type_node, arg_pointer_rtx);
+   d = build (ARRAY_REF, unsigned_type_node, valist, size_zero_node);
+   t = build (MODIFY_EXPR, unsigned_type_node, d, s);
+   TREE_SIDE_EFFECTS (t) = 1;
+   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ 
+   s = build_int_2 ((current_function_args_info.ca_nregparms
+ 		    + current_function_args_info.ca_nstackparms) * 4, 0);
+   d = build (ARRAY_REF, unsigned_type_node, valist, size_one_node);
+   t = build (MODIFY_EXPR, unsigned_type_node, d, s);
+   TREE_SIDE_EFFECTS (t) = 1;
+   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ }
+ 
+ /* Implement `va_arg'.  */
+ 
+ rtx
+ i960_va_arg (valist, type)
+      tree valist, type;
+ {
+   HOST_WIDE_INT siz, ali;
+   tree base, num, pad, next, this, t1, t2, int48;
+   rtx addr_rtx;
+ 
+   base = build (ARRAY_REF, unsigned_type_node, valist, size_zero_node);
+   num = build (ARRAY_REF, unsigned_type_node, valist, size_one_node);
+ 
+   /* Round up sizeof(type) to a word.  */
+   siz = (int_size_in_bytes (type) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
+ 
+   /* Round up alignment to a word.  */
+   ali = TYPE_ALIGN (type);
+   if (ali < BITS_PER_WORD)
+     ali = BITS_PER_WORD;
+   ali /= BITS_PER_UNIT;
+ 
+   /* Align NUM appropriate for the argument.  */
+   pad = fold (build (PLUS_EXPR, unsigned_type_node, num, 
+ 		      build_int_2 (ali - 1, 0)));
+   pad = fold (build (BIT_AND_EXPR, unsigned_type_node, pad,
+ 		      build_int_2 (-ali, -1)));
+   pad = save_expr (pad);
+ 
+   /* Increment VPAD past this argument.  */
+   next = fold (build (PLUS_EXPR, unsigned_type_node, pad,
+ 		      build_int_2 (siz, 0)));
+   next = save_expr (next);
+ 
+   /* Find the offset for the current argument.  Mind peculiar overflow
+      from registers to stack.  */
+   int48 = build_int_2 (48, 0);
+   if (siz > 16)
+     t2 = integer_one_node;
+   else
+     t2 = fold (build (GT_EXPR, integer_type_node, next, int48));
+   t1 = fold (build (LE_EXPR, integer_type_node, num, int48));
+   t1 = fold (build (TRUTH_AND_EXPR, integer_type_node, t1, t2));
+   this = fold (build (COND_EXPR, unsigned_type_node, t1, int48, pad));
+ 
+   /* Find the address for the current argument.  */
+   t1 = fold (build (PLUS_EXPR, unsigned_type_node, base, this));
+   t1 = build1 (NOP_EXPR, ptr_type_node, t1);
+   addr_rtx = expand_expr (t1, NULL_RTX, Pmode, EXPAND_NORMAL);
+ 
+   /* Increment NUM.  */
+   t1 = build (MODIFY_EXPR, unsigned_type_node, num, next);
+   TREE_SIDE_EFFECTS (t1) = 1;
+   expand_expr (t1, const0_rtx, VOIDmode, EXPAND_NORMAL);
+   
+   return addr_rtx;
  }
  
  /* Calculate the final size of the reg parm stack space for the current
Index: config/i960/i960.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/i960/i960.h,v
retrieving revision 1.25
diff -c -p -d -r1.25 i960.h
*** i960.h	1999/04/07 23:03:00	1.25
--- i960.h	1999/07/27 05:26:35
***************
*** 1,5 ****
  /* Definitions of target machine for GNU compiler, for Intel 80960
!    Copyright (C) 1992, 1993, 1995, 1996, 1998 Free Software Foundation, Inc.
     Contributed by Steven McGeady, Intel Corp.
     Additional Work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson
     Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support.
--- 1,6 ----
  /* Definitions of target machine for GNU compiler, for Intel 80960
!    Copyright (C) 1992, 1993, 1995, 1996, 1998, 1999
!    Free Software Foundation, Inc.
     Contributed by Steven McGeady, Intel Corp.
     Additional Work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson
     Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support.
*************** enum reg_class { NO_REGS, GLOBAL_REGS, L
*** 859,864 ****
--- 860,877 ----
  
  #define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
    i960_setup_incoming_varargs(&CUM,MODE,TYPE,&PRETEND_SIZE,NO_RTL)
+ 
+ /* Define the `__builtin_va_list' type for the ABI.  */
+ #define BUILD_VA_LIST_TYPE(VALIST) \
+   (VALIST) = i960_build_va_list ()
+ 
+ /* Implement `va_start' for varargs and stdarg.  */
+ #define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
+   i960_va_start (stdarg, valist, nextarg)
+ 
+ /* Implement `va_arg'.  */
+ #define EXPAND_BUILTIN_VA_ARG(valist, type) \
+   i960_va_arg (valist, type)
  
  /* Define a data type for recording info about an argument list
     during the scan of that argument list.  This data type should
Index: config/i960/i960.md
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/i960/i960.md,v
retrieving revision 1.10
diff -c -p -d -r1.10 i960.md
*** i960.md	1999/04/07 23:03:01	1.10
--- i960.md	1999/07/27 05:26:35
***************
*** 972,978 ****
    int regno;
    int count;
    rtx from;
-   int i;
  
    if (GET_CODE (operands[0]) != MEM
        || GET_CODE (operands[1]) != REG
--- 972,977 ----
***************
*** 987,1013 ****
    from = memory_address (SImode, XEXP (operands[0], 0));
    while (count >= 4 && ((regno & 3) == 0))
      {
!       emit_insn (gen_rtx (SET, VOIDmode,
! 			  gen_rtx (MEM, TImode, from),
! 			  gen_rtx (REG, TImode, regno)));
        count -= 4;
        regno += 4;
        from = memory_address (TImode, plus_constant (from, 16));
      }
    while (count >= 2 && ((regno & 1) == 0))
      {
!       emit_insn (gen_rtx (SET, VOIDmode,
! 			  gen_rtx (MEM, DImode, from),
! 			  gen_rtx (REG, DImode, regno)));
        count -= 2;
        regno += 2;
        from = memory_address (DImode, plus_constant (from, 8));
      }
    while (count > 0)
      {
!       emit_insn (gen_rtx (SET, VOIDmode,
! 			  gen_rtx (MEM, SImode, from),
! 			  gen_rtx (REG, SImode, regno)));
        count -= 1;
        regno += 1;
        from = memory_address (SImode, plus_constant (from, 4));
--- 986,1009 ----
    from = memory_address (SImode, XEXP (operands[0], 0));
    while (count >= 4 && ((regno & 3) == 0))
      {
!       emit_move_insn (change_address (operands[0], TImode, from),
! 		      gen_rtx_REG (TImode, regno));
        count -= 4;
        regno += 4;
        from = memory_address (TImode, plus_constant (from, 16));
      }
    while (count >= 2 && ((regno & 1) == 0))
      {
!       emit_move_insn (change_address (operands[0], DImode, from),
! 		      gen_rtx_REG (DImode, regno));
        count -= 2;
        regno += 2;
        from = memory_address (DImode, plus_constant (from, 8));
      }
    while (count > 0)
      {
!       emit_move_insn (change_address (operands[0], SImode, from),
! 		      gen_rtx_REG (SImode, regno));
        count -= 1;
        regno += 1;
        from = memory_address (SImode, plus_constant (from, 4));
	* builtins.c (stabilize_va_list): Don't INDIRECT_REF through
	an ARRAY_TYPE.
	(std_expand_builtin_va_start): Back out one word if !stdarg_p.
	(expand_builtin_va_end): Evaluate arg for side effects.
	* c-common.c (c_common_nodes_and_builtins): Construct a
	va_list_arg_type_node to handle array decomposition to pointer.

Index: builtins.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/builtins.c,v
retrieving revision 1.2
diff -c -p -d -r1.2 builtins.c
*** builtins.c	1999/07/26 01:21:02	1.2
--- builtins.c	1999/07/27 05:25:53
*************** stabilize_va_list (valist, was_ptr)
*** 1840,1852 ****
        if (is_array
  	  && TREE_CODE (valist) == ADDR_EXPR
  	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (valist, 0))) == POINTER_TYPE)
! 	valist = TREE_OPERAND (valist, 0);
! 
!       if (TREE_SIDE_EFFECTS (valist))
! 	valist = save_expr (valist);
! 
!       if (! is_array)
!         valist = fold (build1 (INDIRECT_REF, va_list_type_node, valist));
      }
    else if (TREE_SIDE_EFFECTS (valist))
      {
--- 1840,1856 ----
        if (is_array
  	  && TREE_CODE (valist) == ADDR_EXPR
  	  && TREE_CODE (TREE_TYPE (TREE_OPERAND (valist, 0))) == POINTER_TYPE)
! 	{
! 	  valist = TREE_OPERAND (valist, 0);
! 	  if (TREE_SIDE_EFFECTS (valist))
! 	    valist = save_expr (valist);
! 	}
!       else
! 	{
! 	  if (TREE_SIDE_EFFECTS (valist))
! 	    valist = save_expr (valist);
! 	  valist = fold (build1 (INDIRECT_REF, va_list_type_node, valist));
! 	}
      }
    else if (TREE_SIDE_EFFECTS (valist))
      {
*************** std_expand_builtin_va_start (stdarg_p, v
*** 1875,1880 ****
--- 1879,1887 ----
  {
    tree t;
  
+   if (!stdarg_p)
+     nextarg = plus_constant (nextarg, -UNITS_PER_WORD);
+ 
    t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
  	     make_tree (ptr_type_node, nextarg));
    TREE_SIDE_EFFECTS (t) = 1;
*************** expand_builtin_va_arg (valist, type)
*** 2002,2013 ****
  /* Expand ARGLIST, from a call to __builtin_va_end.  */
  static rtx
  expand_builtin_va_end (arglist)
!      tree arglist ATTRIBUTE_UNUSED;
  {
  #ifdef EXPAND_BUILTIN_VA_END
-   tree valist = TREE_VALUE (arglist, 0);
    valist = stabilize_va_list (valist, 0);
    EXPAND_BUILTIN_VA_END(arglist);
  #endif
  
    return const0_rtx;
--- 2009,2026 ----
  /* Expand ARGLIST, from a call to __builtin_va_end.  */
  static rtx
  expand_builtin_va_end (arglist)
!      tree arglist;
  {
+   tree valist = TREE_VALUE (arglist);
+ 
  #ifdef EXPAND_BUILTIN_VA_END
    valist = stabilize_va_list (valist, 0);
    EXPAND_BUILTIN_VA_END(arglist);
+ #else
+   /* Evaluate for side effects, if needed.  I hate macros that don't
+      do that.  */
+   if (TREE_SIDE_EFFECTS (valist))
+     expand_expr (valist, const0_rtx, VOIDmode, EXPAND_NORMAL);
  #endif
  
    return const0_rtx;
Index: c-common.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/c-common.c,v
retrieving revision 1.61
diff -c -p -d -r1.61 c-common.c
*** c-common.c	1999/07/26 01:21:02	1.61
--- c-common.c	1999/07/27 05:25:53
*************** c_common_nodes_and_builtins (cplus_mode,
*** 3435,3440 ****
--- 3435,3441 ----
    /* Either char* or void*.  */
    tree traditional_ptr_type_node;
    tree va_list_ptr_type_node;
+   tree va_list_arg_type_node;
  
  #ifdef BUILD_VA_LIST_TYPE
    BUILD_VA_LIST_TYPE(va_list_type_node);
*************** c_common_nodes_and_builtins (cplus_mode,
*** 3443,3450 ****
--- 3444,3457 ----
  #endif
    pushdecl (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"),
  			va_list_type_node));
+ 
    va_list_ptr_type_node = build_pointer_type (va_list_type_node);
  
+   if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
+     va_list_arg_type_node = build_pointer_type (TREE_TYPE (va_list_type_node));
+   else
+     va_list_arg_type_node = va_list_type_node;
+ 
    endlink = void_list_node;
    int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink);
    double_endlink = tree_cons (NULL_TREE, double_type_node, endlink);
*************** c_common_nodes_and_builtins (cplus_mode,
*** 3636,3642 ****
    builtin_function ("__builtin_va_end",
  		    build_function_type (void_type_node,
  					 tree_cons (NULL_TREE,
! 						    va_list_type_node,
  						    endlink)),
  		    BUILT_IN_VA_END, NULL_PTR);
  
--- 3643,3649 ----
    builtin_function ("__builtin_va_end",
  		    build_function_type (void_type_node,
  					 tree_cons (NULL_TREE,
! 						    va_list_arg_type_node,
  						    endlink)),
  		    BUILT_IN_VA_END, NULL_PTR);
  
*************** c_common_nodes_and_builtins (cplus_mode,
*** 3645,3651 ****
  					 tree_cons (NULL_TREE,
  						    va_list_ptr_type_node,
  						    tree_cons (NULL_TREE,
! 						      va_list_type_node,
  						      endlink))),
  		    BUILT_IN_VA_COPY, NULL_PTR);
  
--- 3652,3658 ----
  					 tree_cons (NULL_TREE,
  						    va_list_ptr_type_node,
  						    tree_cons (NULL_TREE,
! 						      va_list_arg_type_node,
  						      endlink))),
  		    BUILT_IN_VA_COPY, NULL_PTR);
  

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