annotate gcc/explow.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 /* Subroutines for manipulating rtx's in semantically interesting ways.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 1987-2020 Free Software Foundation, Inc.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 This file is part of GCC.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it under
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 the terms of the GNU General Public License as published by the Free
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 Software Foundation; either version 3, or (at your option) any later
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 version.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 for more details.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 #include "config.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 #include "system.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 #include "coretypes.h"
111
kono
parents: 67
diff changeset
24 #include "target.h"
kono
parents: 67
diff changeset
25 #include "function.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 #include "rtl.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 #include "tree.h"
111
kono
parents: 67
diff changeset
28 #include "memmodel.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
29 #include "tm_p.h"
111
kono
parents: 67
diff changeset
30 #include "expmed.h"
kono
parents: 67
diff changeset
31 #include "profile-count.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
32 #include "optabs.h"
111
kono
parents: 67
diff changeset
33 #include "emit-rtl.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 #include "recog.h"
111
kono
parents: 67
diff changeset
35 #include "diagnostic-core.h"
kono
parents: 67
diff changeset
36 #include "stor-layout.h"
kono
parents: 67
diff changeset
37 #include "except.h"
kono
parents: 67
diff changeset
38 #include "dojump.h"
kono
parents: 67
diff changeset
39 #include "explow.h"
kono
parents: 67
diff changeset
40 #include "expr.h"
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
41 #include "stringpool.h"
111
kono
parents: 67
diff changeset
42 #include "common/common-target.h"
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
43 #include "output.h"
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
44
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
45 static rtx break_out_memory_refs (rtx);
111
kono
parents: 67
diff changeset
46 static void anti_adjust_stack_and_probe_stack_clash (rtx);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
47
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
48
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
49 /* Truncate and perhaps sign-extend C as appropriate for MODE. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
50
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 HOST_WIDE_INT
111
kono
parents: 67
diff changeset
52 trunc_int_for_mode (HOST_WIDE_INT c, machine_mode mode)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
53 {
111
kono
parents: 67
diff changeset
54 /* Not scalar_int_mode because we also allow pointer bound modes. */
kono
parents: 67
diff changeset
55 scalar_mode smode = as_a <scalar_mode> (mode);
kono
parents: 67
diff changeset
56 int width = GET_MODE_PRECISION (smode);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
57
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
58 /* You want to truncate to a _what_? */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
59 gcc_assert (SCALAR_INT_MODE_P (mode));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
60
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
61 /* Canonicalize BImode to 0 and STORE_FLAG_VALUE. */
111
kono
parents: 67
diff changeset
62 if (smode == BImode)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
63 return c & 1 ? STORE_FLAG_VALUE : 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
64
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
65 /* Sign-extend for the requested mode. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
66
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
67 if (width < HOST_BITS_PER_WIDE_INT)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
68 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
69 HOST_WIDE_INT sign = 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
70 sign <<= width - 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
71 c &= (sign << 1) - 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
72 c ^= sign;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
73 c -= sign;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
74 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
75
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 return c;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
77 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
78
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
79 /* Likewise for polynomial values, using the sign-extended representation
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
80 for each individual coefficient. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
81
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
82 poly_int64
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
83 trunc_int_for_mode (poly_int64 x, machine_mode mode)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
84 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
85 for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
86 x.coeffs[i] = trunc_int_for_mode (x.coeffs[i], mode);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
87 return x;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
88 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
89
111
kono
parents: 67
diff changeset
90 /* Return an rtx for the sum of X and the integer C, given that X has
kono
parents: 67
diff changeset
91 mode MODE. INPLACE is true if X can be modified inplace or false
kono
parents: 67
diff changeset
92 if it must be treated as immutable. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
93
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
94 rtx
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
95 plus_constant (machine_mode mode, rtx x, poly_int64 c, bool inplace)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
96 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
97 RTX_CODE code;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
98 rtx y;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
99 rtx tem;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
100 int all_constant = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
101
111
kono
parents: 67
diff changeset
102 gcc_assert (GET_MODE (x) == VOIDmode || GET_MODE (x) == mode);
kono
parents: 67
diff changeset
103
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
104 if (known_eq (c, 0))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
105 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
106
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 restart:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
108
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
109 code = GET_CODE (x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
110 y = x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
111
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
112 switch (code)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
113 {
111
kono
parents: 67
diff changeset
114 CASE_CONST_SCALAR_INT:
kono
parents: 67
diff changeset
115 return immed_wide_int_const (wi::add (rtx_mode_t (x, mode), c), mode);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
116 case MEM:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
117 /* If this is a reference to the constant pool, try replacing it with
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
118 a reference to a new constant. If the resulting address isn't
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
119 valid, don't return it because we have no way to validize it. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
120 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
121 && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
122 {
111
kono
parents: 67
diff changeset
123 rtx cst = get_pool_constant (XEXP (x, 0));
kono
parents: 67
diff changeset
124
kono
parents: 67
diff changeset
125 if (GET_CODE (cst) == CONST_VECTOR
kono
parents: 67
diff changeset
126 && GET_MODE_INNER (GET_MODE (cst)) == mode)
kono
parents: 67
diff changeset
127 {
kono
parents: 67
diff changeset
128 cst = gen_lowpart (mode, cst);
kono
parents: 67
diff changeset
129 gcc_assert (cst);
kono
parents: 67
diff changeset
130 }
kono
parents: 67
diff changeset
131 if (GET_MODE (cst) == VOIDmode || GET_MODE (cst) == mode)
kono
parents: 67
diff changeset
132 {
kono
parents: 67
diff changeset
133 tem = plus_constant (mode, cst, c);
kono
parents: 67
diff changeset
134 tem = force_const_mem (GET_MODE (x), tem);
kono
parents: 67
diff changeset
135 /* Targets may disallow some constants in the constant pool, thus
kono
parents: 67
diff changeset
136 force_const_mem may return NULL_RTX. */
kono
parents: 67
diff changeset
137 if (tem && memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
kono
parents: 67
diff changeset
138 return tem;
kono
parents: 67
diff changeset
139 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
140 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
141 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
142
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
143 case CONST:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
144 /* If adding to something entirely constant, set a flag
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
145 so that we can add a CONST around the result. */
111
kono
parents: 67
diff changeset
146 if (inplace && shared_const_p (x))
kono
parents: 67
diff changeset
147 inplace = false;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
148 x = XEXP (x, 0);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
149 all_constant = 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
150 goto restart;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
151
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
152 case SYMBOL_REF:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
153 case LABEL_REF:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
154 all_constant = 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
155 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
156
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
157 case PLUS:
111
kono
parents: 67
diff changeset
158 /* The interesting case is adding the integer to a sum. Look
kono
parents: 67
diff changeset
159 for constant term in the sum and combine with C. For an
kono
parents: 67
diff changeset
160 integer constant term or a constant term that is not an
kono
parents: 67
diff changeset
161 explicit integer, we combine or group them together anyway.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
162
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
163 We may not immediately return from the recursive call here, lest
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
164 all_constant gets lost. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
165
111
kono
parents: 67
diff changeset
166 if (CONSTANT_P (XEXP (x, 1)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
167 {
111
kono
parents: 67
diff changeset
168 rtx term = plus_constant (mode, XEXP (x, 1), c, inplace);
kono
parents: 67
diff changeset
169 if (term == const0_rtx)
kono
parents: 67
diff changeset
170 x = XEXP (x, 0);
kono
parents: 67
diff changeset
171 else if (inplace)
kono
parents: 67
diff changeset
172 XEXP (x, 1) = term;
kono
parents: 67
diff changeset
173 else
kono
parents: 67
diff changeset
174 x = gen_rtx_PLUS (mode, XEXP (x, 0), term);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
175 c = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
176 }
111
kono
parents: 67
diff changeset
177 else if (rtx *const_loc = find_constant_term_loc (&y))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
178 {
111
kono
parents: 67
diff changeset
179 if (!inplace)
kono
parents: 67
diff changeset
180 {
kono
parents: 67
diff changeset
181 /* We need to be careful since X may be shared and we can't
kono
parents: 67
diff changeset
182 modify it in place. */
kono
parents: 67
diff changeset
183 x = copy_rtx (x);
kono
parents: 67
diff changeset
184 const_loc = find_constant_term_loc (&x);
kono
parents: 67
diff changeset
185 }
kono
parents: 67
diff changeset
186 *const_loc = plus_constant (mode, *const_loc, c, true);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
187 c = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
188 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
189 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
190
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
191 default:
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
192 if (CONST_POLY_INT_P (x))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
193 return immed_wide_int_const (const_poly_int_value (x) + c, mode);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
194 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
195 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
196
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
197 if (maybe_ne (c, 0))
111
kono
parents: 67
diff changeset
198 x = gen_rtx_PLUS (mode, x, gen_int_mode (c, mode));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
199
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
200 if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
201 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
202 else if (all_constant)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 return gen_rtx_CONST (mode, x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
204 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
205 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
206 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
207
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
208 /* If X is a sum, return a new sum like X but lacking any constant terms.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
209 Add all the removed constant terms into *CONSTPTR.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
210 X itself is not altered. The result != X if and only if
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
211 it is not isomorphic to X. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
212
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
213 rtx
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
214 eliminate_constant_term (rtx x, rtx *constptr)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
215 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
216 rtx x0, x1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
217 rtx tem;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
218
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
219 if (GET_CODE (x) != PLUS)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
220 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
221
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
222 /* First handle constants appearing at this level explicitly. */
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
223 if (CONST_INT_P (XEXP (x, 1))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
224 && (tem = simplify_binary_operation (PLUS, GET_MODE (x), *constptr,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
225 XEXP (x, 1))) != 0
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
226 && CONST_INT_P (tem))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
227 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
228 *constptr = tem;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
229 return eliminate_constant_term (XEXP (x, 0), constptr);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
230 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
231
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
232 tem = const0_rtx;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
233 x0 = eliminate_constant_term (XEXP (x, 0), &tem);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
234 x1 = eliminate_constant_term (XEXP (x, 1), &tem);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
235 if ((x1 != XEXP (x, 1) || x0 != XEXP (x, 0))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
236 && (tem = simplify_binary_operation (PLUS, GET_MODE (x),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
237 *constptr, tem)) != 0
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
238 && CONST_INT_P (tem))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
239 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
240 *constptr = tem;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
241 return gen_rtx_PLUS (GET_MODE (x), x0, x1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
242 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
243
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
244 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
245 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
246
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
247
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
248 /* Return a copy of X in which all memory references
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
249 and all constants that involve symbol refs
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
250 have been replaced with new temporary registers.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
251 Also emit code to load the memory locations and constants
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
252 into those registers.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
253
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
254 If X contains no such constants or memory references,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
255 X itself (not a copy) is returned.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
256
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
257 If a constant is found in the address that is not a legitimate constant
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
258 in an insn, it is left alone in the hope that it might be valid in the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
259 address.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
260
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
261 X may contain no arithmetic except addition, subtraction and multiplication.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
262 Values returned by expand_expr with 1 for sum_ok fit this constraint. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
263
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
264 static rtx
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
265 break_out_memory_refs (rtx x)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
266 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
267 if (MEM_P (x)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
268 || (CONSTANT_P (x) && CONSTANT_ADDRESS_P (x)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
269 && GET_MODE (x) != VOIDmode))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
270 x = force_reg (GET_MODE (x), x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
271 else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
272 || GET_CODE (x) == MULT)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
273 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
274 rtx op0 = break_out_memory_refs (XEXP (x, 0));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
275 rtx op1 = break_out_memory_refs (XEXP (x, 1));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
276
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
277 if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
278 x = simplify_gen_binary (GET_CODE (x), GET_MODE (x), op0, op1);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
279 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
280
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
281 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
282 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
283
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
284 /* Given X, a memory address in address space AS' pointer mode, convert it to
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
285 an address in the address space's address mode, or vice versa (TO_MODE says
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
286 which way). We take advantage of the fact that pointers are not allowed to
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
287 overflow by commuting arithmetic operations over conversions so that address
111
kono
parents: 67
diff changeset
288 arithmetic insns can be used. IN_CONST is true if this conversion is inside
kono
parents: 67
diff changeset
289 a CONST. NO_EMIT is true if no insns should be emitted, and instead
kono
parents: 67
diff changeset
290 it should return NULL if it can't be simplified without emitting insns. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
291
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
292 rtx
111
kono
parents: 67
diff changeset
293 convert_memory_address_addr_space_1 (scalar_int_mode to_mode ATTRIBUTE_UNUSED,
kono
parents: 67
diff changeset
294 rtx x, addr_space_t as ATTRIBUTE_UNUSED,
kono
parents: 67
diff changeset
295 bool in_const ATTRIBUTE_UNUSED,
kono
parents: 67
diff changeset
296 bool no_emit ATTRIBUTE_UNUSED)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
297 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
298 #ifndef POINTERS_EXTEND_UNSIGNED
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
299 gcc_assert (GET_MODE (x) == to_mode || GET_MODE (x) == VOIDmode);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
300 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
301 #else /* defined(POINTERS_EXTEND_UNSIGNED) */
111
kono
parents: 67
diff changeset
302 scalar_int_mode pointer_mode, address_mode, from_mode;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
303 rtx temp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
304 enum rtx_code code;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
305
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
306 /* If X already has the right mode, just return it. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
307 if (GET_MODE (x) == to_mode)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
308 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
309
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
310 pointer_mode = targetm.addr_space.pointer_mode (as);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
311 address_mode = targetm.addr_space.address_mode (as);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
312 from_mode = to_mode == pointer_mode ? address_mode : pointer_mode;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
313
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
314 /* Here we handle some special cases. If none of them apply, fall through
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
315 to the default case. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
316 switch (GET_CODE (x))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
317 {
111
kono
parents: 67
diff changeset
318 CASE_CONST_SCALAR_INT:
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
319 if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
320 code = TRUNCATE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
321 else if (POINTERS_EXTEND_UNSIGNED < 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
322 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
323 else if (POINTERS_EXTEND_UNSIGNED > 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
324 code = ZERO_EXTEND;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
325 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
326 code = SIGN_EXTEND;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
327 temp = simplify_unary_operation (code, to_mode, x, from_mode);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
328 if (temp)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
329 return temp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
330 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
331
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
332 case SUBREG:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
333 if ((SUBREG_PROMOTED_VAR_P (x) || REG_POINTER (SUBREG_REG (x)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
334 && GET_MODE (SUBREG_REG (x)) == to_mode)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
335 return SUBREG_REG (x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
336 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
337
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
338 case LABEL_REF:
111
kono
parents: 67
diff changeset
339 temp = gen_rtx_LABEL_REF (to_mode, label_ref_label (x));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
340 LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
341 return temp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
342
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
343 case SYMBOL_REF:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
344 temp = shallow_copy_rtx (x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
345 PUT_MODE (temp, to_mode);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
346 return temp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
347
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
348 case CONST:
111
kono
parents: 67
diff changeset
349 temp = convert_memory_address_addr_space_1 (to_mode, XEXP (x, 0), as,
kono
parents: 67
diff changeset
350 true, no_emit);
kono
parents: 67
diff changeset
351 return temp ? gen_rtx_CONST (to_mode, temp) : temp;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
352
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
353 case PLUS:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
354 case MULT:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
355 /* For addition we can safely permute the conversion and addition
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
356 operation if one operand is a constant and converting the constant
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
357 does not change it or if one operand is a constant and we are
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
358 using a ptr_extend instruction (POINTERS_EXTEND_UNSIGNED < 0).
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
359 We can always safely permute them if we are making the address
111
kono
parents: 67
diff changeset
360 narrower. Inside a CONST RTL, this is safe for both pointers
kono
parents: 67
diff changeset
361 zero or sign extended as pointers cannot wrap. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
362 if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
363 || (GET_CODE (x) == PLUS
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
364 && CONST_INT_P (XEXP (x, 1))
111
kono
parents: 67
diff changeset
365 && ((in_const && POINTERS_EXTEND_UNSIGNED != 0)
kono
parents: 67
diff changeset
366 || XEXP (x, 1) == convert_memory_address_addr_space_1
kono
parents: 67
diff changeset
367 (to_mode, XEXP (x, 1), as, in_const,
kono
parents: 67
diff changeset
368 no_emit)
kono
parents: 67
diff changeset
369 || POINTERS_EXTEND_UNSIGNED < 0)))
kono
parents: 67
diff changeset
370 {
kono
parents: 67
diff changeset
371 temp = convert_memory_address_addr_space_1 (to_mode, XEXP (x, 0),
kono
parents: 67
diff changeset
372 as, in_const, no_emit);
kono
parents: 67
diff changeset
373 return (temp ? gen_rtx_fmt_ee (GET_CODE (x), to_mode,
kono
parents: 67
diff changeset
374 temp, XEXP (x, 1))
kono
parents: 67
diff changeset
375 : temp);
kono
parents: 67
diff changeset
376 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
377 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
378
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
379 default:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
380 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
381 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
382
111
kono
parents: 67
diff changeset
383 if (no_emit)
kono
parents: 67
diff changeset
384 return NULL_RTX;
kono
parents: 67
diff changeset
385
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
386 return convert_modes (to_mode, from_mode,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
387 x, POINTERS_EXTEND_UNSIGNED);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
388 #endif /* defined(POINTERS_EXTEND_UNSIGNED) */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
389 }
111
kono
parents: 67
diff changeset
390
kono
parents: 67
diff changeset
391 /* Given X, a memory address in address space AS' pointer mode, convert it to
kono
parents: 67
diff changeset
392 an address in the address space's address mode, or vice versa (TO_MODE says
kono
parents: 67
diff changeset
393 which way). We take advantage of the fact that pointers are not allowed to
kono
parents: 67
diff changeset
394 overflow by commuting arithmetic operations over conversions so that address
kono
parents: 67
diff changeset
395 arithmetic insns can be used. */
kono
parents: 67
diff changeset
396
kono
parents: 67
diff changeset
397 rtx
kono
parents: 67
diff changeset
398 convert_memory_address_addr_space (scalar_int_mode to_mode, rtx x,
kono
parents: 67
diff changeset
399 addr_space_t as)
kono
parents: 67
diff changeset
400 {
kono
parents: 67
diff changeset
401 return convert_memory_address_addr_space_1 (to_mode, x, as, false, false);
kono
parents: 67
diff changeset
402 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
403
111
kono
parents: 67
diff changeset
404
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
405 /* Return something equivalent to X but valid as a memory address for something
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
406 of mode MODE in the named address space AS. When X is not itself valid,
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
407 this works by copying X or subexpressions of it into registers. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
408
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
409 rtx
111
kono
parents: 67
diff changeset
410 memory_address_addr_space (machine_mode mode, rtx x, addr_space_t as)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
411 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
412 rtx oldx = x;
111
kono
parents: 67
diff changeset
413 scalar_int_mode address_mode = targetm.addr_space.address_mode (as);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
414
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
415 x = convert_memory_address_addr_space (address_mode, x, as);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
416
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
417 /* By passing constant addresses through registers
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
418 we get a chance to cse them. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
419 if (! cse_not_expected && CONSTANT_P (x) && CONSTANT_ADDRESS_P (x))
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
420 x = force_reg (address_mode, x);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
421
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
422 /* We get better cse by rejecting indirect addressing at this stage.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
423 Let the combiner create indirect addresses where appropriate.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
424 For now, generate the code so that the subexpressions useful to share
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
425 are visible. But not if cse won't be done! */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
426 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
427 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
428 if (! cse_not_expected && !REG_P (x))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
429 x = break_out_memory_refs (x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
430
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
431 /* At this point, any valid address is accepted. */
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
432 if (memory_address_addr_space_p (mode, x, as))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
433 goto done;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
434
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
435 /* If it was valid before but breaking out memory refs invalidated it,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
436 use it the old way. */
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
437 if (memory_address_addr_space_p (mode, oldx, as))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
438 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
439 x = oldx;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
440 goto done;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
441 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
442
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
443 /* Perform machine-dependent transformations on X
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
444 in certain cases. This is not necessary since the code
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
445 below can handle all possible cases, but machine-dependent
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
446 transformations can make better code. */
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
447 {
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
448 rtx orig_x = x;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
449 x = targetm.addr_space.legitimize_address (x, oldx, mode, as);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
450 if (orig_x != x && memory_address_addr_space_p (mode, x, as))
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
451 goto done;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
452 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
453
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
454 /* PLUS and MULT can appear in special ways
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
455 as the result of attempts to make an address usable for indexing.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
456 Usually they are dealt with by calling force_operand, below.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
457 But a sum containing constant terms is special
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
458 if removing them makes the sum a valid address:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
459 then we generate that address in a register
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
460 and index off of it. We do this because it often makes
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
461 shorter code, and because the addresses thus generated
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
462 in registers often become common subexpressions. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
463 if (GET_CODE (x) == PLUS)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
464 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
465 rtx constant_term = const0_rtx;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
466 rtx y = eliminate_constant_term (x, &constant_term);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
467 if (constant_term == const0_rtx
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
468 || ! memory_address_addr_space_p (mode, y, as))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
469 x = force_operand (x, NULL_RTX);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
470 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
471 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
472 y = gen_rtx_PLUS (GET_MODE (x), copy_to_reg (y), constant_term);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
473 if (! memory_address_addr_space_p (mode, y, as))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
474 x = force_operand (x, NULL_RTX);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
475 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
476 x = y;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
477 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
478 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
479
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
480 else if (GET_CODE (x) == MULT || GET_CODE (x) == MINUS)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
481 x = force_operand (x, NULL_RTX);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
482
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
483 /* If we have a register that's an invalid address,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
484 it must be a hard reg of the wrong class. Copy it to a pseudo. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
485 else if (REG_P (x))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
486 x = copy_to_reg (x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
487
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
488 /* Last resort: copy the value to a register, since
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
489 the register is a valid address. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
490 else
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
491 x = force_reg (address_mode, x);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
492 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
493
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
494 done:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
495
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
496 gcc_assert (memory_address_addr_space_p (mode, x, as));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
497 /* If we didn't change the address, we are done. Otherwise, mark
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
498 a reg as a pointer if we have REG or REG + CONST_INT. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
499 if (oldx == x)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
500 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
501 else if (REG_P (x))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
502 mark_reg_pointer (x, BITS_PER_UNIT);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
503 else if (GET_CODE (x) == PLUS
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
504 && REG_P (XEXP (x, 0))
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
505 && CONST_INT_P (XEXP (x, 1)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
506 mark_reg_pointer (XEXP (x, 0), BITS_PER_UNIT);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
507
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
508 /* OLDX may have been the address on a temporary. Update the address
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
509 to indicate that X is now used. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
510 update_temp_slot_address (oldx, x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
511
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
512 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
513 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
514
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
515 /* Convert a mem ref into one with a valid memory address.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
516 Pass through anything else unchanged. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
517
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
518 rtx
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
519 validize_mem (rtx ref)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
520 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
521 if (!MEM_P (ref))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
522 return ref;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
523 ref = use_anchored_address (ref);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
524 if (memory_address_addr_space_p (GET_MODE (ref), XEXP (ref, 0),
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
525 MEM_ADDR_SPACE (ref)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
526 return ref;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
527
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
528 /* Don't alter REF itself, since that is probably a stack slot. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
529 return replace_equiv_address (ref, XEXP (ref, 0));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
530 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
531
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
532 /* If X is a memory reference to a member of an object block, try rewriting
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
533 it to use an anchor instead. Return the new memory reference on success
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
534 and the old one on failure. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
535
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
536 rtx
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
537 use_anchored_address (rtx x)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
538 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
539 rtx base;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
540 HOST_WIDE_INT offset;
111
kono
parents: 67
diff changeset
541 machine_mode mode;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
542
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
543 if (!flag_section_anchors)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
544 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
545
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
546 if (!MEM_P (x))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
547 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
548
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
549 /* Split the address into a base and offset. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
550 base = XEXP (x, 0);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
551 offset = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
552 if (GET_CODE (base) == CONST
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
553 && GET_CODE (XEXP (base, 0)) == PLUS
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
554 && CONST_INT_P (XEXP (XEXP (base, 0), 1)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
555 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
556 offset += INTVAL (XEXP (XEXP (base, 0), 1));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
557 base = XEXP (XEXP (base, 0), 0);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
558 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
559
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
560 /* Check whether BASE is suitable for anchors. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
561 if (GET_CODE (base) != SYMBOL_REF
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
562 || !SYMBOL_REF_HAS_BLOCK_INFO_P (base)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
563 || SYMBOL_REF_ANCHOR_P (base)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
564 || SYMBOL_REF_BLOCK (base) == NULL
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
565 || !targetm.use_anchors_for_symbol_p (base))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
566 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
567
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
568 /* Decide where BASE is going to be. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
569 place_block_symbol (base);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
570
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
571 /* Get the anchor we need to use. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
572 offset += SYMBOL_REF_BLOCK_OFFSET (base);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
573 base = get_section_anchor (SYMBOL_REF_BLOCK (base), offset,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
574 SYMBOL_REF_TLS_MODEL (base));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
575
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
576 /* Work out the offset from the anchor. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
577 offset -= SYMBOL_REF_BLOCK_OFFSET (base);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
578
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
579 /* If we're going to run a CSE pass, force the anchor into a register.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
580 We will then be able to reuse registers for several accesses, if the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
581 target costs say that that's worthwhile. */
111
kono
parents: 67
diff changeset
582 mode = GET_MODE (base);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
583 if (!cse_not_expected)
111
kono
parents: 67
diff changeset
584 base = force_reg (mode, base);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
585
111
kono
parents: 67
diff changeset
586 return replace_equiv_address (x, plus_constant (mode, base, offset));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
587 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
588
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
589 /* Copy the value or contents of X to a new temp reg and return that reg. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
590
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
591 rtx
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
592 copy_to_reg (rtx x)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
593 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
594 rtx temp = gen_reg_rtx (GET_MODE (x));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
595
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
596 /* If not an operand, must be an address with PLUS and MULT so
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
597 do the computation. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
598 if (! general_operand (x, VOIDmode))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
599 x = force_operand (x, temp);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
600
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
601 if (x != temp)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
602 emit_move_insn (temp, x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
603
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
604 return temp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
605 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
606
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
607 /* Like copy_to_reg but always give the new register mode Pmode
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
608 in case X is a constant. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
609
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
610 rtx
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
611 copy_addr_to_reg (rtx x)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
612 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
613 return copy_to_mode_reg (Pmode, x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
614 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
615
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
616 /* Like copy_to_reg but always give the new register mode MODE
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
617 in case X is a constant. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
618
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
619 rtx
111
kono
parents: 67
diff changeset
620 copy_to_mode_reg (machine_mode mode, rtx x)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
621 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
622 rtx temp = gen_reg_rtx (mode);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
623
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
624 /* If not an operand, must be an address with PLUS and MULT so
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
625 do the computation. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
626 if (! general_operand (x, VOIDmode))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
627 x = force_operand (x, temp);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
628
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
629 gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
630 if (x != temp)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
631 emit_move_insn (temp, x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
632 return temp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
633 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
634
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
635 /* Load X into a register if it is not already one.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
636 Use mode MODE for the register.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
637 X should be valid for mode MODE, but it may be a constant which
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
638 is valid for all integer modes; that's why caller must specify MODE.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
639
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
640 The caller must not alter the value in the register we return,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
641 since we mark it as a "constant" register. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
642
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
643 rtx
111
kono
parents: 67
diff changeset
644 force_reg (machine_mode mode, rtx x)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
645 {
111
kono
parents: 67
diff changeset
646 rtx temp, set;
kono
parents: 67
diff changeset
647 rtx_insn *insn;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
648
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
649 if (REG_P (x))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
650 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
651
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
652 if (general_operand (x, mode))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
653 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
654 temp = gen_reg_rtx (mode);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
655 insn = emit_move_insn (temp, x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
656 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
657 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
658 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
659 temp = force_operand (x, NULL_RTX);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
660 if (REG_P (temp))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
661 insn = get_last_insn ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
662 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
663 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
664 rtx temp2 = gen_reg_rtx (mode);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
665 insn = emit_move_insn (temp2, temp);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
666 temp = temp2;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
667 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
668 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
669
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
670 /* Let optimizers know that TEMP's value never changes
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
671 and that X can be substituted for it. Don't get confused
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
672 if INSN set something else (such as a SUBREG of TEMP). */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
673 if (CONSTANT_P (x)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
674 && (set = single_set (insn)) != 0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
675 && SET_DEST (set) == temp
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
676 && ! rtx_equal_p (x, SET_SRC (set)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
677 set_unique_reg_note (insn, REG_EQUAL, x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
678
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
679 /* Let optimizers know that TEMP is a pointer, and if so, the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
680 known alignment of that pointer. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
681 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
682 unsigned align = 0;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
683 if (GET_CODE (x) == SYMBOL_REF)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
684 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
685 align = BITS_PER_UNIT;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
686 if (SYMBOL_REF_DECL (x) && DECL_P (SYMBOL_REF_DECL (x)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
687 align = DECL_ALIGN (SYMBOL_REF_DECL (x));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
688 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
689 else if (GET_CODE (x) == LABEL_REF)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
690 align = BITS_PER_UNIT;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
691 else if (GET_CODE (x) == CONST
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
692 && GET_CODE (XEXP (x, 0)) == PLUS
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
693 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
694 && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
695 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
696 rtx s = XEXP (XEXP (x, 0), 0);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
697 rtx c = XEXP (XEXP (x, 0), 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
698 unsigned sa, ca;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
699
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
700 sa = BITS_PER_UNIT;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
701 if (SYMBOL_REF_DECL (s) && DECL_P (SYMBOL_REF_DECL (s)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
702 sa = DECL_ALIGN (SYMBOL_REF_DECL (s));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
703
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
704 if (INTVAL (c) == 0)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
705 align = sa;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
706 else
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
707 {
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
708 ca = ctz_hwi (INTVAL (c)) * BITS_PER_UNIT;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
709 align = MIN (sa, ca);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
710 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
711 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
712
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
713 if (align || (MEM_P (x) && MEM_POINTER (x)))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
714 mark_reg_pointer (temp, align);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
715 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
716
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
717 return temp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
718 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
719
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
720 /* If X is a memory ref, copy its contents to a new temp reg and return
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
721 that reg. Otherwise, return X. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
722
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
723 rtx
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
724 force_not_mem (rtx x)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
725 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
726 rtx temp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
727
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
728 if (!MEM_P (x) || GET_MODE (x) == BLKmode)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
729 return x;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
730
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
731 temp = gen_reg_rtx (GET_MODE (x));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
732
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
733 if (MEM_POINTER (x))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
734 REG_POINTER (temp) = 1;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
735
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
736 emit_move_insn (temp, x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
737 return temp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
738 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
739
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
740 /* Copy X to TARGET (if it's nonzero and a reg)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
741 or to a new temp reg and return that reg.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
742 MODE is the mode to use for X in case it is a constant. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
743
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
744 rtx
111
kono
parents: 67
diff changeset
745 copy_to_suggested_reg (rtx x, rtx target, machine_mode mode)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
746 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
747 rtx temp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
748
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
749 if (target && REG_P (target))
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
750 temp = target;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
751 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
752 temp = gen_reg_rtx (mode);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
753
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
754 emit_move_insn (temp, x);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
755 return temp;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
756 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
757
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
758 /* Return the mode to use to pass or return a scalar of TYPE and MODE.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
759 PUNSIGNEDP points to the signedness of the type and may be adjusted
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
760 to show what signedness to use on extension operations.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
761
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
762 FOR_RETURN is nonzero if the caller is promoting the return value
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
763 of FNDECL, else it is for promoting args. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
764
111
kono
parents: 67
diff changeset
765 machine_mode
kono
parents: 67
diff changeset
766 promote_function_mode (const_tree type, machine_mode mode, int *punsignedp,
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
767 const_tree funtype, int for_return)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
768 {
111
kono
parents: 67
diff changeset
769 /* Called without a type node for a libcall. */
kono
parents: 67
diff changeset
770 if (type == NULL_TREE)
kono
parents: 67
diff changeset
771 {
kono
parents: 67
diff changeset
772 if (INTEGRAL_MODE_P (mode))
kono
parents: 67
diff changeset
773 return targetm.calls.promote_function_mode (NULL_TREE, mode,
kono
parents: 67
diff changeset
774 punsignedp, funtype,
kono
parents: 67
diff changeset
775 for_return);
kono
parents: 67
diff changeset
776 else
kono
parents: 67
diff changeset
777 return mode;
kono
parents: 67
diff changeset
778 }
kono
parents: 67
diff changeset
779
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
780 switch (TREE_CODE (type))
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
781 {
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
782 case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
783 case REAL_TYPE: case OFFSET_TYPE: case FIXED_POINT_TYPE:
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
784 case POINTER_TYPE: case REFERENCE_TYPE:
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
785 return targetm.calls.promote_function_mode (type, mode, punsignedp, funtype,
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
786 for_return);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
787
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
788 default:
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
789 return mode;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
790 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
791 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
792 /* Return the mode to use to store a scalar of TYPE and MODE.
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
793 PUNSIGNEDP points to the signedness of the type and may be adjusted
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
794 to show what signedness to use on extension operations. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
795
111
kono
parents: 67
diff changeset
796 machine_mode
kono
parents: 67
diff changeset
797 promote_mode (const_tree type ATTRIBUTE_UNUSED, machine_mode mode,
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
798 int *punsignedp ATTRIBUTE_UNUSED)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
799 {
111
kono
parents: 67
diff changeset
800 #ifdef PROMOTE_MODE
kono
parents: 67
diff changeset
801 enum tree_code code;
kono
parents: 67
diff changeset
802 int unsignedp;
kono
parents: 67
diff changeset
803 scalar_mode smode;
kono
parents: 67
diff changeset
804 #endif
kono
parents: 67
diff changeset
805
kono
parents: 67
diff changeset
806 /* For libcalls this is invoked without TYPE from the backends
kono
parents: 67
diff changeset
807 TARGET_PROMOTE_FUNCTION_MODE hooks. Don't do anything in that
kono
parents: 67
diff changeset
808 case. */
kono
parents: 67
diff changeset
809 if (type == NULL_TREE)
kono
parents: 67
diff changeset
810 return mode;
kono
parents: 67
diff changeset
811
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
812 /* FIXME: this is the same logic that was there until GCC 4.4, but we
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
813 probably want to test POINTERS_EXTEND_UNSIGNED even if PROMOTE_MODE
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
814 is not defined. The affected targets are M32C, S390, SPARC. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
815 #ifdef PROMOTE_MODE
111
kono
parents: 67
diff changeset
816 code = TREE_CODE (type);
kono
parents: 67
diff changeset
817 unsignedp = *punsignedp;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
818
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
819 switch (code)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
820 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
821 case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
822 case REAL_TYPE: case OFFSET_TYPE: case FIXED_POINT_TYPE:
111
kono
parents: 67
diff changeset
823 /* Values of these types always have scalar mode. */
kono
parents: 67
diff changeset
824 smode = as_a <scalar_mode> (mode);
kono
parents: 67
diff changeset
825 PROMOTE_MODE (smode, unsignedp, type);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
826 *punsignedp = unsignedp;
111
kono
parents: 67
diff changeset
827 return smode;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
828
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
829 #ifdef POINTERS_EXTEND_UNSIGNED
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
830 case REFERENCE_TYPE:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
831 case POINTER_TYPE:
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
832 *punsignedp = POINTERS_EXTEND_UNSIGNED;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
833 return targetm.addr_space.address_mode
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
834 (TYPE_ADDR_SPACE (TREE_TYPE (type)));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
835 #endif
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
836
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
837 default:
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
838 return mode;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
839 }
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
840 #else
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
841 return mode;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
842 #endif
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
843 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
844
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
845
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
846 /* Use one of promote_mode or promote_function_mode to find the promoted
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
847 mode of DECL. If PUNSIGNEDP is not NULL, store there the unsignedness
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
848 of DECL after promotion. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
849
111
kono
parents: 67
diff changeset
850 machine_mode
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
851 promote_decl_mode (const_tree decl, int *punsignedp)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
852 {
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
853 tree type = TREE_TYPE (decl);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
854 int unsignedp = TYPE_UNSIGNED (type);
111
kono
parents: 67
diff changeset
855 machine_mode mode = DECL_MODE (decl);
kono
parents: 67
diff changeset
856 machine_mode pmode;
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
857
111
kono
parents: 67
diff changeset
858 if (TREE_CODE (decl) == RESULT_DECL && !DECL_BY_REFERENCE (decl))
kono
parents: 67
diff changeset
859 pmode = promote_function_mode (type, mode, &unsignedp,
kono
parents: 67
diff changeset
860 TREE_TYPE (current_function_decl), 1);
kono
parents: 67
diff changeset
861 else if (TREE_CODE (decl) == RESULT_DECL || TREE_CODE (decl) == PARM_DECL)
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
862 pmode = promote_function_mode (type, mode, &unsignedp,
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
863 TREE_TYPE (current_function_decl), 2);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
864 else
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
865 pmode = promote_mode (type, mode, &unsignedp);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
866
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
867 if (punsignedp)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
868 *punsignedp = unsignedp;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
869 return pmode;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
870 }
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
871
111
kono
parents: 67
diff changeset
872 /* Return the promoted mode for name. If it is a named SSA_NAME, it
kono
parents: 67
diff changeset
873 is the same as promote_decl_mode. Otherwise, it is the promoted
kono
parents: 67
diff changeset
874 mode of a temp decl of same type as the SSA_NAME, if we had created
kono
parents: 67
diff changeset
875 one. */
kono
parents: 67
diff changeset
876
kono
parents: 67
diff changeset
877 machine_mode
kono
parents: 67
diff changeset
878 promote_ssa_mode (const_tree name, int *punsignedp)
kono
parents: 67
diff changeset
879 {
kono
parents: 67
diff changeset
880 gcc_assert (TREE_CODE (name) == SSA_NAME);
kono
parents: 67
diff changeset
881
kono
parents: 67
diff changeset
882 /* Partitions holding parms and results must be promoted as expected
kono
parents: 67
diff changeset
883 by function.c. */
kono
parents: 67
diff changeset
884 if (SSA_NAME_VAR (name)
kono
parents: 67
diff changeset
885 && (TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL
kono
parents: 67
diff changeset
886 || TREE_CODE (SSA_NAME_VAR (name)) == RESULT_DECL))
kono
parents: 67
diff changeset
887 {
kono
parents: 67
diff changeset
888 machine_mode mode = promote_decl_mode (SSA_NAME_VAR (name), punsignedp);
kono
parents: 67
diff changeset
889 if (mode != BLKmode)
kono
parents: 67
diff changeset
890 return mode;
kono
parents: 67
diff changeset
891 }
kono
parents: 67
diff changeset
892
kono
parents: 67
diff changeset
893 tree type = TREE_TYPE (name);
kono
parents: 67
diff changeset
894 int unsignedp = TYPE_UNSIGNED (type);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
895 machine_mode pmode = promote_mode (type, TYPE_MODE (type), &unsignedp);
111
kono
parents: 67
diff changeset
896 if (punsignedp)
kono
parents: 67
diff changeset
897 *punsignedp = unsignedp;
kono
parents: 67
diff changeset
898
kono
parents: 67
diff changeset
899 return pmode;
kono
parents: 67
diff changeset
900 }
kono
parents: 67
diff changeset
901
kono
parents: 67
diff changeset
902
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
903
111
kono
parents: 67
diff changeset
904 /* Controls the behavior of {anti_,}adjust_stack. */
kono
parents: 67
diff changeset
905 static bool suppress_reg_args_size;
kono
parents: 67
diff changeset
906
kono
parents: 67
diff changeset
907 /* A helper for adjust_stack and anti_adjust_stack. */
kono
parents: 67
diff changeset
908
kono
parents: 67
diff changeset
909 static void
kono
parents: 67
diff changeset
910 adjust_stack_1 (rtx adjust, bool anti_p)
kono
parents: 67
diff changeset
911 {
kono
parents: 67
diff changeset
912 rtx temp;
kono
parents: 67
diff changeset
913 rtx_insn *insn;
kono
parents: 67
diff changeset
914
kono
parents: 67
diff changeset
915 /* Hereafter anti_p means subtract_p. */
kono
parents: 67
diff changeset
916 if (!STACK_GROWS_DOWNWARD)
kono
parents: 67
diff changeset
917 anti_p = !anti_p;
kono
parents: 67
diff changeset
918
kono
parents: 67
diff changeset
919 temp = expand_binop (Pmode,
kono
parents: 67
diff changeset
920 anti_p ? sub_optab : add_optab,
kono
parents: 67
diff changeset
921 stack_pointer_rtx, adjust, stack_pointer_rtx, 0,
kono
parents: 67
diff changeset
922 OPTAB_LIB_WIDEN);
kono
parents: 67
diff changeset
923
kono
parents: 67
diff changeset
924 if (temp != stack_pointer_rtx)
kono
parents: 67
diff changeset
925 insn = emit_move_insn (stack_pointer_rtx, temp);
kono
parents: 67
diff changeset
926 else
kono
parents: 67
diff changeset
927 {
kono
parents: 67
diff changeset
928 insn = get_last_insn ();
kono
parents: 67
diff changeset
929 temp = single_set (insn);
kono
parents: 67
diff changeset
930 gcc_assert (temp != NULL && SET_DEST (temp) == stack_pointer_rtx);
kono
parents: 67
diff changeset
931 }
kono
parents: 67
diff changeset
932
kono
parents: 67
diff changeset
933 if (!suppress_reg_args_size)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
934 add_args_size_note (insn, stack_pointer_delta);
111
kono
parents: 67
diff changeset
935 }
kono
parents: 67
diff changeset
936
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
937 /* Adjust the stack pointer by ADJUST (an rtx for a number of bytes).
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
938 This pops when ADJUST is positive. ADJUST need not be constant. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
939
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
940 void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
941 adjust_stack (rtx adjust)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
942 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
943 if (adjust == const0_rtx)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
944 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
945
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
946 /* We expect all variable sized adjustments to be multiple of
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
947 PREFERRED_STACK_BOUNDARY. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
948 poly_int64 const_adjust;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
949 if (poly_int_rtx_p (adjust, &const_adjust))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
950 stack_pointer_delta -= const_adjust;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
951
111
kono
parents: 67
diff changeset
952 adjust_stack_1 (adjust, false);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
953 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
954
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
955 /* Adjust the stack pointer by minus ADJUST (an rtx for a number of bytes).
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
956 This pushes when ADJUST is positive. ADJUST need not be constant. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
957
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
958 void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
959 anti_adjust_stack (rtx adjust)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
960 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
961 if (adjust == const0_rtx)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
962 return;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
963
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
964 /* We expect all variable sized adjustments to be multiple of
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
965 PREFERRED_STACK_BOUNDARY. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
966 poly_int64 const_adjust;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
967 if (poly_int_rtx_p (adjust, &const_adjust))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
968 stack_pointer_delta += const_adjust;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
969
111
kono
parents: 67
diff changeset
970 adjust_stack_1 (adjust, true);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
971 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
972
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
973 /* Round the size of a block to be pushed up to the boundary required
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
974 by this machine. SIZE is the desired size, which need not be constant. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
975
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
976 static rtx
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
977 round_push (rtx size)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
978 {
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
979 rtx align_rtx, alignm1_rtx;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
980
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
981 if (!SUPPORTS_STACK_ALIGNMENT
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
982 || crtl->preferred_stack_boundary == MAX_SUPPORTED_STACK_ALIGNMENT)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
983 {
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
984 int align = crtl->preferred_stack_boundary / BITS_PER_UNIT;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
985
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
986 if (align == 1)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
987 return size;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
988
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
989 if (CONST_INT_P (size))
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
990 {
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
991 HOST_WIDE_INT new_size = (INTVAL (size) + align - 1) / align * align;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
992
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
993 if (INTVAL (size) != new_size)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
994 size = GEN_INT (new_size);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
995 return size;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
996 }
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
997
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
998 align_rtx = GEN_INT (align);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
999 alignm1_rtx = GEN_INT (align - 1);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1000 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1001 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1002 {
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1003 /* If crtl->preferred_stack_boundary might still grow, use
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1004 virtual_preferred_stack_boundary_rtx instead. This will be
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1005 substituted by the right value in vregs pass and optimized
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1006 during combine. */
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1007 align_rtx = virtual_preferred_stack_boundary_rtx;
111
kono
parents: 67
diff changeset
1008 alignm1_rtx = force_operand (plus_constant (Pmode, align_rtx, -1),
kono
parents: 67
diff changeset
1009 NULL_RTX);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1010 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1011
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1012 /* CEIL_DIV_EXPR needs to worry about the addition overflowing,
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1013 but we know it can't. So add ourselves and then do
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1014 TRUNC_DIV_EXPR. */
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1015 size = expand_binop (Pmode, add_optab, size, alignm1_rtx,
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1016 NULL_RTX, 1, OPTAB_LIB_WIDEN);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1017 size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size, align_rtx,
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1018 NULL_RTX, 1);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1019 size = expand_mult (Pmode, size, align_rtx, NULL_RTX, 1);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1020
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1021 return size;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1022 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1023
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1024 /* Save the stack pointer for the purpose in SAVE_LEVEL. PSAVE is a pointer
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1025 to a previously-created save area. If no save area has been allocated,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1026 this function will allocate one. If a save area is specified, it
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1027 must be of the proper mode. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1028
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1029 void
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1030 emit_stack_save (enum save_level save_level, rtx *psave)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1031 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1032 rtx sa = *psave;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1033 /* The default is that we use a move insn and save in a Pmode object. */
111
kono
parents: 67
diff changeset
1034 rtx_insn *(*fcn) (rtx, rtx) = gen_move_insn;
kono
parents: 67
diff changeset
1035 machine_mode mode = STACK_SAVEAREA_MODE (save_level);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1036
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1037 /* See if this machine has anything special to do for this kind of save. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1038 switch (save_level)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1039 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1040 case SAVE_BLOCK:
111
kono
parents: 67
diff changeset
1041 if (targetm.have_save_stack_block ())
kono
parents: 67
diff changeset
1042 fcn = targetm.gen_save_stack_block;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1043 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1044 case SAVE_FUNCTION:
111
kono
parents: 67
diff changeset
1045 if (targetm.have_save_stack_function ())
kono
parents: 67
diff changeset
1046 fcn = targetm.gen_save_stack_function;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1047 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1048 case SAVE_NONLOCAL:
111
kono
parents: 67
diff changeset
1049 if (targetm.have_save_stack_nonlocal ())
kono
parents: 67
diff changeset
1050 fcn = targetm.gen_save_stack_nonlocal;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1051 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1052 default:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1053 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1054 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1055
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1056 /* If there is no save area and we have to allocate one, do so. Otherwise
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1057 verify the save area is the proper mode. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1058
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1059 if (sa == 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1060 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1061 if (mode != VOIDmode)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1062 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1063 if (save_level == SAVE_NONLOCAL)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1064 *psave = sa = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1065 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1066 *psave = sa = gen_reg_rtx (mode);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1067 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1068 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1069
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1070 do_pending_stack_adjust ();
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1071 if (sa != 0)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1072 sa = validize_mem (sa);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1073 emit_insn (fcn (sa, stack_pointer_rtx));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1074 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1075
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1076 /* Restore the stack pointer for the purpose in SAVE_LEVEL. SA is the save
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1077 area made by emit_stack_save. If it is zero, we have nothing to do. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1078
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1079 void
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1080 emit_stack_restore (enum save_level save_level, rtx sa)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1081 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1082 /* The default is that we use a move insn. */
111
kono
parents: 67
diff changeset
1083 rtx_insn *(*fcn) (rtx, rtx) = gen_move_insn;
kono
parents: 67
diff changeset
1084
kono
parents: 67
diff changeset
1085 /* If stack_realign_drap, the x86 backend emits a prologue that aligns both
kono
parents: 67
diff changeset
1086 STACK_POINTER and HARD_FRAME_POINTER.
kono
parents: 67
diff changeset
1087 If stack_realign_fp, the x86 backend emits a prologue that aligns only
kono
parents: 67
diff changeset
1088 STACK_POINTER. This renders the HARD_FRAME_POINTER unusable for accessing
kono
parents: 67
diff changeset
1089 aligned variables, which is reflected in ix86_can_eliminate.
kono
parents: 67
diff changeset
1090 We normally still have the realigned STACK_POINTER that we can use.
kono
parents: 67
diff changeset
1091 But if there is a stack restore still present at reload, it can trigger
kono
parents: 67
diff changeset
1092 mark_not_eliminable for the STACK_POINTER, leaving no way to eliminate
kono
parents: 67
diff changeset
1093 FRAME_POINTER into a hard reg.
kono
parents: 67
diff changeset
1094 To prevent this situation, we force need_drap if we emit a stack
kono
parents: 67
diff changeset
1095 restore. */
kono
parents: 67
diff changeset
1096 if (SUPPORTS_STACK_ALIGNMENT)
kono
parents: 67
diff changeset
1097 crtl->need_drap = true;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1098
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1099 /* See if this machine has anything special to do for this kind of save. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1100 switch (save_level)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1101 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1102 case SAVE_BLOCK:
111
kono
parents: 67
diff changeset
1103 if (targetm.have_restore_stack_block ())
kono
parents: 67
diff changeset
1104 fcn = targetm.gen_restore_stack_block;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1105 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1106 case SAVE_FUNCTION:
111
kono
parents: 67
diff changeset
1107 if (targetm.have_restore_stack_function ())
kono
parents: 67
diff changeset
1108 fcn = targetm.gen_restore_stack_function;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1109 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1110 case SAVE_NONLOCAL:
111
kono
parents: 67
diff changeset
1111 if (targetm.have_restore_stack_nonlocal ())
kono
parents: 67
diff changeset
1112 fcn = targetm.gen_restore_stack_nonlocal;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1113 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1114 default:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1115 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1116 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1117
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1118 if (sa != 0)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1119 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1120 sa = validize_mem (sa);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1121 /* These clobbers prevent the scheduler from moving
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1122 references to variable arrays below the code
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1123 that deletes (pops) the arrays. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1124 emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1125 emit_clobber (gen_rtx_MEM (BLKmode, stack_pointer_rtx));
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1126 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1127
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1128 discard_pending_stack_adjust ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1129
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1130 emit_insn (fcn (stack_pointer_rtx, sa));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1131 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1132
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1133 /* Invoke emit_stack_save on the nonlocal_goto_save_area for the current
111
kono
parents: 67
diff changeset
1134 function. This should be called whenever we allocate or deallocate
kono
parents: 67
diff changeset
1135 dynamic stack space. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1136
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1137 void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1138 update_nonlocal_goto_save_area (void)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1139 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1140 tree t_save;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1141 rtx r_save;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1142
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1143 /* The nonlocal_goto_save_area object is an array of N pointers. The
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1144 first one is used for the frame pointer save; the rest are sized by
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1145 STACK_SAVEAREA_MODE. Create a reference to array index 1, the first
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1146 of the stack save area slots. */
111
kono
parents: 67
diff changeset
1147 t_save = build4 (ARRAY_REF,
kono
parents: 67
diff changeset
1148 TREE_TYPE (TREE_TYPE (cfun->nonlocal_goto_save_area)),
kono
parents: 67
diff changeset
1149 cfun->nonlocal_goto_save_area,
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1150 integer_one_node, NULL_TREE, NULL_TREE);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1151 r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1152
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1153 emit_stack_save (SAVE_NONLOCAL, &r_save);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1154 }
111
kono
parents: 67
diff changeset
1155
kono
parents: 67
diff changeset
1156 /* Record a new stack level for the current function. This should be called
kono
parents: 67
diff changeset
1157 whenever we allocate or deallocate dynamic stack space. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1158
111
kono
parents: 67
diff changeset
1159 void
kono
parents: 67
diff changeset
1160 record_new_stack_level (void)
kono
parents: 67
diff changeset
1161 {
kono
parents: 67
diff changeset
1162 /* Record the new stack level for nonlocal gotos. */
kono
parents: 67
diff changeset
1163 if (cfun->nonlocal_goto_save_area)
kono
parents: 67
diff changeset
1164 update_nonlocal_goto_save_area ();
kono
parents: 67
diff changeset
1165
kono
parents: 67
diff changeset
1166 /* Record the new stack level for SJLJ exceptions. */
kono
parents: 67
diff changeset
1167 if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ)
kono
parents: 67
diff changeset
1168 update_sjlj_context ();
kono
parents: 67
diff changeset
1169 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1170
111
kono
parents: 67
diff changeset
1171 /* Return an rtx doing runtime alignment to REQUIRED_ALIGN on TARGET. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1172
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1173 rtx
111
kono
parents: 67
diff changeset
1174 align_dynamic_address (rtx target, unsigned required_align)
kono
parents: 67
diff changeset
1175 {
kono
parents: 67
diff changeset
1176 /* CEIL_DIV_EXPR needs to worry about the addition overflowing,
kono
parents: 67
diff changeset
1177 but we know it can't. So add ourselves and then do
kono
parents: 67
diff changeset
1178 TRUNC_DIV_EXPR. */
kono
parents: 67
diff changeset
1179 target = expand_binop (Pmode, add_optab, target,
kono
parents: 67
diff changeset
1180 gen_int_mode (required_align / BITS_PER_UNIT - 1,
kono
parents: 67
diff changeset
1181 Pmode),
kono
parents: 67
diff changeset
1182 NULL_RTX, 1, OPTAB_LIB_WIDEN);
kono
parents: 67
diff changeset
1183 target = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, target,
kono
parents: 67
diff changeset
1184 gen_int_mode (required_align / BITS_PER_UNIT,
kono
parents: 67
diff changeset
1185 Pmode),
kono
parents: 67
diff changeset
1186 NULL_RTX, 1);
kono
parents: 67
diff changeset
1187 target = expand_mult (Pmode, target,
kono
parents: 67
diff changeset
1188 gen_int_mode (required_align / BITS_PER_UNIT,
kono
parents: 67
diff changeset
1189 Pmode),
kono
parents: 67
diff changeset
1190 NULL_RTX, 1);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1191
111
kono
parents: 67
diff changeset
1192 return target;
kono
parents: 67
diff changeset
1193 }
kono
parents: 67
diff changeset
1194
kono
parents: 67
diff changeset
1195 /* Return an rtx through *PSIZE, representing the size of an area of memory to
kono
parents: 67
diff changeset
1196 be dynamically pushed on the stack.
kono
parents: 67
diff changeset
1197
kono
parents: 67
diff changeset
1198 *PSIZE is an rtx representing the size of the area.
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1199
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1200 SIZE_ALIGN is the alignment (in bits) that we know SIZE has. This
111
kono
parents: 67
diff changeset
1201 parameter may be zero. If so, a proper value will be extracted
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1202 from SIZE if it is constant, otherwise BITS_PER_UNIT will be assumed.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1203
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1204 REQUIRED_ALIGN is the alignment (in bits) required for the region
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1205 of memory.
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1206
111
kono
parents: 67
diff changeset
1207 If PSTACK_USAGE_SIZE is not NULL it points to a value that is increased for
kono
parents: 67
diff changeset
1208 the additional size returned. */
kono
parents: 67
diff changeset
1209 void
kono
parents: 67
diff changeset
1210 get_dynamic_stack_size (rtx *psize, unsigned size_align,
kono
parents: 67
diff changeset
1211 unsigned required_align,
kono
parents: 67
diff changeset
1212 HOST_WIDE_INT *pstack_usage_size)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1213 {
111
kono
parents: 67
diff changeset
1214 rtx size = *psize;
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1215
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1216 /* Ensure the size is in the proper mode. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1217 if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1218 size = convert_to_mode (Pmode, size, 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1219
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1220 if (CONST_INT_P (size))
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1221 {
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1222 unsigned HOST_WIDE_INT lsb;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1223
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1224 lsb = INTVAL (size);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1225 lsb &= -lsb;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1226
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1227 /* Watch out for overflow truncating to "unsigned". */
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1228 if (lsb > UINT_MAX / BITS_PER_UNIT)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1229 size_align = 1u << (HOST_BITS_PER_INT - 1);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1230 else
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1231 size_align = (unsigned)lsb * BITS_PER_UNIT;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1232 }
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1233 else if (size_align < BITS_PER_UNIT)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1234 size_align = BITS_PER_UNIT;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1235
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1236 /* We can't attempt to minimize alignment necessary, because we don't
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1237 know the final value of preferred_stack_boundary yet while executing
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1238 this code. */
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1239 if (crtl->preferred_stack_boundary < PREFERRED_STACK_BOUNDARY)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1240 crtl->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1241
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1242 /* We will need to ensure that the address we return is aligned to
111
kono
parents: 67
diff changeset
1243 REQUIRED_ALIGN. At this point in the compilation, we don't always
kono
parents: 67
diff changeset
1244 know the final value of the STACK_DYNAMIC_OFFSET used in function.c
kono
parents: 67
diff changeset
1245 (it might depend on the size of the outgoing parameter lists, for
kono
parents: 67
diff changeset
1246 example), so we must preventively align the value. We leave space
kono
parents: 67
diff changeset
1247 in SIZE for the hole that might result from the alignment operation. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1248
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1249 unsigned known_align = REGNO_POINTER_ALIGN (VIRTUAL_STACK_DYNAMIC_REGNUM);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1250 if (known_align == 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1251 known_align = BITS_PER_UNIT;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1252 if (required_align > known_align)
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1253 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1254 unsigned extra = (required_align - known_align) / BITS_PER_UNIT;
111
kono
parents: 67
diff changeset
1255 size = plus_constant (Pmode, size, extra);
kono
parents: 67
diff changeset
1256 size = force_operand (size, NULL_RTX);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1257 if (size_align > known_align)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1258 size_align = known_align;
111
kono
parents: 67
diff changeset
1259
kono
parents: 67
diff changeset
1260 if (flag_stack_usage_info && pstack_usage_size)
kono
parents: 67
diff changeset
1261 *pstack_usage_size += extra;
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1262 }
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1263
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1264 /* Round the size to a multiple of the required stack alignment.
111
kono
parents: 67
diff changeset
1265 Since the stack is presumed to be rounded before this allocation,
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1266 this will maintain the required alignment.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1267
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1268 If the stack grows downward, we could save an insn by subtracting
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1269 SIZE from the stack pointer and then aligning the stack pointer.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1270 The problem with this is that the stack pointer may be unaligned
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1271 between the execution of the subtraction and alignment insns and
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1272 some machines do not allow this. Even on those that do, some
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1273 signal handlers malfunction if a signal should occur between those
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1274 insns. Since this is an extremely rare event, we have no reliable
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1275 way of knowing which systems have this problem. So we avoid even
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1276 momentarily mis-aligning the stack. */
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1277 if (size_align % MAX_SUPPORTED_STACK_ALIGNMENT != 0)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1278 {
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1279 size = round_push (size);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1280
111
kono
parents: 67
diff changeset
1281 if (flag_stack_usage_info && pstack_usage_size)
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1282 {
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1283 int align = crtl->preferred_stack_boundary / BITS_PER_UNIT;
111
kono
parents: 67
diff changeset
1284 *pstack_usage_size =
kono
parents: 67
diff changeset
1285 (*pstack_usage_size + align - 1) / align * align;
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1286 }
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1287 }
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1288
111
kono
parents: 67
diff changeset
1289 *psize = size;
kono
parents: 67
diff changeset
1290 }
kono
parents: 67
diff changeset
1291
kono
parents: 67
diff changeset
1292 /* Return the number of bytes to "protect" on the stack for -fstack-check.
kono
parents: 67
diff changeset
1293
kono
parents: 67
diff changeset
1294 "protect" in the context of -fstack-check means how many bytes we
kono
parents: 67
diff changeset
1295 should always ensure are available on the stack. More importantly
kono
parents: 67
diff changeset
1296 this is how many bytes are skipped when probing the stack.
kono
parents: 67
diff changeset
1297
kono
parents: 67
diff changeset
1298 On some targets we want to reuse the -fstack-check prologue support
kono
parents: 67
diff changeset
1299 to give a degree of protection against stack clashing style attacks.
kono
parents: 67
diff changeset
1300
kono
parents: 67
diff changeset
1301 In that scenario we do not want to skip bytes before probing as that
kono
parents: 67
diff changeset
1302 would render the stack clash protections useless.
kono
parents: 67
diff changeset
1303
kono
parents: 67
diff changeset
1304 So we never use STACK_CHECK_PROTECT directly. Instead we indirect though
kono
parents: 67
diff changeset
1305 this helper which allows us to provide different values for
kono
parents: 67
diff changeset
1306 -fstack-check and -fstack-clash-protection. */
kono
parents: 67
diff changeset
1307 HOST_WIDE_INT
kono
parents: 67
diff changeset
1308 get_stack_check_protect (void)
kono
parents: 67
diff changeset
1309 {
kono
parents: 67
diff changeset
1310 if (flag_stack_clash_protection)
kono
parents: 67
diff changeset
1311 return 0;
kono
parents: 67
diff changeset
1312 return STACK_CHECK_PROTECT;
kono
parents: 67
diff changeset
1313 }
kono
parents: 67
diff changeset
1314
kono
parents: 67
diff changeset
1315 /* Return an rtx representing the address of an area of memory dynamically
kono
parents: 67
diff changeset
1316 pushed on the stack.
kono
parents: 67
diff changeset
1317
kono
parents: 67
diff changeset
1318 Any required stack pointer alignment is preserved.
kono
parents: 67
diff changeset
1319
kono
parents: 67
diff changeset
1320 SIZE is an rtx representing the size of the area.
kono
parents: 67
diff changeset
1321
kono
parents: 67
diff changeset
1322 SIZE_ALIGN is the alignment (in bits) that we know SIZE has. This
kono
parents: 67
diff changeset
1323 parameter may be zero. If so, a proper value will be extracted
kono
parents: 67
diff changeset
1324 from SIZE if it is constant, otherwise BITS_PER_UNIT will be assumed.
kono
parents: 67
diff changeset
1325
kono
parents: 67
diff changeset
1326 REQUIRED_ALIGN is the alignment (in bits) required for the region
kono
parents: 67
diff changeset
1327 of memory.
kono
parents: 67
diff changeset
1328
kono
parents: 67
diff changeset
1329 MAX_SIZE is an upper bound for SIZE, if SIZE is not constant, or -1 if
kono
parents: 67
diff changeset
1330 no such upper bound is known.
kono
parents: 67
diff changeset
1331
kono
parents: 67
diff changeset
1332 If CANNOT_ACCUMULATE is set to TRUE, the caller guarantees that the
kono
parents: 67
diff changeset
1333 stack space allocated by the generated code cannot be added with itself
kono
parents: 67
diff changeset
1334 in the course of the execution of the function. It is always safe to
kono
parents: 67
diff changeset
1335 pass FALSE here and the following criterion is sufficient in order to
kono
parents: 67
diff changeset
1336 pass TRUE: every path in the CFG that starts at the allocation point and
kono
parents: 67
diff changeset
1337 loops to it executes the associated deallocation code. */
kono
parents: 67
diff changeset
1338
kono
parents: 67
diff changeset
1339 rtx
kono
parents: 67
diff changeset
1340 allocate_dynamic_stack_space (rtx size, unsigned size_align,
kono
parents: 67
diff changeset
1341 unsigned required_align,
kono
parents: 67
diff changeset
1342 HOST_WIDE_INT max_size,
kono
parents: 67
diff changeset
1343 bool cannot_accumulate)
kono
parents: 67
diff changeset
1344 {
kono
parents: 67
diff changeset
1345 HOST_WIDE_INT stack_usage_size = -1;
kono
parents: 67
diff changeset
1346 rtx_code_label *final_label;
kono
parents: 67
diff changeset
1347 rtx final_target, target;
kono
parents: 67
diff changeset
1348
kono
parents: 67
diff changeset
1349 /* If we're asking for zero bytes, it doesn't matter what we point
kono
parents: 67
diff changeset
1350 to since we can't dereference it. But return a reasonable
kono
parents: 67
diff changeset
1351 address anyway. */
kono
parents: 67
diff changeset
1352 if (size == const0_rtx)
kono
parents: 67
diff changeset
1353 return virtual_stack_dynamic_rtx;
kono
parents: 67
diff changeset
1354
kono
parents: 67
diff changeset
1355 /* Otherwise, show we're calling alloca or equivalent. */
kono
parents: 67
diff changeset
1356 cfun->calls_alloca = 1;
kono
parents: 67
diff changeset
1357
kono
parents: 67
diff changeset
1358 /* If stack usage info is requested, look into the size we are passed.
kono
parents: 67
diff changeset
1359 We need to do so this early to avoid the obfuscation that may be
kono
parents: 67
diff changeset
1360 introduced later by the various alignment operations. */
kono
parents: 67
diff changeset
1361 if (flag_stack_usage_info)
kono
parents: 67
diff changeset
1362 {
kono
parents: 67
diff changeset
1363 if (CONST_INT_P (size))
kono
parents: 67
diff changeset
1364 stack_usage_size = INTVAL (size);
kono
parents: 67
diff changeset
1365 else if (REG_P (size))
kono
parents: 67
diff changeset
1366 {
kono
parents: 67
diff changeset
1367 /* Look into the last emitted insn and see if we can deduce
kono
parents: 67
diff changeset
1368 something for the register. */
kono
parents: 67
diff changeset
1369 rtx_insn *insn;
kono
parents: 67
diff changeset
1370 rtx set, note;
kono
parents: 67
diff changeset
1371 insn = get_last_insn ();
kono
parents: 67
diff changeset
1372 if ((set = single_set (insn)) && rtx_equal_p (SET_DEST (set), size))
kono
parents: 67
diff changeset
1373 {
kono
parents: 67
diff changeset
1374 if (CONST_INT_P (SET_SRC (set)))
kono
parents: 67
diff changeset
1375 stack_usage_size = INTVAL (SET_SRC (set));
kono
parents: 67
diff changeset
1376 else if ((note = find_reg_equal_equiv_note (insn))
kono
parents: 67
diff changeset
1377 && CONST_INT_P (XEXP (note, 0)))
kono
parents: 67
diff changeset
1378 stack_usage_size = INTVAL (XEXP (note, 0));
kono
parents: 67
diff changeset
1379 }
kono
parents: 67
diff changeset
1380 }
kono
parents: 67
diff changeset
1381
kono
parents: 67
diff changeset
1382 /* If the size is not constant, try the maximum size. */
kono
parents: 67
diff changeset
1383 if (stack_usage_size < 0)
kono
parents: 67
diff changeset
1384 stack_usage_size = max_size;
kono
parents: 67
diff changeset
1385
kono
parents: 67
diff changeset
1386 /* If the size is still not constant, we can't say anything. */
kono
parents: 67
diff changeset
1387 if (stack_usage_size < 0)
kono
parents: 67
diff changeset
1388 {
kono
parents: 67
diff changeset
1389 current_function_has_unbounded_dynamic_stack_size = 1;
kono
parents: 67
diff changeset
1390 stack_usage_size = 0;
kono
parents: 67
diff changeset
1391 }
kono
parents: 67
diff changeset
1392 }
kono
parents: 67
diff changeset
1393
kono
parents: 67
diff changeset
1394 get_dynamic_stack_size (&size, size_align, required_align, &stack_usage_size);
kono
parents: 67
diff changeset
1395
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1396 target = gen_reg_rtx (Pmode);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1397
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1398 /* The size is supposed to be fully adjusted at this point so record it
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1399 if stack usage info is requested. */
111
kono
parents: 67
diff changeset
1400 if (flag_stack_usage_info)
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1401 {
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1402 current_function_dynamic_stack_size += stack_usage_size;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1403
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1404 /* ??? This is gross but the only safe stance in the absence
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1405 of stack usage oriented flow analysis. */
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1406 if (!cannot_accumulate)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1407 current_function_has_unbounded_dynamic_stack_size = 1;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1408 }
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1409
111
kono
parents: 67
diff changeset
1410 do_pending_stack_adjust ();
kono
parents: 67
diff changeset
1411
kono
parents: 67
diff changeset
1412 final_label = NULL;
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1413 final_target = NULL_RTX;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1414
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1415 /* If we are splitting the stack, we need to ask the backend whether
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1416 there is enough room on the current stack. If there isn't, or if
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1417 the backend doesn't know how to tell is, then we need to call a
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1418 function to allocate memory in some other way. This memory will
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1419 be released when we release the current stack segment. The
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1420 effect is that stack allocation becomes less efficient, but at
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1421 least it doesn't cause a stack overflow. */
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1422 if (flag_split_stack)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1423 {
111
kono
parents: 67
diff changeset
1424 rtx_code_label *available_label;
kono
parents: 67
diff changeset
1425 rtx ask, space, func;
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1426
111
kono
parents: 67
diff changeset
1427 available_label = NULL;
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1428
111
kono
parents: 67
diff changeset
1429 if (targetm.have_split_stack_space_check ())
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1430 {
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1431 available_label = gen_label_rtx ();
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1432
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1433 /* This instruction will branch to AVAILABLE_LABEL if there
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1434 are SIZE bytes available on the stack. */
111
kono
parents: 67
diff changeset
1435 emit_insn (targetm.gen_split_stack_space_check
kono
parents: 67
diff changeset
1436 (size, available_label));
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1437 }
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1438
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1439 /* The __morestack_allocate_stack_space function will allocate
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1440 memory using malloc. If the alignment of the memory returned
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1441 by malloc does not meet REQUIRED_ALIGN, we increase SIZE to
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1442 make sure we allocate enough space. */
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1443 if (MALLOC_ABI_ALIGNMENT >= required_align)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1444 ask = size;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1445 else
111
kono
parents: 67
diff changeset
1446 ask = expand_binop (Pmode, add_optab, size,
kono
parents: 67
diff changeset
1447 gen_int_mode (required_align / BITS_PER_UNIT - 1,
kono
parents: 67
diff changeset
1448 Pmode),
kono
parents: 67
diff changeset
1449 NULL_RTX, 1, OPTAB_LIB_WIDEN);
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1450
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1451 func = init_one_libfunc ("__morestack_allocate_stack_space");
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1452
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1453 space = emit_library_call_value (func, target, LCT_NORMAL, Pmode,
111
kono
parents: 67
diff changeset
1454 ask, Pmode);
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1455
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1456 if (available_label == NULL_RTX)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1457 return space;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1458
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1459 final_target = gen_reg_rtx (Pmode);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1460
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1461 emit_move_insn (final_target, space);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1462
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1463 final_label = gen_label_rtx ();
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1464 emit_jump (final_label);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1465
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1466 emit_label (available_label);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1467 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1468
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1469 /* We ought to be called always on the toplevel and stack ought to be aligned
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1470 properly. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1471 gcc_assert (multiple_p (stack_pointer_delta,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1472 PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT));
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1473
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1474 /* If needed, check that we have the required amount of stack. Take into
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1475 account what has already been checked. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1476 if (STACK_CHECK_MOVING_SP)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1477 ;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1478 else if (flag_stack_check == GENERIC_STACK_CHECK)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1479 probe_stack_range (STACK_OLD_CHECK_PROTECT + STACK_CHECK_MAX_FRAME_SIZE,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1480 size);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1481 else if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
111
kono
parents: 67
diff changeset
1482 probe_stack_range (get_stack_check_protect (), size);
kono
parents: 67
diff changeset
1483
kono
parents: 67
diff changeset
1484 /* Don't let anti_adjust_stack emit notes. */
kono
parents: 67
diff changeset
1485 suppress_reg_args_size = true;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1486
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1487 /* Perform the required allocation from the stack. Some systems do
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1488 this differently than simply incrementing/decrementing from the
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1489 stack pointer, such as acquiring the space by calling malloc(). */
111
kono
parents: 67
diff changeset
1490 if (targetm.have_allocate_stack ())
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1491 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1492 class expand_operand ops[2];
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1493 /* We don't have to check against the predicate for operand 0 since
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1494 TARGET is known to be a pseudo of the proper mode, which must
111
kono
parents: 67
diff changeset
1495 be valid for the operand. */
kono
parents: 67
diff changeset
1496 create_fixed_operand (&ops[0], target);
kono
parents: 67
diff changeset
1497 create_convert_operand_to (&ops[1], size, STACK_SIZE_MODE, true);
kono
parents: 67
diff changeset
1498 expand_insn (targetm.code_for_allocate_stack, 2, ops);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1499 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1500 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1501 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1502 poly_int64 saved_stack_pointer_delta;
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1503
111
kono
parents: 67
diff changeset
1504 if (!STACK_GROWS_DOWNWARD)
kono
parents: 67
diff changeset
1505 emit_move_insn (target, virtual_stack_dynamic_rtx);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1506
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1507 /* Check stack bounds if necessary. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1508 if (crtl->limit_stack)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1509 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1510 rtx available;
111
kono
parents: 67
diff changeset
1511 rtx_code_label *space_available = gen_label_rtx ();
kono
parents: 67
diff changeset
1512 if (STACK_GROWS_DOWNWARD)
kono
parents: 67
diff changeset
1513 available = expand_binop (Pmode, sub_optab,
kono
parents: 67
diff changeset
1514 stack_pointer_rtx, stack_limit_rtx,
kono
parents: 67
diff changeset
1515 NULL_RTX, 1, OPTAB_WIDEN);
kono
parents: 67
diff changeset
1516 else
kono
parents: 67
diff changeset
1517 available = expand_binop (Pmode, sub_optab,
kono
parents: 67
diff changeset
1518 stack_limit_rtx, stack_pointer_rtx,
kono
parents: 67
diff changeset
1519 NULL_RTX, 1, OPTAB_WIDEN);
kono
parents: 67
diff changeset
1520
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1521 emit_cmp_and_jump_insns (available, size, GEU, NULL_RTX, Pmode, 1,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1522 space_available);
111
kono
parents: 67
diff changeset
1523 if (targetm.have_trap ())
kono
parents: 67
diff changeset
1524 emit_insn (targetm.gen_trap ());
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1525 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1526 error ("stack limits not supported on this target");
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1527 emit_barrier ();
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1528 emit_label (space_available);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1529 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1530
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1531 saved_stack_pointer_delta = stack_pointer_delta;
111
kono
parents: 67
diff changeset
1532
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1533 if (flag_stack_check && STACK_CHECK_MOVING_SP)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1534 anti_adjust_stack_and_probe (size, false);
111
kono
parents: 67
diff changeset
1535 else if (flag_stack_clash_protection)
kono
parents: 67
diff changeset
1536 anti_adjust_stack_and_probe_stack_clash (size);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1537 else
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1538 anti_adjust_stack (size);
111
kono
parents: 67
diff changeset
1539
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1540 /* Even if size is constant, don't modify stack_pointer_delta.
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1541 The constant size alloca should preserve
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1542 crtl->preferred_stack_boundary alignment. */
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1543 stack_pointer_delta = saved_stack_pointer_delta;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1544
111
kono
parents: 67
diff changeset
1545 if (STACK_GROWS_DOWNWARD)
kono
parents: 67
diff changeset
1546 emit_move_insn (target, virtual_stack_dynamic_rtx);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1547 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1548
111
kono
parents: 67
diff changeset
1549 suppress_reg_args_size = false;
kono
parents: 67
diff changeset
1550
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1551 /* Finish up the split stack handling. */
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1552 if (final_label != NULL_RTX)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1553 {
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1554 gcc_assert (flag_split_stack);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1555 emit_move_insn (final_target, target);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1556 emit_label (final_label);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1557 target = final_target;
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1558 }
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1559
111
kono
parents: 67
diff changeset
1560 target = align_dynamic_address (target, required_align);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1561
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1562 /* Now that we've committed to a return value, mark its alignment. */
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1563 mark_reg_pointer (target, required_align);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1564
111
kono
parents: 67
diff changeset
1565 /* Record the new stack level. */
kono
parents: 67
diff changeset
1566 record_new_stack_level ();
kono
parents: 67
diff changeset
1567
kono
parents: 67
diff changeset
1568 return target;
kono
parents: 67
diff changeset
1569 }
kono
parents: 67
diff changeset
1570
kono
parents: 67
diff changeset
1571 /* Return an rtx representing the address of an area of memory already
kono
parents: 67
diff changeset
1572 statically pushed onto the stack in the virtual stack vars area. (It is
kono
parents: 67
diff changeset
1573 assumed that the area is allocated in the function prologue.)
kono
parents: 67
diff changeset
1574
kono
parents: 67
diff changeset
1575 Any required stack pointer alignment is preserved.
kono
parents: 67
diff changeset
1576
kono
parents: 67
diff changeset
1577 OFFSET is the offset of the area into the virtual stack vars area.
kono
parents: 67
diff changeset
1578
kono
parents: 67
diff changeset
1579 REQUIRED_ALIGN is the alignment (in bits) required for the region
kono
parents: 67
diff changeset
1580 of memory. */
kono
parents: 67
diff changeset
1581
kono
parents: 67
diff changeset
1582 rtx
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1583 get_dynamic_stack_base (poly_int64 offset, unsigned required_align)
111
kono
parents: 67
diff changeset
1584 {
kono
parents: 67
diff changeset
1585 rtx target;
kono
parents: 67
diff changeset
1586
kono
parents: 67
diff changeset
1587 if (crtl->preferred_stack_boundary < PREFERRED_STACK_BOUNDARY)
kono
parents: 67
diff changeset
1588 crtl->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
kono
parents: 67
diff changeset
1589
kono
parents: 67
diff changeset
1590 target = gen_reg_rtx (Pmode);
kono
parents: 67
diff changeset
1591 emit_move_insn (target, virtual_stack_vars_rtx);
kono
parents: 67
diff changeset
1592 target = expand_binop (Pmode, add_optab, target,
kono
parents: 67
diff changeset
1593 gen_int_mode (offset, Pmode),
kono
parents: 67
diff changeset
1594 NULL_RTX, 1, OPTAB_LIB_WIDEN);
kono
parents: 67
diff changeset
1595 target = align_dynamic_address (target, required_align);
kono
parents: 67
diff changeset
1596
kono
parents: 67
diff changeset
1597 /* Now that we've committed to a return value, mark its alignment. */
kono
parents: 67
diff changeset
1598 mark_reg_pointer (target, required_align);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1599
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1600 return target;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1601 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1602
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1603 /* A front end may want to override GCC's stack checking by providing a
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1604 run-time routine to call to check the stack, so provide a mechanism for
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1605 calling that routine. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1606
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1607 static GTY(()) rtx stack_check_libfunc;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1608
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1609 void
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1610 set_stack_check_libfunc (const char *libfunc_name)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1611 {
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1612 gcc_assert (stack_check_libfunc == NULL_RTX);
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1613 stack_check_libfunc = gen_rtx_SYMBOL_REF (Pmode, libfunc_name);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1614 tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1615 get_identifier (libfunc_name), void_type_node);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1616 DECL_EXTERNAL (decl) = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1617 SET_SYMBOL_REF_DECL (stack_check_libfunc, decl);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1618 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1619
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1620 /* Emit one stack probe at ADDRESS, an address within the stack. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1621
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1622 void
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1623 emit_stack_probe (rtx address)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1624 {
111
kono
parents: 67
diff changeset
1625 if (targetm.have_probe_stack_address ())
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1626 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1627 class expand_operand ops[1];
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1628 insn_code icode = targetm.code_for_probe_stack_address;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1629 create_address_operand (ops, address);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1630 maybe_legitimize_operands (icode, 0, 1, ops);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1631 expand_insn (icode, 1, ops);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1632 }
111
kono
parents: 67
diff changeset
1633 else
kono
parents: 67
diff changeset
1634 {
kono
parents: 67
diff changeset
1635 rtx memref = gen_rtx_MEM (word_mode, address);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1636
111
kono
parents: 67
diff changeset
1637 MEM_VOLATILE_P (memref) = 1;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1638 memref = validize_mem (memref);
111
kono
parents: 67
diff changeset
1639
kono
parents: 67
diff changeset
1640 /* See if we have an insn to probe the stack. */
kono
parents: 67
diff changeset
1641 if (targetm.have_probe_stack ())
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1642 emit_insn (targetm.gen_probe_stack (memref));
111
kono
parents: 67
diff changeset
1643 else
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1644 emit_move_insn (memref, const0_rtx);
111
kono
parents: 67
diff changeset
1645 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1646 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1647
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1648 /* Probe a range of stack addresses from FIRST to FIRST+SIZE, inclusive.
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1649 FIRST is a constant and size is a Pmode RTX. These are offsets from
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1650 the current stack pointer. STACK_GROWS_DOWNWARD says whether to add
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1651 or subtract them from the stack pointer. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1652
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1653 #define PROBE_INTERVAL (1 << STACK_CHECK_PROBE_INTERVAL_EXP)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1654
111
kono
parents: 67
diff changeset
1655 #if STACK_GROWS_DOWNWARD
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1656 #define STACK_GROW_OP MINUS
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1657 #define STACK_GROW_OPTAB sub_optab
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1658 #define STACK_GROW_OFF(off) -(off)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1659 #else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1660 #define STACK_GROW_OP PLUS
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1661 #define STACK_GROW_OPTAB add_optab
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1662 #define STACK_GROW_OFF(off) (off)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1663 #endif
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1664
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1665 void
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1666 probe_stack_range (HOST_WIDE_INT first, rtx size)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1667 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1668 /* First ensure SIZE is Pmode. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1669 if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1670 size = convert_to_mode (Pmode, size, 1);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1671
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1672 /* Next see if we have a function to check the stack. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1673 if (stack_check_libfunc)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1674 {
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1675 rtx addr = memory_address (Pmode,
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1676 gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1677 stack_pointer_rtx,
111
kono
parents: 67
diff changeset
1678 plus_constant (Pmode,
kono
parents: 67
diff changeset
1679 size, first)));
kono
parents: 67
diff changeset
1680 emit_library_call (stack_check_libfunc, LCT_THROW, VOIDmode,
kono
parents: 67
diff changeset
1681 addr, Pmode);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1682 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1683
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1684 /* Next see if we have an insn to check the stack. */
111
kono
parents: 67
diff changeset
1685 else if (targetm.have_check_stack ())
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1686 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1687 class expand_operand ops[1];
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1688 rtx addr = memory_address (Pmode,
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1689 gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1690 stack_pointer_rtx,
111
kono
parents: 67
diff changeset
1691 plus_constant (Pmode,
kono
parents: 67
diff changeset
1692 size, first)));
kono
parents: 67
diff changeset
1693 bool success;
kono
parents: 67
diff changeset
1694 create_input_operand (&ops[0], addr, Pmode);
kono
parents: 67
diff changeset
1695 success = maybe_expand_insn (targetm.code_for_check_stack, 1, ops);
kono
parents: 67
diff changeset
1696 gcc_assert (success);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1697 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1698
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1699 /* Otherwise we have to generate explicit probes. If we have a constant
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1700 small number of them to generate, that's the easy case. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1701 else if (CONST_INT_P (size) && INTVAL (size) < 7 * PROBE_INTERVAL)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1702 {
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1703 HOST_WIDE_INT isize = INTVAL (size), i;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1704 rtx addr;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1705
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1706 /* Probe at FIRST + N * PROBE_INTERVAL for values of N from 1 until
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1707 it exceeds SIZE. If only one probe is needed, this will not
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1708 generate any code. Then probe at FIRST + SIZE. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1709 for (i = PROBE_INTERVAL; i < isize; i += PROBE_INTERVAL)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1710 {
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1711 addr = memory_address (Pmode,
111
kono
parents: 67
diff changeset
1712 plus_constant (Pmode, stack_pointer_rtx,
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1713 STACK_GROW_OFF (first + i)));
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1714 emit_stack_probe (addr);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1715 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1716
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1717 addr = memory_address (Pmode,
111
kono
parents: 67
diff changeset
1718 plus_constant (Pmode, stack_pointer_rtx,
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1719 STACK_GROW_OFF (first + isize)));
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1720 emit_stack_probe (addr);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1721 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1722
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1723 /* In the variable case, do the same as above, but in a loop. Note that we
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1724 must be extra careful with variables wrapping around because we might be
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1725 at the very top (or the very bottom) of the address space and we have to
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1726 be able to handle this case properly; in particular, we use an equality
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1727 test for the loop condition. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1728 else
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1729 {
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1730 rtx rounded_size, rounded_size_op, test_addr, last_addr, temp;
111
kono
parents: 67
diff changeset
1731 rtx_code_label *loop_lab = gen_label_rtx ();
kono
parents: 67
diff changeset
1732 rtx_code_label *end_lab = gen_label_rtx ();
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1733
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1734 /* Step 1: round SIZE to the previous multiple of the interval. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1735
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1736 /* ROUNDED_SIZE = SIZE & -PROBE_INTERVAL */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1737 rounded_size
111
kono
parents: 67
diff changeset
1738 = simplify_gen_binary (AND, Pmode, size,
kono
parents: 67
diff changeset
1739 gen_int_mode (-PROBE_INTERVAL, Pmode));
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1740 rounded_size_op = force_operand (rounded_size, NULL_RTX);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1741
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1742
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1743 /* Step 2: compute initial and final value of the loop counter. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1744
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1745 /* TEST_ADDR = SP + FIRST. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1746 test_addr = force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1747 stack_pointer_rtx,
111
kono
parents: 67
diff changeset
1748 gen_int_mode (first, Pmode)),
kono
parents: 67
diff changeset
1749 NULL_RTX);
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1750
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1751 /* LAST_ADDR = SP + FIRST + ROUNDED_SIZE. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1752 last_addr = force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1753 test_addr,
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1754 rounded_size_op), NULL_RTX);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1755
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1756
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1757 /* Step 3: the loop
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1758
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1759 while (TEST_ADDR != LAST_ADDR)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1760 {
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1761 TEST_ADDR = TEST_ADDR + PROBE_INTERVAL
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1762 probe at TEST_ADDR
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1763 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1764
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1765 probes at FIRST + N * PROBE_INTERVAL for values of N from 1
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1766 until it is equal to ROUNDED_SIZE. */
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1767
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1768 emit_label (loop_lab);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1769
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1770 /* Jump to END_LAB if TEST_ADDR == LAST_ADDR. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1771 emit_cmp_and_jump_insns (test_addr, last_addr, EQ, NULL_RTX, Pmode, 1,
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1772 end_lab);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1773
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1774 /* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1775 temp = expand_binop (Pmode, STACK_GROW_OPTAB, test_addr,
111
kono
parents: 67
diff changeset
1776 gen_int_mode (PROBE_INTERVAL, Pmode), test_addr,
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1777 1, OPTAB_WIDEN);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1778
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1779 gcc_assert (temp == test_addr);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1780
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1781 /* Probe at TEST_ADDR. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1782 emit_stack_probe (test_addr);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1783
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1784 emit_jump (loop_lab);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1785
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1786 emit_label (end_lab);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1787
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1788
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1789 /* Step 4: probe at FIRST + SIZE if we cannot assert at compile-time
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1790 that SIZE is equal to ROUNDED_SIZE. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1791
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1792 /* TEMP = SIZE - ROUNDED_SIZE. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1793 temp = simplify_gen_binary (MINUS, Pmode, size, rounded_size);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1794 if (temp != const0_rtx)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1795 {
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1796 rtx addr;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1797
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
1798 if (CONST_INT_P (temp))
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1799 {
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1800 /* Use [base + disp} addressing mode if supported. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1801 HOST_WIDE_INT offset = INTVAL (temp);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1802 addr = memory_address (Pmode,
111
kono
parents: 67
diff changeset
1803 plus_constant (Pmode, last_addr,
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1804 STACK_GROW_OFF (offset)));
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1805 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1806 else
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1807 {
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1808 /* Manual CSE if the difference is not known at compile-time. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1809 temp = gen_rtx_MINUS (Pmode, size, rounded_size_op);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1810 addr = memory_address (Pmode,
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1811 gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1812 last_addr, temp));
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1813 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1814
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1815 emit_stack_probe (addr);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1816 }
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1817 }
111
kono
parents: 67
diff changeset
1818
kono
parents: 67
diff changeset
1819 /* Make sure nothing is scheduled before we are done. */
kono
parents: 67
diff changeset
1820 emit_insn (gen_blockage ());
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1821 }
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
1822
111
kono
parents: 67
diff changeset
1823 /* Compute parameters for stack clash probing a dynamic stack
kono
parents: 67
diff changeset
1824 allocation of SIZE bytes.
kono
parents: 67
diff changeset
1825
kono
parents: 67
diff changeset
1826 We compute ROUNDED_SIZE, LAST_ADDR, RESIDUAL and PROBE_INTERVAL.
kono
parents: 67
diff changeset
1827
kono
parents: 67
diff changeset
1828 Additionally we conditionally dump the type of probing that will
kono
parents: 67
diff changeset
1829 be needed given the values computed. */
kono
parents: 67
diff changeset
1830
kono
parents: 67
diff changeset
1831 void
kono
parents: 67
diff changeset
1832 compute_stack_clash_protection_loop_data (rtx *rounded_size, rtx *last_addr,
kono
parents: 67
diff changeset
1833 rtx *residual,
kono
parents: 67
diff changeset
1834 HOST_WIDE_INT *probe_interval,
kono
parents: 67
diff changeset
1835 rtx size)
kono
parents: 67
diff changeset
1836 {
kono
parents: 67
diff changeset
1837 /* Round SIZE down to STACK_CLASH_PROTECTION_PROBE_INTERVAL */
kono
parents: 67
diff changeset
1838 *probe_interval
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1839 = 1 << param_stack_clash_protection_probe_interval;
111
kono
parents: 67
diff changeset
1840 *rounded_size = simplify_gen_binary (AND, Pmode, size,
kono
parents: 67
diff changeset
1841 GEN_INT (-*probe_interval));
kono
parents: 67
diff changeset
1842
kono
parents: 67
diff changeset
1843 /* Compute the value of the stack pointer for the last iteration.
kono
parents: 67
diff changeset
1844 It's just SP + ROUNDED_SIZE. */
kono
parents: 67
diff changeset
1845 rtx rounded_size_op = force_operand (*rounded_size, NULL_RTX);
kono
parents: 67
diff changeset
1846 *last_addr = force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
kono
parents: 67
diff changeset
1847 stack_pointer_rtx,
kono
parents: 67
diff changeset
1848 rounded_size_op),
kono
parents: 67
diff changeset
1849 NULL_RTX);
kono
parents: 67
diff changeset
1850
kono
parents: 67
diff changeset
1851 /* Compute any residuals not allocated by the loop above. Residuals
kono
parents: 67
diff changeset
1852 are just the ROUNDED_SIZE - SIZE. */
kono
parents: 67
diff changeset
1853 *residual = simplify_gen_binary (MINUS, Pmode, size, *rounded_size);
kono
parents: 67
diff changeset
1854
kono
parents: 67
diff changeset
1855 /* Dump key information to make writing tests easy. */
kono
parents: 67
diff changeset
1856 if (dump_file)
kono
parents: 67
diff changeset
1857 {
kono
parents: 67
diff changeset
1858 if (*rounded_size == CONST0_RTX (Pmode))
kono
parents: 67
diff changeset
1859 fprintf (dump_file,
kono
parents: 67
diff changeset
1860 "Stack clash skipped dynamic allocation and probing loop.\n");
kono
parents: 67
diff changeset
1861 else if (CONST_INT_P (*rounded_size)
kono
parents: 67
diff changeset
1862 && INTVAL (*rounded_size) <= 4 * *probe_interval)
kono
parents: 67
diff changeset
1863 fprintf (dump_file,
kono
parents: 67
diff changeset
1864 "Stack clash dynamic allocation and probing inline.\n");
kono
parents: 67
diff changeset
1865 else if (CONST_INT_P (*rounded_size))
kono
parents: 67
diff changeset
1866 fprintf (dump_file,
kono
parents: 67
diff changeset
1867 "Stack clash dynamic allocation and probing in "
kono
parents: 67
diff changeset
1868 "rotated loop.\n");
kono
parents: 67
diff changeset
1869 else
kono
parents: 67
diff changeset
1870 fprintf (dump_file,
kono
parents: 67
diff changeset
1871 "Stack clash dynamic allocation and probing in loop.\n");
kono
parents: 67
diff changeset
1872
kono
parents: 67
diff changeset
1873 if (*residual != CONST0_RTX (Pmode))
kono
parents: 67
diff changeset
1874 fprintf (dump_file,
kono
parents: 67
diff changeset
1875 "Stack clash dynamic allocation and probing residuals.\n");
kono
parents: 67
diff changeset
1876 else
kono
parents: 67
diff changeset
1877 fprintf (dump_file,
kono
parents: 67
diff changeset
1878 "Stack clash skipped dynamic allocation and "
kono
parents: 67
diff changeset
1879 "probing residuals.\n");
kono
parents: 67
diff changeset
1880 }
kono
parents: 67
diff changeset
1881 }
kono
parents: 67
diff changeset
1882
kono
parents: 67
diff changeset
1883 /* Emit the start of an allocate/probe loop for stack
kono
parents: 67
diff changeset
1884 clash protection.
kono
parents: 67
diff changeset
1885
kono
parents: 67
diff changeset
1886 LOOP_LAB and END_LAB are returned for use when we emit the
kono
parents: 67
diff changeset
1887 end of the loop.
kono
parents: 67
diff changeset
1888
kono
parents: 67
diff changeset
1889 LAST addr is the value for SP which stops the loop. */
kono
parents: 67
diff changeset
1890 void
kono
parents: 67
diff changeset
1891 emit_stack_clash_protection_probe_loop_start (rtx *loop_lab,
kono
parents: 67
diff changeset
1892 rtx *end_lab,
kono
parents: 67
diff changeset
1893 rtx last_addr,
kono
parents: 67
diff changeset
1894 bool rotated)
kono
parents: 67
diff changeset
1895 {
kono
parents: 67
diff changeset
1896 /* Essentially we want to emit any setup code, the top of loop
kono
parents: 67
diff changeset
1897 label and the comparison at the top of the loop. */
kono
parents: 67
diff changeset
1898 *loop_lab = gen_label_rtx ();
kono
parents: 67
diff changeset
1899 *end_lab = gen_label_rtx ();
kono
parents: 67
diff changeset
1900
kono
parents: 67
diff changeset
1901 emit_label (*loop_lab);
kono
parents: 67
diff changeset
1902 if (!rotated)
kono
parents: 67
diff changeset
1903 emit_cmp_and_jump_insns (stack_pointer_rtx, last_addr, EQ, NULL_RTX,
kono
parents: 67
diff changeset
1904 Pmode, 1, *end_lab);
kono
parents: 67
diff changeset
1905 }
kono
parents: 67
diff changeset
1906
kono
parents: 67
diff changeset
1907 /* Emit the end of a stack clash probing loop.
kono
parents: 67
diff changeset
1908
kono
parents: 67
diff changeset
1909 This consists of just the jump back to LOOP_LAB and
kono
parents: 67
diff changeset
1910 emitting END_LOOP after the loop. */
kono
parents: 67
diff changeset
1911
kono
parents: 67
diff changeset
1912 void
kono
parents: 67
diff changeset
1913 emit_stack_clash_protection_probe_loop_end (rtx loop_lab, rtx end_loop,
kono
parents: 67
diff changeset
1914 rtx last_addr, bool rotated)
kono
parents: 67
diff changeset
1915 {
kono
parents: 67
diff changeset
1916 if (rotated)
kono
parents: 67
diff changeset
1917 emit_cmp_and_jump_insns (stack_pointer_rtx, last_addr, NE, NULL_RTX,
kono
parents: 67
diff changeset
1918 Pmode, 1, loop_lab);
kono
parents: 67
diff changeset
1919 else
kono
parents: 67
diff changeset
1920 emit_jump (loop_lab);
kono
parents: 67
diff changeset
1921
kono
parents: 67
diff changeset
1922 emit_label (end_loop);
kono
parents: 67
diff changeset
1923
kono
parents: 67
diff changeset
1924 }
kono
parents: 67
diff changeset
1925
kono
parents: 67
diff changeset
1926 /* Adjust the stack pointer by minus SIZE (an rtx for a number of bytes)
kono
parents: 67
diff changeset
1927 while probing it. This pushes when SIZE is positive. SIZE need not
kono
parents: 67
diff changeset
1928 be constant.
kono
parents: 67
diff changeset
1929
kono
parents: 67
diff changeset
1930 This is subtly different than anti_adjust_stack_and_probe to try and
kono
parents: 67
diff changeset
1931 prevent stack-clash attacks
kono
parents: 67
diff changeset
1932
kono
parents: 67
diff changeset
1933 1. It must assume no knowledge of the probing state, any allocation
kono
parents: 67
diff changeset
1934 must probe.
kono
parents: 67
diff changeset
1935
kono
parents: 67
diff changeset
1936 Consider the case of a 1 byte alloca in a loop. If the sum of the
kono
parents: 67
diff changeset
1937 allocations is large, then this could be used to jump the guard if
kono
parents: 67
diff changeset
1938 probes were not emitted.
kono
parents: 67
diff changeset
1939
kono
parents: 67
diff changeset
1940 2. It never skips probes, whereas anti_adjust_stack_and_probe will
kono
parents: 67
diff changeset
1941 skip probes on the first couple PROBE_INTERVALs on the assumption
kono
parents: 67
diff changeset
1942 they're done elsewhere.
kono
parents: 67
diff changeset
1943
kono
parents: 67
diff changeset
1944 3. It only allocates and probes SIZE bytes, it does not need to
kono
parents: 67
diff changeset
1945 allocate/probe beyond that because this probing style does not
kono
parents: 67
diff changeset
1946 guarantee signal handling capability if the guard is hit. */
kono
parents: 67
diff changeset
1947
kono
parents: 67
diff changeset
1948 static void
kono
parents: 67
diff changeset
1949 anti_adjust_stack_and_probe_stack_clash (rtx size)
kono
parents: 67
diff changeset
1950 {
kono
parents: 67
diff changeset
1951 /* First ensure SIZE is Pmode. */
kono
parents: 67
diff changeset
1952 if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
kono
parents: 67
diff changeset
1953 size = convert_to_mode (Pmode, size, 1);
kono
parents: 67
diff changeset
1954
kono
parents: 67
diff changeset
1955 /* We can get here with a constant size on some targets. */
kono
parents: 67
diff changeset
1956 rtx rounded_size, last_addr, residual;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1957 HOST_WIDE_INT probe_interval, probe_range;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1958 bool target_probe_range_p = false;
111
kono
parents: 67
diff changeset
1959 compute_stack_clash_protection_loop_data (&rounded_size, &last_addr,
kono
parents: 67
diff changeset
1960 &residual, &probe_interval, size);
kono
parents: 67
diff changeset
1961
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1962 /* Get the back-end specific probe ranges. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1963 probe_range = targetm.stack_clash_protection_alloca_probe_range ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1964 target_probe_range_p = probe_range != 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1965 gcc_assert (probe_range >= 0);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1966
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1967 /* If no back-end specific range defined, default to the top of the newly
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1968 allocated range. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1969 if (probe_range == 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1970 probe_range = probe_interval - GET_MODE_SIZE (word_mode);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1971
111
kono
parents: 67
diff changeset
1972 if (rounded_size != CONST0_RTX (Pmode))
kono
parents: 67
diff changeset
1973 {
kono
parents: 67
diff changeset
1974 if (CONST_INT_P (rounded_size)
kono
parents: 67
diff changeset
1975 && INTVAL (rounded_size) <= 4 * probe_interval)
kono
parents: 67
diff changeset
1976 {
kono
parents: 67
diff changeset
1977 for (HOST_WIDE_INT i = 0;
kono
parents: 67
diff changeset
1978 i < INTVAL (rounded_size);
kono
parents: 67
diff changeset
1979 i += probe_interval)
kono
parents: 67
diff changeset
1980 {
kono
parents: 67
diff changeset
1981 anti_adjust_stack (GEN_INT (probe_interval));
kono
parents: 67
diff changeset
1982 /* The prologue does not probe residuals. Thus the offset
kono
parents: 67
diff changeset
1983 here to probe just beyond what the prologue had already
kono
parents: 67
diff changeset
1984 allocated. */
kono
parents: 67
diff changeset
1985 emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1986 probe_range));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1987
111
kono
parents: 67
diff changeset
1988 emit_insn (gen_blockage ());
kono
parents: 67
diff changeset
1989 }
kono
parents: 67
diff changeset
1990 }
kono
parents: 67
diff changeset
1991 else
kono
parents: 67
diff changeset
1992 {
kono
parents: 67
diff changeset
1993 rtx loop_lab, end_loop;
kono
parents: 67
diff changeset
1994 bool rotate_loop = CONST_INT_P (rounded_size);
kono
parents: 67
diff changeset
1995 emit_stack_clash_protection_probe_loop_start (&loop_lab, &end_loop,
kono
parents: 67
diff changeset
1996 last_addr, rotate_loop);
kono
parents: 67
diff changeset
1997
kono
parents: 67
diff changeset
1998 anti_adjust_stack (GEN_INT (probe_interval));
kono
parents: 67
diff changeset
1999
kono
parents: 67
diff changeset
2000 /* The prologue does not probe residuals. Thus the offset here
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2001 to probe just beyond what the prologue had already
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2002 allocated. */
111
kono
parents: 67
diff changeset
2003 emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2004 probe_range));
111
kono
parents: 67
diff changeset
2005
kono
parents: 67
diff changeset
2006 emit_stack_clash_protection_probe_loop_end (loop_lab, end_loop,
kono
parents: 67
diff changeset
2007 last_addr, rotate_loop);
kono
parents: 67
diff changeset
2008 emit_insn (gen_blockage ());
kono
parents: 67
diff changeset
2009 }
kono
parents: 67
diff changeset
2010 }
kono
parents: 67
diff changeset
2011
kono
parents: 67
diff changeset
2012 if (residual != CONST0_RTX (Pmode))
kono
parents: 67
diff changeset
2013 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2014 rtx label = NULL_RTX;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2015 /* RESIDUAL could be zero at runtime and in that case *sp could
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2016 hold live data. Furthermore, we do not want to probe into the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2017 red zone.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2018
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2019 If TARGET_PROBE_RANGE_P then the target has promised it's safe to
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2020 probe at offset 0. In which case we no longer have to check for
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2021 RESIDUAL == 0. However we still need to probe at the right offset
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2022 when RESIDUAL > PROBE_RANGE, in which case we probe at PROBE_RANGE.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2023
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2024 If !TARGET_PROBE_RANGE_P then go ahead and just guard the probe at *sp
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2025 on RESIDUAL != 0 at runtime if RESIDUAL is not a compile time constant.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2026 */
111
kono
parents: 67
diff changeset
2027 anti_adjust_stack (residual);
kono
parents: 67
diff changeset
2028
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2029 if (!CONST_INT_P (residual))
111
kono
parents: 67
diff changeset
2030 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2031 label = gen_label_rtx ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2032 rtx_code op = target_probe_range_p ? LT : EQ;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2033 rtx probe_cmp_value = target_probe_range_p
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2034 ? gen_rtx_CONST_INT (GET_MODE (residual), probe_range)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2035 : CONST0_RTX (GET_MODE (residual));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2036
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2037 if (target_probe_range_p)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2038 emit_stack_probe (stack_pointer_rtx);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2039
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2040 emit_cmp_and_jump_insns (residual, probe_cmp_value,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2041 op, NULL_RTX, Pmode, 1, label);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2042 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2043
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2044 rtx x = NULL_RTX;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2045
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2046 /* If RESIDUAL isn't a constant and TARGET_PROBE_RANGE_P then we probe up
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2047 by the ABI defined safe value. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2048 if (!CONST_INT_P (residual) && target_probe_range_p)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2049 x = GEN_INT (probe_range);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2050 /* If RESIDUAL is a constant but smaller than the ABI defined safe value,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2051 we still want to probe up, but the safest amount if a word. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2052 else if (target_probe_range_p)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2053 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2054 if (INTVAL (residual) <= probe_range)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2055 x = GEN_INT (GET_MODE_SIZE (word_mode));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2056 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2057 x = GEN_INT (probe_range);
111
kono
parents: 67
diff changeset
2058 }
kono
parents: 67
diff changeset
2059 else
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2060 /* If nothing else, probe at the top of the new allocation. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2061 x = plus_constant (Pmode, residual, -GET_MODE_SIZE (word_mode));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2062
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2063 emit_stack_probe (gen_rtx_PLUS (Pmode, stack_pointer_rtx, x));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2064
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2065 emit_insn (gen_blockage ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2066 if (!CONST_INT_P (residual))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2067 emit_label (label);
111
kono
parents: 67
diff changeset
2068 }
kono
parents: 67
diff changeset
2069 }
kono
parents: 67
diff changeset
2070
kono
parents: 67
diff changeset
2071
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2072 /* Adjust the stack pointer by minus SIZE (an rtx for a number of bytes)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2073 while probing it. This pushes when SIZE is positive. SIZE need not
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2074 be constant. If ADJUST_BACK is true, adjust back the stack pointer
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2075 by plus SIZE at the end. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2076
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2077 void
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2078 anti_adjust_stack_and_probe (rtx size, bool adjust_back)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2079 {
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2080 /* We skip the probe for the first interval + a small dope of 4 words and
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2081 probe that many bytes past the specified size to maintain a protection
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2082 area at the botton of the stack. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2083 const int dope = 4 * UNITS_PER_WORD;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2084
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2085 /* First ensure SIZE is Pmode. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2086 if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2087 size = convert_to_mode (Pmode, size, 1);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2088
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2089 /* If we have a constant small number of probes to generate, that's the
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2090 easy case. */
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2091 if (CONST_INT_P (size) && INTVAL (size) < 7 * PROBE_INTERVAL)
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2092 {
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2093 HOST_WIDE_INT isize = INTVAL (size), i;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2094 bool first_probe = true;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2095
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2096 /* Adjust SP and probe at PROBE_INTERVAL + N * PROBE_INTERVAL for
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2097 values of N from 1 until it exceeds SIZE. If only one probe is
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2098 needed, this will not generate any code. Then adjust and probe
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2099 to PROBE_INTERVAL + SIZE. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2100 for (i = PROBE_INTERVAL; i < isize; i += PROBE_INTERVAL)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2101 {
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2102 if (first_probe)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2103 {
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2104 anti_adjust_stack (GEN_INT (2 * PROBE_INTERVAL + dope));
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2105 first_probe = false;
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2106 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2107 else
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2108 anti_adjust_stack (GEN_INT (PROBE_INTERVAL));
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2109 emit_stack_probe (stack_pointer_rtx);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2110 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2111
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2112 if (first_probe)
111
kono
parents: 67
diff changeset
2113 anti_adjust_stack (plus_constant (Pmode, size, PROBE_INTERVAL + dope));
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2114 else
111
kono
parents: 67
diff changeset
2115 anti_adjust_stack (plus_constant (Pmode, size, PROBE_INTERVAL - i));
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2116 emit_stack_probe (stack_pointer_rtx);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2117 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2118
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2119 /* In the variable case, do the same as above, but in a loop. Note that we
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2120 must be extra careful with variables wrapping around because we might be
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2121 at the very top (or the very bottom) of the address space and we have to
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2122 be able to handle this case properly; in particular, we use an equality
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2123 test for the loop condition. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2124 else
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2125 {
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2126 rtx rounded_size, rounded_size_op, last_addr, temp;
111
kono
parents: 67
diff changeset
2127 rtx_code_label *loop_lab = gen_label_rtx ();
kono
parents: 67
diff changeset
2128 rtx_code_label *end_lab = gen_label_rtx ();
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2129
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2130
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2131 /* Step 1: round SIZE to the previous multiple of the interval. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2132
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2133 /* ROUNDED_SIZE = SIZE & -PROBE_INTERVAL */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2134 rounded_size
111
kono
parents: 67
diff changeset
2135 = simplify_gen_binary (AND, Pmode, size,
kono
parents: 67
diff changeset
2136 gen_int_mode (-PROBE_INTERVAL, Pmode));
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2137 rounded_size_op = force_operand (rounded_size, NULL_RTX);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2138
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2139
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2140 /* Step 2: compute initial and final value of the loop counter. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2141
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2142 /* SP = SP_0 + PROBE_INTERVAL. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2143 anti_adjust_stack (GEN_INT (PROBE_INTERVAL + dope));
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2144
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2145 /* LAST_ADDR = SP_0 + PROBE_INTERVAL + ROUNDED_SIZE. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2146 last_addr = force_operand (gen_rtx_fmt_ee (STACK_GROW_OP, Pmode,
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2147 stack_pointer_rtx,
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2148 rounded_size_op), NULL_RTX);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2149
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2150
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2151 /* Step 3: the loop
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2152
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2153 while (SP != LAST_ADDR)
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2154 {
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2155 SP = SP + PROBE_INTERVAL
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2156 probe at SP
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2157 }
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2158
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2159 adjusts SP and probes at PROBE_INTERVAL + N * PROBE_INTERVAL for
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2160 values of N from 1 until it is equal to ROUNDED_SIZE. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2161
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2162 emit_label (loop_lab);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2163
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2164 /* Jump to END_LAB if SP == LAST_ADDR. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2165 emit_cmp_and_jump_insns (stack_pointer_rtx, last_addr, EQ, NULL_RTX,
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2166 Pmode, 1, end_lab);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2167
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2168 /* SP = SP + PROBE_INTERVAL and probe at SP. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2169 anti_adjust_stack (GEN_INT (PROBE_INTERVAL));
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2170 emit_stack_probe (stack_pointer_rtx);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2171
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2172 emit_jump (loop_lab);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2173
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2174 emit_label (end_lab);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2175
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2176
67
f6334be47118 update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents: 55
diff changeset
2177 /* Step 4: adjust SP and probe at PROBE_INTERVAL + SIZE if we cannot
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2178 assert at compile-time that SIZE is equal to ROUNDED_SIZE. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2179
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2180 /* TEMP = SIZE - ROUNDED_SIZE. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2181 temp = simplify_gen_binary (MINUS, Pmode, size, rounded_size);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2182 if (temp != const0_rtx)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2183 {
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2184 /* Manual CSE if the difference is not known at compile-time. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2185 if (GET_CODE (temp) != CONST_INT)
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2186 temp = gen_rtx_MINUS (Pmode, size, rounded_size_op);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2187 anti_adjust_stack (temp);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2188 emit_stack_probe (stack_pointer_rtx);
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2189 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2190 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2191
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2192 /* Adjust back and account for the additional first interval. */
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2193 if (adjust_back)
111
kono
parents: 67
diff changeset
2194 adjust_stack (plus_constant (Pmode, size, PROBE_INTERVAL + dope));
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2195 else
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2196 adjust_stack (GEN_INT (PROBE_INTERVAL + dope));
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2197 }
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2198
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2199 /* Return an rtx representing the register or memory location
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2200 in which a scalar value of data type VALTYPE
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2201 was returned by a function call to function FUNC.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2202 FUNC is a FUNCTION_DECL, FNTYPE a FUNCTION_TYPE node if the precise
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2203 function is known, otherwise 0.
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2204 OUTGOING is 1 if on a machine with register windows this function
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2205 should return the register in which the function will put its result
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2206 and 0 otherwise. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2207
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2208 rtx
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2209 hard_function_value (const_tree valtype, const_tree func, const_tree fntype,
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2210 int outgoing ATTRIBUTE_UNUSED)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2211 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2212 rtx val;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2213
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2214 val = targetm.calls.function_value (valtype, func ? func : fntype, outgoing);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2215
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2216 if (REG_P (val)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2217 && GET_MODE (val) == BLKmode)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2218 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2219 unsigned HOST_WIDE_INT bytes = arg_int_size_in_bytes (valtype);
111
kono
parents: 67
diff changeset
2220 opt_scalar_int_mode tmpmode;
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2221
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2222 /* int_size_in_bytes can return -1. We don't need a check here
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2223 since the value of bytes will then be large enough that no
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2224 mode will match anyway. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2225
111
kono
parents: 67
diff changeset
2226 FOR_EACH_MODE_IN_CLASS (tmpmode, MODE_INT)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2227 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2228 /* Have we found a large enough mode? */
111
kono
parents: 67
diff changeset
2229 if (GET_MODE_SIZE (tmpmode.require ()) >= bytes)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2230 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2231 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2232
111
kono
parents: 67
diff changeset
2233 PUT_MODE (val, tmpmode.require ());
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2234 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2235 return val;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2236 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2237
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2238 /* Return an rtx representing the register or memory location
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2239 in which a scalar value of mode MODE was returned by a library call. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2240
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2241 rtx
111
kono
parents: 67
diff changeset
2242 hard_libcall_value (machine_mode mode, rtx fun)
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2243 {
55
77e2b8dfacca update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents: 0
diff changeset
2244 return targetm.calls.libcall_value (mode, fun);
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2245 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2246
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2247 /* Look up the tree code for a given rtx code
111
kono
parents: 67
diff changeset
2248 to provide the arithmetic operation for real_arithmetic.
0
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2249 The function returns an int because the caller may not know
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2250 what `enum tree_code' means. */
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2251
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2252 int
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2253 rtx_to_tree_code (enum rtx_code code)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2254 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2255 enum tree_code tcode;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2256
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2257 switch (code)
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2258 {
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2259 case PLUS:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2260 tcode = PLUS_EXPR;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2261 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2262 case MINUS:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2263 tcode = MINUS_EXPR;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2264 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2265 case MULT:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2266 tcode = MULT_EXPR;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2267 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2268 case DIV:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2269 tcode = RDIV_EXPR;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2270 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2271 case SMIN:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2272 tcode = MIN_EXPR;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2273 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2274 case SMAX:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2275 tcode = MAX_EXPR;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2276 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2277 default:
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2278 tcode = LAST_AND_UNUSED_TREE_CODE;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2279 break;
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2280 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2281 return ((int) tcode);
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2282 }
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2283
a06113de4d67 first commit
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2284 #include "gt-explow.h"