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


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

va_list: alpha


Unlike most of the other ports, Alpha will no longer work without
the header patches, since I removed __builtin_saveregs.  This will
only be temporary.



r~



        * alpha.h (EXPAND_BUILTIN_SAVEREGS): Delete.
        (BUILD_VA_LIST_TYPE): New.
        (EXPAND_BUILTIN_VA_START): New.
        (EXPAND_BUILTIN_VA_ARG): New.
        * alpha.c (alpha_builtin_saveregs): Delete.
        (alpha_build_va_list): New.
        (alpha_va_start): New.
        (alpha_va_arg): New.

Index: alpha.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/alpha/alpha.c,v
retrieving revision 1.90
diff -c -p -d -r1.90 alpha.c
*** alpha.c	1999/06/25 11:34:14	1.90
--- alpha.c	1999/07/26 05:45:35
*************** alpha_initialize_trampoline (tramp, fnad
*** 3083,3183 ****
      emit_insn (gen_imb ());
  }
  
! /* Do what is necessary for `va_start'.  The argument is ignored;
!    We look at the current function to determine if stdarg or varargs
!    is used and fill in an initial va_list.  A pointer to this constructor
!    is returned.  */
! 
! struct rtx_def *
! alpha_builtin_saveregs (arglist)
!      tree arglist ATTRIBUTE_UNUSED;
  {
!   rtx block, addr, dest, argsize;
!   tree fntype = TREE_TYPE (current_function_decl);
!   int stdarg = (TYPE_ARG_TYPES (fntype) != 0
! 		&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
! 		    != void_type_node));
  
!   /* Compute the current position into the args, taking into account
!      both registers and memory.  Both of these are already included in
!      NUM_ARGS.  */
  
!   argsize = GEN_INT (NUM_ARGS * UNITS_PER_WORD);
  
!   /* For Unix, SETUP_INCOMING_VARARGS moves the starting address base up by 48,
!      storing fp arg registers in the first 48 bytes, and the integer arg
!      registers in the next 48 bytes.  This is only done, however, if any
!      integer registers need to be stored.
  
!      If no integer registers need be stored, then we must subtract 48 in
!      order to account for the integer arg registers which are counted in
!      argsize above, but which are not actually stored on the stack.  */
  
    if (TARGET_OPEN_VMS)
!     addr = plus_constant (virtual_incoming_args_rtx,
! 			  NUM_ARGS <= 5 + stdarg
! 			  ? UNITS_PER_WORD : - 6 * UNITS_PER_WORD);
    else
!     addr = (NUM_ARGS <= 5 + stdarg
! 	    ? plus_constant (virtual_incoming_args_rtx,
! 			     6 * UNITS_PER_WORD)
! 	    : plus_constant (virtual_incoming_args_rtx,
! 			     - (6 * UNITS_PER_WORD)));
  
!   /* For VMS, we include the argsize, while on Unix, it's handled as
!      a separate field.  */
!   if (TARGET_OPEN_VMS)
!     addr = plus_constant (addr, INTVAL (argsize));
  
!   addr = force_operand (addr, NULL_RTX);
  
! #ifdef POINTERS_EXTEND_UNSIGNED
!   addr = convert_memory_address (ptr_mode, addr);
! #endif
  
    if (TARGET_OPEN_VMS)
!     return addr;
!   else
!     {
!       /* Allocate the va_list constructor */
!       block = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD);
!       RTX_UNCHANGING_P (block) = 1;
!       RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
  
!       /* Store the address of the first integer register in the __base
! 	 member.  */
  
!       dest = change_address (block, ptr_mode, XEXP (block, 0));
!       emit_move_insn (dest, addr);
  
!       if (current_function_check_memory_usage)
! 	emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
! 			   dest, ptr_mode,
! 			   GEN_INT (GET_MODE_SIZE (ptr_mode)),
! 			   TYPE_MODE (sizetype),
! 			   GEN_INT (MEMORY_USE_RW), 
! 			   TYPE_MODE (integer_type_node));
!   
!       /* Store the argsize as the __va_offset member.  */
!       dest = change_address (block, TYPE_MODE (integer_type_node),
! 			     plus_constant (XEXP (block, 0),
! 					    POINTER_SIZE/BITS_PER_UNIT));
!       emit_move_insn (dest, argsize);
  
!       if (current_function_check_memory_usage)
! 	emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
! 			   dest, ptr_mode,
! 			   GEN_INT (GET_MODE_SIZE
! 				    (TYPE_MODE (integer_type_node))),
! 			   TYPE_MODE (sizetype),
! 			   GEN_INT (MEMORY_USE_RW),
! 			   TYPE_MODE (integer_type_node));
  
!       /* Return the address of the va_list constructor, but don't put it in a
! 	 register.  Doing so would fail when not optimizing and produce worse
! 	 code when optimizing.  */
!       return XEXP (block, 0);
      }
  }
  
  /* This page contains routines that are used to determine what the function
--- 3083,3214 ----
      emit_insn (gen_imb ());
  }
  
! tree
! alpha_build_va_list ()
  {
!   tree base, ofs, record;
  
!   if (TARGET_OPEN_VMS)
!     return ptr_type_node;
  
!   record = make_node (RECORD_TYPE);
!   /* C++? SET_IS_AGGR_TYPE (record, 1); */
  
!   ofs = build_decl (FIELD_DECL, get_identifier ("__offset"),
! 		    integer_type_node);
!   DECL_FIELD_CONTEXT (ofs) = record;
  
!   base = build_decl (FIELD_DECL, get_identifier ("__base"),
! 		     ptr_type_node);
!   DECL_FIELD_CONTEXT (base) = record;
!   TREE_CHAIN (base) = ofs;
! 
!   TYPE_FIELDS (record) = base;
!   layout_type (record);
! 
!   return record;
! }
! 
! void
! alpha_va_start (stdarg_p, valist, nextarg)
!      int stdarg_p;
!      tree valist;
!      rtx nextarg ATTRIBUTE_UNUSED;
! {
!   HOST_WIDE_INT offset;
!   tree t, offset_field, base_field;
  
    if (TARGET_OPEN_VMS)
!     std_expand_builtin_va_start (stdarg_p, valist, nextarg);
! 
!   /* For Unix, SETUP_INCOMING_VARARGS moves the starting address base
!      up by 48, storing fp arg registers in the first 48 bytes, and the
!      integer arg registers in the next 48 bytes.  This is only done,
!      however, if any integer registers need to be stored.
! 
!      If no integer registers need be stored, then we must subtract 48
!      in order to account for the integer arg registers which are counted
!      in argsize above, but which are not actually stored on the stack.  */
! 
!   if (NUM_ARGS <= 5 + stdarg_p)
!     offset = 6 * UNITS_PER_WORD;
    else
!     offset = -6 * UNITS_PER_WORD;
  
!   base_field = TYPE_FIELDS (TREE_TYPE (valist));
!   offset_field = TREE_CHAIN (base_field);
  
!   base_field = build (COMPONENT_REF, TREE_TYPE (base_field),
! 		      valist, base_field);
!   offset_field = build (COMPONENT_REF, TREE_TYPE (offset_field),
! 			valist, offset_field);
  
!   t = make_tree (ptr_type_node, virtual_incoming_args_rtx);
!   t = build (PLUS_EXPR, ptr_type_node, t, build_int_2 (offset, 0));
!   t = build (MODIFY_EXPR, TREE_TYPE (base_field), base_field, t);
!   TREE_SIDE_EFFECTS (t) = 1;
!   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
! 
!   t = build_int_2 (NUM_ARGS*UNITS_PER_WORD, 0);
!   t = build (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field, t);
!   TREE_SIDE_EFFECTS (t) = 1;
!   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
! }
  
+ rtx
+ alpha_va_arg (valist, type)
+      tree valist, type;
+ {
+   HOST_WIDE_INT tsize;
+   rtx addr;
+   tree t;
+   tree offset_field, base_field, addr_tree, addend;
+   tree wide_type, wide_ofs;
+ 
    if (TARGET_OPEN_VMS)
!     return std_expand_builtin_va_arg (valist, type);
  
!   tsize = ((TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT + 7) / 8) * 8;
  
!   base_field = TYPE_FIELDS (TREE_TYPE (valist));
!   offset_field = TREE_CHAIN (base_field);
  
!   base_field = build (COMPONENT_REF, TREE_TYPE (base_field),
! 		      valist, base_field);
!   offset_field = build (COMPONENT_REF, TREE_TYPE (offset_field),
! 			valist, offset_field);
  
!   wide_type = make_signed_type (64);
!   wide_ofs = save_expr (build1 (CONVERT_EXPR, wide_type, offset_field));
  
!   addend = wide_ofs;
!   if (FLOAT_TYPE_P (type))
!     {
!       tree fpaddend, cond;
! 
!       fpaddend = fold (build (PLUS_EXPR, TREE_TYPE (addend),
! 			      addend, build_int_2 (-6*8, 0)));
! 
!       cond = fold (build (LT_EXPR, integer_type_node,
! 			  wide_ofs, build_int_2 (6*8, 0)));
! 
!       addend = fold (build (COND_EXPR, TREE_TYPE (addend), cond,
! 			    fpaddend, addend));
      }
+ 
+   addr_tree = build (PLUS_EXPR, TREE_TYPE (base_field),
+ 		     base_field, addend);
+ 
+   addr = expand_expr (addr_tree, NULL_RTX, Pmode, EXPAND_NORMAL);
+   addr = copy_to_reg (addr);
+ 
+   t = build (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field,
+ 	     build (PLUS_EXPR, TREE_TYPE (offset_field), 
+ 		    offset_field, build_int_2 (tsize, 0)));
+   TREE_SIDE_EFFECTS (t) = 1;
+   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ 
+   return addr;
  }
  
  /* This page contains routines that are used to determine what the function
Index: alpha.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/alpha/alpha.h,v
retrieving revision 1.70
diff -c -p -d -r1.70 alpha.h
*** alpha.h	1999/06/25 05:12:42	1.70
--- alpha.h	1999/07/26 05:45:35
*************** extern int alpha_memory_latency;
*** 1161,1179 ****
      {									\
        if (! (NO_RTL))							\
  	{								\
  	  move_block_from_reg						\
! 	    (16 + CUM,							\
! 	     gen_rtx (MEM, BLKmode,					\
! 		      plus_constant (virtual_incoming_args_rtx,		\
! 				     ((CUM) + 6)* UNITS_PER_WORD)),	\
  	     6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD);			\
  	  move_block_from_reg						\
! 	    (16 + (TARGET_FPREGS ? 32 : 0) + CUM,			\
! 	     gen_rtx (MEM, BLKmode,					\
! 		      plus_constant (virtual_incoming_args_rtx,		\
! 				     (CUM) * UNITS_PER_WORD)),		\
  	     6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD);			\
- 	   emit_insn (gen_blockage ());					\
  	 }								\
        PRETEND_SIZE = 12 * UNITS_PER_WORD;				\
      }									\
--- 1161,1182 ----
      {									\
        if (! (NO_RTL))							\
  	{								\
+ 	  rtx tmp; int set = get_varargs_alias_set ();			\
+ 	  tmp = gen_rtx_MEM (BLKmode,					\
+ 		             plus_constant (virtual_incoming_args_rtx,	\
+ 				            ((CUM) + 6)* UNITS_PER_WORD)); \
+ 	  MEM_ALIAS_SET (tmp) = set;					\
  	  move_block_from_reg						\
! 	    (16 + CUM, tmp,						\
  	     6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD);			\
+ 									\
+ 	  tmp = gen_rtx_MEM (BLKmode,					\
+ 		             plus_constant (virtual_incoming_args_rtx,	\
+ 				            (CUM) * UNITS_PER_WORD));	\
+ 	  MEM_ALIAS_SET (tmp) = set;					\
  	  move_block_from_reg						\
! 	    (16 + (TARGET_FPREGS ? 32 : 0) + CUM, tmp,			\
  	     6 - (CUM), (6 - (CUM)) * UNITS_PER_WORD);			\
  	 }								\
        PRETEND_SIZE = 12 * UNITS_PER_WORD;				\
      }									\
*************** extern struct rtx_def *alpha_emit_set_lo
*** 1189,1199 ****
  extern struct rtx_def *alpha_emit_conditional_branch ();
  extern struct rtx_def *alpha_emit_conditional_move ();
  
- /* Generate necessary RTL for __builtin_saveregs().
-    ARGLIST is the argument list; see expr.c.  */
- extern struct rtx_def *alpha_builtin_saveregs ();
- #define EXPAND_BUILTIN_SAVEREGS(ARGLIST) alpha_builtin_saveregs (ARGLIST)
- 
  /* Define the information needed to generate branch and scc insns.  This is
     stored from the compare operation.  Note that we can't use "rtx" here
     since it hasn't been defined!  */
--- 1192,1197 ----
*************** do {									\
*** 2348,2353 ****
--- 2346,2363 ----
    {"reg_not_elim_operand", {SUBREG, REG}},				\
    {"reg_no_subreg_operand", {REG}},
  
+ /* Define the `__builtin_va_list' type for the ABI.  */
+ #define BUILD_VA_LIST_TYPE(VALIST) \
+   (VALIST) = alpha_build_va_list ()
+ 
+ /* Implement `va_start' for varargs and stdarg.  */
+ #define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
+   alpha_va_start (stdarg, valist, nextarg)
+ 
+ /* Implement `va_arg'.  */
+ #define EXPAND_BUILTIN_VA_ARG(valist, type) \
+   alpha_va_arg (valist, type)
+ 
  /* Tell collect that the object format is ECOFF.  */
  #define OBJECT_FORMAT_COFF
  #define EXTENDED_COFF
*************** extern int alpha_expand_block_move ();
*** 2548,2550 ****
--- 2558,2563 ----
  extern int alpha_expand_block_clear ();
  extern void alpha_expand_prologue ();
  extern void alpha_expand_epilogue ();
+ extern union tree_node *alpha_build_va_list ();
+ extern void alpha_va_start ();
+ extern struct rtx_def *alpha_va_arg ();

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