This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix passing of variable sized arguments on x86_64
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 24 Jan 2003 21:46:49 +0100
- Subject: [PATCH] Fix passing of variable sized arguments on x86_64
Hello,
the patch below implements passing of variable sized arguments by
reference for x86_64. It was approved by Honza, I am commiting it.
Zdenek
* config/i386/i386-protos.h (function_arg_pass_by_reference): Declare.
* config/i386/i386.h (FUNCTION_ARG_PASS_BY_REFERENCE): Use it.
* config/i386/i386.c (function_arg_pass_by_reference): New.
(ix86_va_arg): Support arguments passed by reference.
Index: config/i386/i386-protos.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/i386/i386-protos.h,v
retrieving revision 1.84.2.3
diff -c -3 -p -r1.84.2.3 i386-protos.h
*** config/i386/i386-protos.h 28 Nov 2002 23:19:47 -0000 1.84.2.3
--- config/i386/i386-protos.h 24 Jan 2003 14:57:27 -0000
*************** extern void x86_function_profiler PARAMS
*** 192,197 ****
--- 192,200 ----
#ifdef TREE_CODE
extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx));
extern rtx function_arg PARAMS ((CUMULATIVE_ARGS *, enum machine_mode, tree, int));
+ extern int function_arg_pass_by_reference PARAMS ((CUMULATIVE_ARGS *,
+ enum machine_mode,
+ tree, int));
extern void function_arg_advance PARAMS ((CUMULATIVE_ARGS *, enum machine_mode,
tree, int));
extern rtx ix86_function_value PARAMS ((tree));
Index: config/i386/i386.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.490.2.16
diff -c -3 -p -r1.490.2.16 i386.c
*** config/i386/i386.c 12 Jan 2003 14:24:20 -0000 1.490.2.16
--- config/i386/i386.c 24 Jan 2003 14:57:27 -0000
*************** function_arg (cum, mode, type, named)
*** 2356,2361 ****
--- 2356,2387 ----
return ret;
}
+ /* A C expression that indicates when an argument must be passed by
+ reference. If nonzero for an argument, a copy of that argument is
+ made in memory and a pointer to the argument is passed instead of
+ the argument itself. The pointer is passed in whatever way is
+ appropriate for passing a pointer to that type. */
+
+ int
+ function_arg_pass_by_reference (cum, mode, type, named)
+ CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ tree type;
+ int named ATTRIBUTE_UNUSED;
+ {
+ if (!TARGET_64BIT)
+ return 0;
+
+ if (type && int_size_in_bytes (type) == -1)
+ {
+ if (TARGET_DEBUG_ARG)
+ fprintf (stderr, "function_arg_pass_by_reference\n");
+ return 1;
+ }
+
+ return 0;
+ }
+
/* Gives the alignment boundary, in bits, of an argument with the specified mode
and type. */
*************** ix86_va_arg (valist, type)
*** 2711,2716 ****
--- 2737,2743 ----
rtx lab_false, lab_over = NULL_RTX;
rtx addr_rtx, r;
rtx container;
+ int indirect_p = 0;
/* Only 64bit target needs something special. */
if (!TARGET_64BIT)
*************** ix86_va_arg (valist, type)
*** 2730,2735 ****
--- 2757,2769 ----
sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav);
size = int_size_in_bytes (type);
+ if (size == -1)
+ {
+ /* Passed by reference. */
+ indirect_p = 1;
+ type = build_pointer_type (type);
+ size = int_size_in_bytes (type);
+ }
rsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
container = construct_container (TYPE_MODE (type), type, 0,
*************** ix86_va_arg (valist, type)
*** 2919,2924 ****
--- 2953,2965 ----
if (container)
emit_label (lab_over);
+
+ if (indirect_p)
+ {
+ r = gen_rtx_MEM (Pmode, addr_rtx);
+ set_mem_alias_set (r, get_varargs_alias_set ());
+ emit_move_insn (addr_rtx, r);
+ }
return addr_rtx;
}
Index: config/i386/i386.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/i386/i386.h,v
retrieving revision 1.305.2.7
diff -c -3 -p -r1.305.2.7 i386.h
*** config/i386/i386.h 14 Dec 2002 22:06:12 -0000 1.305.2.7
--- config/i386/i386.h 24 Jan 2003 14:57:27 -0000
*************** typedef struct ix86_args {
*** 1744,1749 ****
--- 1744,1758 ----
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
+ /* A C expression that indicates when an argument must be passed by
+ reference. If nonzero for an argument, a copy of that argument is
+ made in memory and a pointer to the argument is passed instead of
+ the argument itself. The pointer is passed in whatever way is
+ appropriate for passing a pointer to that type. */
+
+ #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
+ function_arg_pass_by_reference(&CUM, MODE, TYPE, NAMED)
+
/* If PIC, we cannot make sibling calls to global functions
because the PLT requires %ebx live.
If we are returning floats on the register stack, we cannot make