From: Richard Henderson Date: Tue, 27 Jul 1999 07:21:59 +0000 (-0700) Subject: m88k.c (m88k_builtin_saveregs): Break out the constructor code to m88k_va_start,... X-Git-Tag: prereleases/libstdc++-2.92~11500 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a9b8384d6e8300bcbccaeaaeb60198fc24017a40;p=thirdparty%2Fgcc.git m88k.c (m88k_builtin_saveregs): Break out the constructor code to m88k_va_start, leaving only the register spill. * 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. From-SVN: r28287 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d1db279202a7..3046572a71ff 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +Tue Jul 27 00:18:34 1999 Richard Henderson + + * 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. + Mon Jul 26 19:07:11 1999 Geoff Keating * config/rs6000/rs6000.c (rs6000_expand_builtin_saveregs): diff --git a/gcc/config/m88k/m88k.c b/gcc/config/m88k/m88k.c index b461782753a5..5d54fdd077ba 100644 --- a/gcc/config/m88k/m88k.c +++ b/gcc/config/m88k/m88k.c @@ -2574,60 +2574,34 @@ m88k_function_arg (args_so_far, mode, type, named) } /* 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. */ + 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 block, addr, argsize, dest; + 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; - 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); + MEM_ALIAS_SET (addr) = get_varargs_alias_set (); 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) @@ -2637,28 +2611,164 @@ m88k_builtin_saveregs () 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)); + 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 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); + /* 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 diff --git a/gcc/config/m88k/m88k.h b/gcc/config/m88k/m88k.h index 2eb2b1f8a80d..2fa1c94bd8c1 100644 --- a/gcc/config/m88k/m88k.h +++ b/gcc/config/m88k/m88k.h @@ -198,13 +198,13 @@ extern char * reg_names[]; Redefined in sysv4.h, and luna.h. */ #define VERSION_INFO1 "m88k, " #ifndef VERSION_INFO2 -#define VERSION_INFO2 "$Revision: 1.12 $" +#define VERSION_INFO2 "$Revision: 1.13 $" #endif #ifndef VERSION_STRING #define VERSION_STRING version_string #ifdef __STDC__ -#define TM_RCS_ID "@(#)" __FILE__ " $Revision: 1.12 $ " __DATE__ +#define TM_RCS_ID "@(#)" __FILE__ " $Revision: 1.13 $ " __DATE__ #else #define TM_RCS_ID "$What: <@(#) m88k.h,v 1.1.1.2.2.2> $" #endif /* __STDC__ */ @@ -1095,6 +1095,21 @@ enum reg_class { NO_REGS, AP_REG, XRF_REGS, GENERAL_REGS, AGRF_REGS, 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)