From 5e2869e6b473100b35b3e0808c0a5a471ffdb9be Mon Sep 17 00:00:00 2001 From: Richard Kenner Date: Tue, 23 Mar 1993 08:10:05 -0500 Subject: [PATCH] Don't include gvarargs.h. (emit_library_call, emit_library_call_value): Delete from here. From-SVN: r3849 --- gcc/expr.c | 599 ----------------------------------------------------- 1 file changed, 599 deletions(-) diff --git a/gcc/expr.c b/gcc/expr.c index 8902d82e16a..0f2885cb104 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -29,7 +29,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "insn-config.h" #include "recog.h" #include "output.h" -#include "gvarargs.h" #include "typeclass.h" #define CEIL(x,y) (((x) + (y) - 1) / (y)) @@ -2125,604 +2124,6 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra, anti_adjust_stack (GEN_INT (extra)); } -/* Output a library call to function FUN (a SYMBOL_REF rtx) - (emitting the queue unless NO_QUEUE is nonzero), - for a value of mode OUTMODE, - with NARGS different arguments, passed as alternating rtx values - and machine_modes to convert them to. - The rtx values should have been passed through protect_from_queue already. - - NO_QUEUE will be true if and only if the library call is a `const' call - which will be enclosed in REG_LIBCALL/REG_RETVAL notes; it is equivalent - to the variable is_const in expand_call. - - NO_QUEUE must be true for const calls, because if it isn't, then - any pending increment will be emitted between REG_LIBCALL/REG_RETVAL notes, - and will be lost if the libcall sequence is optimized away. - - NO_QUEUE must be false for non-const calls, because if it isn't, the - call insn will have its CONST_CALL_P bit set, and it will be incorrectly - optimized. For instance, the instruction scheduler may incorrectly - move memory references across the non-const call. */ - -void -emit_library_call (va_alist) - va_dcl -{ - va_list p; - /* Total size in bytes of all the stack-parms scanned so far. */ - struct args_size args_size; - /* Size of arguments before any adjustments (such as rounding). */ - struct args_size original_args_size; - register int argnum; - enum machine_mode outmode; - int nargs; - rtx fun; - rtx orgfun; - int inc; - int count; - rtx argblock = 0; - CUMULATIVE_ARGS args_so_far; - struct arg { rtx value; enum machine_mode mode; rtx reg; int partial; - struct args_size offset; struct args_size size; }; - struct arg *argvec; - int old_inhibit_defer_pop = inhibit_defer_pop; - int no_queue = 0; - rtx use_insns; - - va_start (p); - orgfun = fun = va_arg (p, rtx); - no_queue = va_arg (p, int); - outmode = va_arg (p, enum machine_mode); - nargs = va_arg (p, int); - - /* Copy all the libcall-arguments out of the varargs data - and into a vector ARGVEC. - - Compute how to pass each argument. We only support a very small subset - of the full argument passing conventions to limit complexity here since - library functions shouldn't have many args. */ - - argvec = (struct arg *) alloca (nargs * sizeof (struct arg)); - - INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE, fun); - - args_size.constant = 0; - args_size.var = 0; - - for (count = 0; count < nargs; count++) - { - rtx val = va_arg (p, rtx); - enum machine_mode mode = va_arg (p, enum machine_mode); - - /* We cannot convert the arg value to the mode the library wants here; - must do it earlier where we know the signedness of the arg. */ - if (mode == BLKmode - || (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)) - abort (); - - /* On some machines, there's no way to pass a float to a library fcn. - Pass it as a double instead. */ -#ifdef LIBGCC_NEEDS_DOUBLE - if (LIBGCC_NEEDS_DOUBLE && mode == SFmode) - val = convert_to_mode (DFmode, val, 0), mode = DFmode; -#endif - - /* There's no need to call protect_from_queue, because - either emit_move_insn or emit_push_insn will do that. */ - - /* Make sure it is a reasonable operand for a move or push insn. */ - if (GET_CODE (val) != REG && GET_CODE (val) != MEM - && ! (CONSTANT_P (val) && LEGITIMATE_CONSTANT_P (val))) - val = force_operand (val, NULL_RTX); - - argvec[count].value = val; - argvec[count].mode = mode; - -#ifdef FUNCTION_ARG_PASS_BY_REFERENCE - if (FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, mode, NULL_TREE, 1)) - abort (); -#endif - - argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1); - if (argvec[count].reg && GET_CODE (argvec[count].reg) == EXPR_LIST) - abort (); -#ifdef FUNCTION_ARG_PARTIAL_NREGS - argvec[count].partial - = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, NULL_TREE, 1); -#else - argvec[count].partial = 0; -#endif - - locate_and_pad_parm (mode, NULL_TREE, - argvec[count].reg && argvec[count].partial == 0, - NULL_TREE, &args_size, &argvec[count].offset, - &argvec[count].size); - - if (argvec[count].size.var) - abort (); - -#ifndef REG_PARM_STACK_SPACE - if (argvec[count].partial) - argvec[count].size.constant -= argvec[count].partial * UNITS_PER_WORD; -#endif - - if (argvec[count].reg == 0 || argvec[count].partial != 0 -#ifdef REG_PARM_STACK_SPACE - || 1 -#endif - ) - args_size.constant += argvec[count].size.constant; - -#ifdef ACCUMULATE_OUTGOING_ARGS - /* If this arg is actually passed on the stack, it might be - clobbering something we already put there (this library call might - be inside the evaluation of an argument to a function whose call - requires the stack). This will only occur when the library call - has sufficient args to run out of argument registers. Abort in - this case; if this ever occurs, code must be added to save and - restore the arg slot. */ - - if (argvec[count].reg == 0 || argvec[count].partial != 0) - abort (); -#endif - - FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree)0, 1); - } - va_end (p); - - /* If this machine requires an external definition for library - functions, write one out. */ - assemble_external_libcall (fun); - - original_args_size = args_size; -#ifdef STACK_BOUNDARY - args_size.constant = (((args_size.constant + (STACK_BYTES - 1)) - / STACK_BYTES) * STACK_BYTES); -#endif - -#ifdef REG_PARM_STACK_SPACE - args_size.constant = MAX (args_size.constant, - REG_PARM_STACK_SPACE (NULL_TREE)); -#ifndef OUTGOING_REG_PARM_STACK_SPACE - args_size.constant -= REG_PARM_STACK_SPACE (NULL_TREE); -#endif -#endif - -#ifdef ACCUMULATE_OUTGOING_ARGS - if (args_size.constant > current_function_outgoing_args_size) - current_function_outgoing_args_size = args_size.constant; - args_size.constant = 0; -#endif - -#ifndef PUSH_ROUNDING - argblock = push_block (GEN_INT (args_size.constant), 0, 0); -#endif - -#ifdef PUSH_ARGS_REVERSED -#ifdef STACK_BOUNDARY - /* If we push args individually in reverse order, perform stack alignment - before the first push (the last arg). */ - if (argblock == 0) - anti_adjust_stack (GEN_INT (args_size.constant - - original_args_size.constant)); -#endif -#endif - -#ifdef PUSH_ARGS_REVERSED - inc = -1; - argnum = nargs - 1; -#else - inc = 1; - argnum = 0; -#endif - - /* Push the args that need to be pushed. */ - - for (count = 0; count < nargs; count++, argnum += inc) - { - register enum machine_mode mode = argvec[argnum].mode; - register rtx val = argvec[argnum].value; - rtx reg = argvec[argnum].reg; - int partial = argvec[argnum].partial; - - if (! (reg != 0 && partial == 0)) - emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0, - argblock, GEN_INT (argvec[count].offset.constant)); - NO_DEFER_POP; - } - -#ifndef PUSH_ARGS_REVERSED -#ifdef STACK_BOUNDARY - /* If we pushed args in forward order, perform stack alignment - after pushing the last arg. */ - if (argblock == 0) - anti_adjust_stack (GEN_INT (args_size.constant - - original_args_size.constant)); -#endif -#endif - -#ifdef PUSH_ARGS_REVERSED - argnum = nargs - 1; -#else - argnum = 0; -#endif - - /* Now load any reg parms into their regs. */ - - for (count = 0; count < nargs; count++, argnum += inc) - { - register enum machine_mode mode = argvec[argnum].mode; - register rtx val = argvec[argnum].value; - rtx reg = argvec[argnum].reg; - int partial = argvec[argnum].partial; - - if (reg != 0 && partial == 0) - emit_move_insn (reg, val); - NO_DEFER_POP; - } - - /* For version 1.37, try deleting this entirely. */ - if (! no_queue) - emit_queue (); - - /* Any regs containing parms remain in use through the call. */ - start_sequence (); - for (count = 0; count < nargs; count++) - if (argvec[count].reg != 0) - emit_insn (gen_rtx (USE, VOIDmode, argvec[count].reg)); - - use_insns = get_insns (); - end_sequence (); - - fun = prepare_call_address (fun, NULL_TREE, &use_insns); - - /* Don't allow popping to be deferred, since then - cse'ing of library calls could delete a call and leave the pop. */ - NO_DEFER_POP; - - /* We pass the old value of inhibit_defer_pop + 1 to emit_call_1, which - will set inhibit_defer_pop to that value. */ - - emit_call_1 (fun, get_identifier (XSTR (orgfun, 0)), args_size.constant, 0, - FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1), - outmode != VOIDmode ? hard_libcall_value (outmode) : NULL_RTX, - old_inhibit_defer_pop + 1, use_insns, no_queue); - - /* Now restore inhibit_defer_pop to its actual original value. */ - OK_DEFER_POP; -} - -/* Like emit_library_call except that an extra argument, VALUE, - comes second and says where to store the result. - (If VALUE is zero, the result comes in the function value register.) */ - -void -emit_library_call_value (va_alist) - va_dcl -{ - va_list p; - /* Total size in bytes of all the stack-parms scanned so far. */ - struct args_size args_size; - /* Size of arguments before any adjustments (such as rounding). */ - struct args_size original_args_size; - register int argnum; - enum machine_mode outmode; - int nargs; - rtx fun; - rtx orgfun; - int inc; - int count; - rtx argblock = 0; - CUMULATIVE_ARGS args_so_far; - struct arg { rtx value; enum machine_mode mode; rtx reg; int partial; - struct args_size offset; struct args_size size; }; - struct arg *argvec; - int old_inhibit_defer_pop = inhibit_defer_pop; - int no_queue = 0; - rtx use_insns; - rtx value; - rtx mem_value = 0; - - va_start (p); - orgfun = fun = va_arg (p, rtx); - value = va_arg (p, rtx); - no_queue = va_arg (p, int); - outmode = va_arg (p, enum machine_mode); - nargs = va_arg (p, int); - - /* If this kind of value comes back in memory, - decide where in memory it should come back. */ - if (RETURN_IN_MEMORY (type_for_mode (outmode, 0))) - { - if (GET_CODE (value) == MEM) - mem_value = value; - else - mem_value = assign_stack_temp (outmode, GET_MODE_SIZE (outmode), 0); - } - - /* ??? Unfinished: must pass the memory address as an argument. */ - - /* Copy all the libcall-arguments out of the varargs data - and into a vector ARGVEC. - - Compute how to pass each argument. We only support a very small subset - of the full argument passing conventions to limit complexity here since - library functions shouldn't have many args. */ - - argvec = (struct arg *) alloca ((nargs + 1) * sizeof (struct arg)); - - INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE, fun); - - args_size.constant = 0; - args_size.var = 0; - - count = 0; - - /* If there's a structure value address to be passed, - either pass it in the special place, or pass it as an extra argument. */ - if (mem_value) - { - rtx addr = XEXP (mem_value, 0); - - if (! struct_value_rtx) - { - nargs++; - - /* Make sure it is a reasonable operand for a move or push insn. */ - if (GET_CODE (addr) != REG && GET_CODE (addr) != MEM - && ! (CONSTANT_P (addr) && LEGITIMATE_CONSTANT_P (addr))) - addr = force_operand (addr, NULL_RTX); - - argvec[count].value = addr; - argvec[count].mode = outmode; - argvec[count].partial = 0; - - argvec[count].reg = FUNCTION_ARG (args_so_far, outmode, NULL_TREE, 1); -#ifdef FUNCTION_ARG_PARTIAL_NREGS - if (FUNCTION_ARG_PARTIAL_NREGS (args_so_far, outmode, NULL_TREE, 1)) - abort (); -#endif - - locate_and_pad_parm (outmode, NULL_TREE, - argvec[count].reg && argvec[count].partial == 0, - NULL_TREE, &args_size, &argvec[count].offset, - &argvec[count].size); - - - if (argvec[count].reg == 0 || argvec[count].partial != 0 -#ifdef REG_PARM_STACK_SPACE - || 1 -#endif - ) - args_size.constant += argvec[count].size.constant; - - FUNCTION_ARG_ADVANCE (args_so_far, outmode, (tree)0, 1); - } - } - - for (; count < nargs; count++) - { - rtx val = va_arg (p, rtx); - enum machine_mode mode = va_arg (p, enum machine_mode); - - /* We cannot convert the arg value to the mode the library wants here; - must do it earlier where we know the signedness of the arg. */ - if (mode == BLKmode - || (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)) - abort (); - - /* On some machines, there's no way to pass a float to a library fcn. - Pass it as a double instead. */ -#ifdef LIBGCC_NEEDS_DOUBLE - if (LIBGCC_NEEDS_DOUBLE && mode == SFmode) - val = convert_to_mode (DFmode, val, 0), mode = DFmode; -#endif - - /* There's no need to call protect_from_queue, because - either emit_move_insn or emit_push_insn will do that. */ - - /* Make sure it is a reasonable operand for a move or push insn. */ - if (GET_CODE (val) != REG && GET_CODE (val) != MEM - && ! (CONSTANT_P (val) && LEGITIMATE_CONSTANT_P (val))) - val = force_operand (val, NULL_RTX); - - argvec[count].value = val; - argvec[count].mode = mode; - -#ifdef FUNCTION_ARG_PASS_BY_REFERENCE - if (FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, mode, NULL_TREE, 1)) - abort (); -#endif - - argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1); - if (argvec[count].reg && GET_CODE (argvec[count].reg) == EXPR_LIST) - abort (); -#ifdef FUNCTION_ARG_PARTIAL_NREGS - argvec[count].partial - = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, NULL_TREE, 1); -#else - argvec[count].partial = 0; -#endif - - locate_and_pad_parm (mode, NULL_TREE, - argvec[count].reg && argvec[count].partial == 0, - NULL_TREE, &args_size, &argvec[count].offset, - &argvec[count].size); - - if (argvec[count].size.var) - abort (); - -#ifndef REG_PARM_STACK_SPACE - if (argvec[count].partial) - argvec[count].size.constant -= argvec[count].partial * UNITS_PER_WORD; -#endif - - if (argvec[count].reg == 0 || argvec[count].partial != 0 -#ifdef REG_PARM_STACK_SPACE - || 1 -#endif - ) - args_size.constant += argvec[count].size.constant; - -#ifdef ACCUMULATE_OUTGOING_ARGS - /* If this arg is actually passed on the stack, it might be - clobbering something we already put there (this library call might - be inside the evaluation of an argument to a function whose call - requires the stack). This will only occur when the library call - has sufficient args to run out of argument registers. Abort in - this case; if this ever occurs, code must be added to save and - restore the arg slot. */ - - if (argvec[count].reg == 0 || argvec[count].partial != 0) - abort (); -#endif - - FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree)0, 1); - } - va_end (p); - - /* If this machine requires an external definition for library - functions, write one out. */ - assemble_external_libcall (fun); - - original_args_size = args_size; -#ifdef STACK_BOUNDARY - args_size.constant = (((args_size.constant + (STACK_BYTES - 1)) - / STACK_BYTES) * STACK_BYTES); -#endif - -#ifdef REG_PARM_STACK_SPACE - args_size.constant = MAX (args_size.constant, - REG_PARM_STACK_SPACE (NULL_TREE)); -#ifndef OUTGOING_REG_PARM_STACK_SPACE - args_size.constant -= REG_PARM_STACK_SPACE (NULL_TREE); -#endif -#endif - -#ifdef ACCUMULATE_OUTGOING_ARGS - if (args_size.constant > current_function_outgoing_args_size) - current_function_outgoing_args_size = args_size.constant; - args_size.constant = 0; -#endif - -#ifndef PUSH_ROUNDING - argblock = push_block (GEN_INT (args_size.constant), 0, 0); -#endif - -#ifdef PUSH_ARGS_REVERSED -#ifdef STACK_BOUNDARY - /* If we push args individually in reverse order, perform stack alignment - before the first push (the last arg). */ - if (argblock == 0) - anti_adjust_stack (GEN_INT (args_size.constant - - original_args_size.constant)); -#endif -#endif - -#ifdef PUSH_ARGS_REVERSED - inc = -1; - argnum = nargs - 1; -#else - inc = 1; - argnum = 0; -#endif - - /* Push the args that need to be pushed. */ - - for (count = 0; count < nargs; count++, argnum += inc) - { - register enum machine_mode mode = argvec[argnum].mode; - register rtx val = argvec[argnum].value; - rtx reg = argvec[argnum].reg; - int partial = argvec[argnum].partial; - - if (! (reg != 0 && partial == 0)) - emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0, - argblock, GEN_INT (argvec[count].offset.constant)); - NO_DEFER_POP; - } - -#ifndef PUSH_ARGS_REVERSED -#ifdef STACK_BOUNDARY - /* If we pushed args in forward order, perform stack alignment - after pushing the last arg. */ - if (argblock == 0) - anti_adjust_stack (GEN_INT (args_size.constant - - original_args_size.constant)); -#endif -#endif - -#ifdef PUSH_ARGS_REVERSED - argnum = nargs - 1; -#else - argnum = 0; -#endif - - /* Now load any reg parms into their regs. */ - - if (mem_value != 0 && struct_value_rtx != 0) - emit_move_insn (struct_value_rtx, XEXP (mem_value, 0)); - - for (count = 0; count < nargs; count++, argnum += inc) - { - register enum machine_mode mode = argvec[argnum].mode; - register rtx val = argvec[argnum].value; - rtx reg = argvec[argnum].reg; - int partial = argvec[argnum].partial; - - if (reg != 0 && partial == 0) - emit_move_insn (reg, val); - NO_DEFER_POP; - } - -#if 0 - /* For version 1.37, try deleting this entirely. */ - if (! no_queue) - emit_queue (); -#endif - - /* Any regs containing parms remain in use through the call. */ - start_sequence (); - for (count = 0; count < nargs; count++) - if (argvec[count].reg != 0) - emit_insn (gen_rtx (USE, VOIDmode, argvec[count].reg)); - - use_insns = get_insns (); - end_sequence (); - - fun = prepare_call_address (fun, NULL_TREE, &use_insns); - - /* Don't allow popping to be deferred, since then - cse'ing of library calls could delete a call and leave the pop. */ - NO_DEFER_POP; - - /* We pass the old value of inhibit_defer_pop + 1 to emit_call_1, which - will set inhibit_defer_pop to that value. */ - - emit_call_1 (fun, get_identifier (XSTR (orgfun, 0)), args_size.constant, 0, - FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1), - outmode != VOIDmode ? hard_libcall_value (outmode) : NULL_RTX, - old_inhibit_defer_pop + 1, use_insns, no_queue); - - /* Now restore inhibit_defer_pop to its actual original value. */ - OK_DEFER_POP; - - /* Copy the value to the right place. */ - if (outmode != VOIDmode) - { - if (mem_value) - { - if (value == 0) - value = hard_libcall_value (outmode); - if (value != mem_value) - emit_move_insn (value, mem_value); - } - else if (value != 0) - emit_move_insn (value, hard_libcall_value (outmode)); - } -} - /* Expand an assignment that stores the value of FROM into TO. If WANT_VALUE is nonzero, return an rtx for the value of TO. (This may contain a QUEUED rtx.) -- 2.30.2