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: m88k


Rather easy since like Alpha it had all the code for constructing
a va_list struct in __builtin_saveregs.  Like Alpha, it won't work
without the header file changes though.  No loss.



r~


        * m88k.c (m88k_builtin_saveregs): Break out the constructor code
        to m88k_va_start, leaving only the register spill.
        (m88k_build_va_list): New.
        (m88k_va_start): New.
        (m88k_va_arg): New.
        * m88k.h (BUILD_VA_LIST_TYPE): New.
        (EXPAND_BUILTIN_VA_START): New.
        (EXPAND_BUILTIN_VA_ARG): New.

Index: config/m88k/m88k.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/m88k/m88k.c,v
retrieving revision 1.14
diff -c -p -d -r1.14 m88k.c
*** m88k.c	1999/07/26 01:21:57	1.14
--- m88k.c	1999/07/27 07:17:53
*************** m88k_function_arg (args_so_far, mode, ty
*** 2574,2633 ****
  }
  
  /* Do what is necessary for `va_start'.  We look at the current function
!    to determine if stdargs or varargs is used and fill in an initial
!    va_list.  A pointer to this constructor is returned.  */
  
  struct rtx_def *
  m88k_builtin_saveregs ()
  {
!   rtx block, addr, argsize, dest;
    tree fntype = TREE_TYPE (current_function_decl);
    int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
  		   && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
  		       != void_type_node)))
  		? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
    int fixed;
    variable_args_p = 1;
  
    if (CONSTANT_P (current_function_arg_offset_rtx))
      {
        fixed = (XINT (current_function_arg_offset_rtx, 0)
  	       + argadj) / UNITS_PER_WORD;
-       argsize = GEN_INT (fixed);
      }
-   else
-     {
-       fixed = 0;
-       argsize = plus_constant (current_function_arg_offset_rtx, argadj);
-       argsize = expand_shift (RSHIFT_EXPR, Pmode, argsize,
- 			      build_int_2 (2, 0), argsize, 0);
-     }
  
-   /* Allocate the va_list constructor */
-   block = assign_stack_local (BLKmode, 3 * UNITS_PER_WORD, BITS_PER_WORD);
-   MEM_SET_IN_STRUCT_P (block, 1);
-   RTX_UNCHANGING_P (block) = 1;
-   RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
- 
-   /* Store the argsize as the __va_arg member.  */
-   emit_move_insn (change_address (block, SImode, XEXP (block, 0)),
- 		  argsize);
- 
-   /* Store the arg pointer in the __va_stk member.  */
-   emit_move_insn (change_address (block, Pmode,
- 				  plus_constant (XEXP (block, 0),
- 						 UNITS_PER_WORD)),
- 		  copy_to_reg (virtual_incoming_args_rtx));
- 
    /* Allocate the register space, and store it as the __va_reg member.  */
    addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
!   MEM_SET_IN_STRUCT_P (addr, 1);
    RTX_UNCHANGING_P (addr) = 1;
    RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
-   emit_move_insn (change_address (block, Pmode,
- 				  plus_constant (XEXP (block, 0),
- 						 2 * UNITS_PER_WORD)),
- 		  copy_to_reg (XEXP (addr, 0)));
  
    /* Now store the incoming registers.  */
    if (fixed < 8)
--- 2574,2607 ----
  }
  
  /* Do what is necessary for `va_start'.  We look at the current function
!    to determine if stdargs or varargs is used and spill as necessary. 
!    We return a pointer to the spill area.  */
  
  struct rtx_def *
  m88k_builtin_saveregs ()
  {
!   rtx addr, dest;
    tree fntype = TREE_TYPE (current_function_decl);
    int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
  		   && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
  		       != void_type_node)))
  		? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
    int fixed;
+ 
    variable_args_p = 1;
  
+   fixed = 0;
    if (CONSTANT_P (current_function_arg_offset_rtx))
      {
        fixed = (XINT (current_function_arg_offset_rtx, 0)
  	       + argadj) / UNITS_PER_WORD;
      }
  
    /* Allocate the register space, and store it as the __va_reg member.  */
    addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
!   MEM_ALIAS_SET (addr) = get_varargs_alias_set ();
    RTX_UNCHANGING_P (addr) = 1;
    RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
  
    /* Now store the incoming registers.  */
    if (fixed < 8)
*************** m88k_builtin_saveregs ()
*** 2637,2664 ****
  					    fixed * UNITS_PER_WORD));
        move_block_from_reg (2 + fixed, dest, 8 - fixed,
  			   UNITS_PER_WORD * (8 - fixed));
-     }
  
!   if (current_function_check_memory_usage)
!     {
!       emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
! 			 block, ptr_mode,
! 			 GEN_INT (3 * UNITS_PER_WORD), TYPE_MODE (sizetype),
! 			 GEN_INT (MEMORY_USE_RW),
! 			 TYPE_MODE (integer_type_node));
!       if (fixed < 8)
! 	emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
! 			   dest, ptr_mode,
! 			   GEN_INT (UNITS_PER_WORD * (8 - fixed)),
! 			   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.  This fails when not optimizing and produces worse code when
!      optimizing.  */
!   return XEXP (block, 0);
  }
  
  /* If cmpsi has not been generated, emit code to do the test.  Return the
--- 2611,2774 ----
  					    fixed * UNITS_PER_WORD));
        move_block_from_reg (2 + fixed, dest, 8 - fixed,
  			   UNITS_PER_WORD * (8 - fixed));
  
!       if (current_function_check_memory_usage)
! 	{
! 	  emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
! 			     dest, ptr_mode,
! 			     GEN_INT (UNITS_PER_WORD * (8 - fixed)),
! 			     TYPE_MODE (sizetype),
! 			     GEN_INT (MEMORY_USE_RW),
! 			     TYPE_MODE (integer_type_node));
! 	}
      }
  
!   /* Return the address of the save area, but don't put it in a
!      register.  This fails when not optimizing and produces worse code
!      when optimizing.  */
!   return XEXP (addr, 0);
! }
! 
! /* Define the `__builtin_va_list' type for the ABI.  */
! 
! tree
! m88k_build_va_list ()
! {
!   tree field_reg, field_stk, field_arg, int_ptr_type_node, record;
! 
!   int_ptr_type_node = build_pointer_type (integer_type_node);
! 
!   record = make_node (RECORD_TYPE);
! 
!   field_arg = build_decl (FIELD_DECL, get_identifier ("__va_arg"),
! 			  integer_type_node);
!   field_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
! 			  int_ptr_type_node);
!   field_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
! 			  int_ptr_type_node);
! 
!   DECL_FIELD_CONTEXT (field_arg) = record;
!   DECL_FIELD_CONTEXT (field_stk) = record;
!   DECL_FIELD_CONTEXT (field_reg) = record;
! 
!   TYPE_FIELDS (record) = field_arg;
!   TREE_CHAIN (field_arg) = field_stk;
!   TREE_CHAIN (field_stk) = field_reg;
! 
!   layout_type (record);
!   return record;
! }
! 
! /* Implement `va_start' for varargs and stdarg.  */
! 
! void
! m88k_va_start (stdarg_p, valist, nextarg)
!      int stdarg_p;
!      tree valist;
!      rtx nextarg ATTRIBUTE_UNUSED;
! {
!   tree field_reg, field_stk, field_arg;
!   tree reg, stk, arg, t;
! 
!   field_arg = TYPE_FIELDS (va_list_type_node);
!   field_stk = TREE_CHAIN (field_arg);
!   field_reg = TREE_CHAIN (field_stk);
! 
!   arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
!   stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
!   reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
! 
!   /* Fill in the ARG member.  */
!   {
!     tree fntype = TREE_TYPE (current_function_decl);
!     int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
! 		     && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
! 			 != void_type_node)))
! 		  ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
!     tree argsize;
! 
!     if (CONSTANT_P (current_function_arg_offset_rtx))
!       {
! 	int fixed = (INTVAL (current_function_arg_offset_rtx)
! 		     + argadj) / UNITS_PER_WORD;
! 
! 	argsize = build_int_2 (fixed, 0);
!       }
!     else
!       {
! 	argsize = make_tree (integer_type_node,
! 			     current_function_arg_offset_rtx);
! 	argsize = fold (build (PLUS_EXPR, integer_type_node, argsize,
! 			       build_int_2 (argadj, 0)));
! 	argsize = fold (build (RSHIFT_EXPR, integer_type_node, argsize,
! 			       build_int_2 (2, 0)));
!       }
! 
!     t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, argsize);
!     TREE_SIDE_EFFECTS (t) = 1;
!     expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
!   }
! 
!   /* Store the arg pointer in the __va_stk member.  */
!   t = make_tree (TREE_TYPE (stk), virtual_incoming_args_rtx);
!   t = build (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
!   TREE_SIDE_EFFECTS (t) = 1;
!   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
! 
!   /* Tuck the return value from __builtin_saveregs into __va_reg.  */
!   t = make_tree (TREE_TYPE (reg), expand_builtin_saveregs ());
!   t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, t);
!   TREE_SIDE_EFFECTS (t) = 1;
!   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
! }
! 
! /* Implement `va_arg'.  */
! 
! rtx
! m88k_va_arg (valist, type)
!      tree valist, type;
! {
!   tree field_reg, field_stk, field_arg;
!   tree reg, stk, arg, arg_align, base, t;
!   int size, wsize, align, reg_p;
!   rtx addr_rtx;
! 
!   field_arg = TYPE_FIELDS (va_list_type_node);
!   field_stk = TREE_CHAIN (field_arg);
!   field_reg = TREE_CHAIN (field_stk);
! 
!   arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
!   stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
!   reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
! 
!   size = int_size_in_bytes (type);
!   wsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
!   align = 1 << ((TYPE_ALIGN (type) / BITS_PER_UNIT) >> 3);
!   reg_p = (AGGREGATE_TYPE_P (type)
! 	   ? size == UNITS_PER_WORD && TYPE_ALIGN (type) == BITS_PER_WORD
! 	   : size <= 2*UNITS_PER_WORD);
! 
!   /* Align __va_arg to the (doubleword?) boundary above.  */
!   t = build (PLUS_EXPR, TREE_TYPE (arg), arg, build_int_2 (align - 1, 0));
!   arg_align = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
!   arg_align = save_expr (arg_align);
! 
!   /* Decide if we should read from stack or regs.  */
!   t = build (LT_EXPR, integer_type_node, arg_align, build_int_2 (8, 0));
!   base = build (COND_EXPR, TREE_TYPE (reg), t, reg, stk);
! 
!   /* Find the final address.  */
!   t = build (PLUS_EXPR, TREE_TYPE (base), base, arg_align);
!   addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
!   addr_rtx = copy_to_reg (addr_rtx);
! 
!   /* Increment __va_arg.  */
!   t = build (PLUS_EXPR, TREE_TYPE (arg), arg_align, build_int_2 (wsize, 0));
!   t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, t);
!   TREE_SIDE_EFFECTS (t) = 1;
!   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
! 
!   return addr_rtx;
  }
  
  /* If cmpsi has not been generated, emit code to do the test.  Return the
Index: config/m88k/m88k.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/m88k/m88k.h,v
retrieving revision 1.13
diff -c -p -d -r1.13 m88k.h
*** m88k.h	1999/07/26 01:21:57	1.13
--- m88k.h	1999/07/27 07:17:53
*************** enum reg_class { NO_REGS, AP_REG, XRF_RE
*** 1095,1100 ****
--- 1095,1115 ----
     ARGLIST is the argument list; see expr.c.  */
  #define EXPAND_BUILTIN_SAVEREGS() m88k_builtin_saveregs ()
  
+ /* Define the `__builtin_va_list' type for the ABI.  */
+ #define BUILD_VA_LIST_TYPE(VALIST) \
+   (VALIST) = m88k_build_va_list ()
+ extern union tree_node *m88k_build_va_list ();
+ 
+ /* Implement `va_start' for varargs and stdarg.  */
+ #define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
+   m88k_va_start (stdarg, valist, nextarg)
+ extern void m88k_va_start ();
+ 
+ /* Implement `va_arg'.  */
+ #define EXPAND_BUILTIN_VA_ARG(valist, type) \
+   m88k_va_arg (valist, type)
+ extern struct rtx_def *m88k_va_arg ();
+ 
  /* Generate the assembly code for function entry. */
  #define FUNCTION_PROLOGUE(FILE, SIZE) m88k_begin_prologue(FILE, SIZE)
  


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