This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the EGCS project.
va_list: i960
- To: Jim Wilson <wilson@cygnus.com>, gcc-patches@gcc.gnu.org
- Subject: va_list: i960
- From: Richard Henderson <rth@cygnus.com>
- Date: Mon, 26 Jul 1999 22:42:56 -0700
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);