Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998
1999, 2000, 2001 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "tree.h"
#include "flags.h"
#include "expr.h"
+#include "libfuncs.h"
#include "function.h"
#include "regs.h"
#include "toplev.h"
tree exp;
int which;
{
- register int i;
+ int i;
enum tree_code code = TREE_CODE (exp);
int class = TREE_CODE_CLASS (code);
int length = first_rtl_op (code);
case BLOCK:
{
- register tree local;
- register tree subblock;
+ tree local;
+ tree subblock;
for (local = BLOCK_VARS (exp); local; local = TREE_CHAIN (local))
if (DECL_INITIAL (local) != 0
We restore `inhibit_defer_pop' to that value.
CALL_FUSAGE is either empty or an EXPR_LIST of USE expressions that
- denote registers used by the called function. */
+ denote registers used by the called function. */
static void
emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
REG_NOTES (call_insn));
if (ecf_flags & ECF_RETURNS_TWICE)
- REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_SETJMP, const0_rtx,
- REG_NOTES (call_insn));
+ {
+ REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_SETJMP, const0_rtx,
+ REG_NOTES (call_insn));
+ current_function_calls_setjmp = 1;
+ }
SIBLING_CALL_P (call_insn) = ((ecf_flags & ECF_SIBCALL) != 0);
int old_inhibit_defer_pop = inhibit_defer_pop;
int old_stack_allocated;
rtx call_fusage;
- register tree p = TREE_OPERAND (exp, 0);
- register int i;
+ tree p = TREE_OPERAND (exp, 0);
+ int i;
/* The alignment of the stack, in bits. */
HOST_WIDE_INT preferred_stack_boundary;
/* The alignment of the stack, in bytes. */
/* If this function requires a variable-sized argument list, don't
try to make a cse'able block for this call. We may be able to
do this eventually, but it is too complicated to keep track of
- what insns go in the cse'able block and which don't. */
+ what insns go in the cse'able block and which don't. */
flags &= ~(ECF_CONST | ECF_PURE);
must_preallocate = 1;
struct args_size args_size;
/* Size of arguments before any adjustments (such as rounding). */
struct args_size original_args_size;
- register int argnum;
+ int argnum;
rtx fun;
int inc;
int count;
case LCT_ALWAYS_RETURN:
flags = ECF_ALWAYS_RETURN;
break;
+ case LCT_RETURNS_TWICE:
+ flags = ECF_RETURNS_TWICE;
+ break;
}
fun = orgfun;
are 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;
+ enum machine_mode mode = argvec[argnum].mode;
+ rtx val = argvec[argnum].value;
rtx reg = argvec[argnum].reg;
int partial = argvec[argnum].partial;
int lower_bound = 0, upper_bound = 0, i;
are to be pushed. */
for (count = 0; count < nargs; count++, argnum += inc)
{
- register rtx val = argvec[argnum].value;
+ rtx val = argvec[argnum].value;
rtx reg = argvec[argnum].reg;
int partial = argvec[argnum].partial;
and machine_modes to convert them to.
The rtx values should have been passed through protect_from_queue already.
- FN_TYPE will is zero for `normal' calls, one for `const' calls, wich
- which will be enclosed in REG_LIBCALL/REG_RETVAL notes and two for `pure'
- calls, that are handled like `const' calls with extra
+ FN_TYPE will be zero for `normal' calls, one for `const' calls,
+ which will be enclosed in REG_LIBCALL/REG_RETVAL notes, and two for
+ `pure' calls, that are handled like `const' calls with extra
(use (memory (scratch)). */
void
emit_library_call VPARAMS((rtx orgfun, enum libcall_type fn_type,
enum machine_mode outmode, int nargs, ...))
{
-#ifndef ANSI_PROTOTYPES
- rtx orgfun;
- int fn_type;
- enum machine_mode outmode;
- int nargs;
-#endif
- va_list p;
-
- VA_START (p, nargs);
-
-#ifndef ANSI_PROTOTYPES
- orgfun = va_arg (p, rtx);
- fn_type = va_arg (p, int);
- outmode = va_arg (p, enum machine_mode);
- nargs = va_arg (p, int);
-#endif
+ VA_OPEN (p, nargs);
+ VA_FIXEDARG (p, rtx, orgfun);
+ VA_FIXEDARG (p, int, fn_type);
+ VA_FIXEDARG (p, enum machine_mode, outmode);
+ VA_FIXEDARG (p, int, nargs);
emit_library_call_value_1 (0, orgfun, NULL_RTX, fn_type, outmode, nargs, p);
- va_end (p);
+ VA_CLOSE (p);
}
\f
/* Like emit_library_call except that an extra argument, VALUE,
enum libcall_type fn_type,
enum machine_mode outmode, int nargs, ...))
{
-#ifndef ANSI_PROTOTYPES
- rtx orgfun;
- rtx value;
- int fn_type;
- enum machine_mode outmode;
- int nargs;
-#endif
- va_list p;
-
- VA_START (p, nargs);
-
-#ifndef ANSI_PROTOTYPES
- orgfun = va_arg (p, rtx);
- value = va_arg (p, rtx);
- fn_type = va_arg (p, int);
- outmode = va_arg (p, enum machine_mode);
- nargs = va_arg (p, int);
-#endif
+ rtx result;
+
+ VA_OPEN (p, nargs);
+ VA_FIXEDARG (p, rtx, orgfun);
+ VA_FIXEDARG (p, rtx, value);
+ VA_FIXEDARG (p, int, fn_type);
+ VA_FIXEDARG (p, enum machine_mode, outmode);
+ VA_FIXEDARG (p, int, nargs);
- value = emit_library_call_value_1 (1, orgfun, value, fn_type, outmode, nargs, p);
+ result = emit_library_call_value_1 (1, orgfun, value, fn_type, outmode,
+ nargs, p);
- va_end (p);
+ VA_CLOSE (p);
- return value;
+ return result;
}
\f
#if 0
int variable_size ATTRIBUTE_UNUSED;
int reg_parm_stack_space;
{
- register tree pval = arg->tree_value;
+ tree pval = arg->tree_value;
rtx reg = 0;
int partial = 0;
int used = 0;
if (reg != 0 && partial == 0)
/* Being passed entirely in a register. We shouldn't be called in
- this case. */
+ this case. */
abort ();
/* If this arg needs special alignment, don't load the registers
}
else if (arg->mode != BLKmode)
{
- register int size;
+ int size;
/* Argument is a scalar, not entirely passed in registers.
(If part is passed in registers, arg->partial says how much
{
/* BLKmode, at least partly to be pushed. */
- register int excess;
+ int excess;
rtx size_rtx;
/* Pushing a nonscalar.
}
}
- /* If parm is passed both in stack and in register and offset is
- greater than reg_parm_stack_space, split the offset. */
+ /* Special handling is required if part of the parameter lies in the
+ register parameter area. The argument may be copied into the stack
+ slot using memcpy(), but the original contents of the register
+ parameter area will be restored after the memcpy() call.
+
+ To ensure that the part that lies in the register parameter area
+ is copied correctly, we emit a separate push for that part. This
+ push should be small enough to avoid a call to memcpy(). */
+#ifndef STACK_PARMS_IN_REG_PARM_AREA
if (arg->reg && arg->pass_on_stack)
+#else
+ if (1)
+#endif
{
if (arg->offset.constant < reg_parm_stack_space && arg->offset.var)
error ("variable offset is passed paritially in stack and in reg");
excess, argblock, ARGS_SIZE_RTX (arg->offset),
reg_parm_stack_space,
ARGS_SIZE_RTX (arg->alignment_pad));
-
- size_rtx = GEN_INT (INTVAL(size_rtx) - reg_parm_stack_space);
}
}