summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2002-12-02 09:00:27 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2002-12-02 09:00:27 +0000
commit22703df0df76accb65607f28070a9771b5bb42de (patch)
tree2f2aa0ebf948ee4580b10bb0a41b7f258b40d0e8
parent560fab27442ac85618b1720e90581c295ae1ea83 (diff)
Import propolice (http://www.trl.ibm.com/projects/security/ssp), a stack
attack protection scheme, into gcc. This protection is enabled by default. It can be turned off by using the -fno-stack-protector flag. Code by Hiroaki Etoh (etoh at jp dot ibm dot com); work on openbsd-specific integration by fgsch@, deraadt@ and myself; tests by fgsch@, naddy@ and myself; beer drinking by myself. Please note that system upgrades with this new code will require a new libc and ld.so to be build and installed before the propolice-enabled compiler can be installed.
-rw-r--r--gnu/egcs/gcc/Makefile.in6
-rw-r--r--gnu/egcs/gcc/combine.c147
-rw-r--r--gnu/egcs/gcc/cse.c50
-rw-r--r--gnu/egcs/gcc/explow.c15
-rw-r--r--gnu/egcs/gcc/expr.c438
-rw-r--r--gnu/egcs/gcc/flags.h14
-rw-r--r--gnu/egcs/gcc/function.c28
-rw-r--r--gnu/egcs/gcc/gcse.c34
-rw-r--r--gnu/egcs/gcc/optabs.c534
-rw-r--r--gnu/egcs/gcc/protector.c2269
-rw-r--r--gnu/egcs/gcc/protector.h38
-rw-r--r--gnu/egcs/gcc/reload1.c236
-rw-r--r--gnu/egcs/gcc/toplev.c19
-rw-r--r--gnu/usr.bin/ld/rtld/rtld.c14
-rw-r--r--lib/libc/shlib_version2
-rw-r--r--lib/libc/sys/Makefile.inc5
-rw-r--r--lib/libc/sys/stack_protector.c87
-rw-r--r--lib/libc_r/shlib_version2
-rw-r--r--libexec/ld.so/util.c14
-rw-r--r--sys/arch/alpha/conf/Makefile.alpha4
-rw-r--r--sys/arch/alpha/stand/Makefile.inc3
-rw-r--r--sys/arch/amiga/conf/Makefile.amiga4
-rw-r--r--sys/arch/amiga/stand/binpatch/Makefile3
-rw-r--r--sys/arch/amiga/stand/boot/Makefile3
-rw-r--r--sys/arch/amiga/stand/loadbsd/Makefile3
-rw-r--r--sys/arch/amiga/stand/loadkmap/Makefile3
-rw-r--r--sys/arch/hp300/conf/Makefile.hp3004
-rw-r--r--sys/arch/hp300/stand/Makefile.inc4
-rw-r--r--sys/arch/hppa/conf/Makefile.hppa5
-rw-r--r--sys/arch/hppa/stand/Makefile.inc3
-rw-r--r--sys/arch/i386/conf/Makefile.i3863
-rw-r--r--sys/arch/i386/stand/Makefile.inc3
-rw-r--r--sys/arch/mac68k/conf/Makefile.mac68k4
-rw-r--r--sys/arch/macppc/conf/Makefile.macppc4
-rw-r--r--sys/arch/macppc/stand/Makefile.inc3
-rw-r--r--sys/arch/mvme68k/conf/Makefile.mvme68k4
-rw-r--r--sys/arch/mvme68k/stand/Makefile.inc3
-rw-r--r--sys/arch/mvme88k/conf/Makefile.mvme88k4
-rw-r--r--sys/arch/mvme88k/stand/Makefile.inc3
-rw-r--r--sys/arch/mvmeppc/conf/Makefile.mvmeppc4
-rw-r--r--sys/arch/mvmeppc/stand/Makefile.inc3
-rw-r--r--sys/arch/sparc/conf/Makefile.sparc3
-rw-r--r--sys/arch/sparc/stand/Makefile.inc4
-rw-r--r--sys/arch/sparc64/conf/Makefile.sparc642
-rw-r--r--sys/arch/sparc64/stand/Makefile.inc3
-rw-r--r--sys/arch/sun3/conf/Makefile.sun34
-rw-r--r--sys/arch/sun3/stand/Makefile.inc3
-rw-r--r--sys/arch/vax/boot/Makefile.inc3
-rw-r--r--sys/arch/vax/conf/Makefile.vax5
-rw-r--r--sys/arch/vax/stand/Makefile.inc3
50 files changed, 3621 insertions, 438 deletions
diff --git a/gnu/egcs/gcc/Makefile.in b/gnu/egcs/gcc/Makefile.in
index ac9959a3977..a5eeadfd0f5 100644
--- a/gnu/egcs/gcc/Makefile.in
+++ b/gnu/egcs/gcc/Makefile.in
@@ -685,7 +685,7 @@ OBJS = toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o \
insn-peep.o reorg.o $(SCHED_PREFIX)sched.o final.o recog.o reg-stack.o \
insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o lcm.o \
profile.o insn-attrtab.o $(out_object_file) getpwd.o $(EXTRA_OBJS) convert.o \
- mbchar.o dyn-string.o graph.o sbitmap.o resource.o hash.o
+ mbchar.o dyn-string.o graph.o sbitmap.o resource.o hash.o protector.o
# GEN files are listed separately, so they can be built before doing parallel
# makes for cc1 or cc1plus. Otherwise sequent parallel make attempts to load
@@ -1138,7 +1138,7 @@ libgcc2.a: libgcc2.c libgcc2.ready $(CONFIG_H) $(FPBIT) $(DPBIT) $(LIB2ADD) \
if [ $${name}.asm = $${file} ]; then \
cp $${file} $${name}.s || exit 1; file=$${name}.s; \
else true; fi; \
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) -c $${file}; \
+ $(GCC_FOR_TARGET) -fno-stack-protector $(LIBGCC2_CFLAGS) $(INCLUDES) -c $${file}; \
if [ $$? -eq 0 ] ; then true; else exit 1; fi; \
$(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) tmplibgcc2.a $${oname}$(objext); \
rm -f $${name}.s $${oname}$(objext); \
@@ -1465,7 +1465,7 @@ toplev.o : toplev.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) \
dwarf2out.h sdbout.h dbxout.h $(EXPR_H) $(BASIC_BLOCK_H) \
$(lang_options_files)
$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(MAYBE_USE_COLLECT2) \
- -DTARGET_NAME=\"$(target_alias)\" \
+ -DSTACK_PROTECTOR -DTARGET_NAME=\"$(target_alias)\" \
-c `echo $(srcdir)/toplev.c | sed 's,^\./,,'`
rtl.o : rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h
diff --git a/gnu/egcs/gcc/combine.c b/gnu/egcs/gcc/combine.c
index 0b64a86a548..ad97d3a5b83 100644
--- a/gnu/egcs/gcc/combine.c
+++ b/gnu/egcs/gcc/combine.c
@@ -1,5 +1,6 @@
/* Optimize by combining instructions for GNU compiler.
- Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -392,6 +393,7 @@ static int n_occurrences;
static void init_reg_last_arrays PROTO((void));
static void setup_incoming_promotions PROTO((void));
static void set_nonzero_bits_and_sign_copies PROTO((rtx, rtx));
+static int cant_combine_insn_p PROTO((rtx));
static int can_combine_p PROTO((rtx, rtx, rtx, rtx, rtx *, rtx *));
static int sets_function_arg_p PROTO((rtx));
static int combinable_i3pat PROTO((rtx, rtx *, rtx, rtx, int, rtx *));
@@ -1312,6 +1314,54 @@ combinable_i3pat (i3, loc, i2dest, i1dest, i1_not_in_src, pi3dest_killed)
return 1;
}
+/* Determine whether INSN can be used in a combination. Return nonzero if
+ not. This is used in try_combine to detect early some cases where we
+ can't perform combinations. */
+
+static int
+cant_combine_insn_p (insn)
+ rtx insn;
+{
+ rtx set;
+ rtx src, dest;
+
+ /* If this isn't really an insn, we can't do anything.
+ This can occur when flow deletes an insn that it has merged into an
+ auto-increment address. */
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ return 1;
+
+ /* For the 2.95.3 release, restrict this code to only handle the machines
+ where it's strictly needed. */
+ if (! SMALL_REGISTER_CLASSES)
+ return 0;
+
+ /* Never combine loads and stores involving hard regs. The register
+ allocator can usually handle such reg-reg moves by tying. If we allow
+ the combiner to make substitutions of hard regs, we risk aborting in
+ reload on machines that have SMALL_REGISTER_CLASSES.
+ As an exception, we allow combinations involving fixed regs; these are
+ not available to the register allocator so there's no risk involved. */
+
+ set = single_set (insn);
+ if (! set)
+ return 0;
+ src = SET_SRC (set);
+ dest = SET_DEST (set);
+ if (GET_CODE (src) == SUBREG)
+ src = SUBREG_REG (src);
+ if (GET_CODE (dest) == SUBREG)
+ dest = SUBREG_REG (dest);
+ if (REG_P (src) && REG_P (dest)
+ && ((REGNO (src) < FIRST_PSEUDO_REGISTER
+ && ! fixed_regs[REGNO (src)])
+ || (REGNO (dest) < FIRST_PSEUDO_REGISTER
+ && ! fixed_regs[REGNO (dest)])))
+ return 1;
+
+ return 0;
+}
+
/* Try to combine the insns I1 and I2 into I3.
Here I1 and I2 appear earlier than I3.
I1 can be zero; then we combine just I2 into I3.
@@ -1362,21 +1412,20 @@ try_combine (i3, i2, i1)
register rtx link;
int i;
- /* If any of I1, I2, and I3 isn't really an insn, we can't do anything.
- This can occur when flow deletes an insn that it has merged into an
- auto-increment address. We also can't do anything if I3 has a
- REG_LIBCALL note since we don't want to disrupt the contiguity of a
- libcall. */
-
- if (GET_RTX_CLASS (GET_CODE (i3)) != 'i'
- || GET_RTX_CLASS (GET_CODE (i2)) != 'i'
- || (i1 && GET_RTX_CLASS (GET_CODE (i1)) != 'i')
+ /* Exit early if one of the insns involved can't be used for
+ combinations. */
+ if (cant_combine_insn_p (i3)
+ || cant_combine_insn_p (i2)
+ || (i1 && cant_combine_insn_p (i1))
+ /* We also can't do anything if I3 has a
+ REG_LIBCALL note since we don't want to disrupt the contiguity of a
+ libcall. */
#if 0
/* ??? This gives worse code, and appears to be unnecessary, since no
pass after flow uses REG_LIBCALL/REG_RETVAL notes. */
|| find_reg_note (i3, REG_LIBCALL, NULL_RTX)
#endif
-)
+ )
return 0;
combine_attempts++;
@@ -3904,6 +3953,11 @@ simplify_rtx (x, op0_mode, last, in_dest)
they are now checked elsewhere. */
if (GET_CODE (XEXP (x, 0)) == PLUS
&& CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1)))
+#ifndef FRAME_GROWS_DOWNWARD
+ if (! (flag_propolice_protection
+ && XEXP (XEXP (x, 0), 0) == frame_pointer_rtx
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
+#endif
return gen_binary (PLUS, mode,
gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0),
XEXP (x, 1)),
@@ -4015,7 +4069,8 @@ simplify_rtx (x, op0_mode, last, in_dest)
gen_binary (MULT, mode,
XEXP (XEXP (x, 0), 0), XEXP (x, 1)),
gen_binary (MULT, mode,
- XEXP (XEXP (x, 0), 1), XEXP (x, 1))));
+ XEXP (XEXP (x, 0), 1),
+ copy_rtx (XEXP (x, 1)))));
if (GET_CODE (x) != MULT)
return x;
@@ -4954,7 +5009,8 @@ simplify_logical (x, last)
x = apply_distributive_law
(gen_binary (GET_CODE (op0), mode,
gen_binary (AND, mode, XEXP (op0, 0), op1),
- gen_binary (AND, mode, XEXP (op0, 1), op1)));
+ gen_binary (AND, mode, XEXP (op0, 1),
+ copy_rtx (op1))));
if (GET_CODE (x) != AND)
return x;
}
@@ -4963,7 +5019,8 @@ simplify_logical (x, last)
return apply_distributive_law
(gen_binary (GET_CODE (op1), mode,
gen_binary (AND, mode, XEXP (op1, 0), op0),
- gen_binary (AND, mode, XEXP (op1, 1), op0)));
+ gen_binary (AND, mode, XEXP (op1, 1),
+ copy_rtx (op0))));
/* Similarly, taking advantage of the fact that
(and (not A) (xor B C)) == (xor (ior A B) (ior A C)) */
@@ -4972,13 +5029,14 @@ simplify_logical (x, last)
return apply_distributive_law
(gen_binary (XOR, mode,
gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 0)),
- gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 1))));
+ gen_binary (IOR, mode, copy_rtx (XEXP (op0, 0)),
+ XEXP (op1, 1))));
else if (GET_CODE (op1) == NOT && GET_CODE (op0) == XOR)
return apply_distributive_law
(gen_binary (XOR, mode,
gen_binary (IOR, mode, XEXP (op1, 0), XEXP (op0, 0)),
- gen_binary (IOR, mode, XEXP (op1, 0), XEXP (op0, 1))));
+ gen_binary (IOR, mode, copy_rtx (XEXP (op1, 0)), XEXP (op0, 1))));
break;
case IOR:
@@ -5004,7 +5062,8 @@ simplify_logical (x, last)
x = apply_distributive_law
(gen_binary (AND, mode,
gen_binary (IOR, mode, XEXP (op0, 0), op1),
- gen_binary (IOR, mode, XEXP (op0, 1), op1)));
+ gen_binary (IOR, mode, XEXP (op0, 1),
+ copy_rtx (op1))));
if (GET_CODE (x) != IOR)
return x;
@@ -5015,7 +5074,8 @@ simplify_logical (x, last)
x = apply_distributive_law
(gen_binary (AND, mode,
gen_binary (IOR, mode, XEXP (op1, 0), op0),
- gen_binary (IOR, mode, XEXP (op1, 1), op0)));
+ gen_binary (IOR, mode, XEXP (op1, 1),
+ copy_rtx (op0))));
if (GET_CODE (x) != IOR)
return x;
@@ -10834,56 +10894,9 @@ get_last_value (x)
return 0;
/* If the value was set in a later insn than the ones we are processing,
- we can't use it even if the register was only set once, but make a quick
- check to see if the previous insn set it to something. This is commonly
- the case when the same pseudo is used by repeated insns.
-
- This does not work if there exists an instruction which is temporarily
- not on the insn chain. */
-
+ we can't use it even if the register was only set once. */
if (INSN_CUID (reg_last_set[regno]) >= subst_low_cuid)
- {
- rtx insn, set;
-
- /* We can not do anything useful in this case, because there is
- an instruction which is not on the insn chain. */
- if (subst_prev_insn)
- return 0;
-
- /* Skip over USE insns. They are not useful here, and they may have
- been made by combine, in which case they do not have a INSN_CUID
- value. We can't use prev_real_insn, because that would incorrectly
- take us backwards across labels. Skip over BARRIERs also, since
- they could have been made by combine. If we see one, we must be
- optimizing dead code, so it doesn't matter what we do. */
- for (insn = prev_nonnote_insn (subst_insn);
- insn && ((GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) == USE)
- || GET_CODE (insn) == BARRIER
- || INSN_CUID (insn) >= subst_low_cuid);
- insn = prev_nonnote_insn (insn))
- ;
-
- if (insn
- && (set = single_set (insn)) != 0
- && rtx_equal_p (SET_DEST (set), x))
- {
- value = SET_SRC (set);
-
- /* Make sure that VALUE doesn't reference X. Replace any
- explicit references with a CLOBBER. If there are any remaining
- references (rare), don't use the value. */
-
- if (reg_mentioned_p (x, value))
- value = replace_rtx (copy_rtx (value), x,
- gen_rtx_CLOBBER (GET_MODE (x), const0_rtx));
-
- if (reg_overlap_mentioned_p (x, value))
- return 0;
- }
- else
- return 0;
- }
+ return 0;
/* If the value has all its registers valid, return it. */
if (get_last_value_validate (&value, reg_last_set[regno],
diff --git a/gnu/egcs/gcc/cse.c b/gnu/egcs/gcc/cse.c
index 2947d8ef6a6..8d2b72898ba 100644
--- a/gnu/egcs/gcc/cse.c
+++ b/gnu/egcs/gcc/cse.c
@@ -4532,6 +4532,7 @@ simplify_plus_minus (code, mode, op0, op1)
int n_ops = 2, input_ops = 2, input_consts = 0, n_consts = 0;
int first = 1, negate = 0, changed;
int i, j;
+ HOST_WIDE_INT fp_offset = 0;
bzero ((char *) ops, sizeof ops);
@@ -4550,6 +4551,10 @@ simplify_plus_minus (code, mode, op0, op1)
switch (GET_CODE (ops[i]))
{
case PLUS:
+ if (flag_propolice_protection
+ && XEXP (ops[i], 0) == virtual_stack_vars_rtx
+ && GET_CODE (XEXP (ops[i], 1)) == CONST_INT)
+ fp_offset = INTVAL (XEXP (ops[i], 1));
case MINUS:
if (n_ops == 7)
return 0;
@@ -4665,7 +4670,43 @@ simplify_plus_minus (code, mode, op0, op1)
j = negs[n_ops - 1], negs[n_ops - 1] = negs[i], negs[i] = j;
}
- /* Put a non-negated operand first. If there aren't any, make all
+ if (flag_propolice_protection)
+ {
+ /* keep the addressing style of local variables
+ as (plus (virtual_stack_vars_rtx) (CONST_int x))
+ (1) inline function is expanded, (+ (+VFP c1) -c2)=>(+ VFP c1-c2)
+ (2) the case ary[r-1], (+ (+VFP c1) (+r -1))=>(+ R (+r -1))
+ */
+ for (i = 0; i < n_ops; i++)
+#ifdef FRAME_GROWS_DOWNWARD
+ if (ops[i] == virtual_stack_vars_rtx)
+#else
+ if (ops[i] == virtual_stack_vars_rtx
+ || ops[i] == frame_pointer_rtx)
+#endif
+ {
+ if (GET_CODE (ops[n_ops - 1]) == CONST_INT)
+ {
+ HOST_WIDE_INT value = INTVAL (ops[n_ops - 1]);
+ if (n_ops < 3 || value >= fp_offset)
+ {
+ ops[i] = plus_constant (ops[i], value);
+ n_ops--;
+ }
+ else
+ {
+ if (n_ops+1 + n_consts > input_ops
+ || (n_ops+1 + n_consts == input_ops && n_consts <= input_consts))
+ return 0;
+ ops[n_ops - 1] = GEN_INT (value-fp_offset);
+ ops[i] = plus_constant (ops[i], fp_offset);
+ }
+ }
+ break;
+ }
+ }
+
+/* Put a non-negated operand first. If there aren't any, make all
operands positive and negate the whole thing later. */
for (i = 0; i < n_ops && negs[i]; i++)
;
@@ -6511,6 +6552,13 @@ cse_insn (insn, libcall_insn)
if (SET_DEST (x) == pc_rtx
&& GET_CODE (SET_SRC (x)) == LABEL_REF)
;
+ else if (x->volatil) {
+ rtx x1 = SET_DEST (x);
+ if (GET_CODE (x1) == SUBREG && GET_CODE (SUBREG_REG (x1)) == REG)
+ x1 = SUBREG_REG (x1);
+ make_new_qty (REGNO (x1));
+ qty_mode[REG_QTY (REGNO (x1))] = GET_MODE (x1);
+ }
/* Don't count call-insns, (set (reg 0) (call ...)), as a set.
The hard function value register is used only once, to copy to
diff --git a/gnu/egcs/gcc/explow.c b/gnu/egcs/gcc/explow.c
index f06d99214e1..603a8d7c594 100644
--- a/gnu/egcs/gcc/explow.c
+++ b/gnu/egcs/gcc/explow.c
@@ -473,6 +473,21 @@ memory_address (mode, x)
in certain cases. This is not necessary since the code
below can handle all possible cases, but machine-dependent
transformations can make better code. */
+ if (flag_propolice_protection)
+ {
+#define FRAMEADDR_P(X) (GET_CODE (X) == PLUS \
+ && XEXP (X, 0) == virtual_stack_vars_rtx \
+ && GET_CODE (XEXP (X, 1)) == CONST_INT)
+ rtx y;
+ if (FRAMEADDR_P (x)) goto win;
+ for (y=x; y!=0 && GET_CODE (y)==PLUS; y = XEXP (y, 0))
+ {
+ if (FRAMEADDR_P (XEXP (y, 0)))
+ XEXP (y, 0) = force_reg (GET_MODE (XEXP (y, 0)), XEXP (y, 0));
+ if (FRAMEADDR_P (XEXP (y, 1)))
+ XEXP (y, 1) = force_reg (GET_MODE (XEXP (y, 1)), XEXP (y, 1));
+ }
+ }
LEGITIMIZE_ADDRESS (x, oldx, mode, win);
/* PLUS and MULT can appear in special ways
diff --git a/gnu/egcs/gcc/expr.c b/gnu/egcs/gcc/expr.c
index 17fa1be1fdc..996c277a5cc 100644
--- a/gnu/egcs/gcc/expr.c
+++ b/gnu/egcs/gcc/expr.c
@@ -1,5 +1,6 @@
/* Convert tree expression to rtl instructions, for GNU compiler.
- Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -191,6 +192,7 @@ static rtx expand_builtin PROTO((tree, rtx, rtx,
static int apply_args_size PROTO((void));
static int apply_result_size PROTO((void));
static rtx result_vector PROTO((int, rtx));
+static rtx expand_builtin_setjmp PROTO((tree, rtx));
static rtx expand_builtin_apply_args PROTO((void));
static rtx expand_builtin_apply PROTO((rtx, rtx, rtx));
static void expand_builtin_return PROTO((rtx));
@@ -1467,7 +1469,7 @@ move_by_pieces (to, from, len, align)
if (USE_LOAD_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_from)
{
- data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
+ data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len-GET_MODE_SIZE (mode)));
data.autinc_from = 1;
data.explicit_inc_from = -1;
}
@@ -1481,7 +1483,7 @@ move_by_pieces (to, from, len, align)
data.from_addr = copy_addr_to_reg (from_addr);
if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to)
{
- data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
+ data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len-GET_MODE_SIZE (mode)));
data.autinc_to = 1;
data.explicit_inc_to = -1;
}
@@ -1599,9 +1601,9 @@ move_by_pieces_1 (genfun, mode, data)
MEM_IN_STRUCT_P (from1) = data->from_struct;
if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
- emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));
+ if (data->explicit_inc_to-- < -1) emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));
if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0)
- emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size)));
+ if (data->explicit_inc_from-- < -1) emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size)));
emit_insn ((*genfun) (to1, from1));
if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
@@ -1710,6 +1712,37 @@ emit_block_move (x, y, size, align)
}
}
+ /* X, Y, or SIZE may have been passed through protect_from_queue.
+
+ It is unsafe to save the value generated by protect_from_queue
+ and reuse it later. Consider what happens if emit_queue is
+ called before the return value from protect_from_queue is used.
+
+ Expansion of the CALL_EXPR below will call emit_queue before
+ we are finished emitting RTL for argument setup. So if we are
+ not careful we could get the wrong value for an argument.
+
+ To avoid this problem we go ahead and emit code to copy X, Y &
+ SIZE into new pseudos. We can then place those new pseudos
+ into an RTL_EXPR and use them later, even after a call to
+ emit_queue.
+
+ Note this is not strictly needed for library calls since they
+ do not call emit_queue before loading their arguments. However,
+ we may need to have library calls call emit_queue in the future
+ since failing to do so could cause problems for targets which
+ define SMALL_REGISTER_CLASSES and pass arguments in registers. */
+ x = copy_to_mode_reg (Pmode, XEXP (x, 0));
+ y = copy_to_mode_reg (Pmode, XEXP (y, 0));
+
+#ifdef TARGET_MEM_FUNCTIONS
+ size = copy_to_mode_reg (TYPE_MODE (sizetype), size);
+#else
+ size = convert_to_mode (TYPE_MODE (integer_type_node), size,
+ TREE_UNSIGNED (integer_type_node));
+ size = copy_to_mode_reg (TYPE_MODE (integer_type_node), size);
+#endif
+
#ifdef TARGET_MEM_FUNCTIONS
/* It is incorrect to use the libcall calling conventions to call
memcpy in this context.
@@ -1748,12 +1781,10 @@ emit_block_move (x, y, size, align)
the last is a size_t byte count for the copy. */
arg_list
= build_tree_list (NULL_TREE,
- make_tree (build_pointer_type (void_type_node),
- XEXP (x, 0)));
+ make_tree (build_pointer_type (void_type_node), x));
TREE_CHAIN (arg_list)
= build_tree_list (NULL_TREE,
- make_tree (build_pointer_type (void_type_node),
- XEXP (y, 0)));
+ make_tree (build_pointer_type (void_type_node), y));
TREE_CHAIN (TREE_CHAIN (arg_list))
= build_tree_list (NULL_TREE, make_tree (sizetype, size));
TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE;
@@ -1767,8 +1798,7 @@ emit_block_move (x, y, size, align)
retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
#else
emit_library_call (bcopy_libfunc, 0,
- VOIDmode, 3, XEXP (y, 0), Pmode,
- XEXP (x, 0), Pmode,
+ VOIDmode, 3, y, Pmode, x, Pmode,
convert_to_mode (TYPE_MODE (integer_type_node), size,
TREE_UNSIGNED (integer_type_node)),
TYPE_MODE (integer_type_node));
@@ -2284,7 +2314,7 @@ clear_by_pieces (to, len, align)
if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to)
{
- data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
+ data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len-GET_MODE_SIZE (mode)));
data.autinc_to = 1;
data.explicit_inc_to = -1;
}
@@ -2354,7 +2384,7 @@ clear_by_pieces_1 (genfun, mode, data)
MEM_IN_STRUCT_P (to1) = data->to_struct;
if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
- emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));
+ if (data->explicit_inc_to-- < -1) emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));
emit_insn ((*genfun) (to1, const0_rtx));
if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
@@ -2444,69 +2474,97 @@ clear_storage (object, size, align)
}
}
+ /* OBJECT or SIZE may have been passed through protect_from_queue.
-#ifdef TARGET_MEM_FUNCTIONS
- /* It is incorrect to use the libcall calling conventions to call
- memset in this context.
+ It is unsafe to save the value generated by protect_from_queue
+ and reuse it later. Consider what happens if emit_queue is
+ called before the return value from protect_from_queue is used.
- This could be a user call to memset and the user may wish to
- examine the return value from memset.
+ Expansion of the CALL_EXPR below will call emit_queue before
+ we are finished emitting RTL for argument setup. So if we are
+ not careful we could get the wrong value for an argument.
- For targets where libcalls and normal calls have different conventions
- for returning pointers, we could end up generating incorrect code.
+ To avoid this problem we go ahead and emit code to copy OBJECT
+ and SIZE into new pseudos. We can then place those new pseudos
+ into an RTL_EXPR and use them later, even after a call to
+ emit_queue.
- So instead of using a libcall sequence we build up a suitable
- CALL_EXPR and expand the call in the normal fashion. */
- if (fn == NULL_TREE)
- {
- tree fntype;
+ Note this is not strictly needed for library calls since they
+ do not call emit_queue before loading their arguments. However,
+ we may need to have library calls call emit_queue in the future
+ since failing to do so could cause problems for targets which
+ define SMALL_REGISTER_CLASSES and pass arguments in registers. */
+ object = copy_to_mode_reg (Pmode, XEXP (object, 0));
- /* This was copied from except.c, I don't know if all this is
- necessary in this context or not. */
- fn = get_identifier ("memset");
- push_obstacks_nochange ();
- end_temporary_allocation ();
- fntype = build_pointer_type (void_type_node);
- fntype = build_function_type (fntype, NULL_TREE);
- fn = build_decl (FUNCTION_DECL, fn, fntype);
- DECL_EXTERNAL (fn) = 1;
- TREE_PUBLIC (fn) = 1;
- DECL_ARTIFICIAL (fn) = 1;
- make_decl_rtl (fn, NULL_PTR, 1);
- assemble_external (fn);
- pop_obstacks ();
- }
+#ifdef TARGET_MEM_FUNCTIONS
+ size = copy_to_mode_reg (TYPE_MODE (sizetype), size);
+#else
+ size = convert_to_mode (TYPE_MODE (integer_type_node), size,
+ TREE_UNSIGNED (integer_type_node));
+ size = copy_to_mode_reg (TYPE_MODE (integer_type_node), size);
+#endif
- /* We need to make an argument list for the function call.
- memset has three arguments, the first is a void * addresses, the
- second a integer with the initialization value, the last is a size_t
- byte count for the copy. */
- arg_list
- = build_tree_list (NULL_TREE,
- make_tree (build_pointer_type (void_type_node),
- XEXP (object, 0)));
- TREE_CHAIN (arg_list)
- = build_tree_list (NULL_TREE,
- make_tree (integer_type_node, const0_rtx));
- TREE_CHAIN (TREE_CHAIN (arg_list))
- = build_tree_list (NULL_TREE, make_tree (sizetype, size));
- TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE;
+#ifdef TARGET_MEM_FUNCTIONS
+ /* It is incorrect to use the libcall calling conventions to call
+ memset in this context.
- /* Now we have to build up the CALL_EXPR itself. */
- call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
- call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
- call_expr, arg_list, NULL_TREE);
- TREE_SIDE_EFFECTS (call_expr) = 1;
+ This could be a user call to memset and the user may wish to
+ examine the return value from memset.
- retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
+ For targets where libcalls and normal calls have different
+ conventions for returning pointers, we could end up generating
+ incorrect code.
+
+ So instead of using a libcall sequence we build up a suitable
+ CALL_EXPR and expand the call in the normal fashion. */
+ if (fn == NULL_TREE)
+ {
+ tree fntype;
+
+ /* This was copied from except.c, I don't know if all this is
+ necessary in this context or not. */
+ fn = get_identifier ("memset");
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ fntype = build_pointer_type (void_type_node);
+ fntype = build_function_type (fntype, NULL_TREE);
+ fn = build_decl (FUNCTION_DECL, fn, fntype);
+ DECL_EXTERNAL (fn) = 1;
+ TREE_PUBLIC (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ make_decl_rtl (fn, NULL_PTR, 1);
+ assemble_external (fn);
+ pop_obstacks ();
+ }
+
+ /* We need to make an argument list for the function call.
+
+ memset has three arguments, the first is a void * addresses, the
+ second a integer with the initialization value, the last is a
+ size_t byte count for the copy. */
+ arg_list
+ = build_tree_list (NULL_TREE,
+ make_tree (build_pointer_type (void_type_node),
+ object));
+ TREE_CHAIN (arg_list)
+ = build_tree_list (NULL_TREE,
+ make_tree (integer_type_node, const0_rtx));
+ TREE_CHAIN (TREE_CHAIN (arg_list))
+ = build_tree_list (NULL_TREE, make_tree (sizetype, size));
+ TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arg_list))) = NULL_TREE;
+
+ /* Now we have to build up the CALL_EXPR itself. */
+ call_expr = build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (fn)), fn);
+ call_expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+ call_expr, arg_list, NULL_TREE);
+ TREE_SIDE_EFFECTS (call_expr) = 1;
+
+ retval = expand_expr (call_expr, NULL_RTX, VOIDmode, 0);
#else
emit_library_call (bzero_libfunc, 0,
- VOIDmode, 2,
- XEXP (object, 0), Pmode,
- convert_to_mode
- (TYPE_MODE (integer_type_node), size,
- TREE_UNSIGNED (integer_type_node)),
+ VOIDmode, 2, object, Pmode, size,
TYPE_MODE (integer_type_node));
#endif
}
@@ -2623,19 +2681,79 @@ emit_move_insn_1 (x, y)
}
else
{
- /* Show the output dies here. This is necessary for pseudos;
+ rtx realpart_x, realpart_y;
+ rtx imagpart_x, imagpart_y;
+
+ /* If this is a complex value with each part being smaller than a
+ word, the usual calling sequence will likely pack the pieces into
+ a single register. Unfortunately, SUBREG of hard registers only
+ deals in terms of words, so we have a problem converting input
+ arguments to the CONCAT of two registers that is used elsewhere
+ for complex values. If this is before reload, we can copy it into
+ memory and reload. FIXME, we should see about using extract and
+ insert on integer registers, but complex short and complex char
+ variables should be rarely used. */
+ if (GET_MODE_BITSIZE (mode) < 2*BITS_PER_WORD
+ && (reload_in_progress | reload_completed) == 0)
+ {
+ int packed_dest_p = (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER);
+ int packed_src_p = (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER);
+
+ if (packed_dest_p || packed_src_p)
+ {
+ enum mode_class reg_class = ((class == MODE_COMPLEX_FLOAT)
+ ? MODE_FLOAT : MODE_INT);
+
+ enum machine_mode reg_mode =
+ mode_for_size (GET_MODE_BITSIZE (mode), reg_class, 1);
+
+ if (reg_mode != BLKmode)
+ {
+ rtx mem = assign_stack_temp (reg_mode,
+ GET_MODE_SIZE (mode), 0);
+
+ rtx cmem = change_address (mem, mode, NULL_RTX);
+
+ current_function_cannot_inline
+ = "function using short complex types cannot be inline";
+
+ if (packed_dest_p)
+ {
+ rtx sreg = gen_rtx_SUBREG (reg_mode, x, 0);
+ emit_move_insn_1 (cmem, y);
+ return emit_move_insn_1 (sreg, mem);
+ }
+ else
+ {
+ rtx sreg = gen_rtx_SUBREG (reg_mode, y, 0);
+ emit_move_insn_1 (mem, sreg);
+ return emit_move_insn_1 (x, cmem);
+ }
+ }
+ }
+ }
+
+ realpart_x = gen_realpart (submode, x);
+ realpart_y = gen_realpart (submode, y);
+ imagpart_x = gen_imagpart (submode, x);
+ imagpart_y = gen_imagpart (submode, y);
+
+ /* Show the output dies here. This is necessary for SUBREGs
+ of pseudos since we cannot track their lifetimes correctly;
hard regs shouldn't appear here except as return values.
We never want to emit such a clobber after reload. */
if (x != y
- && ! (reload_in_progress || reload_completed))
+ && ! (reload_in_progress || reload_completed)
+ && (GET_CODE (realpart_x) == SUBREG
+ || GET_CODE (imagpart_x) == SUBREG))
{
emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
}
emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
- (gen_realpart (submode, x), gen_realpart (submode, y)));
+ (realpart_x, realpart_y));
emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
- (gen_imagpart (submode, x), gen_imagpart (submode, y)));
+ (imagpart_x, imagpart_y));
}
return get_last_insn ();
@@ -2647,6 +2765,8 @@ emit_move_insn_1 (x, y)
else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
{
rtx last_insn = 0;
+ rtx seq;
+ int need_clobber;
#ifdef PUSH_ROUNDING
@@ -2659,15 +2779,9 @@ emit_move_insn_1 (x, y)
}
#endif
- /* Show the output dies here. This is necessary for pseudos;
- hard regs shouldn't appear here except as return values.
- We never want to emit such a clobber after reload. */
- if (x != y
- && ! (reload_in_progress || reload_completed))
- {
- emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
- }
+ start_sequence ();
+ need_clobber = 0;
for (i = 0;
i < (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
i++)
@@ -2689,9 +2803,27 @@ emit_move_insn_1 (x, y)
if (xpart == 0 || ypart == 0)
abort ();
+ need_clobber |= (GET_CODE (xpart) == SUBREG);
+
last_insn = emit_move_insn (xpart, ypart);
}
+ seq = gen_sequence ();
+ end_sequence ();
+
+ /* Show the output dies here. This is necessary for SUBREGs
+ of pseudos since we cannot track their lifetimes correctly;
+ hard regs shouldn't appear here except as return values.
+ We never want to emit such a clobber after reload. */
+ if (x != y
+ && ! (reload_in_progress || reload_completed)
+ && need_clobber != 0)
+ {
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
+ }
+
+ emit_insn (seq);
+
return last_insn;
}
else
@@ -5097,7 +5229,7 @@ init_noncopied_parts (lhs, list)
for (tail = list; tail; tail = TREE_CHAIN (tail))
if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
parts = chainon (parts, init_noncopied_parts (lhs, TREE_VALUE (tail)));
- else
+ else if (TREE_PURPOSE (tail))
{
tree part = TREE_VALUE (tail);
tree part_type = TREE_TYPE (part);
@@ -6206,12 +6338,8 @@ expand_expr (exp, target, tmode, modifier)
}
temp = gen_rtx_MEM (mode, op0);
- /* If address was computed by addition,
- mark this as an element of an aggregate. */
- if (TREE_CODE (exp1) == PLUS_EXPR
- || (TREE_CODE (exp1) == SAVE_EXPR
- && TREE_CODE (TREE_OPERAND (exp1, 0)) == PLUS_EXPR)
- || AGGREGATE_TYPE_P (TREE_TYPE (exp))
+
+ if (AGGREGATE_TYPE_P (TREE_TYPE (exp))
|| (TREE_CODE (exp1) == ADDR_EXPR
&& (exp2 = TREE_OPERAND (exp1, 0))
&& AGGREGATE_TYPE_P (TREE_TYPE (exp2))))
@@ -6948,7 +7076,8 @@ expand_expr (exp, target, tmode, modifier)
/* If adding to a sum including a constant,
associate it to put the constant outside. */
if (GET_CODE (op1) == PLUS
- && CONSTANT_P (XEXP (op1, 1)))
+ && CONSTANT_P (XEXP (op1, 1))
+ && !(flag_propolice_protection && XEXP (op1, 0) == virtual_stack_vars_rtx))
{
rtx constant_term = const0_rtx;
@@ -8417,44 +8546,29 @@ expand_builtin_return_addr (fndecl_code, count, tem)
return tem;
}
-/* __builtin_setjmp is passed a pointer to an array of five words (not
- all will be used on all machines). It operates similarly to the C
- library function of the same name, but is more efficient. Much of
- the code below (and for longjmp) is copied from the handling of
- non-local gotos.
+/* Construct the leading half of a __builtin_setjmp call. Control will
+ return to RECEIVER_LABEL. This is used directly by sjlj exception
+ handling code. */
- NOTE: This is intended for use by GNAT and the exception handling
- scheme in the compiler and will only work in the method used by
- them. */
-
-rtx
-expand_builtin_setjmp (buf_addr, target, first_label, next_label)
+void
+expand_builtin_setjmp_setup (buf_addr, receiver_label)
rtx buf_addr;
- rtx target;
- rtx first_label, next_label;
+ rtx receiver_label;
{
- rtx lab1 = gen_label_rtx ();
enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
- enum machine_mode value_mode;
rtx stack_save;
- value_mode = TYPE_MODE (integer_type_node);
-
#ifdef POINTERS_EXTEND_UNSIGNED
buf_addr = convert_memory_address (Pmode, buf_addr);
#endif
buf_addr = force_reg (Pmode, buf_addr);
- if (target == 0 || GET_CODE (target) != REG
- || REGNO (target) < FIRST_PSEUDO_REGISTER)
- target = gen_reg_rtx (value_mode);
-
emit_queue ();
- /* We store the frame pointer and the address of lab1 in the buffer
- and use the rest of it for the stack save area, which is
- machine-dependent. */
+ /* We store the frame pointer and the address of receiver_label in
+ the buffer and use the rest of it for the stack save area, which
+ is machine-dependent. */
#ifndef BUILTIN_SETJMP_FRAME_VALUE
#define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
@@ -8466,7 +8580,7 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
(gen_rtx_MEM (Pmode,
plus_constant (buf_addr,
GET_MODE_SIZE (Pmode)))),
- force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, lab1)));
+ force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label)));
stack_save = gen_rtx_MEM (sa_mode,
plus_constant (buf_addr,
@@ -8479,20 +8593,22 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
emit_insn (gen_builtin_setjmp_setup (buf_addr));
#endif
- /* Set TARGET to zero and branch to the first-time-through label. */
- emit_move_insn (target, const0_rtx);
- emit_jump_insn (gen_jump (first_label));
- emit_barrier ();
- emit_label (lab1);
-
- /* Tell flow about the strange goings on. Putting `lab1' on
- `nonlocal_goto_handler_labels' to indicates that function
- calls may traverse the arc back to this label. */
+ /* Tell optimize_save_area_alloca that extra work is going to
+ need to go on during alloca. */
+ current_function_calls_setjmp = 1;
+ /* Set this so all the registers get saved in our frame; we need to be
+ able to copy the saved values for any registers from frames we unwind. */
current_function_has_nonlocal_label = 1;
- nonlocal_goto_handler_labels =
- gen_rtx_EXPR_LIST (VOIDmode, lab1, nonlocal_goto_handler_labels);
+}
+/* Construct the trailing part of a __builtin_setjmp call.
+ This is used directly by sjlj exception handling code. */
+
+void
+expand_builtin_setjmp_receiver (receiver_label)
+ rtx receiver_label ATTRIBUTE_UNUSED;
+{
/* Clobber the FP when we get here, so we have to make sure it's
marked as used by this function. */
emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
@@ -8539,7 +8655,7 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
#ifdef HAVE_builtin_setjmp_receiver
if (HAVE_builtin_setjmp_receiver)
- emit_insn (gen_builtin_setjmp_receiver (lab1));
+ emit_insn (gen_builtin_setjmp_receiver (receiver_label));
else
#endif
#ifdef HAVE_nonlocal_goto_receiver
@@ -8551,11 +8667,67 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
; /* Nothing */
}
- /* Set TARGET, and branch to the next-time-through label. */
- emit_move_insn (target, const1_rtx);
- emit_jump_insn (gen_jump (next_label));
+ /* @@@ This is a kludge. Not all machine descriptions define a blockage
+ insn, but we must not allow the code we just generated to be reordered
+ by scheduling. Specifically, the update of the frame pointer must
+ happen immediately, not later. So emit an ASM_INPUT to act as blockage
+ insn. */
+ emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
+}
+
+
+/* __builtin_setjmp is passed a pointer to an array of five words (not
+ all will be used on all machines). It operates similarly to the C
+ library function of the same name, but is more efficient. Much of
+ the code below (and for longjmp) is copied from the handling of
+ non-local gotos.
+
+ NOTE: This is intended for use by GNAT and the exception handling
+ scheme in the compiler and will only work in the method used by
+ them. */
+
+static rtx
+expand_builtin_setjmp (arglist, target)
+ tree arglist;
+ rtx target;
+{
+ rtx buf_addr, next_lab, cont_lab;
+
+ if (arglist == 0
+ || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
+ return NULL_RTX;
+
+ if (target == 0 || GET_CODE (target) != REG
+ || REGNO (target) < FIRST_PSEUDO_REGISTER)
+ target = gen_reg_rtx (TYPE_MODE (integer_type_node));
+
+ buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
+
+ next_lab = gen_label_rtx ();
+ cont_lab = gen_label_rtx ();
+
+ expand_builtin_setjmp_setup (buf_addr, next_lab);
+
+ /* Set TARGET to zero and branch to the continue label. */
+ emit_move_insn (target, const0_rtx);
+ emit_jump_insn (gen_jump (cont_lab));
emit_barrier ();
+ emit_label (next_lab);
+
+ expand_builtin_setjmp_receiver (next_lab);
+
+ /* Set TARGET to one. */
+ emit_move_insn (target, const1_rtx);
+ emit_label (cont_lab);
+
+ /* Tell flow about the strange goings on. Putting `next_lab' on
+ `nonlocal_goto_handler_labels' to indicates that function
+ calls may traverse the arc back to this label. */
+ current_function_has_nonlocal_label = 1;
+ nonlocal_goto_handler_labels
+ = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels);
+
return target;
}
@@ -9576,18 +9748,10 @@ expand_builtin (exp, target, subtarget, mode, ignore)
#endif
case BUILT_IN_SETJMP:
- if (arglist == 0
- || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
- break;
- else
- {
- rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
- VOIDmode, 0);
- rtx lab = gen_label_rtx ();
- rtx ret = expand_builtin_setjmp (buf_addr, target, lab, lab);
- emit_label (lab);
- return ret;
- }
+ target = expand_builtin_setjmp (arglist, target);
+ if (target)
+ return target;
+ break;
/* __builtin_longjmp is passed a pointer to an array of five words.
It's similar to the C library longjmp function but works with
diff --git a/gnu/egcs/gcc/flags.h b/gnu/egcs/gcc/flags.h
index df736988cce..24ef2a1a80c 100644
--- a/gnu/egcs/gcc/flags.h
+++ b/gnu/egcs/gcc/flags.h
@@ -296,6 +296,12 @@ extern int flag_fast_math;
extern int flag_errno_math;
+/* 0 means straightforward implementation of complex divide acceptable.
+ 1 means wide ranges of inputs must work for complex divide.
+ 2 means C9X-like requirements for complex divide (not yet implemented). */
+
+extern int flag_complex_divide_method;
+
/* Nonzero means to run loop optimizations twice. */
extern int flag_rerun_loop_opt;
@@ -532,3 +538,11 @@ extern enum graph_dump_types graph_dump_format;
string identifying the compiler. */
extern int flag_no_ident;
+
+/* Nonzero means use propolice as a stack protection method */
+
+extern int flag_propolice_protection;
+
+/* Warn when not issuing stack smashing protection for some reason */
+
+extern int warn_stack_protector;
diff --git a/gnu/egcs/gcc/function.c b/gnu/egcs/gcc/function.c
index edd0bca1216..88523dfcc79 100644
--- a/gnu/egcs/gcc/function.c
+++ b/gnu/egcs/gcc/function.c
@@ -58,6 +58,7 @@ Boston, MA 02111-1307, USA. */
#include "obstack.h"
#include "toplev.h"
#include "hash.h"
+#include "protector.h"
#ifndef TRAMPOLINE_ALIGNMENT
#define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
@@ -430,6 +431,8 @@ struct temp_slot
/* The size of the slot, including extra space for alignment. This
info is for combine_temp_slots. */
HOST_WIDE_INT full_size;
+ /* Boundary mark of a character array and the others. This info is for propolice */
+ int boundary_mark;
};
/* List of all temporaries allocated, both available and in use. */
@@ -449,6 +452,11 @@ int var_temp_slot_level;
until no longer needed. CLEANUP_POINT_EXPRs define the lifetime
of TARGET_EXPRs. */
int target_temp_slot_level;
+
+/* Current boundary mark for character arrays. */
+
+int temp_boundary_mark;
+
/* This structure is used to record MEMs or pseudos used to replace VAR, any
SUBREGs of VAR, and any MEMs containing VAR as an address. We need to
@@ -931,6 +939,10 @@ assign_stack_temp_for_type (mode, size, keep, type)
int align;
int alias_set;
struct temp_slot *p, *best_p = 0;
+ int char_array = type && (TREE_TYPE (type)==char_type_node
+ || (TREE_TYPE (type)
+ && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
+ && TYPE_PRECISION (TREE_TYPE (type)) == 8));
/* If SIZE is -1 it means that somebody tried to allocate a temporary
of a variable size. */
@@ -963,7 +975,8 @@ assign_stack_temp_for_type (mode, size, keep, type)
&& (!flag_strict_aliasing
|| (alias_set && p->alias_set == alias_set))
&& (best_p == 0 || best_p->size > p->size
- || (best_p->size == p->size && best_p->align > p->align)))
+ || (best_p->size == p->size && best_p->align > p->align))
+ && (! char_array || p->boundary_mark != 0))
{
if (p->align == align && p->size == size)
{
@@ -1001,6 +1014,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
p->align = best_p->align;
p->address = 0;
p->rtl_expr = 0;
+ p->boundary_mark = best_p->boundary_mark;
p->next = temp_slots;
temp_slots = p;
@@ -1062,6 +1076,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
p->full_size = frame_offset - frame_offset_old;
#endif
p->address = 0;
+ p->boundary_mark = char_array?++temp_boundary_mark:0;
p->next = temp_slots;
temp_slots = p;
}
@@ -1186,14 +1201,16 @@ combine_temp_slots ()
int delete_q = 0;
if (! q->in_use && GET_MODE (q->slot) == BLKmode)
{
- if (p->base_offset + p->full_size == q->base_offset)
+ if (p->base_offset + p->full_size == q->base_offset &&
+ p->boundary_mark == q->boundary_mark)
{
/* Q comes after P; combine Q into P. */
p->size += q->size;
p->full_size += q->full_size;
delete_q = 1;
}
- else if (q->base_offset + q->full_size == p->base_offset)
+ else if (q->base_offset + q->full_size == p->base_offset &&
+ p->boundary_mark == q->boundary_mark)
{
/* P comes after Q; combine P into Q. */
q->size += p->size;
@@ -1702,7 +1719,7 @@ put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
if (regno < max_parm_reg)
new = parm_reg_stack_loc[regno];
if (new == 0)
- new = assign_stack_local (decl_mode, GET_MODE_SIZE (decl_mode), 0);
+ new = assign_stack_local_for_pseudo_reg (decl_mode, GET_MODE_SIZE (decl_mode), 0);
}
PUT_MODE (reg, decl_mode);
@@ -3860,7 +3877,8 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
constant with that register. */
temp = gen_reg_rtx (Pmode);
XEXP (x, 0) = new;
- if (validate_change (object, &XEXP (x, 1), temp, 0))
+ if (validate_change (object, &XEXP (x, 1), temp, 0)
+ && ! flag_propolice_protection)
emit_insn_before (gen_move_insn (temp, new_offset), object);
else
{
diff --git a/gnu/egcs/gcc/gcse.c b/gnu/egcs/gcc/gcse.c
index d7fde36ecd8..3dab465ee4b 100644
--- a/gnu/egcs/gcc/gcse.c
+++ b/gnu/egcs/gcc/gcse.c
@@ -1394,6 +1394,7 @@ hash_expr_1 (x, mode, do_not_record_p)
return 0;
}
hash += (unsigned) MEM;
+ hash += MEM_ALIAS_SET (x);
x = XEXP (x, 0);
goto repeat;
@@ -1526,6 +1527,14 @@ expr_equiv_p (x, y)
case REG:
return REGNO (x) == REGNO (y);
+ case MEM:
+ /* Can't merge two expressions in different alias sets, since we can
+ decide that the expression is transparent in a block when it isn't,
+ due to it being set with the different alias set. */
+ if (MEM_ALIAS_SET (x) != MEM_ALIAS_SET (y))
+ return 0;
+ break;
+
/* For commutative operations, check both orders. */
case PLUS:
case MULT:
@@ -3709,7 +3718,7 @@ cprop_insn (insn, alter_jumps)
/* Find an assignment that sets reg_used and is available
at the start of the block. */
set = find_avail_set (regno, insn);
- if (! set)
+ if (! set || set->expr->volatil)
continue;
pat = set->expr;
@@ -4189,9 +4198,26 @@ insert_insn_end_bb (expr, bb, pre)
}
}
- new_insn = emit_insn_before (pat, insn);
- if (BLOCK_HEAD (bb) == insn)
- BLOCK_HEAD (bb) = new_insn;
+ /* If we found all the parameter loads, then we want to insert
+ before the first parameter load.
+
+ If we did not find all the parameter loads, then we might have
+ stopped on the head of the block, which could be a CODE_LABEL.
+ If we inserted before the CODE_LABEL, then we would be putting
+ the insn in the wrong basic block. In that case, put the insn
+ after the CODE_LABEL.
+
+ ?!? Do we need to account for NOTE_INSN_BASIC_BLOCK here? */
+ if (GET_CODE (insn) != CODE_LABEL)
+ {
+ new_insn = emit_insn_before (pat, insn);
+ if (BLOCK_HEAD (bb) == insn)
+ BLOCK_HEAD (bb) = new_insn;
+ }
+ else
+ {
+ new_insn = emit_insn_after (pat, insn);
+ }
}
else
{
diff --git a/gnu/egcs/gcc/optabs.c b/gnu/egcs/gcc/optabs.c
index 75f224c4809..d195d692b45 100644
--- a/gnu/egcs/gcc/optabs.c
+++ b/gnu/egcs/gcc/optabs.c
@@ -1,5 +1,6 @@
/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
- Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -246,6 +247,14 @@ enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
static int add_equal_note PROTO((rtx, rtx, enum rtx_code, rtx, rtx));
static rtx widen_operand PROTO((rtx, enum machine_mode,
enum machine_mode, int, int));
+static int expand_cmplxdiv_straight PROTO((rtx, rtx, rtx, rtx,
+ rtx, rtx, enum machine_mode,
+ int, enum optab_methods,
+ enum mode_class, optab));
+static int expand_cmplxdiv_wide PROTO((rtx, rtx, rtx, rtx,
+ rtx, rtx, enum machine_mode,
+ int, enum optab_methods,
+ enum mode_class, optab));
static enum insn_code can_fix_p PROTO((enum machine_mode, enum machine_mode,
int, int *));
static enum insn_code can_float_p PROTO((enum machine_mode, enum machine_mode,
@@ -348,6 +357,379 @@ widen_operand (op, mode, oldmode, unsignedp, no_extend)
return result;
}
+/* Generate code to perform a straightforward complex divide. */
+
+static int
+expand_cmplxdiv_straight (real0, real1, imag0, imag1, realr, imagr, submode,
+ unsignedp, methods, class, binoptab)
+ rtx real0, real1, imag0, imag1, realr, imagr;
+ enum machine_mode submode;
+ int unsignedp;
+ enum optab_methods methods;
+ enum mode_class class;
+ optab binoptab;
+{
+ rtx divisor;
+ rtx real_t, imag_t;
+ rtx temp1, temp2;
+ rtx res;
+
+ /* Don't fetch these from memory more than once. */
+ real0 = force_reg (submode, real0);
+ real1 = force_reg (submode, real1);
+
+ if (imag0 != 0)
+ imag0 = force_reg (submode, imag0);
+
+ imag1 = force_reg (submode, imag1);
+
+ /* Divisor: c*c + d*d. */
+ temp1 = expand_binop (submode, smul_optab, real1, real1,
+ NULL_RTX, unsignedp, methods);
+
+ temp2 = expand_binop (submode, smul_optab, imag1, imag1,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0 || temp2 == 0)
+ return 0;
+
+ divisor = expand_binop (submode, add_optab, temp1, temp2,
+ NULL_RTX, unsignedp, methods);
+ if (divisor == 0)
+ return 0;
+
+ if (imag0 == 0)
+ {
+ /* Mathematically, ((a)(c-id))/divisor. */
+ /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)). */
+
+ /* Calculate the dividend. */
+ real_t = expand_binop (submode, smul_optab, real0, real1,
+ NULL_RTX, unsignedp, methods);
+
+ imag_t = expand_binop (submode, smul_optab, real0, imag1,
+ NULL_RTX, unsignedp, methods);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+
+ imag_t = expand_unop (submode, neg_optab, imag_t,
+ NULL_RTX, unsignedp);
+ }
+ else
+ {
+ /* Mathematically, ((a+ib)(c-id))/divider. */
+ /* Calculate the dividend. */
+ temp1 = expand_binop (submode, smul_optab, real0, real1,
+ NULL_RTX, unsignedp, methods);
+
+ temp2 = expand_binop (submode, smul_optab, imag0, imag1,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0 || temp2 == 0)
+ return 0;
+
+ real_t = expand_binop (submode, add_optab, temp1, temp2,
+ NULL_RTX, unsignedp, methods);
+
+ temp1 = expand_binop (submode, smul_optab, imag0, real1,
+ NULL_RTX, unsignedp, methods);
+
+ temp2 = expand_binop (submode, smul_optab, real0, imag1,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0 || temp2 == 0)
+ return 0;
+
+ imag_t = expand_binop (submode, sub_optab, temp1, temp2,
+ NULL_RTX, unsignedp, methods);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+ }
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, real_t, divisor,
+ realr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ real_t, divisor, realr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != realr)
+ emit_move_insn (realr, res);
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, imag_t, divisor,
+ imagr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ imag_t, divisor, imagr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != imagr)
+ emit_move_insn (imagr, res);
+
+ return 1;
+}
+
+/* Generate code to perform a wide-input-range-acceptable complex divide. */
+
+static int
+expand_cmplxdiv_wide (real0, real1, imag0, imag1, realr, imagr, submode,
+ unsignedp, methods, class, binoptab)
+ rtx real0, real1, imag0, imag1, realr, imagr;
+ enum machine_mode submode;
+ int unsignedp;
+ enum optab_methods methods;
+ enum mode_class class;
+ optab binoptab;
+{
+ rtx ratio, divisor;
+ rtx real_t, imag_t;
+ rtx temp1, temp2, lab1, lab2;
+ enum machine_mode mode;
+ int align;
+ rtx res;
+
+ /* Don't fetch these from memory more than once. */
+ real0 = force_reg (submode, real0);
+ real1 = force_reg (submode, real1);
+
+ if (imag0 != 0)
+ imag0 = force_reg (submode, imag0);
+
+ imag1 = force_reg (submode, imag1);
+
+ /* XXX What's an "unsigned" complex number? */
+ if (unsignedp)
+ {
+ temp1 = real1;
+ temp2 = imag1;
+ }
+ else
+ {
+ temp1 = expand_abs (submode, real1, NULL_RTX, 1);
+ temp2 = expand_abs (submode, imag1, NULL_RTX, 1);
+ }
+
+ if (temp1 == 0 || temp2 == 0)
+ return 0;
+
+ mode = GET_MODE (temp1);
+ align = GET_MODE_ALIGNMENT (mode);
+ lab1 = gen_label_rtx ();
+ emit_cmp_and_jump_insns (temp1, temp2, LT, NULL_RTX,
+ mode, unsignedp, align, lab1);
+
+ /* |c| >= |d|; use ratio d/c to scale dividend and divisor. */
+
+ if (class == MODE_COMPLEX_FLOAT)
+ ratio = expand_binop (submode, binoptab, imag1, real1,
+ NULL_RTX, unsignedp, methods);
+ else
+ ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ imag1, real1, NULL_RTX, unsignedp);
+
+ if (ratio == 0)
+ return 0;
+
+ /* Calculate divisor. */
+
+ temp1 = expand_binop (submode, smul_optab, imag1, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ divisor = expand_binop (submode, add_optab, temp1, real1,
+ NULL_RTX, unsignedp, methods);
+
+ if (divisor == 0)
+ return 0;
+
+ /* Calculate dividend. */
+
+ if (imag0 == 0)
+ {
+ real_t = real0;
+
+ /* Compute a / (c+id) as a / (c+d(d/c)) + i (-a(d/c)) / (c+d(d/c)). */
+
+ imag_t = expand_binop (submode, smul_optab, real0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (imag_t == 0)
+ return 0;
+
+ imag_t = expand_unop (submode, neg_optab, imag_t,
+ NULL_RTX, unsignedp);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+ }
+ else
+ {
+ /* Compute (a+ib)/(c+id) as
+ (a+b(d/c))/(c+d(d/c) + i(b-a(d/c))/(c+d(d/c)). */
+
+ temp1 = expand_binop (submode, smul_optab, imag0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ real_t = expand_binop (submode, add_optab, temp1, real0,
+ NULL_RTX, unsignedp, methods);
+
+ temp1 = expand_binop (submode, smul_optab, real0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ imag_t = expand_binop (submode, sub_optab, imag0, temp1,
+ NULL_RTX, unsignedp, methods);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+ }
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, real_t, divisor,
+ realr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ real_t, divisor, realr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != realr)
+ emit_move_insn (realr, res);
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, imag_t, divisor,
+ imagr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ imag_t, divisor, imagr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != imagr)
+ emit_move_insn (imagr, res);
+
+ lab2 = gen_label_rtx ();
+ emit_jump_insn (gen_jump (lab2));
+ emit_barrier ();
+
+ emit_label (lab1);
+
+ /* |d| > |c|; use ratio c/d to scale dividend and divisor. */
+
+ if (class == MODE_COMPLEX_FLOAT)
+ ratio = expand_binop (submode, binoptab, real1, imag1,
+ NULL_RTX, unsignedp, methods);
+ else
+ ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ real1, imag1, NULL_RTX, unsignedp);
+
+ if (ratio == 0)
+ return 0;
+
+ /* Calculate divisor. */
+
+ temp1 = expand_binop (submode, smul_optab, real1, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ divisor = expand_binop (submode, add_optab, temp1, imag1,
+ NULL_RTX, unsignedp, methods);
+
+ if (divisor == 0)
+ return 0;
+
+ /* Calculate dividend. */
+
+ if (imag0 == 0)
+ {
+ /* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d). */
+
+ real_t = expand_binop (submode, smul_optab, real0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ imag_t = expand_unop (submode, neg_optab, real0,
+ NULL_RTX, unsignedp);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+ }
+ else
+ {
+ /* Compute (a+ib)/(c+id) as
+ (a(c/d)+b)/(c(c/d)+d) + i (b(c/d)-a)/(c(c/d)+d). */
+
+ temp1 = expand_binop (submode, smul_optab, real0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ real_t = expand_binop (submode, add_optab, temp1, imag0,
+ NULL_RTX, unsignedp, methods);
+
+ temp1 = expand_binop (submode, smul_optab, imag0, ratio,
+ NULL_RTX, unsignedp, methods);
+
+ if (temp1 == 0)
+ return 0;
+
+ imag_t = expand_binop (submode, sub_optab, temp1, real0,
+ NULL_RTX, unsignedp, methods);
+
+ if (real_t == 0 || imag_t == 0)
+ return 0;
+ }
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, real_t, divisor,
+ realr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ real_t, divisor, realr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != realr)
+ emit_move_insn (realr, res);
+
+ if (class == MODE_COMPLEX_FLOAT)
+ res = expand_binop (submode, binoptab, imag_t, divisor,
+ imagr, unsignedp, methods);
+ else
+ res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
+ imag_t, divisor, imagr, unsignedp);
+
+ if (res == 0)
+ return 0;
+
+ if (res != imagr)
+ emit_move_insn (imagr, res);
+
+ emit_label (lab2);
+
+ return 1;
+}
+
/* Generate code to perform an operation specified by BINOPTAB
on operands OP0 and OP1, with result having machine-mode MODE.
@@ -390,6 +772,25 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
if (target)
target = protect_from_queue (target, 1);
+ if (flag_propolice_protection
+ && binoptab->code == PLUS
+ && op0 == virtual_stack_vars_rtx
+ && GET_CODE(op1) == CONST_INT)
+ {
+ int icode = (int) binoptab->handlers[(int) mode].insn_code;
+ if (target)
+ temp = target;
+ else
+ temp = gen_reg_rtx (mode);
+
+ if (! (*insn_operand_predicate[icode][0]) (temp, mode))
+ temp = gen_reg_rtx (mode);
+
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ gen_rtx_PLUS (GET_MODE (op0), op0, op1)));
+ return temp;
+ }
+
if (flag_force_mem)
{
op0 = force_not_mem (op0);
@@ -1219,12 +1620,12 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
start_sequence ();
- realr = gen_realpart (submode, target);
+ realr = gen_realpart (submode, target);
imagr = gen_imagpart (submode, target);
if (GET_MODE (op0) == mode)
{
- real0 = gen_realpart (submode, op0);
+ real0 = gen_realpart (submode, op0);
imag0 = gen_imagpart (submode, op0);
}
else
@@ -1232,7 +1633,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
if (GET_MODE (op1) == mode)
{
- real1 = gen_realpart (submode, op1);
+ real1 = gen_realpart (submode, op1);
imag1 = gen_imagpart (submode, op1);
}
else
@@ -1390,111 +1791,25 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
}
else
{
- /* Divisor is of complex type:
- X/(a+ib) */
- rtx divisor;
- rtx real_t, imag_t;
- rtx temp1, temp2;
-
- /* Don't fetch these from memory more than once. */
- real0 = force_reg (submode, real0);
- real1 = force_reg (submode, real1);
-
- if (imag0 != 0)
- imag0 = force_reg (submode, imag0);
-
- imag1 = force_reg (submode, imag1);
-
- /* Divisor: c*c + d*d */
- temp1 = expand_binop (submode, smul_optab, real1, real1,
- NULL_RTX, unsignedp, methods);
-
- temp2 = expand_binop (submode, smul_optab, imag1, imag1,
- NULL_RTX, unsignedp, methods);
-
- if (temp1 == 0 || temp2 == 0)
- break;
-
- divisor = expand_binop (submode, add_optab, temp1, temp2,
- NULL_RTX, unsignedp, methods);
- if (divisor == 0)
- break;
-
- if (imag0 == 0)
+ switch (flag_complex_divide_method)
{
- /* ((a)(c-id))/divisor */
- /* (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)) */
-
- /* Calculate the dividend */
- real_t = expand_binop (submode, smul_optab, real0, real1,
- NULL_RTX, unsignedp, methods);
-
- imag_t = expand_binop (submode, smul_optab, real0, imag1,
- NULL_RTX, unsignedp, methods);
-
- if (real_t == 0 || imag_t == 0)
- break;
-
- imag_t = expand_unop (submode, neg_optab, imag_t,
- NULL_RTX, unsignedp);
- }
- else
- {
- /* ((a+ib)(c-id))/divider */
- /* Calculate the dividend */
- temp1 = expand_binop (submode, smul_optab, real0, real1,
- NULL_RTX, unsignedp, methods);
-
- temp2 = expand_binop (submode, smul_optab, imag0, imag1,
- NULL_RTX, unsignedp, methods);
-
- if (temp1 == 0 || temp2 == 0)
- break;
-
- real_t = expand_binop (submode, add_optab, temp1, temp2,
- NULL_RTX, unsignedp, methods);
-
- temp1 = expand_binop (submode, smul_optab, imag0, real1,
- NULL_RTX, unsignedp, methods);
-
- temp2 = expand_binop (submode, smul_optab, real0, imag1,
- NULL_RTX, unsignedp, methods);
-
- if (temp1 == 0 || temp2 == 0)
- break;
+ case 0:
+ ok = expand_cmplxdiv_straight (real0, real1, imag0, imag1,
+ realr, imagr, submode,
+ unsignedp, methods,
+ class, binoptab);
+ break;
- imag_t = expand_binop (submode, sub_optab, temp1, temp2,
- NULL_RTX, unsignedp, methods);
+ case 1:
+ ok = expand_cmplxdiv_wide (real0, real1, imag0, imag1,
+ realr, imagr, submode,
+ unsignedp, methods,
+ class, binoptab);
+ break;
- if (real_t == 0 || imag_t == 0)
- break;
+ default:
+ abort ();
}
-
- if (class == MODE_COMPLEX_FLOAT)
- res = expand_binop (submode, binoptab, real_t, divisor,
- realr, unsignedp, methods);
- else
- res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
- real_t, divisor, realr, unsignedp);
-
- if (res == 0)
- break;
- else if (res != realr)
- emit_move_insn (realr, res);
-
- if (class == MODE_COMPLEX_FLOAT)
- res = expand_binop (submode, binoptab, imag_t, divisor,
- imagr, unsignedp, methods);
- else
- res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
- imag_t, divisor, imagr, unsignedp);
-
- if (res == 0)
- break;
- else if (res != imagr)
- emit_move_insn (imagr, res);
-
- ok = 1;
}
break;
@@ -2592,8 +2907,14 @@ emit_libcall_block (insns, target, result, equiv)
rtx result;
rtx equiv;
{
+ rtx final_dest = target;
rtx prev, next, first, last, insn;
+ /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
+ into a MEM later. Protect the libcall block from this change. */
+ if (! REG_P (target) || REG_USERVAR_P (target))
+ target = gen_reg_rtx (GET_MODE (target));
+
/* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
reg note to indicate that this call cannot throw. (Unless there is
already a REG_EH_REGION note.) */
@@ -2657,6 +2978,9 @@ emit_libcall_block (insns, target, result, equiv)
!= CODE_FOR_nothing)
set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
+ if (final_dest != target)
+ emit_move_insn (final_dest, target);
+
if (prev == 0)
first = get_insns ();
else
diff --git a/gnu/egcs/gcc/protector.c b/gnu/egcs/gcc/protector.c
new file mode 100644
index 00000000000..efbe22dba71
--- /dev/null
+++ b/gnu/egcs/gcc/protector.c
@@ -0,0 +1,2269 @@
+/* Top level of GNU C compiler
+ Copyright (C) 1987, 88, 89, 92-7, 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+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.
+
+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.
+
+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. */
+
+#include "config.h"
+#include "system.h"
+#include "machmode.h"
+
+#include "rtl.h"
+#include "tree.h"
+#include "regs.h"
+#include "flags.h"
+#include "insn-config.h"
+#include "insn-flags.h"
+#include "expr.h"
+#include "output.h"
+#include "recog.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "except.h"
+#include "function.h"
+#include "toplev.h"
+#include "conditions.h"
+#include "insn-attr.h"
+#include "c-tree.h"
+#include "protector.h"
+
+
+rtx assign_stack_local_for_pseudo_reg PARAMS ((enum machine_mode, HOST_WIDE_INT, int));
+
+
+/* Warn when not issuing stack smashing protection for some reason */
+int warn_stack_protector;
+
+/* Round a value to the lowest integer less than it that is a multiple of
+ the required alignment. Avoid using division in case the value is
+ negative. Assume the alignment is a power of two. */
+#define FLOOR_ROUND(VALUE,ALIGN) ((VALUE) & ~((ALIGN) - 1))
+
+/* Similar, but round to the next highest integer that meets the
+ alignment. */
+#define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
+
+
+/* Nonzero means use propolice as a stack protection method */
+extern int flag_propolice_protection;
+
+/* This file contains several memory arrangement functions to protect
+ the return address and the frame pointer of the stack
+ from a stack-smashing attack. It also
+ provides the function that protects pointer variables. */
+
+/* Nonzero if function being compiled can define string buffers that may be
+ damaged by the stack-smash attack */
+static int current_function_defines_vulnerable_string;
+static int current_function_defines_short_string;
+static int current_function_has_variable_string;
+static int current_function_defines_vsized_array;
+static int saved_optimize_size = -1;
+
+static rtx guard_area, _guard;
+static rtx function_first_insn, prologue_insert_point;
+static rtx debuginsn;
+
+/* */
+static HOST_WIDE_INT sweep_frame_offset;
+static HOST_WIDE_INT push_allocated_offset = 0;
+static HOST_WIDE_INT push_frame_offset = 0;
+
+static int search_string_from_argsandvars PARAMS ((int caller));
+static int search_string_from_local_vars PARAMS ((tree block));
+static int search_string_def PARAMS ((tree names));
+static int search_pointer_def PARAMS ((tree names));
+static int search_func_pointer PARAMS ((tree type, int mark));
+static void reset_used_flags_for_insns PARAMS ((rtx insn));
+static void reset_used_flags_for_decls PARAMS ((tree block));
+static void reset_used_flags_of_plus PARAMS ((rtx x));
+static void rtl_prologue PARAMS ((rtx insn));
+static void rtl_epilogue PARAMS ((rtx fnlastinsn));
+static void arrange_var_order PARAMS ((tree blocks));
+static void copy_args_for_protection PARAMS ((void));
+static void sweep_string_variable PARAMS ((rtx sweep_var, HOST_WIDE_INT var_size));
+static void sweep_string_in_decls PARAMS ((tree block, HOST_WIDE_INT sweep_offset, HOST_WIDE_INT size));
+static void sweep_string_in_args PARAMS ((tree parms, HOST_WIDE_INT sweep_offset, HOST_WIDE_INT size));
+static void sweep_string_use_of_insns PARAMS ((rtx insn, HOST_WIDE_INT sweep_offset, HOST_WIDE_INT size));
+static void sweep_string_in_operand PARAMS ((rtx insn, rtx orig, HOST_WIDE_INT sweep_offset, HOST_WIDE_INT size));
+static void move_arg_location PARAMS ((rtx insn, rtx orig, rtx new, HOST_WIDE_INT var_size));
+static void change_arg_use_of_insns PARAMS ((rtx insn, rtx orig, rtx new, HOST_WIDE_INT size));
+static void change_arg_use_in_operand PARAMS ((rtx x, rtx orig, rtx new, HOST_WIDE_INT size));
+static void expand_value_return PARAMS ((rtx val));
+static int replace_return_reg PARAMS ((rtx insn, rtx return_save));
+static void propagate_virtual_stack_vars_in_insns PARAMS ((rtx insn));
+static void propagate_virtual_stack_vars_in_operand PARAMS ((rtx x, rtx orig));
+
+
+#define SUSPICIOUS_BUF_SIZE 8
+
+#define AUTO_BASEPTR(X) \
+ (GET_CODE (X) == PLUS ? XEXP (X, 0) : X)
+#define AUTO_OFFSET(X) \
+ (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
+#undef PARM_PASSED_IN_MEMORY
+#define PARM_PASSED_IN_MEMORY(PARM) \
+ (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
+#define VIRTUAL_STACK_VARS_P(X) \
+ ((X) == virtual_stack_vars_rtx || (GET_CODE (X) == REG && (X)->used))
+
+
+
+void
+prepare_stack_protection (void)
+{
+ tree blocks = DECL_INITIAL (current_function_decl);
+ current_function_defines_short_string = FALSE;
+ current_function_has_variable_string = FALSE;
+ current_function_defines_vsized_array = FALSE;
+ push_frame_offset = push_allocated_offset = 0;
+
+ /* solve for ssp-ppc-20021125 */
+ if (saved_optimize_size < 0) saved_optimize_size = optimize_size;
+ optimize_size = saved_optimize_size;
+
+ /*
+ skip the protection if the function has no block or it is an inline function
+ */
+ if (! blocks || DECL_INLINE (current_function_decl)) return;
+
+ current_function_defines_vulnerable_string = search_string_from_argsandvars (0);
+
+ if (current_function_defines_vulnerable_string)
+ {
+ HOST_WIDE_INT offset;
+ function_first_insn = get_insns ();
+
+ if (current_function_contains_functions) {
+ if (warn_stack_protector)
+ warning ("not protecting function: it contains functions");
+ return;
+ }
+
+ /* propagate virtual_stack_vars_rtx to access arg_pointer_save_area */
+ if (arg_pointer_save_area)
+ propagate_virtual_stack_vars_in_insns (function_first_insn);
+
+ sweep_frame_offset = 0;
+
+#ifdef STACK_GROWS_DOWNWARD
+ /*
+ frame_offset: offset to end of allocated area of stack frame.
+ It is defined in the function.c
+ */
+
+ /* the location must be before buffers */
+ guard_area = assign_stack_local (BLKmode, UNITS_PER_GUARD, -1);
+ PUT_MODE (guard_area, GUARD_m);
+ MEM_VOLATILE_P (guard_area) = 1;
+
+#ifndef FRAME_GROWS_DOWNWARD
+ sweep_frame_offset = frame_offset;
+#endif
+
+ /* For making room for guard value, scan all insns and fix the offset address
+ of the variable that is based on frame pointer.
+ Scan all declarations of variables and fix the offset address of the variable that
+ is based on the frame pointer */
+ sweep_string_variable (guard_area, UNITS_PER_GUARD);
+
+
+ /* the location of guard area moves to the beginning of stack frame */
+ if ((offset = AUTO_OFFSET(XEXP (guard_area, 0))))
+ XEXP (XEXP (guard_area, 0), 1) = gen_rtx_CONST_INT (VOIDmode, sweep_frame_offset);
+
+
+ /* Insert prologue rtl instructions */
+ rtl_prologue (function_first_insn);
+
+ if (! current_function_has_variable_string)
+ {
+ /* Generate argument saving instruction */
+ copy_args_for_protection ();
+
+#ifndef FRAME_GROWS_DOWNWARD
+ /* If frame grows upward, character string copied from an arg stays top of
+ the guard variable. So sweep the guard variable again */
+ sweep_frame_offset = CEIL_ROUND (frame_offset, BIGGEST_ALIGNMENT / BITS_PER_UNIT);
+ sweep_string_variable (guard_area, UNITS_PER_GUARD);
+#endif
+ }
+ else if (warn_stack_protector)
+ warning ("not protecting variables: it has a variable length buffer");
+#endif
+#ifndef FRAME_GROWS_DOWNWARD
+ if (STARTING_FRAME_OFFSET == 0)
+ {
+ /* this may be only for alpha */
+ push_allocated_offset = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+ assign_stack_local (BLKmode, push_allocated_offset, -1);
+ sweep_frame_offset = frame_offset;
+ sweep_string_variable (const0_rtx, -push_allocated_offset);
+ sweep_frame_offset = AUTO_OFFSET (XEXP (guard_area, 0));
+ }
+#endif
+
+ /* Arrange the order of local variables */
+ arrange_var_order (blocks);
+
+#ifdef STACK_GROWS_DOWNWARD
+ /* Insert epilogue rtl instructions */
+ rtl_epilogue (get_last_insn ());
+#endif
+ }
+ else if (current_function_defines_short_string
+ && warn_stack_protector)
+ warning ("not protecting function: buffer is less than %d bytes long",
+ SUSPICIOUS_BUF_SIZE);
+}
+
+/*
+ search string from arguments and local variables
+ caller: 0 means call from protector_stack_protection
+ 1 means call from push_frame
+*/
+static int
+search_string_from_argsandvars (caller)
+ int caller;
+{
+ tree blocks, parms;
+ int string_p;
+
+ /* saves a latest search result as a cached infomation */
+ static tree __latest_search_decl = 0;
+ static int __latest_search_result = FALSE;
+
+ if (__latest_search_decl == current_function_decl)
+ return __latest_search_result;
+ else if (caller) return FALSE;
+ __latest_search_decl = current_function_decl;
+ __latest_search_result = TRUE;
+
+ /*
+ search a string variable from local variables
+ */
+ blocks = DECL_INITIAL (current_function_decl);
+ string_p = search_string_from_local_vars (blocks);
+
+ if (!current_function_defines_vsized_array && current_function_calls_alloca)
+ {
+ current_function_has_variable_string = TRUE;
+ return TRUE;
+ }
+
+ if (string_p) return TRUE;
+
+#ifdef STACK_GROWS_DOWNWARD
+ /*
+ search a string variable from arguments
+ */
+ parms = DECL_ARGUMENTS (current_function_decl);
+
+ for (; parms; parms = TREE_CHAIN (parms))
+ if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node)
+ {
+ if (PARM_PASSED_IN_MEMORY (parms) && DECL_NAME (parms))
+ {
+ string_p = search_string_def (TREE_TYPE(parms));
+ if (string_p) return TRUE;
+ }
+ }
+#endif
+
+ __latest_search_result = FALSE;
+ return FALSE;
+}
+
+
+static int
+search_string_from_local_vars (block)
+ tree block;
+{
+ tree types;
+ int found = FALSE;
+
+ while (block)
+ {
+ types = BLOCK_VARS(block);
+
+ while (types)
+ {
+ /* skip the declaration that refers an external variable */
+ /* name: types.decl.name.identifier.id */
+ if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types)
+ && TREE_CODE (types) == VAR_DECL
+ && ! DECL_ARTIFICIAL (types)
+ && DECL_RTL (types)
+ && GET_CODE (DECL_RTL (types)) == MEM)
+ {
+ if (search_string_def (TREE_TYPE (types)))
+ {
+ rtx home = DECL_RTL (types);
+
+ if (GET_CODE (home) == MEM
+ && (GET_CODE (XEXP (home, 0)) == MEM
+ || (GET_CODE (XEXP (home, 0)) == REG
+ && XEXP (home, 0) != virtual_stack_vars_rtx
+ && REGNO (XEXP (home, 0)) != HARD_FRAME_POINTER_REGNUM
+ && REGNO (XEXP (home, 0)) != STACK_POINTER_REGNUM
+#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+ && REGNO (XEXP (home, 0)) != ARG_POINTER_REGNUM
+#endif
+ )))
+ /* If the value is indirect by memory or by a register
+ that isn't the frame pointer
+ then it means the object is variable-sized and address through
+ that register or stack slot. The protection has no way to hide pointer variables
+ behind the array, so all we can do is staying arguments. */
+ {
+ current_function_has_variable_string = TRUE;
+ }
+ /* found character array */
+ found = TRUE;
+ }
+ }
+
+ types = TREE_CHAIN(types);
+ }
+
+ if (search_string_from_local_vars (BLOCK_SUBBLOCKS (block)))
+ {
+ found = TRUE;
+ }
+
+ block = BLOCK_CHAIN (block);
+ }
+
+ return found;
+}
+
+static int
+search_string_def (type)
+ tree type;
+{
+ tree tem;
+
+ /* Mark it as defined, so that if it is self-referent
+ we will not get into an infinite recursion of definitions. */
+
+ switch (TREE_CODE (type))
+ {
+ case ARRAY_TYPE:
+ /* Check if the array is a variable-sized array */
+ if (TYPE_DOMAIN (type) == 0 ||
+ TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == NOP_EXPR)
+ current_function_defines_vsized_array = TRUE;
+
+ if (TREE_TYPE (type) == char_type_node
+ || (TREE_TYPE (type)
+ && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
+ && TYPE_PRECISION (TREE_TYPE (type)) == 8))
+ {
+ /* Check if the string is a variable string */
+ if (TYPE_DOMAIN (type) == 0 ||
+ TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == NOP_EXPR)
+ return TRUE;
+
+ /* Check if the string size is greater than SUSPICIOUS_BUF_SIZE */
+ if (TREE_INT_CST_LOW(TYPE_MAX_VALUE(TYPE_DOMAIN(type)))+1 >= SUSPICIOUS_BUF_SIZE)
+ return TRUE;
+
+ current_function_defines_short_string = TRUE;
+ }
+ return search_string_def(TREE_TYPE(type));
+
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ case RECORD_TYPE:
+ /* Output the name, type, position (in bits), size (in bits) of each
+ field. */
+ for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
+ {
+ /* Omit here local type decls until we know how to support them. */
+ if ((TREE_CODE (tem) == TYPE_DECL)
+ || (TREE_CODE (tem) == VAR_DECL && TREE_STATIC (tem)))
+ continue;
+
+ if (search_string_def(TREE_TYPE(tem))) return TRUE;
+ }
+ break;
+
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ /* I'm not sure whether OFFSET_TYPE needs this treatment,
+ so I'll play safe and return 1. */
+ case OFFSET_TYPE:
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+
+static int
+search_pointer_def (type)
+ tree type;
+{
+ tree tem;
+
+ /* Mark it as defined, so that if it is self-referent
+ we will not get into an infinite recursion of definitions. */
+
+ switch (TREE_CODE (type))
+ {
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ case RECORD_TYPE:
+ /* Output the name, type, position (in bits), size (in bits) of each
+ field. */
+ for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
+ {
+ /* Omit here local type decls until we know how to support them. */
+ if ((TREE_CODE (tem) == TYPE_DECL)
+ || (TREE_CODE (tem) == VAR_DECL && TREE_STATIC (tem)))
+ continue;
+
+ if (search_pointer_def (TREE_TYPE(tem))) return TRUE;
+ }
+ break;
+
+ case ARRAY_TYPE:
+ return search_pointer_def (TREE_TYPE(type));
+
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ /* I'm not sure whether OFFSET_TYPE needs this treatment,
+ so I'll play safe and return 1. */
+ case OFFSET_TYPE:
+ if (TYPE_READONLY (TREE_TYPE (type)))
+ {
+ int funcp = search_func_pointer (TREE_TYPE (type), 1);
+ /* Un-mark the type as having been visited already */
+ search_func_pointer (TREE_TYPE (type), 0);
+ return funcp;
+ }
+ return TRUE;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+
+static int
+search_func_pointer (type, mark)
+ tree type;
+ int mark;
+{
+ tree tem;
+
+ /* Mark it as defined, so that if it is self-referent
+ we will not get into an infinite recursion of definitions. */
+
+ switch (TREE_CODE (type))
+ {
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ case RECORD_TYPE:
+ if (TREE_ASM_WRITTEN (type) != mark)
+ {
+ /* mark the type as having been visited already */
+ TREE_ASM_WRITTEN (type) = mark;
+
+ /* Output the name, type, position (in bits), size (in bits) of
+ each field. */
+ for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
+ {
+ /* Omit here local type decls until we know how to support them. */
+ if (TREE_CODE (tem) == FIELD_DECL
+ && search_func_pointer (TREE_TYPE(tem), mark)) return TRUE;
+ }
+ }
+ break;
+
+ case ARRAY_TYPE:
+ return search_func_pointer (TREE_TYPE(type), mark);
+
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ /* I'm not sure whether OFFSET_TYPE needs this treatment,
+ so I'll play safe and return 1. */
+ case OFFSET_TYPE:
+ return TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+
+static void
+reset_used_flags_for_insns (insn)
+ rtx insn;
+{
+ register int i, j;
+ register enum rtx_code code;
+ register const char *format_ptr;
+
+ for (; insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
+ || GET_CODE (insn) == CALL_INSN)
+ {
+ code = GET_CODE (insn);
+ insn->used = 0;
+ format_ptr = GET_RTX_FORMAT (code);
+
+ for (i = 0; i < GET_RTX_LENGTH (code); i++)
+ {
+ switch (*format_ptr++) {
+ case 'e':
+ reset_used_flags_of_plus (XEXP (insn, i));
+ break;
+
+ case 'E':
+ for (j = 0; j < XVECLEN (insn, i); j++)
+ reset_used_flags_of_plus (XVECEXP (insn, i, j));
+ break;
+ }
+ }
+ }
+}
+
+static void
+reset_used_flags_for_decls (block)
+ tree block;
+{
+ tree types;
+ rtx home;
+
+ while (block)
+ {
+ types = BLOCK_VARS(block);
+
+ while (types)
+ {
+ /* skip the declaration that refers an external variable and
+ also skip an global variable */
+ if (! DECL_EXTERNAL (types))
+ {
+ home = DECL_RTL (types);
+ if (home == 0) goto next;
+
+ if (GET_CODE (home) == MEM
+ && GET_CODE (XEXP (home, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (home, 0), 1)) == CONST_INT)
+ {
+ XEXP (home, 0)->used = 0;
+ }
+ }
+ next:
+ types = TREE_CHAIN(types);
+ }
+
+ reset_used_flags_for_decls (BLOCK_SUBBLOCKS (block));
+
+ block = BLOCK_CHAIN (block);
+ }
+}
+
+/* Clear the USED bits only of type PLUS in X */
+
+static void
+reset_used_flags_of_plus (x)
+ rtx x;
+{
+ register int i, j;
+ register enum rtx_code code;
+ register const char *format_ptr;
+
+ if (x == 0)
+ return;
+
+ code = GET_CODE (x);
+
+ /* These types may be freely shared so we needn't do any resetting
+ for them. */
+
+ switch (code)
+ {
+ case REG:
+ case QUEUED:
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case SYMBOL_REF:
+ case CODE_LABEL:
+ case PC:
+ case CC0:
+ return;
+
+ case INSN:
+ case JUMP_INSN:
+ case CALL_INSN:
+ case NOTE:
+ case LABEL_REF:
+ case BARRIER:
+ /* The chain of insns is not being copied. */
+ return;
+
+ case PLUS:
+ x->used = 0;
+ break;
+
+ case CALL_PLACEHOLDER:
+ reset_used_flags_for_insns (XEXP (x, 0));
+ reset_used_flags_for_insns (XEXP (x, 1));
+ reset_used_flags_for_insns (XEXP (x, 2));
+ break;
+
+ default:
+ break;
+ }
+
+ format_ptr = GET_RTX_FORMAT (code);
+ for (i = 0; i < GET_RTX_LENGTH (code); i++)
+ {
+ switch (*format_ptr++)
+ {
+ case 'e':
+ reset_used_flags_of_plus (XEXP (x, i));
+ break;
+
+ case 'E':
+ for (j = 0; j < XVECLEN (x, i); j++)
+ reset_used_flags_of_plus (XVECEXP (x, i, j));
+ break;
+ }
+ }
+}
+
+
+static void
+rtl_prologue (insn)
+ rtx insn;
+{
+#if defined(INIT_SECTION_ASM_OP) && !defined(INVOKE__main)
+#undef HAS_INIT_SECTION
+#define HAS_INIT_SECTION
+#endif
+ rtx _val;
+
+
+ for (; insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
+ break;
+
+#if !defined (HAS_INIT_SECTION)
+ /* If this function is `main', skip a call to `__main'
+ to run guard instruments after global initializers, etc. */
+ if (DECL_NAME (current_function_decl)
+ && strcmp (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)), "main") == 0
+ && DECL_CONTEXT (current_function_decl) == NULL_TREE)
+ {
+ rtx fbinsn = insn;
+ for (; insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
+ break;
+ if (insn == 0) insn = fbinsn;
+ }
+#endif
+
+ prologue_insert_point = NEXT_INSN (insn); /* mark the next insn of FUNCTION_BEG insn */
+
+ start_sequence ();
+
+ _guard = gen_rtx_MEM (GUARD_m, gen_rtx_SYMBOL_REF (Pmode, "__guard"));
+ _guard = force_reg (GUARD_m, _guard);
+ emit_move_insn ( guard_area, _guard);
+
+ _val = gen_sequence ();
+ end_sequence ();
+
+ emit_insn_before (_val, prologue_insert_point);
+}
+
+static void
+rtl_epilogue (insn)
+ rtx insn;
+{
+ rtx if_false_label;
+ rtx _val;
+ rtx funcname;
+ tree funcstr;
+ rtx return_reg = DECL_RTL (DECL_RESULT (current_function_decl)), return_save;
+ int flag_have_return = FALSE;
+
+ start_sequence ();
+
+#ifdef HAVE_return
+ if (HAVE_return)
+ {
+ rtx insn;
+ return_label = gen_label_rtx ();
+
+ for (insn = prologue_insert_point; insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == JUMP_INSN
+ && GET_CODE (PATTERN (insn)) == RETURN
+ && GET_MODE (PATTERN (insn)) == VOIDmode)
+ {
+ rtx pat = gen_rtx_SET (VOIDmode,
+ pc_rtx,
+ gen_rtx_LABEL_REF (VOIDmode,
+ return_label));
+ PATTERN (insn) = pat;
+ flag_have_return = TRUE;
+ }
+
+
+ emit_label (return_label);
+ }
+#endif
+
+ if (return_reg
+ && ! (current_function_returns_struct
+ || current_function_returns_pcc_struct))
+ {
+ return_save = GET_CODE (return_reg)==REG?
+ gen_reg_rtx (GET_MODE (return_reg)):return_reg;
+
+ if (! replace_return_reg (prologue_insert_point, return_save))
+ emit_move_insn (return_save, return_reg);
+ }
+
+ compare_from_rtx (guard_area, _guard, NE, 0, GUARD_m, 0, 0); /* if (guard_area != _guard) */
+
+ if_false_label = gen_label_rtx (); /* { */
+ emit_jump_insn ( gen_beq(if_false_label));
+
+ /*
+ In the function force_const_mem in varasm.c of egcs-1.1.2-30, there is a
+ failure to assign the guard_area variable to eax register, which destroys
+ the return value of the function.
+
+ The BUG preceding comment is an apropriate processes.
+ When the bug is fixed, removes the comment
+ */
+
+ /* generate string for the current function name */
+ funcstr = build_string (strlen(current_function_name)+1, current_function_name);
+ TREE_TYPE (funcstr) = build_array_type (char_type_node, 0);/* = char_array_type_node;*/
+ funcname = output_constant_def (funcstr);
+
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__stack_smash_handler"),
+ 0, VOIDmode, 2,
+ XEXP (funcname, 0), Pmode, guard_area, GUARD_m);
+
+ /* generate RTL to return from the current function */
+
+ emit_barrier (); /* } */
+ emit_label (if_false_label);
+
+ /* generate RTL to return from the current function */
+ if (return_reg)
+ {
+ if (!current_function_returns_struct && !current_function_returns_pcc_struct)
+ expand_value_return (return_save);
+
+
+ /* If returning a structure, arrange to return the address of the value
+ in a place where debuggers expect to find it.
+
+ If returning a structure PCC style,
+ the caller also depends on this value.
+ And current_function_returns_pcc_struct is not necessarily set. */
+ else
+ {
+ rtx value_address = XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
+ tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
+#ifdef FUNCTION_OUTGOING_VALUE
+ rtx outgoing
+ = FUNCTION_OUTGOING_VALUE (build_pointer_type (type),
+ current_function_decl);
+#else
+ rtx outgoing
+ = FUNCTION_VALUE (build_pointer_type (type),
+ current_function_decl);
+#endif
+
+ /* Mark this as a function return value so integrate will delete the
+ assignment and USE below when inlining this function. */
+ REG_FUNCTION_VALUE_P (outgoing) = 1;
+
+ emit_move_insn (outgoing, value_address);
+ use_variable (outgoing);
+ }
+ }
+
+#ifdef HAVE_return
+ if (HAVE_return && flag_have_return)
+ {
+ emit_jump_insn (gen_return ());
+ emit_barrier ();
+ }
+#endif
+
+ _val = gen_sequence ();
+ end_sequence ();
+
+ emit_insn_after (_val, insn);
+}
+
+
+static void
+arrange_var_order (block)
+ tree block;
+{
+ tree types;
+ HOST_WIDE_INT offset;
+
+ while (block)
+ {
+ types = BLOCK_VARS (block);
+
+ while (types)
+ {
+ /* skip the declaration that refers an external variable */
+ /* name: types.decl.assembler_name.id */
+ if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types)
+ && TREE_CODE (types) == VAR_DECL
+ && ! DECL_ARTIFICIAL (types)
+ && DECL_RTL (types)
+ && GET_CODE (DECL_RTL (types)) == MEM)
+ {
+ if (search_string_def (TREE_TYPE (types)))
+ {
+ rtx home = DECL_RTL (types);
+
+ if (! (GET_CODE (home) == MEM
+ && (GET_CODE (XEXP (home, 0)) == MEM
+ || (GET_CODE (XEXP (home, 0)) == REG
+ && XEXP (home, 0) != virtual_stack_vars_rtx
+ && REGNO (XEXP (home, 0)) != HARD_FRAME_POINTER_REGNUM
+ && REGNO (XEXP (home, 0)) != STACK_POINTER_REGNUM
+#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+ && REGNO (XEXP (home, 0)) != ARG_POINTER_REGNUM
+#endif
+ ))))
+ {
+ /* found a string variable */
+ HOST_WIDE_INT var_size =
+ ((TREE_INT_CST_LOW (DECL_SIZE (types)) + BITS_PER_UNIT - 1)
+ / BITS_PER_UNIT);
+
+ if (GET_MODE (DECL_RTL (types)) == BLKmode)
+ {
+ int alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+ var_size = CEIL_ROUND (var_size, alignment);
+ }
+
+ /* skip the variable if it is top of the region
+ specified by sweep_frame_offset */
+ offset = AUTO_OFFSET (XEXP (DECL_RTL (types), 0));
+ if (offset >= sweep_frame_offset - var_size)
+ sweep_frame_offset -= var_size;
+
+ else
+ sweep_string_variable (DECL_RTL (types), var_size);
+ }
+ }
+ }
+
+ types = TREE_CHAIN(types);
+ }
+
+ arrange_var_order (BLOCK_SUBBLOCKS (block));
+
+ block = BLOCK_CHAIN (block);
+ }
+}
+
+
+static void
+copy_args_for_protection (void)
+{
+ tree parms = DECL_ARGUMENTS (current_function_decl);
+ rtx temp_rtx;
+ int idx;
+
+ parms = DECL_ARGUMENTS (current_function_decl);
+ for (idx = 0; parms; parms = TREE_CHAIN (parms))
+ if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node)
+ {
+ if (PARM_PASSED_IN_MEMORY (parms) && DECL_NAME (parms))
+ {
+ int string_p;
+
+ /*
+ skip arguemnt protection if the last argument is used
+ for the variable argument
+ */
+ /*
+ tree fntype;
+ if (TREE_CHAIN (parms) == 0)
+ {
+ fntype = TREE_TYPE (current_function_decl);
+
+ if ((TYPE_ARG_TYPES (fntype) != 0 &&
+ TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) != void_type_node)
+ || current_function_varargs)
+ continue;
+ }
+ */
+
+ string_p = search_string_def (TREE_TYPE(parms));
+
+ /* check if it is a candidate to move */
+ if (string_p || search_pointer_def (TREE_TYPE (parms)))
+ {
+ int arg_size
+ = ((TREE_INT_CST_LOW (DECL_SIZE (parms)) + BITS_PER_UNIT - 1)
+ / BITS_PER_UNIT);
+
+ start_sequence ();
+
+ if (GET_CODE (DECL_RTL (parms)) == REG)
+ {
+ rtx movinsn;
+ rtx safe = gen_reg_rtx (GET_MODE (DECL_RTL (parms)));
+
+ /* generate codes for copying the content */
+ movinsn = emit_move_insn (safe, DECL_RTL (parms));
+ PATTERN (movinsn)->volatil = 1; /* avoid register elimination in gcse.c (COPY-PROP)*/
+
+ change_arg_use_of_insns (prologue_insert_point, DECL_RTL (parms), safe, 0);
+
+ /* save debugger info */
+ DECL_INCOMING_RTL (parms) = safe;
+ }
+
+ else if (GET_CODE (DECL_RTL (parms)) == MEM
+ && GET_CODE (XEXP (DECL_RTL (parms), 0)) == ADDRESSOF)
+ {
+ rtx movinsn;
+ rtx safe = gen_reg_rtx (GET_MODE (DECL_RTL (parms)));
+
+ /* generate codes for copying the content */
+ movinsn = emit_move_insn (safe, DECL_INCOMING_RTL (parms));
+ PATTERN (movinsn)->volatil = 1; /* avoid register elimination in gcse.c (COPY-PROP)*/
+
+ /* change the addressof information to the newly allocated pseudo register */
+ emit_move_insn (DECL_RTL (parms), safe);
+
+ /* save debugger info */
+ DECL_INCOMING_RTL (parms) = safe;
+ }
+
+ else
+ {
+ /* declare temporary local variable DECL_NAME (parms) for it */
+ temp_rtx
+ = assign_stack_local (DECL_MODE (parms), arg_size,
+ DECL_MODE (parms) == BLKmode ? -1 : 0);
+
+ MEM_IN_STRUCT_P (temp_rtx) = AGGREGATE_TYPE_P (TREE_TYPE (parms));
+ MEM_ALIAS_SET (temp_rtx) = get_alias_set (parms);
+
+ /* generate codes for copying the content */
+ store_expr (parms, temp_rtx, 0);
+
+ /* change the reference for each instructions */
+ move_arg_location (prologue_insert_point, DECL_RTL (parms),
+ temp_rtx, arg_size);
+
+ /* change the location of parms variable */
+ DECL_RTL (parms) = temp_rtx;
+
+ /* change debugger info */
+ DECL_INCOMING_RTL (parms) = temp_rtx;
+ }
+
+ emit_insn_before (gen_sequence (), prologue_insert_point);
+ end_sequence ();
+
+#ifdef FRAME_GROWS_DOWNWARD
+ /* process the string argument */
+ if (string_p && DECL_MODE (parms) == BLKmode)
+ {
+ int alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+ arg_size = CEIL_ROUND (arg_size, alignment);
+
+ /* change the reference for each instructions */
+ sweep_string_variable (DECL_RTL (parms), arg_size);
+ }
+#endif
+ }
+ }
+ }
+}
+
+
+/*
+ sweep a string variable to the local variable addressed by sweep_frame_offset, that is
+ a last position of string variables.
+*/
+static void
+sweep_string_variable (sweep_var, var_size)
+ rtx sweep_var;
+ HOST_WIDE_INT var_size;
+{
+ HOST_WIDE_INT sweep_offset;
+
+ switch (GET_CODE (sweep_var))
+ {
+ case MEM:
+ sweep_offset = AUTO_OFFSET(XEXP (sweep_var, 0));
+ break;
+ case CONST_INT:
+ sweep_offset = INTVAL (sweep_var);
+ break;
+ default:
+ abort ();
+ }
+
+ /* scan all declarations of variables and fix the offset address of
+ the variable based on the frame pointer */
+ sweep_string_in_decls (DECL_INITIAL (current_function_decl), sweep_offset, var_size);
+
+ /* scan all argument variable and fix the offset address based on the frame pointer */
+ sweep_string_in_args (DECL_ARGUMENTS (current_function_decl), sweep_offset, var_size);
+
+ /* For making room for sweep variable, scan all insns and fix the offset address
+ of the variable that is based on frame pointer*/
+ sweep_string_use_of_insns (function_first_insn, sweep_offset, var_size);
+
+
+ /* Clear all the USED bits in operands of all insns and declarations of local vars */
+ reset_used_flags_for_decls (DECL_INITIAL (current_function_decl));
+ reset_used_flags_for_insns (function_first_insn);
+
+ sweep_frame_offset -= var_size;
+}
+
+
+
+/*
+ move an argument to the local variable addressed by frame_offset
+*/
+static void
+move_arg_location (insn, orig, new, var_size)
+ rtx insn, orig, new;
+ HOST_WIDE_INT var_size;
+{
+ /* For making room for sweep variable, scan all insns and fix the offset address
+ of the variable that is based on frame pointer*/
+ change_arg_use_of_insns (insn, orig, new, var_size);
+
+
+ /* Clear all the USED bits in operands of all insns and declarations of local vars */
+ reset_used_flags_for_insns (insn);
+}
+
+
+static void
+sweep_string_in_decls (block, sweep_offset, sweep_size)
+ tree block;
+ HOST_WIDE_INT sweep_offset, sweep_size;
+{
+ tree types;
+ HOST_WIDE_INT offset;
+ rtx home;
+
+ while (block)
+ {
+ types = BLOCK_VARS(block);
+
+ while (types)
+ {
+ /* skip the declaration that refers an external variable and
+ also skip an global variable */
+ if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types)) {
+
+ home = DECL_RTL (types);
+ if (home == 0) goto next;
+
+ /* process for static local variable */
+ if (GET_CODE (home) == MEM
+ && GET_CODE (XEXP (home, 0)) == SYMBOL_REF)
+ goto next;
+
+ if (GET_CODE (home) == MEM
+ && XEXP (home, 0) == virtual_stack_vars_rtx)
+ {
+ offset = 0;
+
+ /* the operand related to the sweep variable */
+ if (sweep_offset <= offset
+ && offset < sweep_offset + sweep_size)
+ {
+ offset = sweep_frame_offset - sweep_size - sweep_offset;
+
+ XEXP (home, 0) = plus_constant (virtual_stack_vars_rtx, offset);
+ XEXP (home, 0)->used = 1;
+ }
+ else if (sweep_offset <= offset
+ && offset < sweep_frame_offset)
+ { /* the rest of variables under sweep_frame_offset, so shift the location */
+ XEXP (home, 0) = plus_constant (virtual_stack_vars_rtx, -sweep_size);
+ XEXP (home, 0)->used = 1;
+ }
+ }
+
+ if (GET_CODE (home) == MEM
+ && GET_CODE (XEXP (home, 0)) == MEM)
+ {
+ /* process for dynamically allocated aray */
+ home = XEXP (home, 0);
+ }
+
+ if (GET_CODE (home) == MEM
+ && GET_CODE (XEXP (home, 0)) == PLUS
+ && XEXP (XEXP (home, 0), 0) == virtual_stack_vars_rtx
+ && GET_CODE (XEXP (XEXP (home, 0), 1)) == CONST_INT)
+ {
+ if (! XEXP (home, 0)->used)
+ {
+ offset = AUTO_OFFSET(XEXP (home, 0));
+
+ /* the operand related to the sweep variable */
+ if (sweep_offset <= offset
+ && offset < sweep_offset + sweep_size)
+ {
+
+ offset += sweep_frame_offset - sweep_size - sweep_offset;
+ XEXP (XEXP (home, 0), 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+
+ /* mark */
+ XEXP (home, 0)->used = 1;
+ }
+ else if (sweep_offset <= offset
+ && offset < sweep_frame_offset)
+ { /* the rest of variables under sweep_frame_offset,
+ so shift the location */
+
+ XEXP (XEXP (home, 0), 1)
+ = gen_rtx_CONST_INT (VOIDmode, offset - sweep_size);
+
+ /* mark */
+ XEXP (home, 0)->used = 1;
+ }
+ }
+ }
+
+ }
+ next:
+ types = TREE_CHAIN(types);
+ }
+
+ sweep_string_in_decls (BLOCK_SUBBLOCKS (block), sweep_offset, sweep_size);
+ block = BLOCK_CHAIN (block);
+ }
+}
+
+
+static void
+sweep_string_in_args (parms, sweep_offset, sweep_size)
+ tree parms;
+ HOST_WIDE_INT sweep_offset, sweep_size;
+{
+ rtx home;
+ HOST_WIDE_INT offset;
+
+ for (; parms; parms = TREE_CHAIN (parms))
+ if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node)
+ {
+ if (PARM_PASSED_IN_MEMORY (parms) && DECL_NAME (parms))
+ {
+ home = DECL_INCOMING_RTL (parms);
+
+ if (XEXP (home, 0)->used) continue;
+
+ offset = AUTO_OFFSET(XEXP (home, 0));
+
+ /* the operand related to the sweep variable */
+ if (AUTO_BASEPTR (XEXP (home, 0)) == virtual_stack_vars_rtx)
+ {
+ if (sweep_offset <= offset
+ && offset < sweep_offset + sweep_size)
+ {
+ offset += sweep_frame_offset - sweep_size - sweep_offset;
+ XEXP (XEXP (home, 0), 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+
+ /* mark */
+ XEXP (home, 0)->used = 1;
+ }
+ else if (sweep_offset <= offset
+ && offset < sweep_frame_offset)
+ { /* the rest of variables under sweep_frame_offset, so shift the location */
+ XEXP (XEXP (home, 0), 1) = gen_rtx_CONST_INT (VOIDmode, offset - sweep_size);
+
+ /* mark */
+ XEXP (home, 0)->used = 1;
+ }
+ }
+ }
+ }
+}
+
+
+static void
+sweep_string_use_of_insns (insn, sweep_offset, sweep_size)
+ rtx insn;
+ HOST_WIDE_INT sweep_offset, sweep_size;
+{
+ for (; insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
+ || GET_CODE (insn) == CALL_INSN)
+ {
+ sweep_string_in_operand (insn, PATTERN (insn), sweep_offset, sweep_size);
+ }
+}
+
+
+static void
+sweep_string_in_operand (insn, orig, sweep_offset, sweep_size)
+ rtx insn, orig;
+ HOST_WIDE_INT sweep_offset, sweep_size;
+{
+ register rtx x = orig;
+ register enum rtx_code code;
+ int i, j;
+ HOST_WIDE_INT offset;
+ const char *fmt;
+
+ if (x == 0)
+ return;
+
+ code = GET_CODE (x);
+
+ switch (code)
+ {
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case CONST:
+ case SYMBOL_REF:
+ case CODE_LABEL:
+ case PC:
+ case CC0:
+ case ASM_INPUT:
+ case ADDR_VEC:
+ case ADDR_DIFF_VEC:
+ case RETURN:
+ case REG:
+ case ADDRESSOF:
+ return;
+
+ case SET:
+ break;
+
+ case PLUS:
+ /* Handle typical case of frame register plus constant. */
+ if (XEXP (x, 0) == virtual_stack_vars_rtx
+ && CONSTANT_P (XEXP (x, 1)))
+ {
+ if (x->used) return;
+
+ offset = AUTO_OFFSET(x);
+
+ /* the operand related to the sweep variable */
+ if (sweep_offset <= offset
+ && offset < sweep_offset + sweep_size)
+ {
+ offset += sweep_frame_offset - sweep_size - sweep_offset;
+
+ XEXP (x, 0) = virtual_stack_vars_rtx;
+ XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+ x->used = 1;
+ }
+ else if (sweep_offset <= offset
+ && offset < sweep_frame_offset)
+ { /* the rest of variables under sweep_frame_offset, so shift the location */
+ XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset - sweep_size);
+ x->used = 1;
+ }
+ return;
+ }
+
+#ifdef FRAME_GROWS_DOWNWARD
+ /*
+ Handle special case of frame register plus constant given by reg.
+ This is happen when the mem is refered by legitimized address.
+
+ CAUTION:
+ This is only used at the case of guard sweep, not arrange_var_order.
+
+ Example:
+ (plus:SI (reg:SI 78) (reg:SI 109))
+ */
+ else if (XEXP (x, 0) == virtual_stack_vars_rtx
+ && GET_CODE (XEXP (x, 1)) == REG)
+ {
+ rtx temp, *loc, seq;
+
+ temp = plus_constant (virtual_stack_vars_rtx, -sweep_size);
+ temp->used = 1;
+
+ loc = &XEXP (x, 0);
+ if (! validate_change (insn, loc, temp, 0)) {
+ start_sequence ();
+ temp = force_operand (temp, NULL_RTX);
+ seq = get_insns ();
+ end_sequence ();
+
+ emit_insns_before (seq, insn);
+ if (! validate_change (insn, loc, temp, 0)
+ && ! validate_replace_rtx (XEXP (x, 0), temp, insn))
+ *loc = temp; /* abort (); */
+ }
+ return;
+ }
+#endif
+
+ /*
+ process further subtree:
+ Example: (plus:SI (mem/s:SI (plus:SI (reg:SI 17) (const_int 8)))
+ (const_int 5))
+ */
+ break;
+
+ case CALL_PLACEHOLDER:
+ sweep_string_use_of_insns (XEXP (x, 0), sweep_offset, sweep_size);
+ sweep_string_use_of_insns (XEXP (x, 1), sweep_offset, sweep_size);
+ sweep_string_use_of_insns (XEXP (x, 2), sweep_offset, sweep_size);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Scan all subexpressions. */
+ fmt = GET_RTX_FORMAT (code);
+ for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+ if (*fmt == 'e')
+ {
+ /*
+ virtual_stack_vars_rtx without offset
+ Example:
+ (set (reg:SI xx) (reg:SI 78))
+ (set (reg:SI xx) (MEM (reg:SI 78)))
+ */
+ if (XEXP (x, i) == virtual_stack_vars_rtx)
+ {
+ rtx temp = 0, *loc, seq;
+ offset = 0;
+
+ /* the operand related to the sweep variable */
+ if (sweep_offset <= offset
+ && offset < sweep_offset + sweep_size)
+ {
+ offset = sweep_frame_offset - sweep_size - sweep_offset;
+
+ temp = plus_constant (virtual_stack_vars_rtx, offset);
+ temp->used = 1;
+ }
+ else if (sweep_offset <= offset
+ && offset < sweep_frame_offset)
+ { /* the rest of variables under sweep_frame_offset, so shift the location */
+ temp = plus_constant (virtual_stack_vars_rtx, -sweep_size);
+ temp->used = 1;
+ }
+
+ if (temp) {
+ loc = &XEXP (x, i);
+ if (! validate_change (insn, loc, temp, 0)) {
+ start_sequence ();
+ temp = force_operand (temp, NULL_RTX);
+ seq = get_insns ();
+ end_sequence ();
+
+ emit_insns_before (seq, insn);
+ if (! validate_change (insn, loc, temp, 0)
+ && ! validate_replace_rtx (XEXP (x, i), temp, insn))
+ *loc = temp; /* abort (); */
+ }
+ }
+ return;
+ }
+
+ sweep_string_in_operand (insn, XEXP (x, i), sweep_offset, sweep_size);
+ }
+ else if (*fmt == 'E')
+ for (j = 0; j < XVECLEN (x, i); j++)
+ sweep_string_in_operand (insn, XVECEXP (x, i, j), sweep_offset, sweep_size);
+}
+
+
+/*
+ change a argument variable to the local variable addressed by the "new" variable.
+*/
+static void
+change_arg_use_of_insns (insn, orig, new, size)
+ rtx insn, orig, new;
+ HOST_WIDE_INT size;
+{
+ for (; insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
+ || GET_CODE (insn) == CALL_INSN)
+ {
+ change_arg_use_in_operand (PATTERN (insn), orig, new, size);
+ }
+}
+
+
+static void
+change_arg_use_in_operand (x, orig, new, size)
+ rtx x, orig, new;
+ HOST_WIDE_INT size;
+{
+ register enum rtx_code code;
+ int i, j;
+ HOST_WIDE_INT offset;
+ const char *fmt;
+
+ if (x == 0)
+ return;
+
+ code = GET_CODE (x);
+
+ switch (code)
+ {
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case CONST:
+ case SYMBOL_REF:
+ case CODE_LABEL:
+ case PC:
+ case CC0:
+ case ASM_INPUT:
+ case ADDR_VEC:
+ case ADDR_DIFF_VEC:
+ case RETURN:
+ case REG:
+ case ADDRESSOF:
+ return;
+
+ case PLUS:
+ /* Handle special case of frame register plus constant. */
+ if (GET_CODE (orig) == MEM /* skip if orig is register variable in the optimization */
+ && XEXP (x, 0) == virtual_incoming_args_rtx && CONSTANT_P (XEXP (x, 1))
+ && ! x->used)
+ {
+ offset = AUTO_OFFSET(x);
+
+ /* the operand related to the sweep variable */
+ if (AUTO_OFFSET(XEXP (orig, 0)) <= offset &&
+ offset < AUTO_OFFSET(XEXP (orig, 0)) + size) {
+
+ offset = AUTO_OFFSET(XEXP (new, 0))
+ + (offset - AUTO_OFFSET(XEXP (orig, 0)));
+
+ XEXP (x, 0) = virtual_stack_vars_rtx;
+ XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+ x->used = 1;
+
+ return;
+ }
+
+ /*
+ process further subtree:
+ Example: (plus:SI (mem/s:SI (plus:SI (reg:SI 17) (const_int 8)))
+ (const_int 5))
+ */
+ }
+ break;
+
+ case CALL_PLACEHOLDER:
+ change_arg_use_of_insns (XEXP (x, 0), orig, new, size);
+ change_arg_use_of_insns (XEXP (x, 1), orig, new, size);
+ change_arg_use_of_insns (XEXP (x, 2), orig, new, size);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Scan all subexpressions. */
+ fmt = GET_RTX_FORMAT (code);
+ for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+ if (*fmt == 'e')
+ {
+ if (XEXP (x, i) == orig)
+ {
+ XEXP (x, i) = new;
+ continue;
+ }
+ change_arg_use_in_operand (XEXP (x, i), orig, new, size);
+ }
+ else if (*fmt == 'E')
+ for (j = 0; j < XVECLEN (x, i); j++)
+ {
+
+ if (XVECEXP (x, i, j) == orig)
+ {
+ XVECEXP (x, i, j) = new;
+ continue;
+ }
+ change_arg_use_in_operand (XVECEXP (x, i, j), orig, new, size);
+ }
+}
+
+static int
+replace_return_reg (first, return_save)
+ rtx first, return_save;
+{
+ rtx return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
+ rtx insn;
+
+ /* comfirm that insn patterns are the expected order */
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ {
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ {
+
+ rtx prev;
+
+ if (PREV_INSN (insn)) prev = PREV_INSN (insn);
+
+ if (GET_CODE (PATTERN (insn)) == USE && XEXP (PATTERN (insn), 0) == return_reg)
+ if (!(prev && GET_CODE (PATTERN (prev)) == SET && XEXP (PATTERN (prev), 0) == return_reg))
+ return FALSE;
+ }
+ }
+
+ /* replace return register */
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ {
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ {
+ rtx prev;
+
+ if (PREV_INSN (insn)) prev = PREV_INSN (insn);
+ if (GET_CODE (PATTERN (insn)) == USE
+ && XEXP (PATTERN (insn), 0) == return_reg
+ && prev
+ && GET_CODE (PATTERN (prev)) == SET
+ && XEXP (PATTERN (prev), 0) == return_reg)
+ {
+ XEXP (PATTERN (prev), 0) = return_save;
+
+ /* change use insn to NOTE_INSN_DELETED */
+ PUT_CODE (insn, NOTE);
+ NOTE_SOURCE_FILE (insn) = 0;
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*
+ Generate RTL to return from the current function, with value VAL.
+ It is copied and modified based on expand_value_return function of stmt.c
+*/
+
+static void
+expand_value_return (val)
+ rtx val;
+{
+ rtx return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
+
+ /* Copy the value to the return location
+ unless it's already there. */
+
+ if (return_reg != val)
+ {
+#ifdef PROMOTE_FUNCTION_RETURN
+ tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
+ int unsignedp = TREE_UNSIGNED (type);
+ enum machine_mode mode
+ = promote_mode (type, DECL_MODE (DECL_RESULT (current_function_decl)),
+ &unsignedp, 1);
+
+ if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode)
+ convert_move (return_reg, val, unsignedp);
+ else
+#endif
+ emit_move_insn (return_reg, val);
+ }
+ if (GET_CODE (return_reg) == REG
+ && REGNO (return_reg) < FIRST_PSEUDO_REGISTER)
+ emit_insn (gen_rtx_USE (VOIDmode, return_reg));
+ /* Handle calls that return values in multiple non-contiguous locations.
+ The Irix 6 ABI has examples of this. */
+ else if (GET_CODE (return_reg) == PARALLEL)
+ {
+ int i;
+
+ for (i = 0; i < XVECLEN (return_reg, 0); i++)
+ {
+ rtx x = XEXP (XVECEXP (return_reg, 0, i), 0);
+
+ if (GET_CODE (x) == REG
+ && REGNO (x) < FIRST_PSEUDO_REGISTER)
+ emit_insn (gen_rtx_USE (VOIDmode, x));
+ }
+ }
+}
+
+
+static void
+propagate_virtual_stack_vars_in_insns (insn)
+ rtx insn;
+{
+ for (; insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
+ || GET_CODE (insn) == CALL_INSN)
+ {
+ propagate_virtual_stack_vars_in_operand (insn, PATTERN (insn));
+ }
+}
+
+
+static void
+propagate_virtual_stack_vars_in_operand (insn, orig)
+ rtx insn, orig;
+{
+ register rtx x = orig;
+ register enum rtx_code code;
+ int i, j;
+ const char *fmt;
+
+ if (x == 0)
+ return;
+
+ code = GET_CODE (x);
+
+ switch (code)
+ {
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case CONST:
+ case SYMBOL_REF:
+ case CODE_LABEL:
+ case PC:
+ case CC0:
+ case ASM_INPUT:
+ case ADDR_VEC:
+ case ADDR_DIFF_VEC:
+ case RETURN:
+ case REG:
+ case ADDRESSOF:
+ return;
+
+ case SET:
+ if (RTX_INTEGRATED_P (insn)
+ && (GET_CODE (SET_SRC (x)) == REG && GET_CODE (SET_DEST (x)) == REG)
+ && VIRTUAL_STACK_VARS_P (SET_SRC (x)))
+ {
+ SET_DEST (x)->used = 1; debug_rtx (insn);
+ return;
+ }
+ break;
+
+ case PLUS:
+ /* Handle typical case of frame register plus constant. */
+ if (VIRTUAL_STACK_VARS_P (XEXP (x, 0))
+ && (CONSTANT_P (XEXP (x, 1))
+ || GET_CODE (XEXP (x, 1)) == REG))
+ {
+ XEXP (x, 0) = virtual_stack_vars_rtx;
+ return;
+ }
+
+ /*
+ process further subtree:
+ Example: (plus:SI (mem/s:SI (plus:SI (reg:SI 17) (const_int 8)))
+ (const_int 5))
+ */
+ break;
+
+ case CALL_PLACEHOLDER:
+ propagate_virtual_stack_vars_in_insns (XEXP (x, 0));
+ propagate_virtual_stack_vars_in_insns (XEXP (x, 1));
+ propagate_virtual_stack_vars_in_insns (XEXP (x, 2));
+ break;
+
+ default:
+ break;
+ }
+
+ /* Scan all subexpressions. */
+ fmt = GET_RTX_FORMAT (code);
+ for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+ if (*fmt == 'e')
+ propagate_virtual_stack_vars_in_operand (insn, XEXP (x, i));
+ else if (*fmt == 'E')
+ for (j = 0; j < XVECLEN (x, i); j++)
+ propagate_virtual_stack_vars_in_operand (insn, XVECEXP (x, i, j));
+}
+
+
+
+
+/*
+ The following codes are invoked after the instantiation of pseuso registers.
+
+ Reorder local variables to place a peudo register after buffers to avoid
+ the corruption of local variables that could be used to further corrupt
+ arbitrary memory locations.
+*/
+#ifndef FRAME_GROWS_DOWNWARD
+static void push_frame PARAMS ((HOST_WIDE_INT var_size, HOST_WIDE_INT boundary));
+static void push_frame_in_decls PARAMS ((tree block, HOST_WIDE_INT push_size, HOST_WIDE_INT boundary));
+static void push_frame_in_args PARAMS ((tree parms, HOST_WIDE_INT push_size, HOST_WIDE_INT boundary));
+static void push_frame_of_insns PARAMS ((rtx insn, HOST_WIDE_INT push_size, HOST_WIDE_INT boundary));
+static void push_frame_in_operand PARAMS ((rtx orig, HOST_WIDE_INT push_size, HOST_WIDE_INT boundary));
+static void push_frame_of_reg_equiv_memory_loc PARAMS ((HOST_WIDE_INT push_size, HOST_WIDE_INT boundary));
+static void push_frame_of_reg_equiv_constant PARAMS ((HOST_WIDE_INT push_size, HOST_WIDE_INT boundary));
+static void reset_used_flags_for_push_frame PARAMS ((void));
+static int check_out_of_frame_access PARAMS ((rtx insn, HOST_WIDE_INT boundary));
+static int check_out_of_frame_access_in_operand PARAMS ((rtx, HOST_WIDE_INT boundary));
+#endif
+
+rtx
+assign_stack_local_for_pseudo_reg (mode, size, align)
+ enum machine_mode mode;
+ HOST_WIDE_INT size;
+ int align;
+{
+#ifdef FRAME_GROWS_DOWNWARD
+ return assign_stack_local (mode, size, align);
+#else
+ tree blocks = DECL_INITIAL (current_function_decl);
+ rtx new;
+ HOST_WIDE_INT saved_frame_offset, units_per_push;
+
+ if (! flag_propolice_protection
+ || size == 0
+ || ! blocks || TREE_CODE (blocks) != BLOCK
+ || DECL_INLINE (current_function_decl)
+ || ! search_string_from_argsandvars (1)
+ || current_function_contains_functions)
+ return assign_stack_local (mode, size, align);
+
+ optimize_size = 1; /* solve for ssp-ppc-20021125 */
+ units_per_push = MAX(BIGGEST_ALIGNMENT / BITS_PER_UNIT,
+ GET_MODE_SIZE (mode));
+
+ if (push_frame_offset == 0
+ && check_out_of_frame_access (get_insns (), STARTING_FRAME_OFFSET))
+ {
+ /* if there is an access beyond frame, push dummy region to seperate
+ the address of instantiated variables */
+ push_frame (GET_MODE_SIZE (DImode), 0);
+ assign_stack_local (BLKmode, GET_MODE_SIZE (DImode), -1);
+ }
+
+ saved_frame_offset = frame_offset;
+ frame_offset = push_frame_offset;
+
+ new = assign_stack_local (mode, size, align);
+
+ push_frame_offset = frame_offset;
+ frame_offset = saved_frame_offset;
+
+ if (push_frame_offset > push_allocated_offset) {
+ push_frame (units_per_push, AUTO_OFFSET(XEXP (new, 0)));
+
+ assign_stack_local (BLKmode, units_per_push, -1);
+ push_allocated_offset += units_per_push;
+ }
+
+ return new;
+#endif
+}
+
+
+#ifndef FRAME_GROWS_DOWNWARD
+/*
+ push frame infomation for instantiating pseudo register at the top of stack.
+ This is only for the "frame grows upward", it means FRAME_GROWS_DOWNWARD is
+ not defined.
+
+ It is called by purge_addressof function and global_alloc (or reload)
+ function.
+*/
+static void
+push_frame (var_size, boundary)
+ HOST_WIDE_INT var_size, boundary;
+{
+ reset_used_flags_for_push_frame();
+
+ /* scan all declarations of variables and fix the offset address of the variable based on the frame pointer */
+ push_frame_in_decls (DECL_INITIAL (current_function_decl), var_size, boundary);
+
+ /* scan all argument variable and fix the offset address based on the frame pointer */
+ push_frame_in_args (DECL_ARGUMENTS (current_function_decl), var_size, boundary);
+
+ /* scan all operands of all insns and fix the offset address based on the frame pointer */
+ push_frame_of_insns (get_insns (), var_size, boundary);
+
+ /* scan all reg_equiv_memory_loc and reg_equiv_constant*/
+ push_frame_of_reg_equiv_memory_loc (var_size, boundary);
+ push_frame_of_reg_equiv_constant (var_size, boundary);
+
+ reset_used_flags_for_push_frame();
+}
+
+static void
+reset_used_flags_for_push_frame()
+{
+ int i;
+ extern rtx *reg_equiv_memory_loc;
+ extern rtx *reg_equiv_constant;
+
+ /* Clear all the USED bits in operands of all insns and declarations of local vars */
+ reset_used_flags_for_decls (DECL_INITIAL (current_function_decl));
+ reset_used_flags_for_insns (get_insns ());
+
+
+ /* The following codes are processed if the push_frame is called from
+ global_alloc (or reload) function */
+ if (reg_equiv_memory_loc == 0) return;
+
+ for (i=LAST_VIRTUAL_REGISTER+1; i < max_regno; i++)
+ if (reg_equiv_memory_loc[i])
+ {
+ rtx x = reg_equiv_memory_loc[i];
+
+ if (GET_CODE (x) == MEM
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && AUTO_BASEPTR (XEXP (x, 0)) == frame_pointer_rtx)
+ {
+ /* reset */
+ XEXP (x, 0)->used = 0;
+ }
+ }
+
+
+ if (reg_equiv_constant == 0) return;
+
+ for (i=LAST_VIRTUAL_REGISTER+1; i < max_regno; i++)
+ if (reg_equiv_constant[i])
+ {
+ rtx x = reg_equiv_constant[i];
+
+ if (GET_CODE (x) == PLUS
+ && AUTO_BASEPTR (x) == frame_pointer_rtx)
+ {
+ /* reset */
+ x->used = 0;
+ }
+ }
+}
+
+static void
+push_frame_in_decls (block, push_size, boundary)
+ tree block;
+ HOST_WIDE_INT push_size, boundary;
+{
+ tree types;
+ HOST_WIDE_INT offset;
+ rtx home;
+
+ while (block)
+ {
+ types = BLOCK_VARS(block);
+
+ while (types)
+ {
+ /* skip the declaration that refers an external variable and
+ also skip an global variable */
+ if (! DECL_EXTERNAL (types) && ! TREE_STATIC (types))
+ {
+
+ home = DECL_RTL (types);
+ if (home == 0) goto next;
+
+ /* process for static local variable */
+ if (GET_CODE (home) == MEM
+ && GET_CODE (XEXP (home, 0)) == SYMBOL_REF)
+ goto next;
+
+ if (GET_CODE (home) == MEM
+ && GET_CODE (XEXP (home, 0)) == REG)
+ {
+ if (XEXP (home, 0) != frame_pointer_rtx
+ || boundary != 0)
+ goto next;
+
+ XEXP (home, 0) = plus_constant (frame_pointer_rtx,
+ push_size);
+
+ /* mark */
+ XEXP (home, 0)->used = 1;
+ }
+
+ if (GET_CODE (home) == MEM
+ && GET_CODE (XEXP (home, 0)) == MEM)
+ {
+
+ /* process for dynamically allocated aray */
+ home = XEXP (home, 0);
+ }
+
+ if (GET_CODE (home) == MEM
+ && GET_CODE (XEXP (home, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (home, 0), 1)) == CONST_INT)
+ {
+ offset = AUTO_OFFSET(XEXP (home, 0));
+
+ if (! XEXP (home, 0)->used
+ && offset >= boundary)
+ {
+ offset += push_size;
+ XEXP (XEXP (home, 0), 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+
+ /* mark */
+ XEXP (home, 0)->used = 1;
+ }
+ }
+
+ }
+ next:
+ types = TREE_CHAIN(types);
+ }
+
+ push_frame_in_decls (BLOCK_SUBBLOCKS (block), push_size, boundary);
+ block = BLOCK_CHAIN (block);
+ }
+}
+
+
+static void
+push_frame_in_args (parms, push_size, boundary)
+ tree parms;
+ HOST_WIDE_INT push_size, boundary;
+{
+ rtx home;
+ HOST_WIDE_INT offset;
+
+ for (; parms; parms = TREE_CHAIN (parms))
+ if (DECL_NAME (parms) && TREE_TYPE (parms) != error_mark_node)
+ {
+ if (PARM_PASSED_IN_MEMORY (parms) && DECL_NAME (parms))
+ {
+ home = DECL_INCOMING_RTL (parms);
+ offset = AUTO_OFFSET(XEXP (home, 0));
+
+ if (XEXP (home, 0)->used || offset < boundary) continue;
+
+ /* the operand related to the sweep variable */
+ if (AUTO_BASEPTR (XEXP (home, 0)) == frame_pointer_rtx)
+ {
+ offset += push_size;
+ XEXP (XEXP (home, 0), 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+
+ /* mark */
+ XEXP (home, 0)->used = 1;
+ }
+ }
+ }
+}
+
+
+static void
+push_frame_of_insns (insn, push_size, boundary)
+ rtx insn;
+ HOST_WIDE_INT push_size, boundary;
+{
+ for (; insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
+ || GET_CODE (insn) == CALL_INSN)
+ {
+ debuginsn = insn;
+ push_frame_in_operand (PATTERN (insn), push_size, boundary);
+
+ /* push frame in NOTE */
+ push_frame_in_operand (REG_NOTES (insn), push_size, boundary);
+
+ /* push frame in CALL EXPR_LIST */
+ if (GET_CODE (insn) == CALL_INSN)
+ push_frame_in_operand (CALL_INSN_FUNCTION_USAGE (insn), push_size, boundary);
+ }
+}
+
+
+static void
+push_frame_in_operand (orig, push_size, boundary)
+ rtx orig;
+ HOST_WIDE_INT push_size, boundary;
+{
+ register rtx x = orig;
+ register enum rtx_code code;
+ int i, j;
+ HOST_WIDE_INT offset;
+ const char *fmt;
+
+ if (x == 0)
+ return;
+
+ code = GET_CODE (x);
+
+ switch (code)
+ {
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case CONST:
+ case SYMBOL_REF:
+ case CODE_LABEL:
+ case PC:
+ case CC0:
+ case ASM_INPUT:
+ case ADDR_VEC:
+ case ADDR_DIFF_VEC:
+ case RETURN:
+ case REG:
+ case ADDRESSOF:
+ return;
+
+ case SET:
+ break;
+
+ case MEM:
+ if (XEXP (x, 0) == frame_pointer_rtx
+ && boundary == 0)
+ {
+ XEXP (x, 0) = plus_constant (frame_pointer_rtx, push_size);
+ XEXP (x, 0)->used = 1;
+ return;
+ }
+ break;
+
+ case PLUS:
+ offset = AUTO_OFFSET(x);
+
+ /* Handle special case of frame register plus constant. */
+ if (CONSTANT_P (XEXP (x, 1))
+ && XEXP (x, 0) == frame_pointer_rtx)
+ {
+ if (x->used || abs (offset) < boundary)
+ return;
+
+ if (offset > 0)
+ offset += push_size;
+ else
+ offset -= push_size;
+
+ /* XEXP (x, 0) is frame_pointer_rtx */
+ XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+ x->used = 1;
+
+ return;
+ }
+ /*
+ process further subtree:
+ Example: (plus:SI (mem/s:SI (plus:SI (reg:SI 17) (const_int 8)))
+ (const_int 5))
+ */
+ break;
+
+ case CALL_PLACEHOLDER:
+ push_frame_of_insns (XEXP (x, 0), push_size, boundary);
+ push_frame_of_insns (XEXP (x, 1), push_size, boundary);
+ push_frame_of_insns (XEXP (x, 2), push_size, boundary);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Scan all subexpressions. */
+ fmt = GET_RTX_FORMAT (code);
+ for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+ if (*fmt == 'e')
+ {
+ if (XEXP (x, i) == frame_pointer_rtx && boundary == 0)
+ fatal_insn ("push_frame_in_operand", debuginsn);
+ push_frame_in_operand (XEXP (x, i), push_size, boundary);
+ }
+ else if (*fmt == 'E')
+ for (j = 0; j < XVECLEN (x, i); j++)
+ push_frame_in_operand (XVECEXP (x, i, j), push_size, boundary);
+}
+
+static void
+push_frame_of_reg_equiv_memory_loc (push_size, boundary)
+ HOST_WIDE_INT push_size, boundary;
+{
+ int i;
+ extern rtx *reg_equiv_memory_loc;
+
+ /* This function is processed if the push_frame is called from
+ global_alloc (or reload) function */
+ if (reg_equiv_memory_loc == 0) return;
+
+ for (i=LAST_VIRTUAL_REGISTER+1; i < max_regno; i++)
+ if (reg_equiv_memory_loc[i])
+ {
+ rtx x = reg_equiv_memory_loc[i];
+ int offset;
+
+ if (GET_CODE (x) == MEM
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && XEXP (XEXP (x, 0), 0) == frame_pointer_rtx)
+ {
+ offset = AUTO_OFFSET(XEXP (x, 0));
+
+ if (! XEXP (x, 0)->used
+ && offset >= boundary)
+ {
+ offset += push_size;
+ XEXP (XEXP (x, 0), 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+
+ /* mark */
+ XEXP (x, 0)->used = 1;
+ }
+ }
+ }
+}
+
+static void
+push_frame_of_reg_equiv_constant (push_size, boundary)
+ HOST_WIDE_INT push_size, boundary;
+{
+ int i;
+ extern rtx *reg_equiv_constant;
+
+ /* This function is processed if the push_frame is called from
+ global_alloc (or reload) function */
+ if (reg_equiv_constant == 0) return;
+
+ for (i=LAST_VIRTUAL_REGISTER+1; i < max_regno; i++)
+ if (reg_equiv_constant[i])
+ {
+ rtx x = reg_equiv_constant[i];
+ int offset;
+
+ if (GET_CODE (x) == PLUS
+ && XEXP (x, 0) == frame_pointer_rtx)
+ {
+ offset = AUTO_OFFSET(x);
+
+ if (! x->used
+ && offset >= boundary)
+ {
+ offset += push_size;
+ XEXP (x, 1) = gen_rtx_CONST_INT (VOIDmode, offset);
+
+ /* mark */
+ x->used = 1;
+ }
+ }
+ }
+}
+
+static int
+check_out_of_frame_access (insn, boundary)
+ rtx insn;
+ HOST_WIDE_INT boundary;
+{
+ for (; insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
+ || GET_CODE (insn) == CALL_INSN)
+ {
+ if (check_out_of_frame_access_in_operand (PATTERN (insn), boundary))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+static int
+check_out_of_frame_access_in_operand (orig, boundary)
+ rtx orig;
+ HOST_WIDE_INT boundary;
+{
+ register rtx x = orig;
+ register enum rtx_code code;
+ int i, j;
+ const char *fmt;
+
+ if (x == 0)
+ return FALSE;
+
+ code = GET_CODE (x);
+
+ switch (code)
+ {
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case CONST:
+ case SYMBOL_REF:
+ case CODE_LABEL:
+ case PC:
+ case CC0:
+ case ASM_INPUT:
+ case ADDR_VEC:
+ case ADDR_DIFF_VEC:
+ case RETURN:
+ case REG:
+ case ADDRESSOF:
+ return FALSE;
+
+ case MEM:
+ if (XEXP (x, 0) == frame_pointer_rtx)
+ if (0 < boundary) return TRUE;
+ break;
+
+ case PLUS:
+ /* Handle special case of frame register plus constant. */
+ if (CONSTANT_P (XEXP (x, 1))
+ && XEXP (x, 0) == frame_pointer_rtx)
+ {
+ if (0 <= AUTO_OFFSET(x)
+ && AUTO_OFFSET(x) < boundary) return TRUE;
+ return FALSE;
+ }
+ /*
+ process further subtree:
+ Example: (plus:SI (mem/s:SI (plus:SI (reg:SI 17) (const_int 8)))
+ (const_int 5))
+ */
+ break;
+
+ case CALL_PLACEHOLDER:
+ if (check_out_of_frame_access (XEXP (x, 0), boundary)) return TRUE;
+ if (check_out_of_frame_access (XEXP (x, 1), boundary)) return TRUE;
+ if (check_out_of_frame_access (XEXP (x, 2), boundary)) return TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Scan all subexpressions. */
+ fmt = GET_RTX_FORMAT (code);
+ for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+ if (*fmt == 'e')
+ {
+ if (check_out_of_frame_access_in_operand (XEXP (x, i), boundary))
+ return TRUE;
+ }
+ else if (*fmt == 'E')
+ for (j = 0; j < XVECLEN (x, i); j++)
+ if (check_out_of_frame_access_in_operand (XVECEXP (x, i, j), boundary))
+ return TRUE;
+
+ return FALSE;
+}
+#endif
diff --git a/gnu/egcs/gcc/protector.h b/gnu/egcs/gcc/protector.h
new file mode 100644
index 00000000000..8e7061a955f
--- /dev/null
+++ b/gnu/egcs/gcc/protector.h
@@ -0,0 +1,38 @@
+/* Top level of GNU C compiler
+ Copyright (C) 1987, 88, 89, 92-7, 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+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.
+
+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.
+
+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. */
+
+
+/* declaration of GUARD variable */
+#define GUARD_m Pmode
+#define UNITS_PER_GUARD MAX(BIGGEST_ALIGNMENT / BITS_PER_UNIT, GET_MODE_SIZE (GUARD_m))
+
+#ifndef L_stack_smash_handler
+
+/* insert a guard variable before a character buffer and change the order
+ of pointer variables, character buffers and pointer arguments */
+
+extern void prepare_stack_protection PARAMS ((void));
+
+/* allocate a local variable in the stack area before character buffers
+ to avoid the corruption of it */
+
+extern rtx assign_stack_local_for_pseudo_reg PARAMS ((enum machine_mode, HOST_WIDE_INT, int));
+
+#endif
diff --git a/gnu/egcs/gcc/reload1.c b/gnu/egcs/gcc/reload1.c
index f16ed109875..ac64db8eaf4 100644
--- a/gnu/egcs/gcc/reload1.c
+++ b/gnu/egcs/gcc/reload1.c
@@ -1,5 +1,6 @@
/* Reload pseudo regs into hard regs for insns that require hard regs.
- Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -38,6 +39,7 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "real.h"
#include "toplev.h"
+#include "protector.h"
#if !defined PREFERRED_STACK_BOUNDARY && defined STACK_BOUNDARY
#define PREFERRED_STACK_BOUNDARY STACK_BOUNDARY
@@ -420,9 +422,13 @@ static void clear_reload_reg_in_use PROTO((int, int, enum reload_type,
enum machine_mode));
static int reload_reg_free_p PROTO((int, int, enum reload_type));
static int reload_reg_free_for_value_p PROTO((int, int, enum reload_type, rtx, rtx, int, int));
+static int free_for_value_p PROTO((int, enum machine_mode, int,
+ enum reload_type, rtx, rtx,
+ int, int));
static int reload_reg_reaches_end_p PROTO((int, int, enum reload_type));
static int allocate_reload_reg PROTO((struct insn_chain *, int, int,
int));
+static int conflicts_with_override PROTO((rtx));
static void choose_reload_regs PROTO((struct insn_chain *));
static void merge_assigned_reloads PROTO((rtx));
static void emit_reload_insns PROTO((struct insn_chain *));
@@ -2419,7 +2425,7 @@ alter_reg (i, from_reg)
if (from_reg == -1)
{
/* No known place to spill from => no slot to reuse. */
- x = assign_stack_local (GET_MODE (regno_reg_rtx[i]), total_size,
+ x = assign_stack_local_for_pseudo_reg (GET_MODE (regno_reg_rtx[i]), total_size,
inherent_size == total_size ? 0 : -1);
if (BYTES_BIG_ENDIAN)
/* Cancel the big-endian correction done in assign_stack_local.
@@ -4518,7 +4524,10 @@ forget_old_reloads_1 (x, ignored)
reload reg in the current instruction. */
if (n_reloads == 0
|| ! TEST_HARD_REG_BIT (reg_is_output_reload, regno + i))
- CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i);
+ {
+ CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i);
+ spill_reg_store[regno + i] = 0;
+ }
}
/* Since value of X has changed,
@@ -4577,6 +4586,8 @@ reload_reg_class_lower (r1p, r2p)
/* The following HARD_REG_SETs indicate when each hard register is
used for a reload of various parts of the current insn. */
+/* If reg is unavailable for all reloads. */
+static HARD_REG_SET reload_reg_unavailable;
/* If reg is in use as a reload reg for a RELOAD_OTHER reload. */
static HARD_REG_SET reload_reg_used;
/* If reg is in use for a RELOAD_FOR_INPUT_ADDRESS reload for operand I. */
@@ -4799,8 +4810,8 @@ reload_reg_free_p (regno, opnum, type)
{
int i;
- /* In use for a RELOAD_OTHER means it's not available for anything. */
- if (TEST_HARD_REG_BIT (reload_reg_used, regno))
+ if (TEST_HARD_REG_BIT (reload_reg_used, regno)
+ || TEST_HARD_REG_BIT (reload_reg_unavailable, regno))
return 0;
switch (type)
@@ -5133,7 +5144,7 @@ reloads_conflict (r1, r2)
return (r2_type == RELOAD_FOR_INSN || r2_type == RELOAD_FOR_OUTPUT
|| ((r2_type == RELOAD_FOR_OUTPUT_ADDRESS
|| r2_type == RELOAD_FOR_OUTADDR_ADDRESS)
- && r2_opnum >= r1_opnum));
+ && r2_opnum <= r1_opnum));
case RELOAD_FOR_INSN:
return (r2_type == RELOAD_FOR_INPUT || r2_type == RELOAD_FOR_OUTPUT
@@ -5171,25 +5182,8 @@ rtx reload_override_in[MAX_RELOADS];
or -1 if we did not need a register for this reload. */
int reload_spill_index[MAX_RELOADS];
-/* Return 1 if the value in reload reg REGNO, as used by a reload
- needed for the part of the insn specified by OPNUM and TYPE,
- may be used to load VALUE into it.
-
- Other read-only reloads with the same value do not conflict
- unless OUT is non-zero and these other reloads have to live while
- output reloads live.
- If OUT is CONST0_RTX, this is a special case: it means that the
- test should not be for using register REGNO as reload register, but
- for copying from register REGNO into the reload register.
+/* Subroutine of free_for_value_p, used to check a single register. */
- RELOADNUM is the number of the reload we want to load this value for;
- a reload does not conflict with itself.
-
- When IGNORE_ADDRESS_RELOADS is set, we can not have conflicts with
- reloads that load an address for the very reload we are considering.
-
- The caller has to make sure that there is no conflict with the return
- register. */
static int
reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
ignore_address_reloads)
@@ -5201,9 +5195,20 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
int ignore_address_reloads;
{
int time1;
+ /* Set if we see an input reload that must not share its reload register
+ with any new earlyclobber, but might otherwise share the reload
+ register with an output or input-output reload. */
+ int check_earlyclobber = 0;
int i;
int copy = 0;
+ /* ??? reload_reg_used is abused to hold the registers that are not
+ available as spill registers, including hard registers that are
+ earlyclobbered in asms. As a temporary measure, reject anything
+ in reload_reg_used. */
+ if (TEST_HARD_REG_BIT (reload_reg_unavailable, regno))
+ return 0;
+
if (out == const0_rtx)
{
copy = 1;
@@ -5228,7 +5233,8 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
switch (type)
{
case RELOAD_FOR_OTHER_ADDRESS:
- time1 = 0;
+ /* RELOAD_FOR_OTHER_ADDRESS conflicts with RELOAD_OTHER reloads. */
+ time1 = copy ? 0 : 1;
break;
case RELOAD_OTHER:
time1 = copy ? 1 : MAX_RECOG_OPERANDS * 5 + 5;
@@ -5320,6 +5326,7 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
break;
case RELOAD_FOR_INPUT:
time2 = reload_opnum[i] * 4 + 4;
+ check_earlyclobber = 1;
break;
/* reload_opnum[i] * 4 + 4 <= (MAX_RECOG_OPERAND - 1) * 4 + 4
== MAX_RECOG_OPERAND * 4 */
@@ -5332,6 +5339,7 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
break;
case RELOAD_FOR_OPERAND_ADDRESS:
time2 = MAX_RECOG_OPERANDS * 4 + 2;
+ check_earlyclobber = 1;
break;
case RELOAD_FOR_INSN:
time2 = MAX_RECOG_OPERANDS * 4 + 3;
@@ -5360,6 +5368,9 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
if (! reload_in[i] || rtx_equal_p (reload_in[i], value))
{
time2 = MAX_RECOG_OPERANDS * 4 + 4;
+ /* Earlyclobbered outputs must conflict with inputs. */
+ if (earlyclobber_operand_p (reload_out[i]))
+ time2 = MAX_RECOG_OPERANDS * 4 + 3;
break;
}
time2 = 1;
@@ -5382,9 +5393,71 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum,
}
}
}
+
+ /* Earlyclobbered outputs must conflict with inputs. */
+ if (check_earlyclobber && out && earlyclobber_operand_p (out))
+ return 0;
+
+ return 1;
+}
+
+/* Return 1 if the value in reload reg REGNO, as used by a reload
+ needed for the part of the insn specified by OPNUM and TYPE,
+ may be used to load VALUE into it.
+
+ MODE is the mode in which the register is used, this is needed to
+ determine how many hard regs to test.
+
+ Other read-only reloads with the same value do not conflict
+ unless OUT is non-zero and these other reloads have to live while
+ output reloads live.
+ If OUT is CONST0_RTX, this is a special case: it means that the
+ test should not be for using register REGNO as reload register, but
+ for copying from register REGNO into the reload register.
+
+ RELOADNUM is the number of the reload we want to load this value for;
+ a reload does not conflict with itself.
+
+ When IGNORE_ADDRESS_RELOADS is set, we can not have conflicts with
+ reloads that load an address for the very reload we are considering.
+
+ The caller has to make sure that there is no conflict with the return
+ register. */
+
+static int
+free_for_value_p (regno, mode, opnum, type, value, out, reloadnum,
+ ignore_address_reloads)
+ int regno;
+ enum machine_mode mode;
+ int opnum;
+ enum reload_type type;
+ rtx value, out;
+ int reloadnum;
+ int ignore_address_reloads;
+{
+ int nregs = HARD_REGNO_NREGS (regno, mode);
+ while (nregs-- > 0)
+ if (! reload_reg_free_for_value_p (regno + nregs, opnum, type, value, out,
+ reloadnum, ignore_address_reloads))
+ return 0;
return 1;
}
+/* Determine whether the reload reg X overlaps any rtx'es used for
+ overriding inheritance. Return nonzero if so. */
+
+static int
+conflicts_with_override (x)
+ rtx x;
+{
+ int i;
+ for (i = 0; i < n_reloads; i++)
+ if (reload_override_in[i]
+ && reg_overlap_mentioned_p (x, reload_override_in[i]))
+ return 1;
+ return 0;
+}
+
/* Find a spill register to use as a reload register for reload R.
LAST_RELOAD is non-zero if this is the last reload for the insn being
processed.
@@ -5465,11 +5538,10 @@ allocate_reload_reg (chain, r, last_reload, noerror)
/* We check reload_reg_used to make sure we
don't clobber the return register. */
&& ! TEST_HARD_REG_BIT (reload_reg_used, regnum)
- && reload_reg_free_for_value_p (regnum,
- reload_opnum[r],
- reload_when_needed[r],
- reload_in[r],
- reload_out[r], r, 1)))
+ && free_for_value_p (regnum, reload_mode[r],
+ reload_opnum[r],
+ reload_when_needed[r],
+ reload_in[r], reload_out[r], r, 1)))
&& TEST_HARD_REG_BIT (reg_class_contents[class], regnum)
&& HARD_REGNO_MODE_OK (regnum, reload_mode[r])
/* Look first for regs to share, then for unshared. But
@@ -5662,7 +5734,7 @@ choose_reload_regs (chain)
CLEAR_HARD_REG_SET (reload_reg_used_in_outaddr_addr[i]);
}
- IOR_COMPL_HARD_REG_SET (reload_reg_used, chain->used_spill_regs);
+ COMPL_HARD_REG_SET (reload_reg_unavailable, chain->used_spill_regs);
#if 0 /* Not needed, now that we can always retry without inheritance. */
/* See if we have more mandatory reloads than spill regs.
@@ -5924,10 +5996,9 @@ choose_reload_regs (chain)
&& (reload_nregs[r] == max_group_size
|| ! TEST_HARD_REG_BIT (reg_class_contents[(int) group_class],
i))
- && reload_reg_free_for_value_p (i, reload_opnum[r],
- reload_when_needed[r],
- reload_in[r],
- const0_rtx, r, 1))
+ && free_for_value_p (i, reload_mode[r], reload_opnum[r],
+ reload_when_needed[r], reload_in[r],
+ const0_rtx, r, 1))
{
/* If a group is needed, verify that all the subsequent
registers still have their values intact. */
@@ -5961,9 +6032,11 @@ choose_reload_regs (chain)
break;
if (i1 != n_earlyclobbers
- || ! (reload_reg_free_for_value_p
- (i, reload_opnum[r], reload_when_needed[r],
- reload_in[r], reload_out[r], r, 1))
+ || ! (free_for_value_p (i, reload_mode[r],
+ reload_opnum[r],
+ reload_when_needed[r],
+ reload_in[r],
+ reload_out[r], r, 1))
/* Don't use it if we'd clobber a pseudo reg. */
|| (TEST_HARD_REG_BIT (reg_used_in_insn, i)
&& reload_out[r]
@@ -5985,9 +6058,12 @@ choose_reload_regs (chain)
&& rtx_equal_p (reload_out[r],
reload_reg_rtx[r])))
{
- reload_override_in[r] = last_reg;
- reload_inheritance_insn[r]
- = reg_reloaded_insn[i];
+ if (! reload_optional[r])
+ {
+ reload_override_in[r] = last_reg;
+ reload_inheritance_insn[r]
+ = reg_reloaded_insn[i];
+ }
}
else
{
@@ -6065,10 +6141,11 @@ choose_reload_regs (chain)
and of the desired class. */
if (equiv != 0
&& ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno)
- && ! reload_reg_free_for_value_p (regno, reload_opnum[r],
- reload_when_needed[r],
- reload_in[r],
- reload_out[r], r, 1))
+ && ! free_for_value_p (regno, reload_mode[r],
+ reload_opnum[r],
+ reload_when_needed[r],
+ reload_in[r], reload_out[r], r,
+ 1))
|| ! TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]],
regno)))
equiv = 0;
@@ -6086,7 +6163,8 @@ choose_reload_regs (chain)
if (reg_overlap_mentioned_for_reload_p (equiv,
reload_earlyclobbers[i]))
{
- reload_override_in[r] = equiv;
+ if (! reload_optional[r])
+ reload_override_in[r] = equiv;
equiv = 0;
break;
}
@@ -6097,7 +6175,8 @@ choose_reload_regs (chain)
In particular, we then can't use EQUIV for a
RELOAD_FOR_OUTPUT_ADDRESS reload. */
- if (equiv != 0 && regno_clobbered_p (regno, insn))
+ if (equiv != 0 && regno_clobbered_p (regno, insn,
+ reload_mode[r], 0))
{
switch (reload_when_needed[r])
{
@@ -6109,13 +6188,32 @@ choose_reload_regs (chain)
case RELOAD_OTHER:
case RELOAD_FOR_INPUT:
case RELOAD_FOR_OPERAND_ADDRESS:
- reload_override_in[r] = equiv;
+ if (! reload_optional[r])
+ reload_override_in[r] = equiv;
/* Fall through. */
default:
equiv = 0;
break;
}
}
+ else if (regno_clobbered_p (regno, insn, reload_mode[r], 1))
+ switch (reload_when_needed[r])
+ {
+ case RELOAD_FOR_OTHER_ADDRESS:
+ case RELOAD_FOR_INPADDR_ADDRESS:
+ case RELOAD_FOR_INPUT_ADDRESS:
+ case RELOAD_FOR_OPADDR_ADDR:
+ case RELOAD_FOR_OPERAND_ADDRESS:
+ case RELOAD_FOR_INPUT:
+ break;
+ case RELOAD_OTHER:
+ if (! reload_optional[r])
+ reload_override_in[r] = equiv;
+ /* Fall through. */
+ default:
+ equiv = 0;
+ break;
+ }
/* If we found an equivalent reg, say no code need be generated
to load it, and use it as our reload reg. */
@@ -6276,13 +6374,12 @@ choose_reload_regs (chain)
check_reg = reload_override_in[r];
else
continue;
- if (! reload_reg_free_for_value_p (true_regnum (check_reg),
- reload_opnum[r],
- reload_when_needed[r],
- reload_in[r],
- (reload_inherited[r]
- ? reload_out[r] : const0_rtx),
- r, 1))
+ if (! free_for_value_p (true_regnum (check_reg), reload_mode[r],
+ reload_opnum[r], reload_when_needed[r],
+ reload_in[r],
+ (reload_inherited[r]
+ ? reload_out[r] : const0_rtx),
+ r, 1))
{
if (pass)
continue;
@@ -6330,6 +6427,7 @@ choose_reload_regs (chain)
clear_reload_reg_in_use (regno, reload_opnum[j],
reload_when_needed[j], reload_mode[j]);
reload_reg_rtx[j] = 0;
+ reload_spill_index[j] = -1;
}
/* Record which pseudos and which spill regs have output reloads. */
@@ -6638,10 +6736,10 @@ emit_reload_insns (chain)
/* Don't use OLDEQUIV if any other reload changes it at an
earlier stage of this insn or at this stage. */
- if (! reload_reg_free_for_value_p (regno, reload_opnum[j],
- reload_when_needed[j],
- reload_in[j], const0_rtx, j,
- 0))
+ if (! free_for_value_p (regno, reload_mode[j],
+ reload_opnum[j],
+ reload_when_needed[j],
+ reload_in[j], const0_rtx, j, 0))
oldequiv = 0;
/* If it is no cheaper to copy from OLDEQUIV into the
@@ -6791,11 +6889,10 @@ emit_reload_insns (chain)
&& dead_or_set_p (insn, old)
/* This is unsafe if some other reload
uses the same reg first. */
- && reload_reg_free_for_value_p (REGNO (reloadreg),
- reload_opnum[j],
- reload_when_needed[j],
- old, reload_out[j],
- j, 0))
+ && ! conflicts_with_override (reloadreg)
+ && free_for_value_p (REGNO (reloadreg), reload_mode[j],
+ reload_opnum[j], reload_when_needed[j],
+ old, reload_out[j], j, 0))
{
rtx temp = PREV_INSN (insn);
while (temp && GET_CODE (temp) == NOTE)
@@ -7104,7 +7201,8 @@ emit_reload_insns (chain)
/* We don't need to test full validity of last_regno for
inherit here; we only want to know if the store actually
matches the pseudo. */
- if (reg_reloaded_contents[last_regno] == pseudo_no
+ if (TEST_HARD_REG_BIT (reg_reloaded_valid, last_regno)
+ && reg_reloaded_contents[last_regno] == pseudo_no
&& spill_reg_store[last_regno]
&& rtx_equal_p (pseudo, spill_reg_stored_to[last_regno]))
delete_output_reload (insn, j, last_regno);
@@ -7280,7 +7378,7 @@ emit_reload_insns (chain)
|| !(set = single_set (insn))
|| rtx_equal_p (old, SET_DEST (set))
|| !reg_mentioned_p (old, SET_SRC (set))
- || !regno_clobbered_p (REGNO (old), insn))
+ || !regno_clobbered_p (REGNO (old), insn, reload_mode[j], 0))
gen_reload (old, reloadreg, reload_opnum[j],
reload_when_needed[j]);
}
@@ -7819,9 +7917,13 @@ gen_reload (out, in, opnum, type)
DEFINE_PEEPHOLE should be specified that recognizes the sequence
we emit below. */
+ code = (int) add_optab->handlers[(int) GET_MODE (out)].insn_code;
+
if (CONSTANT_P (op1) || GET_CODE (op1) == MEM || GET_CODE (op1) == SUBREG
|| (GET_CODE (op1) == REG
- && REGNO (op1) >= FIRST_PSEUDO_REGISTER))
+ && REGNO (op1) >= FIRST_PSEUDO_REGISTER)
+ || (code != CODE_FOR_nothing
+ && ! (*insn_operand_predicate[code][2]) (op1, insn_operand_mode[code][2])))
tem = op0, op0 = op1, op1 = tem;
gen_reload (out, op0, opnum, type);
diff --git a/gnu/egcs/gcc/toplev.c b/gnu/egcs/gcc/toplev.c
index 7b7f6a87fcb..56e9ab0a44f 100644
--- a/gnu/egcs/gcc/toplev.c
+++ b/gnu/egcs/gcc/toplev.c
@@ -772,6 +772,13 @@ int flag_instrument_function_entry_exit = 0;
int flag_no_ident = 0;
+#ifdef STACK_PROTECTOR
+/* Nonzero means use propolice as a stack protection method */
+int flag_propolice_protection = 1;
+#else
+int flag_propolice_protection = 0;
+#endif
+
/* Table of supported debugging formats. */
static struct
{
@@ -979,7 +986,11 @@ lang_independent_options f_options[] =
{"leading-underscore", &flag_leading_underscore, 1,
"External symbols have a leading underscore" },
{"ident", &flag_no_ident, 0,
- "Process #ident directives"}
+ "Process #ident directives"},
+ {"stack-protector", &flag_propolice_protection, 1,
+ "Enables stack protection" },
+ {"no-stack-protector", &flag_propolice_protection, 0,
+ "Disables stack protection" },
};
#define NUM_ELEM(a) (sizeof (a) / sizeof ((a)[0]))
@@ -1258,7 +1269,9 @@ lang_independent_options W_options[] =
{"uninitialized", &warn_uninitialized, 1,
"Warn about unitialized automatic variables"},
{"inline", &warn_inline, 1,
- "Warn when an inlined function cannot be inlined"}
+ "Warn when an inlined function cannot be inlined"},
+ {"stack-protector", &warn_stack_protector, 1,
+ "Warn when disabling stack protector for some reason"}
};
/* Output files for assembler code (real compiler output)
@@ -3646,6 +3659,8 @@ rest_of_compilation (decl)
insns = get_insns ();
+ if (flag_propolice_protection) prepare_stack_protection ();
+
/* Dump the rtl code if we are dumping rtl. */
if (rtl_dump)
diff --git a/gnu/usr.bin/ld/rtld/rtld.c b/gnu/usr.bin/ld/rtld/rtld.c
index 0fb7e6184b8..f100fb1ae25 100644
--- a/gnu/usr.bin/ld/rtld/rtld.c
+++ b/gnu/usr.bin/ld/rtld/rtld.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld.c,v 1.29 2002/09/07 01:25:34 marc Exp $ */
+/* $OpenBSD: rtld.c,v 1.30 2002/12/02 09:00:11 miod Exp $ */
/* $NetBSD: rtld.c,v 1.43 1996/01/14 00:35:17 pk Exp $ */
/*
* Copyright (c) 1993 Paul Kranenburg
@@ -59,6 +59,18 @@
#include "ld.h"
+/*
+ * Stack protector dummies.
+ * Ideally, a scheme to compile these stubs from libc should be used, but
+ * this would end up dragging too much code from libc here.
+ */
+long __guard[8] = {0,0,0,0,0,0,0,0};
+void
+__stack_smash_handler(char func[], int damaged)
+{
+ _exit(127);
+}
+
#ifndef MAP_ANON
#define MAP_ANON 0
#define anon_open() do { \
diff --git a/lib/libc/shlib_version b/lib/libc/shlib_version
index 59ded4be242..05b2c1e70b5 100644
--- a/lib/libc/shlib_version
+++ b/lib/libc/shlib_version
@@ -1,2 +1,2 @@
major=28
-minor=8 # note: remember to update minor in ../libc_r/shlib_version
+minor=9 # note: remember to update minor in ../libc_r/shlib_version
diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc
index 90862148b46..26ac85b48ff 100644
--- a/lib/libc/sys/Makefile.inc
+++ b/lib/libc/sys/Makefile.inc
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.inc,v 1.61 2002/11/10 03:21:02 fgsch Exp $
+# $OpenBSD: Makefile.inc,v 1.62 2002/12/02 09:00:14 miod Exp $
# $NetBSD: Makefile.inc,v 1.35 1995/10/16 23:49:07 jtc Exp $
# @(#)Makefile.inc 8.1 (Berkeley) 6/17/93
@@ -25,6 +25,9 @@ SRCS+= ftruncate.c lseek.c mmap.c ptrace.c semctl.c truncate.c \
timer_create.c timer_delete.c timer_getoverrun.c timer_gettime.c \
timer_settime.c pread.c preadv.c pwrite.c pwritev.c
+# stack protector helper functions
+SRCS+= stack_protector.c
+
# modules with default implementations on all architectures:
ASM= accept.o access.o acct.o adjtime.o bind.o chdir.o chflags.o chmod.o \
chown.o chroot.o clock_gettime.o clock_settime.o clock_getres.o \
diff --git a/lib/libc/sys/stack_protector.c b/lib/libc/sys/stack_protector.c
new file mode 100644
index 00000000000..a51fe1e463f
--- /dev/null
+++ b/lib/libc/sys/stack_protector.c
@@ -0,0 +1,87 @@
+/* $OpenBSD: stack_protector.c,v 1.1 2002/12/02 09:00:15 miod Exp $ */
+
+/*
+ * Copyright (c) 2002 Hiroaki Etoh, Federico G. Schwindt, and Miodrag Vallat.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#if defined(LIBC_SCCS) && !defined(list)
+static char rcsid[] = "$OpenBSD: stack_protector.c,v 1.1 2002/12/02 09:00:15 miod Exp $";
+#endif
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <syslog.h>
+
+long __guard[8] = {0,0,0,0,0,0,0,0};
+static void __guard_setup(void) __attribute__ ((constructor));
+void __stack_smash_handler(char func[], int damaged __attribute__((unused)));
+
+static void
+__guard_setup(void)
+{
+ int i, mib[2];
+ size_t len;
+
+ if (__guard[0] != 0)
+ return;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_ARND;
+
+ len = 4;
+ for (i = 0; i < sizeof(__guard) / 4; i++) {
+ if (sysctl(mib, 2, (char*)&((int*)__guard)[i],
+ &len, NULL, 0) == -1)
+ break;
+ }
+
+ if (i < sizeof(__guard) / 4) {
+ /* If sysctl was unsuccessful, use the "terminator canary". */
+ ((char*)__guard)[0] = 0; ((char*)__guard)[1] = 0;
+ ((char*)__guard)[2] = '\n'; ((char*)__guard)[3] = 255;
+ }
+}
+
+void
+__stack_smash_handler(char func[], int damaged)
+{
+ struct syslog_data sdata = SYSLOG_DATA_INIT;
+ const char message[] = "stack overflow in function %s";
+ struct sigaction sa;
+
+ /* this may fail on a chroot jail, though luck */
+ syslog_r(LOG_CRIT, &sdata, message, func);
+
+ bzero(sa, sizeof(struct sigaction));
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = SIG_DFL;
+ sigaction(SIGABRT, &sa, NULL);
+
+ kill(getpid(), SIGABRT);
+
+ _exit(127);
+}
diff --git a/lib/libc_r/shlib_version b/lib/libc_r/shlib_version
index e29c46e3713..e941ec1f045 100644
--- a/lib/libc_r/shlib_version
+++ b/lib/libc_r/shlib_version
@@ -1,2 +1,2 @@
major=6
-minor=8
+minor=9
diff --git a/libexec/ld.so/util.c b/libexec/ld.so/util.c
index 62790011ce8..a6f1447f676 100644
--- a/libexec/ld.so/util.c
+++ b/libexec/ld.so/util.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: util.c,v 1.9 2002/07/24 04:11:10 deraadt Exp $ */
+/* $OpenBSD: util.c,v 1.10 2002/12/02 09:00:18 miod Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -38,6 +38,18 @@
#include "archdep.h"
/*
+ * Stack protector dummies.
+ * Ideally, a scheme to compile these stubs from libc should be used, but
+ * this would end up dragging too much code from libc here.
+ */
+long __guard[8] = {0,0,0,0,0,0,0,0};
+void
+stack_smash_handler(char func[], int damaged)
+{
+ _dl_exit(127);
+}
+
+/*
* Static vars usable after bootstrapping.
*/
static void *_dl_malloc_base;
diff --git a/sys/arch/alpha/conf/Makefile.alpha b/sys/arch/alpha/conf/Makefile.alpha
index 47f2425d94e..930fa5d9e18 100644
--- a/sys/arch/alpha/conf/Makefile.alpha
+++ b/sys/arch/alpha/conf/Makefile.alpha
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.alpha,v 1.25 2002/08/09 20:24:41 miod Exp $
+# $OpenBSD: Makefile.alpha,v 1.26 2002/12/02 09:00:21 miod Exp $
# $NetBSD: Makefile.alpha,v 1.27 1996/12/01 06:12:25 jonathan Exp $
# Makefile for OpenBSD
@@ -38,7 +38,7 @@ CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL -Dalpha
CDIAGFLAGS?= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \
-Wno-uninitialized -Wno-format -Wno-main
-CMACHFLAGS= -mno-fp-regs
+CMACHFLAGS= -mno-fp-regs -fno-stack-protector
COPTS?= -O2
CFLAGS= ${DEBUG} ${CDIAGFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE}
AFLAGS= -traditional -D_LOCORE
diff --git a/sys/arch/alpha/stand/Makefile.inc b/sys/arch/alpha/stand/Makefile.inc
index 1264f2a431d..d71f2ca141c 100644
--- a/sys/arch/alpha/stand/Makefile.inc
+++ b/sys/arch/alpha/stand/Makefile.inc
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.inc,v 1.6 2001/02/03 03:22:47 art Exp $
+# $OpenBSD: Makefile.inc,v 1.7 2002/12/02 09:00:22 miod Exp $
# $NetBSD: Makefile.inc,v 1.8 1997/04/06 08:39:38 cgd Exp $
.include <bsd.own.mk> # for ELF_TOOLCHAIN definition
@@ -20,3 +20,4 @@ CPPFLAGS+= -D_STANDALONE
XCPPFLAGS+= -DHEAP_LIMIT="0x${HEAP_LIMIT}"
+CFLAGS+= -fno-stack-protector
diff --git a/sys/arch/amiga/conf/Makefile.amiga b/sys/arch/amiga/conf/Makefile.amiga
index fc3b2875945..2043585b546 100644
--- a/sys/arch/amiga/conf/Makefile.amiga
+++ b/sys/arch/amiga/conf/Makefile.amiga
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.amiga,v 1.32 2002/08/09 20:24:43 miod Exp $
+# $OpenBSD: Makefile.amiga,v 1.33 2002/12/02 09:00:22 miod Exp $
# $NetBSD: Makefile.amiga,v 1.60 1997/07/23 10:19:42 is Exp $
# Makefile for OpenBSD
@@ -50,7 +50,7 @@ CMACHFLAGS= -m68020
.else
CMACHFLAGS= -m68060 -Wa,-m68030
.endif
-CMACHFLAGS+= -msoft-float
+CMACHFLAGS+= -msoft-float -fno-stack-protector
COPTS?= -O2
CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${CMACHFLAGS} ${PIPE}
diff --git a/sys/arch/amiga/stand/binpatch/Makefile b/sys/arch/amiga/stand/binpatch/Makefile
index 71c609261ba..7377c0aa588 100644
--- a/sys/arch/amiga/stand/binpatch/Makefile
+++ b/sys/arch/amiga/stand/binpatch/Makefile
@@ -1,10 +1,11 @@
-# $OpenBSD: Makefile,v 1.5 2000/02/12 15:29:05 espie Exp $
+# $OpenBSD: Makefile,v 1.6 2002/12/02 09:00:22 miod Exp $
# $NetBSD: Makefile,v 1.6 1996/09/27 03:23:12 chopps Exp $
.if ${MACHINE} == "amiga"
PROG=binpatch
BINDIR=/sbin
LDFLAGS+=-static
+CFLAGS+= -fno-stack-protector
.else
NOPROG=Yes
.endif
diff --git a/sys/arch/amiga/stand/boot/Makefile b/sys/arch/amiga/stand/boot/Makefile
index f101ec86bad..16e33064893 100644
--- a/sys/arch/amiga/stand/boot/Makefile
+++ b/sys/arch/amiga/stand/boot/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.6 2000/02/12 15:29:06 espie Exp $
+# $OpenBSD: Makefile,v 1.7 2002/12/02 09:00:22 miod Exp $
NOPROG= installboot
MAN=installboot.8
@@ -39,6 +39,7 @@ INCPATH= -I${.CURDIR} -I${.CURDIR}/../.. -I${S} -I${S}/lib/libsa
COPTIM= -O -fomit-frame-pointer -fno-function-cse -Wa,-l -m68060 \
-Wa,-m68030
CFLAGS= ${COPTIM} ${INCPATH} ${DEFS}
+CFLAGS+= -fno-stack-protector
COPTS+= -Wall -Wstrict-prototypes
BOOTBLOCKS= xxboot # XXX fdboot is too large at the moment.
diff --git a/sys/arch/amiga/stand/loadbsd/Makefile b/sys/arch/amiga/stand/loadbsd/Makefile
index bf93cb95b8c..e81d493d99b 100644
--- a/sys/arch/amiga/stand/loadbsd/Makefile
+++ b/sys/arch/amiga/stand/loadbsd/Makefile
@@ -1,7 +1,8 @@
-# $OpenBSD: Makefile,v 1.4 1999/09/09 21:25:13 espie Exp $
+# $OpenBSD: Makefile,v 1.5 2002/12/02 09:00:22 miod Exp $
CC = gcc
CFLAGS = -m68030 -Wall -O3 -fomit-frame-pointer -D__progname=program_name -msmall-code -resident
+CFLAGS+= -fno-stack-protector
OBJS1 = loadbsd.o poolmem.o getopt.o sleep.o vers.o openlibs_stub.o
OBJS2 = loadbsd.o poolmem.o vers_ixemul.o openlibs_ixemul.o
diff --git a/sys/arch/amiga/stand/loadkmap/Makefile b/sys/arch/amiga/stand/loadkmap/Makefile
index daf487ccae0..3a6858b3454 100644
--- a/sys/arch/amiga/stand/loadkmap/Makefile
+++ b/sys/arch/amiga/stand/loadkmap/Makefile
@@ -1,10 +1,11 @@
-# $OpenBSD: Makefile,v 1.8 2000/02/13 13:15:23 espie Exp $
+# $OpenBSD: Makefile,v 1.9 2002/12/02 09:00:22 miod Exp $
# $NetBSD: Makefile,v 1.5 1996/09/27 03:23:13 chopps Exp $
.if ${MACHINE}=="amiga"
PROG=loadkmap
BINDIR=/usr/sbin
SUBDIR=din es fr sw us
+CFLAGS+= -fno-stack-protector
.else
NOPROG=Yes
.endif
diff --git a/sys/arch/hp300/conf/Makefile.hp300 b/sys/arch/hp300/conf/Makefile.hp300
index 5cbe14603fe..e4aff570362 100644
--- a/sys/arch/hp300/conf/Makefile.hp300
+++ b/sys/arch/hp300/conf/Makefile.hp300
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.hp300,v 1.28 2002/08/09 20:24:43 miod Exp $
+# $OpenBSD: Makefile.hp300,v 1.29 2002/12/02 09:00:22 miod Exp $
# $NetBSD: Makefile.hp300,v 1.54 1997/04/01 23:16:41 scottr Exp $
# Makefile for OpenBSD
@@ -44,7 +44,7 @@ CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL \
-Dmc68020 -Dhp300
CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \
-Wno-uninitialized -Wno-format -Wno-main
-CMACHFLAGS= -msoft-float
+CMACHFLAGS= -msoft-float -fno-stack-protector
COPTS?= -O2
CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${CMACHFLAGS} ${PIPE}
AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE
diff --git a/sys/arch/hp300/stand/Makefile.inc b/sys/arch/hp300/stand/Makefile.inc
index b1b016609d6..524af1b2d99 100644
--- a/sys/arch/hp300/stand/Makefile.inc
+++ b/sys/arch/hp300/stand/Makefile.inc
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.inc,v 1.3 1999/08/16 09:43:07 downsj Exp $
+# $OpenBSD: Makefile.inc,v 1.4 2002/12/02 09:00:23 miod Exp $
# $NetBSD: Makefile.inc,v 1.7 1997/05/12 07:43:18 thorpej Exp $
BINDIR= /usr/mdec
@@ -6,6 +6,8 @@ BINDIR= /usr/mdec
# RELOC=FFF00000 allows for boot prog up to FF000 (1044480) bytes long
RELOC= FFF00000
+CFLAGS+= -fno-stack-protector
+
CPPFLAGS+= -DDCACONSOLE -DAPCICONSOLE -DITECONSOLE -DDCMCONSOLE
CPPFLAGS+= -DHIL_KEYBOARD -DUK_KEYBOARD
CPPFLAGS+= -DDOMAIN_KEYBOARD
diff --git a/sys/arch/hppa/conf/Makefile.hppa b/sys/arch/hppa/conf/Makefile.hppa
index f15c89fb047..7f3a469df63 100644
--- a/sys/arch/hppa/conf/Makefile.hppa
+++ b/sys/arch/hppa/conf/Makefile.hppa
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.hppa,v 1.16 2002/08/09 20:24:43 miod Exp $
+# $OpenBSD: Makefile.hppa,v 1.17 2002/12/02 09:00:23 miod Exp $
# Makefile for OpenBSD
#
@@ -42,7 +42,8 @@ CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL \
-Dhppa
CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wno-uninitialized \
-Wno-format -Wno-main
-CMACHFLAGS= -mfast-indirect-calls -mportable-runtime -mno-space-regs
+CMACHFLAGS= -mfast-indirect-calls -mportable-runtime -mno-space-regs \
+ -fno-stack-protector
COPTS?= -Os
CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${CMACHFLAGS} ${PIPE}
AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE
diff --git a/sys/arch/hppa/stand/Makefile.inc b/sys/arch/hppa/stand/Makefile.inc
index 93652e1ea78..5893f128ea9 100644
--- a/sys/arch/hppa/stand/Makefile.inc
+++ b/sys/arch/hppa/stand/Makefile.inc
@@ -1,6 +1,7 @@
-# $OpenBSD: Makefile.inc,v 1.8 2002/03/15 21:22:50 mickey Exp $
+# $OpenBSD: Makefile.inc,v 1.9 2002/12/02 09:00:23 miod Exp $
CFLAGS=${DEBUG} -Os -Wall -Werror
+CFLAGS+= -fno-stack-protector
CPPFLAGS+=-I${S} -I. -I${.CURDIR}
SACFLAGS=-nostdinc -fno-builtin -D_STANDALONE -I${SADIR}/libsa
SACFLAGS+=-mdisable-fpregs -mfast-indirect-calls -mpa-risc-1-0
diff --git a/sys/arch/i386/conf/Makefile.i386 b/sys/arch/i386/conf/Makefile.i386
index 23f19662ce8..f1791a9e38d 100644
--- a/sys/arch/i386/conf/Makefile.i386
+++ b/sys/arch/i386/conf/Makefile.i386
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.i386,v 1.31 2002/08/09 20:24:43 miod Exp $
+# $OpenBSD: Makefile.i386,v 1.32 2002/12/02 09:00:23 miod Exp $
# $NetBSD: Makefile.i386,v 1.67 1996/05/11 16:12:11 mycroft Exp $
# Makefile for OpenBSD
@@ -48,6 +48,7 @@ CMACHFLAGS= -march=i486
.else
CMACHFLAGS=
.endif
+CMACHFLAGS+= -fno-stack-protector
COPTS?= -O2
CFLAGS= ${DEBUG} ${CDIAGFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE}
diff --git a/sys/arch/i386/stand/Makefile.inc b/sys/arch/i386/stand/Makefile.inc
index adebaa94ec6..7b6147b3e42 100644
--- a/sys/arch/i386/stand/Makefile.inc
+++ b/sys/arch/i386/stand/Makefile.inc
@@ -1,6 +1,7 @@
-# $OpenBSD: Makefile.inc,v 1.29 2000/10/09 20:25:10 mickey Exp $
+# $OpenBSD: Makefile.inc,v 1.30 2002/12/02 09:00:23 miod Exp $
CFLAGS=${DEBUG} -Os -Wall -Werror
+CFLAGS+= -fno-stack-protector
CPPFLAGS+=-I${S} -I${SADIR}/libsa -I. -I${.CURDIR}
SACFLAGS=-D_STANDALONE
DEBUGLIBS=no
diff --git a/sys/arch/mac68k/conf/Makefile.mac68k b/sys/arch/mac68k/conf/Makefile.mac68k
index 7911e0935e0..a44dada32e3 100644
--- a/sys/arch/mac68k/conf/Makefile.mac68k
+++ b/sys/arch/mac68k/conf/Makefile.mac68k
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.mac68k,v 1.27 2002/08/09 20:24:43 miod Exp $
+# $OpenBSD: Makefile.mac68k,v 1.28 2002/12/02 09:00:24 miod Exp $
# $NetBSD: Makefile.mac68k,v 1.53 1997/04/15 06:11:38 scottr Exp $
# Makefile for OpenBSD
@@ -44,7 +44,7 @@ CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL \
-Dmc68020 -Dmac68k
CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \
-Wno-uninitialized -Wno-format -Wno-main
-CMACHFLAGS= -msoft-float
+CMACHFLAGS= -msoft-float -fno-stack-protector
COPTS?= -O2
CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${CMACHFLAGS} ${PIPE}
AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE
diff --git a/sys/arch/macppc/conf/Makefile.macppc b/sys/arch/macppc/conf/Makefile.macppc
index a10be37b0f5..2ccb0bf9075 100644
--- a/sys/arch/macppc/conf/Makefile.macppc
+++ b/sys/arch/macppc/conf/Makefile.macppc
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.macppc,v 1.8 2002/08/09 20:24:43 miod Exp $
+# $OpenBSD: Makefile.macppc,v 1.9 2002/12/02 09:00:24 miod Exp $
#
# Makefile for OpenBSD PowerPC
#
@@ -44,7 +44,7 @@ CPPFLAGS= ${INCLUDES} ${IDENT} -D_KERNEL \
-Dmacppc
CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \
-Wno-uninitialized -Wno-format -Wno-main
-CMACHFLAGS= -msoft-float -Wa,-m7400
+CMACHFLAGS= -msoft-float -Wa,-m7400 -fno-stack-protector
COPTS?= -O2
CFLAGS= ${DEBUG} ${CWARNFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE}
AFLAGS= -D_LOCORE
diff --git a/sys/arch/macppc/stand/Makefile.inc b/sys/arch/macppc/stand/Makefile.inc
index 00a156e277b..df2635a710d 100644
--- a/sys/arch/macppc/stand/Makefile.inc
+++ b/sys/arch/macppc/stand/Makefile.inc
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.inc,v 1.2 2001/10/03 17:10:06 drahn Exp $
+# $OpenBSD: Makefile.inc,v 1.3 2002/12/02 09:00:24 miod Exp $
# $NetBSD: Makefile.inc,v 1.1 1996/09/30 16:34:59 ws Exp $
.if !defined(__stand_makefile_inc)
@@ -22,6 +22,7 @@ INCLUDES+= -I. -I$(.OBJDIR) -I$(.CURDIR)/.. -I$(S)/arch -I$(S)
INCLUDES+= -I$(S)/lib/libsa
DEFS+= -DSTANDALONE -DFIREPOWERBUGS
CFLAGS+= $(INCLUDES) $(DEFS) $(EXTRACFLAGS)
+CFLAGS+= -fno-stack-protector
LDFLAGS?= -X -N -Ttext $(RELOC) -e $(ENTRY)
cleandir:
diff --git a/sys/arch/mvme68k/conf/Makefile.mvme68k b/sys/arch/mvme68k/conf/Makefile.mvme68k
index 0baa9ba4309..26dd4ab3205 100644
--- a/sys/arch/mvme68k/conf/Makefile.mvme68k
+++ b/sys/arch/mvme68k/conf/Makefile.mvme68k
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.mvme68k,v 1.17 2002/08/09 20:24:43 miod Exp $
+# $OpenBSD: Makefile.mvme68k,v 1.18 2002/12/02 09:00:24 miod Exp $
# This makefile is constructed from a machine description:
# config machineid
@@ -47,7 +47,7 @@ CMACHFLAGS= -m68020
.else
CMACHFLAGS= -m68060 -Wa,-m68030
.endif
-CMACHFLAGS+= -msoft-float
+CMACHFLAGS+= -msoft-float -fno-stack-protector
COPTS?= -O2
CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${CMACHFLAGS} ${PIPE}
diff --git a/sys/arch/mvme68k/stand/Makefile.inc b/sys/arch/mvme68k/stand/Makefile.inc
index a3f02f3f7c9..e622ccccb11 100644
--- a/sys/arch/mvme68k/stand/Makefile.inc
+++ b/sys/arch/mvme68k/stand/Makefile.inc
@@ -1,3 +1,4 @@
-# $OpenBSD: Makefile.inc,v 1.3 2000/03/03 00:54:52 todd Exp $
+# $OpenBSD: Makefile.inc,v 1.4 2002/12/02 09:00:24 miod Exp $
MDEC_DIR?=/usr/mdec
+CFLAGS+= -fno-stack-protector
diff --git a/sys/arch/mvme88k/conf/Makefile.mvme88k b/sys/arch/mvme88k/conf/Makefile.mvme88k
index f3926027d93..ceb32a9e28c 100644
--- a/sys/arch/mvme88k/conf/Makefile.mvme88k
+++ b/sys/arch/mvme88k/conf/Makefile.mvme88k
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.mvme88k,v 1.21 2002/08/09 20:24:43 miod Exp $
+# $OpenBSD: Makefile.mvme88k,v 1.22 2002/12/02 09:00:24 miod Exp $
#
# Makefile for OpenBSD
#
@@ -41,7 +41,7 @@ INCLUDES= -nostdinc -I. -I$S/arch -I$S
CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL -Dmvme88k -Dm88k
CWARNFLAGS= -Wall -Werror -Wmissing-prototypes \
-Wno-uninitialized -Wno-format -Wno-main -Wstrict-prototypes
-CMACHFLAGS=
+CMACHFLAGS= -fno-stack-protector
COPTS?= -O
CFLAGS= ${DEBUG} ${CWARNFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE}
AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE ${CMACHFLAGS}
diff --git a/sys/arch/mvme88k/stand/Makefile.inc b/sys/arch/mvme88k/stand/Makefile.inc
index 5a0216193f1..8955102edea 100644
--- a/sys/arch/mvme88k/stand/Makefile.inc
+++ b/sys/arch/mvme88k/stand/Makefile.inc
@@ -1,6 +1,7 @@
-# $OpenBSD: Makefile.inc,v 1.4 2001/03/27 21:13:51 miod Exp $
+# $OpenBSD: Makefile.inc,v 1.5 2002/12/02 09:00:25 miod Exp $
MDEC_DIR?=/usr/mdec
+CFLAGS+= -fno-stack-protector
# Load addresses for first and second stage bootstraps
STAGE1_RELOC=0x009F0000
diff --git a/sys/arch/mvmeppc/conf/Makefile.mvmeppc b/sys/arch/mvmeppc/conf/Makefile.mvmeppc
index e215c41ee48..0e217bf98b1 100644
--- a/sys/arch/mvmeppc/conf/Makefile.mvmeppc
+++ b/sys/arch/mvmeppc/conf/Makefile.mvmeppc
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.mvmeppc,v 1.9 2002/08/09 20:24:43 miod Exp $
+# $OpenBSD: Makefile.mvmeppc,v 1.10 2002/12/02 09:00:25 miod Exp $
#
# Makefile for OpenBSD PowerPC
#
@@ -44,7 +44,7 @@ CPPFLAGS= ${INCLUDES} ${IDENT} -D_KERNEL \
-Dpowerpc -D__mvmeppc__
CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \
-Wno-uninitialized -Wno-format -Wno-main
-CMACHFLAGS= -msoft-float -Wa,-m7400
+CMACHFLAGS= -msoft-float -Wa,-m7400 -fno-stack-protector
COPTS?= -O2
CFLAGS= ${DEBUG} ${CWARNFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE}
AFLAGS= -D_LOCORE
diff --git a/sys/arch/mvmeppc/stand/Makefile.inc b/sys/arch/mvmeppc/stand/Makefile.inc
index 5404d746abb..e14f6de44eb 100644
--- a/sys/arch/mvmeppc/stand/Makefile.inc
+++ b/sys/arch/mvmeppc/stand/Makefile.inc
@@ -1,6 +1,7 @@
-# $OpenBSD: Makefile.inc,v 1.1 2001/06/26 21:57:58 smurph Exp $
+# $OpenBSD: Makefile.inc,v 1.2 2002/12/02 09:00:25 miod Exp $
MDEC_DIR?=/usr/mdec
+CFLAGS+= -fno-stack-protector
# Load addresses for first and second stage bootstraps
STAGE1_RELOC=4000
diff --git a/sys/arch/sparc/conf/Makefile.sparc b/sys/arch/sparc/conf/Makefile.sparc
index 7aaad1f1522..60f2fa9160d 100644
--- a/sys/arch/sparc/conf/Makefile.sparc
+++ b/sys/arch/sparc/conf/Makefile.sparc
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.sparc,v 1.26 2002/09/23 01:43:14 art Exp $
+# $OpenBSD: Makefile.sparc,v 1.27 2002/12/02 09:00:25 miod Exp $
# $NetBSD: Makefile.sparc,v 1.32.4.1 1996/06/12 20:26:32 pk Exp $
# Makefile for OpenBSD
@@ -49,6 +49,7 @@ CMACHFLAGS= -mcpu=supersparc
.else
CMACHFLAGS=
.endif
+CMACHFLAGS+= -fno-stack-protector
CFLAGS= ${DEBUG} -O2 ${CDIAGFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE}
# add `-mno-fpu' to work around gcc (last noticed in v2.7.2) bug
diff --git a/sys/arch/sparc/stand/Makefile.inc b/sys/arch/sparc/stand/Makefile.inc
index b261d414d95..1c1d5e4417d 100644
--- a/sys/arch/sparc/stand/Makefile.inc
+++ b/sys/arch/sparc/stand/Makefile.inc
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.inc,v 1.10 2000/07/18 01:28:48 deraadt Exp $
+# $OpenBSD: Makefile.inc,v 1.11 2002/12/02 09:00:25 miod Exp $
# $NetBSD: Makefile.inc,v 1.5 1996/02/01 22:33:01 mycroft Exp $
BINDIR= /usr/mdec
@@ -12,6 +12,8 @@ RELOC_SUN4M= 0x440000
RELOC?= ${RELOC_TEST}
RELOC2!= perl -e 'printf "0x%x", ${RELOC_TEST} + 0x40000'
+CFLAGS+= -fno-stack-protector
+
DEFS= -DSTANDALONE -DRELOC=${RELOC} -DSUN4 -DSUN4C -DSUN_BOOTPARAMS
### Figure out what to use for libkern
diff --git a/sys/arch/sparc64/conf/Makefile.sparc64 b/sys/arch/sparc64/conf/Makefile.sparc64
index b20c4628ed4..bdb41113bfb 100644
--- a/sys/arch/sparc64/conf/Makefile.sparc64
+++ b/sys/arch/sparc64/conf/Makefile.sparc64
@@ -22,7 +22,7 @@ CPPFLAGS= ${INCLUDES} ${IDENT} -D_KERNEL
CDIAGFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \
-Wno-uninitialized -Wno-format -Wno-main
-CMACHFLAGS= -Wa,-Av9a, -mno-fpu
+CMACHFLAGS= -Wa,-Av9a, -mno-fpu -fno-stack-protector
CFLAGS= ${DEBUG} -O2 ${CDIAGFLAGS} ${CMACHFLAGS} ${COPTS} ${PIPE}
AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE -Wa,-Av9a
diff --git a/sys/arch/sparc64/stand/Makefile.inc b/sys/arch/sparc64/stand/Makefile.inc
index 2b8f6616321..ecb8d086a2d 100644
--- a/sys/arch/sparc64/stand/Makefile.inc
+++ b/sys/arch/sparc64/stand/Makefile.inc
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.inc,v 1.2 2001/08/20 19:55:33 jason Exp $
+# $OpenBSD: Makefile.inc,v 1.3 2002/12/02 09:00:25 miod Exp $
# $NetBSD: Makefile.inc,v 1.7 2000/08/20 14:57:16 mrg Exp $
.ifndef __INCLUDED_STAND_MAKEFILE_INC
@@ -13,6 +13,7 @@ BINDIR= /usr/mdec
CPPFLAGS+= -D_STANDALONE -DSUN4U
CPPFLAGS+= -I.
+CFLAGS+= -fno-stack-protector
CFLAGS+= -msoft-float
.endif
diff --git a/sys/arch/sun3/conf/Makefile.sun3 b/sys/arch/sun3/conf/Makefile.sun3
index dff3e30ec28..c3410ec93c7 100644
--- a/sys/arch/sun3/conf/Makefile.sun3
+++ b/sys/arch/sun3/conf/Makefile.sun3
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.sun3,v 1.32 2002/08/09 20:24:43 miod Exp $
+# $OpenBSD: Makefile.sun3,v 1.33 2002/12/02 09:00:26 miod Exp $
# $NetBSD: Makefile.sun3,v 1.51 1996/09/09 21:07:08 mycroft Exp $
# Makefile for OpenBSD
@@ -44,7 +44,7 @@ CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL \
-Dmc68020 -Dsun3
CWARNFLAGS= -Werror -Wall -Wstrict-prototypes -Wmissing-prototypes \
-Wno-uninitialized -Wno-format -Wno-main
-CMACHFLAGS= -m68020 -msoft-float
+CMACHFLAGS= -m68020 -msoft-float -fno-stack-protector
COPTS?= -O2
CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${CMACHFLAGS} ${PIPE}
AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE ${CMACHFLAGS}
diff --git a/sys/arch/sun3/stand/Makefile.inc b/sys/arch/sun3/stand/Makefile.inc
index 55a5079c590..719bd9aeb0c 100644
--- a/sys/arch/sun3/stand/Makefile.inc
+++ b/sys/arch/sun3/stand/Makefile.inc
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.inc,v 1.5 2001/07/04 08:33:43 niklas Exp $
+# $OpenBSD: Makefile.inc,v 1.6 2002/12/02 09:00:26 miod Exp $
# $NetBSD: Makefile.inc,v 1.6 1995/11/17 23:23:44 gwr Exp $
.if defined(SA_PROG)
@@ -10,6 +10,7 @@ S= ${.CURDIR}/../../../..
RELOC?= 240000
DEFS?= -DSTANDALONE
INCL?= -I${.CURDIR} -I${.CURDIR}/../libsa -I${S}/lib/libsa -I${S}
+CFLAGS+=-fno-stack-protector
COPTS?= -msoft-float ${DEFS} ${DBG} ${INCL}
LIBSA?= ../libsa
diff --git a/sys/arch/vax/boot/Makefile.inc b/sys/arch/vax/boot/Makefile.inc
index bbe032e06d2..068de9c7b4d 100644
--- a/sys/arch/vax/boot/Makefile.inc
+++ b/sys/arch/vax/boot/Makefile.inc
@@ -1,9 +1,10 @@
-# $OpenBSD: Makefile.inc,v 1.3 2002/06/11 09:36:23 hugh Exp $
+# $OpenBSD: Makefile.inc,v 1.4 2002/12/02 09:00:26 miod Exp $
# $NetBSD: Makefile.inc,v 1.6 2002/02/24 01:04:23 matt Exp $
RELOC=0x39F000
.PATH: ${.CURDIR}/../../vax ${.CURDIR}/../common
+CFLAGS+= -fno-stack-protector
CPPFLAGS+=-I. -I${.CURDIR}/../../../../ -I${.CURDIR}/../../ -I${.CURDIR}/../common -I${.CURDIR}/../../include
CPPFLAGS+=-DRELOC=${RELOC}
diff --git a/sys/arch/vax/conf/Makefile.vax b/sys/arch/vax/conf/Makefile.vax
index 56bdc81a8ef..452c8a84407 100644
--- a/sys/arch/vax/conf/Makefile.vax
+++ b/sys/arch/vax/conf/Makefile.vax
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.vax,v 1.19 2002/08/09 20:24:43 miod Exp $
+# $OpenBSD: Makefile.vax,v 1.20 2002/12/02 09:00:26 miod Exp $
# $NetBSD: Makefile.vax,v 1.49 1999/07/26 05:20:49 cgd Exp $
# Makefile for OpenBSD/vax
@@ -78,7 +78,8 @@ INCLUDES= -I. -I$S/arch -I$S -nostdinc
CPPFLAGS= ${INCLUDES} ${IDENT} ${PARAM} -D_KERNEL \
-D_VAX_INLINE_
CWARNFLAGS?= -Werror -Wall -Wno-main -Wno-format -Wno-uninitialized
-CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${PIPE}
+CMACHFLAGS= -fno-stack-protector
+CFLAGS= ${DEBUG} ${COPTS} ${CWARNFLAGS} ${CMACHFLAGS} ${PIPE}
AFLAGS= -x assembler-with-cpp -traditional-cpp -D_LOCORE
LINKFLAGS= -N -Ttext 80000000 -e start
STRIPFLAGS= -d
diff --git a/sys/arch/vax/stand/Makefile.inc b/sys/arch/vax/stand/Makefile.inc
index bbe032e06d2..068de9c7b4d 100644
--- a/sys/arch/vax/stand/Makefile.inc
+++ b/sys/arch/vax/stand/Makefile.inc
@@ -1,9 +1,10 @@
-# $OpenBSD: Makefile.inc,v 1.3 2002/06/11 09:36:23 hugh Exp $
+# $OpenBSD: Makefile.inc,v 1.4 2002/12/02 09:00:26 miod Exp $
# $NetBSD: Makefile.inc,v 1.6 2002/02/24 01:04:23 matt Exp $
RELOC=0x39F000
.PATH: ${.CURDIR}/../../vax ${.CURDIR}/../common
+CFLAGS+= -fno-stack-protector
CPPFLAGS+=-I. -I${.CURDIR}/../../../../ -I${.CURDIR}/../../ -I${.CURDIR}/../common -I${.CURDIR}/../../include
CPPFLAGS+=-DRELOC=${RELOC}