]>
Commit | Line | Data |
---|---|---|
1322177d | 1 | /* Procedure integration for GCC. |
8beccec8 | 2 | Copyright (C) 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
fe9565ed | 3 | 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. |
175160e7 MT |
4 | Contributed by Michael Tiemann (tiemann@cygnus.com) |
5 | ||
1322177d | 6 | This file is part of GCC. |
175160e7 | 7 | |
1322177d LB |
8 | GCC is free software; you can redistribute it and/or modify it under |
9 | the terms of the GNU General Public License as published by the Free | |
10 | Software Foundation; either version 2, or (at your option) any later | |
11 | version. | |
175160e7 | 12 | |
1322177d LB |
13 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 | for more details. | |
175160e7 MT |
17 | |
18 | You should have received a copy of the GNU General Public License | |
1322177d LB |
19 | along with GCC; see the file COPYING. If not, write to the Free |
20 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA | |
21 | 02111-1307, USA. */ | |
175160e7 | 22 | |
175160e7 | 23 | #include "config.h" |
670ee920 | 24 | #include "system.h" |
4977bab6 ZW |
25 | #include "coretypes.h" |
26 | #include "tm.h" | |
ccd043a9 | 27 | |
175160e7 MT |
28 | #include "rtl.h" |
29 | #include "tree.h" | |
6baf1cc8 | 30 | #include "tm_p.h" |
12307ca2 | 31 | #include "regs.h" |
175160e7 | 32 | #include "flags.h" |
135d50f1 | 33 | #include "debug.h" |
175160e7 | 34 | #include "insn-config.h" |
175160e7 MT |
35 | #include "expr.h" |
36 | #include "output.h" | |
e9a25f70 | 37 | #include "recog.h" |
175160e7 MT |
38 | #include "integrate.h" |
39 | #include "real.h" | |
6adb4e3a | 40 | #include "except.h" |
175160e7 | 41 | #include "function.h" |
d6f4ec51 | 42 | #include "toplev.h" |
ab87f8c8 | 43 | #include "intl.h" |
c6d9a88c | 44 | #include "params.h" |
c0e7830f | 45 | #include "ggc.h" |
91d231cb | 46 | #include "target.h" |
63e1b1c4 | 47 | #include "langhooks.h" |
175160e7 | 48 | |
6de9cd9a | 49 | /* Round to the next highest integer that meets the alignment. */ |
175160e7 | 50 | #define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1)) |
175160e7 | 51 | \f |
c0e7830f | 52 | |
f7239224 | 53 | /* Private type used by {get/has}_hard_reg_initial_val. */ |
e2500fed | 54 | typedef struct initial_value_pair GTY(()) { |
c0e7830f DD |
55 | rtx hard_reg; |
56 | rtx pseudo; | |
57 | } initial_value_pair; | |
e2500fed | 58 | typedef struct initial_value_struct GTY(()) { |
c0e7830f DD |
59 | int num_entries; |
60 | int max_entries; | |
e2500fed | 61 | initial_value_pair * GTY ((length ("%h.num_entries"))) entries; |
c0e7830f DD |
62 | } initial_value_struct; |
63 | ||
1d088dee AJ |
64 | static void set_block_origin_self (tree); |
65 | static void set_block_abstract_flags (tree, int); | |
175160e7 | 66 | \f |
1f3d3a31 | 67 | |
91d231cb JM |
68 | /* Return false if the function FNDECL cannot be inlined on account of its |
69 | attributes, true otherwise. */ | |
588d3ade | 70 | bool |
1d088dee | 71 | function_attribute_inlinable_p (tree fndecl) |
91d231cb | 72 | { |
b9a26d09 | 73 | if (targetm.attribute_table) |
91d231cb | 74 | { |
b9a26d09 | 75 | tree a; |
91d231cb | 76 | |
b9a26d09 | 77 | for (a = DECL_ATTRIBUTES (fndecl); a; a = TREE_CHAIN (a)) |
91d231cb | 78 | { |
b9a26d09 NB |
79 | tree name = TREE_PURPOSE (a); |
80 | int i; | |
81 | ||
82 | for (i = 0; targetm.attribute_table[i].name != NULL; i++) | |
83 | if (is_attribute_p (targetm.attribute_table[i].name, name)) | |
5fd9b178 | 84 | return targetm.function_attribute_inlinable_p (fndecl); |
91d231cb | 85 | } |
91d231cb JM |
86 | } |
87 | ||
b9a26d09 | 88 | return true; |
91d231cb | 89 | } |
175160e7 | 90 | \f |
5377d5ba RK |
91 | /* Copy NODE (which must be a DECL). The DECL originally was in the FROM_FN, |
92 | but now it will be in the TO_FN. */ | |
02e24c7a | 93 | |
94755d92 | 94 | tree |
1d088dee | 95 | copy_decl_for_inlining (tree decl, tree from_fn, tree to_fn) |
02e24c7a | 96 | { |
94755d92 MM |
97 | tree copy; |
98 | ||
99 | /* Copy the declaration. */ | |
100 | if (TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL) | |
a8f8d1cc | 101 | { |
669d6ecc | 102 | tree type = TREE_TYPE (decl); |
c246c65d | 103 | |
5377d5ba | 104 | /* For a parameter or result, we must make an equivalent VAR_DECL, not a |
a8f8d1cc | 105 | new PARM_DECL. */ |
c246c65d | 106 | copy = build_decl (VAR_DECL, DECL_NAME (decl), type); |
669d6ecc JM |
107 | TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl); |
108 | TREE_READONLY (copy) = TREE_READONLY (decl); | |
109 | TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl); | |
a8f8d1cc | 110 | } |
94755d92 MM |
111 | else |
112 | { | |
113 | copy = copy_node (decl); | |
1e7ee6ad MM |
114 | /* The COPY is not abstract; it will be generated in TO_FN. */ |
115 | DECL_ABSTRACT (copy) = 0; | |
ae2bcd98 | 116 | lang_hooks.dup_lang_specific_decl (copy); |
a71811fe MM |
117 | |
118 | /* TREE_ADDRESSABLE isn't used to indicate that a label's | |
119 | address has been taken; it's for internal bookkeeping in | |
120 | expand_goto_internal. */ | |
121 | if (TREE_CODE (copy) == LABEL_DECL) | |
6de9cd9a DN |
122 | { |
123 | TREE_ADDRESSABLE (copy) = 0; | |
6de9cd9a | 124 | } |
94755d92 MM |
125 | } |
126 | ||
b785f485 RH |
127 | /* Don't generate debug information for the copy if we wouldn't have |
128 | generated it for the copy either. */ | |
129 | DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (decl); | |
130 | DECL_IGNORED_P (copy) = DECL_IGNORED_P (decl); | |
131 | ||
94755d92 MM |
132 | /* Set the DECL_ABSTRACT_ORIGIN so the debugging routines know what |
133 | declaration inspired this copy. */ | |
99ceae26 | 134 | DECL_ABSTRACT_ORIGIN (copy) = DECL_ORIGIN (decl); |
94755d92 MM |
135 | |
136 | /* The new variable/label has no RTL, yet. */ | |
4e8dca1c JM |
137 | if (!TREE_STATIC (copy) && !DECL_EXTERNAL (copy)) |
138 | SET_DECL_RTL (copy, NULL_RTX); | |
94755d92 MM |
139 | |
140 | /* These args would always appear unused, if not for this. */ | |
141 | TREE_USED (copy) = 1; | |
142 | ||
143 | /* Set the context for the new declaration. */ | |
144 | if (!DECL_CONTEXT (decl)) | |
145 | /* Globals stay global. */ | |
00174bdf | 146 | ; |
94755d92 MM |
147 | else if (DECL_CONTEXT (decl) != from_fn) |
148 | /* Things that weren't in the scope of the function we're inlining | |
4e8dca1c | 149 | from aren't in the scope we're inlining to, either. */ |
94755d92 MM |
150 | ; |
151 | else if (TREE_STATIC (decl)) | |
4e8dca1c | 152 | /* Function-scoped static variables should stay in the original |
94755d92 | 153 | function. */ |
02e24c7a MM |
154 | ; |
155 | else | |
94755d92 MM |
156 | /* Ordinary automatic local variables are now in the scope of the |
157 | new function. */ | |
158 | DECL_CONTEXT (copy) = to_fn; | |
02e24c7a MM |
159 | |
160 | return copy; | |
161 | } | |
12307ca2 | 162 | |
175160e7 | 163 | \f |
81578142 RS |
164 | /* Given a pointer to some BLOCK node, if the BLOCK_ABSTRACT_ORIGIN for the |
165 | given BLOCK node is NULL, set the BLOCK_ABSTRACT_ORIGIN for the node so | |
166 | that it points to the node itself, thus indicating that the node is its | |
167 | own (abstract) origin. Additionally, if the BLOCK_ABSTRACT_ORIGIN for | |
168 | the given node is NULL, recursively descend the decl/block tree which | |
169 | it is the root of, and for each other ..._DECL or BLOCK node contained | |
170 | therein whose DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also | |
171 | still NULL, set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN | |
172 | values to point to themselves. */ | |
173 | ||
81578142 | 174 | static void |
1d088dee | 175 | set_block_origin_self (tree stmt) |
81578142 RS |
176 | { |
177 | if (BLOCK_ABSTRACT_ORIGIN (stmt) == NULL_TREE) | |
178 | { | |
179 | BLOCK_ABSTRACT_ORIGIN (stmt) = stmt; | |
180 | ||
181 | { | |
b3694847 | 182 | tree local_decl; |
81578142 | 183 | |
00174bdf | 184 | for (local_decl = BLOCK_VARS (stmt); |
81578142 RS |
185 | local_decl != NULL_TREE; |
186 | local_decl = TREE_CHAIN (local_decl)) | |
00174bdf | 187 | set_decl_origin_self (local_decl); /* Potential recursion. */ |
81578142 RS |
188 | } |
189 | ||
190 | { | |
b3694847 | 191 | tree subblock; |
81578142 | 192 | |
00174bdf | 193 | for (subblock = BLOCK_SUBBLOCKS (stmt); |
81578142 RS |
194 | subblock != NULL_TREE; |
195 | subblock = BLOCK_CHAIN (subblock)) | |
00174bdf | 196 | set_block_origin_self (subblock); /* Recurse. */ |
81578142 RS |
197 | } |
198 | } | |
199 | } | |
200 | ||
201 | /* Given a pointer to some ..._DECL node, if the DECL_ABSTRACT_ORIGIN for | |
202 | the given ..._DECL node is NULL, set the DECL_ABSTRACT_ORIGIN for the | |
203 | node to so that it points to the node itself, thus indicating that the | |
204 | node represents its own (abstract) origin. Additionally, if the | |
205 | DECL_ABSTRACT_ORIGIN for the given node is NULL, recursively descend | |
206 | the decl/block tree of which the given node is the root of, and for | |
207 | each other ..._DECL or BLOCK node contained therein whose | |
208 | DECL_ABSTRACT_ORIGINs or BLOCK_ABSTRACT_ORIGINs are also still NULL, | |
209 | set *their* DECL_ABSTRACT_ORIGIN or BLOCK_ABSTRACT_ORIGIN values to | |
210 | point to themselves. */ | |
211 | ||
1cfdcc15 | 212 | void |
1d088dee | 213 | set_decl_origin_self (tree decl) |
81578142 RS |
214 | { |
215 | if (DECL_ABSTRACT_ORIGIN (decl) == NULL_TREE) | |
216 | { | |
217 | DECL_ABSTRACT_ORIGIN (decl) = decl; | |
218 | if (TREE_CODE (decl) == FUNCTION_DECL) | |
219 | { | |
b3694847 | 220 | tree arg; |
81578142 RS |
221 | |
222 | for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg)) | |
223 | DECL_ABSTRACT_ORIGIN (arg) = arg; | |
29d356fb RK |
224 | if (DECL_INITIAL (decl) != NULL_TREE |
225 | && DECL_INITIAL (decl) != error_mark_node) | |
81578142 RS |
226 | set_block_origin_self (DECL_INITIAL (decl)); |
227 | } | |
228 | } | |
229 | } | |
230 | \f | |
231 | /* Given a pointer to some BLOCK node, and a boolean value to set the | |
232 | "abstract" flags to, set that value into the BLOCK_ABSTRACT flag for | |
233 | the given block, and for all local decls and all local sub-blocks | |
234 | (recursively) which are contained therein. */ | |
235 | ||
81578142 | 236 | static void |
1d088dee | 237 | set_block_abstract_flags (tree stmt, int setting) |
81578142 | 238 | { |
b3694847 SS |
239 | tree local_decl; |
240 | tree subblock; | |
81578142 | 241 | |
12307ca2 | 242 | BLOCK_ABSTRACT (stmt) = setting; |
81578142 | 243 | |
12307ca2 RK |
244 | for (local_decl = BLOCK_VARS (stmt); |
245 | local_decl != NULL_TREE; | |
246 | local_decl = TREE_CHAIN (local_decl)) | |
247 | set_decl_abstract_flags (local_decl, setting); | |
81578142 | 248 | |
12307ca2 RK |
249 | for (subblock = BLOCK_SUBBLOCKS (stmt); |
250 | subblock != NULL_TREE; | |
251 | subblock = BLOCK_CHAIN (subblock)) | |
252 | set_block_abstract_flags (subblock, setting); | |
81578142 RS |
253 | } |
254 | ||
255 | /* Given a pointer to some ..._DECL node, and a boolean value to set the | |
256 | "abstract" flags to, set that value into the DECL_ABSTRACT flag for the | |
257 | given decl, and (in the case where the decl is a FUNCTION_DECL) also | |
258 | set the abstract flags for all of the parameters, local vars, local | |
259 | blocks and sub-blocks (recursively) to the same setting. */ | |
260 | ||
261 | void | |
1d088dee | 262 | set_decl_abstract_flags (tree decl, int setting) |
81578142 RS |
263 | { |
264 | DECL_ABSTRACT (decl) = setting; | |
265 | if (TREE_CODE (decl) == FUNCTION_DECL) | |
266 | { | |
b3694847 | 267 | tree arg; |
81578142 RS |
268 | |
269 | for (arg = DECL_ARGUMENTS (decl); arg; arg = TREE_CHAIN (arg)) | |
270 | DECL_ABSTRACT (arg) = setting; | |
29d356fb RK |
271 | if (DECL_INITIAL (decl) != NULL_TREE |
272 | && DECL_INITIAL (decl) != error_mark_node) | |
81578142 RS |
273 | set_block_abstract_flags (DECL_INITIAL (decl), setting); |
274 | } | |
275 | } | |
c0e7830f DD |
276 | \f |
277 | /* Functions to keep track of the values hard regs had at the start of | |
278 | the function. */ | |
279 | ||
902197eb | 280 | rtx |
1d088dee | 281 | get_hard_reg_initial_reg (struct function *fun, rtx reg) |
902197eb DD |
282 | { |
283 | struct initial_value_struct *ivs = fun->hard_reg_initial_vals; | |
284 | int i; | |
285 | ||
286 | if (ivs == 0) | |
287 | return NULL_RTX; | |
288 | ||
289 | for (i = 0; i < ivs->num_entries; i++) | |
290 | if (rtx_equal_p (ivs->entries[i].pseudo, reg)) | |
291 | return ivs->entries[i].hard_reg; | |
292 | ||
293 | return NULL_RTX; | |
294 | } | |
295 | ||
f7239224 RS |
296 | /* Make sure that there's a pseudo register of mode MODE that stores the |
297 | initial value of hard register REGNO. Return an rtx for such a pseudo. */ | |
c0e7830f | 298 | |
f7239224 RS |
299 | rtx |
300 | get_hard_reg_initial_val (enum machine_mode mode, int regno) | |
c0e7830f | 301 | { |
f7239224 RS |
302 | struct initial_value_struct *ivs; |
303 | rtx rv; | |
c0e7830f | 304 | |
f7239224 | 305 | rv = has_hard_reg_initial_val (mode, regno); |
c0e7830f DD |
306 | if (rv) |
307 | return rv; | |
308 | ||
f7239224 | 309 | ivs = cfun->hard_reg_initial_vals; |
c0e7830f DD |
310 | if (ivs == 0) |
311 | { | |
f7239224 | 312 | ivs = ggc_alloc (sizeof (initial_value_struct)); |
c0e7830f DD |
313 | ivs->num_entries = 0; |
314 | ivs->max_entries = 5; | |
703ad42b | 315 | ivs->entries = ggc_alloc (5 * sizeof (initial_value_pair)); |
f7239224 | 316 | cfun->hard_reg_initial_vals = ivs; |
c0e7830f DD |
317 | } |
318 | ||
319 | if (ivs->num_entries >= ivs->max_entries) | |
320 | { | |
321 | ivs->max_entries += 5; | |
703ad42b KG |
322 | ivs->entries = ggc_realloc (ivs->entries, |
323 | ivs->max_entries | |
324 | * sizeof (initial_value_pair)); | |
c0e7830f DD |
325 | } |
326 | ||
f7239224 RS |
327 | ivs->entries[ivs->num_entries].hard_reg = gen_rtx_REG (mode, regno); |
328 | ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (mode); | |
c0e7830f DD |
329 | |
330 | return ivs->entries[ivs->num_entries++].pseudo; | |
331 | } | |
332 | ||
f7239224 RS |
333 | /* See if get_hard_reg_initial_val has been used to create a pseudo |
334 | for the initial value of hard register REGNO in mode MODE. Return | |
335 | the associated pseudo if so, otherwise return NULL. */ | |
c0e7830f DD |
336 | |
337 | rtx | |
1d088dee | 338 | has_hard_reg_initial_val (enum machine_mode mode, int regno) |
c0e7830f | 339 | { |
f7239224 RS |
340 | struct initial_value_struct *ivs; |
341 | int i; | |
342 | ||
343 | ivs = cfun->hard_reg_initial_vals; | |
344 | if (ivs != 0) | |
345 | for (i = 0; i < ivs->num_entries; i++) | |
346 | if (GET_MODE (ivs->entries[i].hard_reg) == mode | |
347 | && REGNO (ivs->entries[i].hard_reg) == (unsigned int) regno) | |
348 | return ivs->entries[i].pseudo; | |
349 | ||
350 | return NULL_RTX; | |
c0e7830f DD |
351 | } |
352 | ||
c0e7830f | 353 | void |
1d088dee | 354 | emit_initial_value_sets (void) |
c0e7830f DD |
355 | { |
356 | struct initial_value_struct *ivs = cfun->hard_reg_initial_vals; | |
357 | int i; | |
358 | rtx seq; | |
359 | ||
360 | if (ivs == 0) | |
361 | return; | |
362 | ||
363 | start_sequence (); | |
364 | for (i = 0; i < ivs->num_entries; i++) | |
365 | emit_move_insn (ivs->entries[i].pseudo, ivs->entries[i].hard_reg); | |
366 | seq = get_insns (); | |
367 | end_sequence (); | |
368 | ||
91278841 | 369 | emit_insn_after (seq, entry_of_function ()); |
c0e7830f | 370 | } |
385b6e2d R |
371 | |
372 | /* If the backend knows where to allocate pseudos for hard | |
373 | register initial values, register these allocations now. */ | |
374 | void | |
1d088dee | 375 | allocate_initial_values (rtx *reg_equiv_memory_loc ATTRIBUTE_UNUSED) |
385b6e2d R |
376 | { |
377 | #ifdef ALLOCATE_INITIAL_VALUE | |
378 | struct initial_value_struct *ivs = cfun->hard_reg_initial_vals; | |
379 | int i; | |
380 | ||
381 | if (ivs == 0) | |
382 | return; | |
383 | ||
384 | for (i = 0; i < ivs->num_entries; i++) | |
385 | { | |
386 | int regno = REGNO (ivs->entries[i].pseudo); | |
387 | rtx x = ALLOCATE_INITIAL_VALUE (ivs->entries[i].hard_reg); | |
388 | ||
41806d92 | 389 | if (x && REG_N_SETS (REGNO (ivs->entries[i].pseudo)) <= 1) |
385b6e2d | 390 | { |
41806d92 NS |
391 | if (MEM_P (x)) |
392 | reg_equiv_memory_loc[regno] = x; | |
393 | else | |
394 | { | |
395 | gcc_assert (REG_P (x)); | |
396 | reg_renumber[regno] = REGNO (x); | |
397 | /* Poke the regno right into regno_reg_rtx so that even | |
398 | fixed regs are accepted. */ | |
399 | REGNO (ivs->entries[i].pseudo) = REGNO (x); | |
400 | } | |
385b6e2d | 401 | } |
385b6e2d R |
402 | } |
403 | #endif | |
404 | } | |
e2500fed GK |
405 | |
406 | #include "gt-integrate.h" |