* Problem with existing code: machine state wasn't being saved properly for nested functions. This caused bad code on PowerPC systems with SYSV ABI. An equivalent problem existed for inline functions as well. Adapted from GCC-2.8.0 patch diff -uNr egcs-1.0.OLD/gcc/function.c egcs-1.0/gcc/function.c --- egcs-1.0.1.OLD/gcc/function.c Wed Oct 29 15:54:49 1997 +++ egcs-1.0.1/gcc/function.c Tue Feb 24 16:33:43 1998 @@ -533,13 +533,18 @@ save_tree_status (p, context); save_storage_status (p); save_emit_status (p); +#if 1 /* The call to 'init_emit()' below may alter saveable machine state! */ + if (save_machine_status) + (*save_machine_status) (p); +#endif init_emit (); save_expr_status (p); save_stmt_status (p); save_varasm_status (p); - +#if 0 if (save_machine_status) (*save_machine_status) (p); +#endif } void --- egcs-1.0/gcc/config/rs6000/rs6000.c.orig Mon Feb 9 17:54:44 1998 +++ egcs-1.0/gcc/config/rs6000/rs6000.c Mon Feb 9 19:00:00 1998 @@ -1486,11 +1486,14 @@ "setup_vararg: words = %2d, fregno = %2d, nargs = %4d, proto = %d, mode = %4s, no_rtl= %d\n", cum->words, cum->fregno, cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode), no_rtl); - if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) && !no_rtl) + if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) { rs6000_sysv_varargs_p = 1; - save_area = plus_constant (frame_pointer_rtx, RS6000_VARARGS_OFFSET); + if (! no_rtl) + save_area = plus_constant (frame_pointer_rtx, RS6000_VARARGS_OFFSET); } + else + rs6000_sysv_varargs_p = 0; if (cum->words < 8) { * This fixes a problem with passing 'long long' as varargs --- egcs-1.0/gcc/ginclude/va-ppc.h.ORIG Sun Mar 2 23:37:13 1997 +++ egcs-1.0/gcc/ginclude/va-ppc.h Tue Feb 10 11:04:33 1998 @@ -134,7 +134,7 @@ else if (!__va_float_p (TYPE) && !__va_aggregate_p (TYPE) \ && (AP)->gpr + __va_size(TYPE) <= 8 \ && (!__va_longlong_p(TYPE) \ - || (AP)->gpr + __va_size(TYPE) <= 7)) \ + || (AP)->gpr != 7)) \ { \ if (__va_longlong_p(TYPE) && ((AP)->gpr & 1) != 0) \ (AP)->gpr++; \ *** DEPRECIATED PATCH (Same result, bigger hammer... ) *** --- egcs-1.0/gcc/integrate.c.orig Fri Dec 12 13:54:40 1997 *** +++ egcs-1.0/gcc/integrate.c Sat Feb 7 18:15:07 1998 *** @@ -76,6 +76,13 @@ *** static void set_block_abstract_flags PROTO((tree, int)); *** *** void set_decl_abstract_flags PROTO((tree, int)); *** + *** +/* These variables hold pointers to functions to *** + save and restore machine-specific context data, *** + used to properly handle inline function code generation */ *** +void *(*save_machine_context) PROTO((void)); *** +void (*restore_machine_context) PROTO((void *)); *** + *** *** /* Zero if the current function (whose FUNCTION_DECL is FNDECL) *** is safe and reasonable to integrate into other functions. *** @@ -252,6 +259,10 @@ *** rtvec arg_vector; *** tree parms; *** *** + /* Save context specific for this function */ *** + if (save_machine_context) *** + fndecl->decl.machine_context = (*save_machine_context)(); *** + *** /* Compute the values of any flags we must restore when inlining this. */ *** *** function_flags *** @@ -3248,6 +3259,10 @@ *** *** /* This call is only used to initialize global variables. */ *** init_function_start (fndecl, "lossage", 1); *** + *** + /* Restore context - maybe instead of 'init_function_start()' */ *** + if (restore_machine_context) *** + (*restore_machine_context)(fndecl->decl.machine_context); *** *** /* Redo parameter determinations in case the FUNCTION_... *** macros took machine-specific actions that need to be redone. */ *** --- egcs-1.0/gcc/integrate.h~ Wed Oct 9 13:25:51 1996 *** +++ egcs-1.0/gcc/integrate.h Sat Feb 7 18:18:13 1998 *** @@ -128,3 +128,9 @@ *** *** extern rtx *global_const_equiv_map; *** extern int global_const_equiv_map_size; *** + *** +/* These variables hold pointers to functions to *** + save and restore machine-specific context data, *** + used to properly handle inline function code generation */ *** +extern void *(*save_machine_context) PROTO((void)); *** +extern void (*restore_machine_context) PROTO((void *)); *** *** diff -uNr egcs-1.0/gcc/tree.h egcs-1.0.NEW/tree.h *** --- egcs-1.0/gcc/tree.h Wed Dec 3 14:11:46 1997 *** +++ egcs-1.0.NEW/tree.h Sat Feb 7 13:14:19 1998 *** @@ -1168,6 +1168,7 @@ *** union tree_node *assembler_name; *** union tree_node *section_name; *** union tree_node *machine_attributes; *** + void *machine_context; *** struct rtx_def *rtl; /* acts as link to register transfer language *** (rtl) info */ *** /* For FUNCTION_DECLs: points to insn that constitutes its definition *** *** --- egcs-1.0/gcc/config/rs6000/rs6000.c.orig Sat Feb 7 19:13:31 1998 *** +++ egcs-1.0/gcc/config/rs6000/rs6000.c Sat Feb 7 19:53:35 1998 *** @@ -38,6 +38,7 @@ *** #include "tree.h" *** #include "except.h" *** #include "function.h" *** +#include "integrate.h" *** *** #ifndef TARGET_NO_PROTOTYPE *** #define TARGET_NO_PROTOTYPE 0 *** @@ -2383,6 +2384,32 @@ *** p->machine = (struct machine_function *)0; *** } *** *** +void * *** +rs6000_save_machine_context(void) *** +{ *** + struct machine_function *machine = *** + (struct machine_function *) xmalloc (sizeof (struct machine_function)); *** + *** + machine->sysv_varargs_p = rs6000_sysv_varargs_p; *** + machine->fpmem_size = rs6000_fpmem_size; *** + machine->fpmem_offset = rs6000_fpmem_offset; *** + machine->pic_offset_table_rtx = pic_offset_table_rtx; *** + return((void *)machine); *** +} *** + *** +void *** +rs6000_restore_machine_context(void *p) *** +{ *** + struct machine_function *machine = p; *** + *** + rs6000_sysv_varargs_p = machine->sysv_varargs_p; *** + rs6000_fpmem_size = machine->fpmem_size; *** + rs6000_fpmem_offset = machine->fpmem_offset; *** + pic_offset_table_rtx = machine->pic_offset_table_rtx; *** + *** + free (machine); *** +} *** + *** /* Do anything needed before RTL is emitted for each function. */ *** *** void *** @@ -2397,6 +2424,9 @@ *** /* Arrange to save and restore machine status around nested functions. */ *** save_machine_status = rs6000_save_machine_status; *** restore_machine_status = rs6000_restore_machine_status; *** + /* And for inline routines */ *** + save_machine_context = rs6000_save_machine_context; *** + restore_machine_context = rs6000_restore_machine_context; *** } *** *** *** * This patch fixes problems with the RS6000/PowerPC compilers. Nested functions and inline functions which have varargs will generate incorrect code (for SYSV4 ABI only). This is because the code generation 'back end' tries to optimize information about stack usage. 'varargs' functions need very different stack layouts and without the patch, the fact that a function contains 'varargs' get's lost. Note: Mike Meissner already had some of this support in the code for nested functions, but it wasn't correct (see change to "function.c"). I couldn't see how to use those changes for inline functions, so I mimicked them in the changes in "integrate.c". --- egcs-1.0/gcc/config/rs6000/rs6000.c.orig Sun Feb 8 07:41:41 1998 +++ egcs-1.0/gcc/config/rs6000/rs6000.c Sun Feb 8 07:43:43 1998 @@ -38,6 +38,7 @@ #include "tree.h" #include "except.h" #include "function.h" +#include "integrate.h" #ifndef TARGET_NO_PROTOTYPE #define TARGET_NO_PROTOTYPE 0 @@ -2385,6 +2386,32 @@ p->machine = (struct machine_function *)0; } +void * +rs6000_save_machine_context(void) +{ + struct machine_function *machine = + (struct machine_function *) xmalloc (sizeof (struct machine_function)); + + machine->sysv_varargs_p = rs6000_sysv_varargs_p; + machine->fpmem_size = rs6000_fpmem_size; + machine->fpmem_offset = rs6000_fpmem_offset; + machine->pic_offset_table_rtx = pic_offset_table_rtx; + return((void *)machine); +} + +void +rs6000_restore_machine_context(void *p) +{ + struct machine_function *machine = p; + + rs6000_sysv_varargs_p = machine->sysv_varargs_p; + rs6000_fpmem_size = machine->fpmem_size; + rs6000_fpmem_offset = machine->fpmem_offset; + pic_offset_table_rtx = machine->pic_offset_table_rtx; + + free (machine); +} + /* Do anything needed before RTL is emitted for each function. */ void @@ -2399,6 +2426,9 @@ /* Arrange to save and restore machine status around nested functions. */ save_machine_status = rs6000_save_machine_status; restore_machine_status = rs6000_restore_machine_status; + /* And for inline routines */ + save_machine_context = rs6000_save_machine_context; + restore_machine_context = rs6000_restore_machine_context; } --- egcs-1.0/gcc/integrate.c.orig Sat Oct 25 18:23:10 1997 +++ egcs-1.0/gcc/integrate.c Sun Feb 8 07:43:30 1998 @@ -76,6 +76,13 @@ static void set_block_abstract_flags PROTO((tree, int)); void set_decl_abstract_flags PROTO((tree, int)); + +/* These variables hold pointers to functions to + save and restore machine-specific context data, + used to properly handle inline function code generation */ +void *(*save_machine_context) PROTO((void)); +void (*restore_machine_context) PROTO((void *)); + /* Zero if the current function (whose FUNCTION_DECL is FNDECL) is safe and reasonable to integrate into other functions. @@ -251,6 +258,10 @@ rtvec arg_vector; tree parms; + /* Save context specific for this function */ + if (save_machine_context) + fndecl->decl.machine_context = (*save_machine_context)(); + /* Compute the values of any flags we must restore when inlining this. */ function_flags @@ -3183,6 +3194,10 @@ /* This call is only used to initialize global variables. */ init_function_start (fndecl, "lossage", 1); + + /* Restore context - maybe instead of 'init_function_start()' */ + if (restore_machine_context) + (*restore_machine_context)(fndecl->decl.machine_context); /* Redo parameter determinations in case the FUNCTION_... macros took machine-specific actions that need to be redone. */ --- egcs-1.0/gcc/integrate.h.orig Mon Aug 11 17:57:10 1997 +++ egcs-1.0/gcc/integrate.h Sun Feb 8 07:43:30 1998 @@ -128,3 +128,9 @@ extern rtx *global_const_equiv_map; extern int global_const_equiv_map_size; + +/* These variables hold pointers to functions to + save and restore machine-specific context data, + used to properly handle inline function code generation */ +extern void *(*save_machine_context) PROTO((void)); +extern void (*restore_machine_context) PROTO((void *)); --- egcs-1.0/gcc/tree.h.orig Wed Oct 15 19:19:40 1997 +++ egcs-1.0/gcc/tree.h Sun Feb 8 07:43:30 1998 @@ -1165,6 +1165,7 @@ union tree_node *assembler_name; union tree_node *section_name; union tree_node *machine_attributes; + void *machine_context; struct rtx_def *rtl; /* acts as link to register transfer language (rtl) info */ /* For FUNCTION_DECLs: points to insn that constitutes its definition