]>
Commit | Line | Data |
---|---|---|
f2c5f623 BC |
1 | /* This file contains the definitions and documentation for the common |
2 | tree codes used in the GNU C and C++ compilers (see c-common.def | |
2f6e4e97 | 3 | for the standard codes). |
283334f0 | 4 | Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. |
4f78b9a8 | 5 | Written by Benjamin Chelf (chelf@codesourcery.com). |
f2c5f623 | 6 | |
1322177d | 7 | This file is part of GCC. |
f2c5f623 | 8 | |
1322177d LB |
9 | GCC is free software; you can redistribute it and/or modify it under |
10 | the terms of the GNU General Public License as published by the Free | |
11 | Software Foundation; either version 2, or (at your option) any later | |
12 | version. | |
f2c5f623 | 13 | |
1322177d LB |
14 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
15 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 | for more details. | |
f2c5f623 BC |
18 | |
19 | You should have received a copy of the GNU General Public License | |
1322177d LB |
20 | along with GCC; see the file COPYING. If not, write to the Free |
21 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA | |
22 | 02111-1307, USA. */ | |
f2c5f623 BC |
23 | |
24 | #include "config.h" | |
25 | #include "system.h" | |
4977bab6 ZW |
26 | #include "coretypes.h" |
27 | #include "tm.h" | |
f2c5f623 BC |
28 | #include "tree.h" |
29 | #include "function.h" | |
30 | #include "splay-tree.h" | |
31 | #include "varray.h" | |
32 | #include "c-common.h" | |
33 | #include "except.h" | |
5f1989e6 KG |
34 | /* In order for the format checking to accept the C frontend |
35 | diagnostic framework extensions, you must define this token before | |
36 | including toplev.h. */ | |
37 | #define GCC_DIAG_STYLE __gcc_cdiag__ | |
f2c5f623 BC |
38 | #include "toplev.h" |
39 | #include "flags.h" | |
40 | #include "ggc.h" | |
41 | #include "rtl.h" | |
d6684bc8 | 42 | #include "expr.h" |
f2c5f623 BC |
43 | #include "output.h" |
44 | #include "timevar.h" | |
969d70ca | 45 | #include "predict.h" |
96c6931d | 46 | #include "tree-inline.h" |
6de9cd9a | 47 | #include "langhooks.h" |
96c6931d | 48 | |
ae499cce MM |
49 | /* Create an empty statement tree rooted at T. */ |
50 | ||
51 | void | |
2f6e4e97 | 52 | begin_stmt_tree (tree *t) |
ae499cce MM |
53 | { |
54 | /* We create a trivial EXPR_STMT so that last_tree is never NULL in | |
55 | what follows. We remove the extraneous statement in | |
56 | finish_stmt_tree. */ | |
57 | *t = build_nt (EXPR_STMT, void_zero_node); | |
58 | last_tree = *t; | |
59 | last_expr_type = NULL_TREE; | |
de097a2d | 60 | last_expr_filename = input_filename; |
ae499cce MM |
61 | } |
62 | ||
63 | /* T is a statement. Add it to the statement-tree. */ | |
64 | ||
56cb9733 | 65 | tree |
2f6e4e97 | 66 | add_stmt (tree t) |
ae499cce | 67 | { |
6de9cd9a DN |
68 | if (!EXPR_LOCUS (t)) |
69 | annotate_with_locus (t, input_location); | |
de097a2d | 70 | |
ae499cce MM |
71 | /* Add T to the statement-tree. */ |
72 | TREE_CHAIN (last_tree) = t; | |
73 | last_tree = t; | |
2f6e4e97 | 74 | |
ae499cce | 75 | /* When we expand a statement-tree, we must know whether or not the |
0ba8a114 | 76 | statements are full-expressions. We record that fact here. */ |
ae499cce | 77 | STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p (); |
b850de4f | 78 | |
56cb9733 | 79 | return t; |
ae499cce MM |
80 | } |
81 | ||
8f17b5c5 MM |
82 | /* Create a declaration statement for the declaration given by the |
83 | DECL. */ | |
84 | ||
85 | void | |
2f6e4e97 | 86 | add_decl_stmt (tree decl) |
8f17b5c5 MM |
87 | { |
88 | tree decl_stmt; | |
89 | ||
90 | /* We need the type to last until instantiation time. */ | |
91 | decl_stmt = build_stmt (DECL_STMT, decl); | |
2f6e4e97 | 92 | add_stmt (decl_stmt); |
8f17b5c5 MM |
93 | } |
94 | ||
95 | /* Add a scope-statement to the statement-tree. BEGIN_P indicates | |
96 | whether this statements opens or closes a scope. PARTIAL_P is true | |
97 | for a partial scope, i.e, the scope that begins after a label when | |
98 | an object that needs a cleanup is created. If BEGIN_P is nonzero, | |
99 | returns a new TREE_LIST representing the top of the SCOPE_STMT | |
100 | stack. The TREE_PURPOSE is the new SCOPE_STMT. If BEGIN_P is | |
101 | zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT, | |
0ba8a114 | 102 | and whose TREE_PURPOSE is the matching SCOPE_STMT with |
8f17b5c5 MM |
103 | SCOPE_BEGIN_P set. */ |
104 | ||
105 | tree | |
2f6e4e97 | 106 | add_scope_stmt (int begin_p, int partial_p) |
8f17b5c5 | 107 | { |
de8e49f3 | 108 | tree *stack_ptr = current_scope_stmt_stack (); |
8f17b5c5 | 109 | tree ss; |
de8e49f3 | 110 | tree top = *stack_ptr; |
8f17b5c5 MM |
111 | |
112 | /* Build the statement. */ | |
113 | ss = build_stmt (SCOPE_STMT, NULL_TREE); | |
114 | SCOPE_BEGIN_P (ss) = begin_p; | |
115 | SCOPE_PARTIAL_P (ss) = partial_p; | |
116 | ||
117 | /* Keep the scope stack up to date. */ | |
118 | if (begin_p) | |
119 | { | |
de8e49f3 NS |
120 | top = tree_cons (ss, NULL_TREE, top); |
121 | *stack_ptr = top; | |
8f17b5c5 MM |
122 | } |
123 | else | |
124 | { | |
9f175208 JM |
125 | if (partial_p != SCOPE_PARTIAL_P (TREE_PURPOSE (top))) |
126 | abort (); | |
8f17b5c5 | 127 | TREE_VALUE (top) = ss; |
de8e49f3 | 128 | *stack_ptr = TREE_CHAIN (top); |
8f17b5c5 MM |
129 | } |
130 | ||
131 | /* Add the new statement to the statement-tree. */ | |
132 | add_stmt (ss); | |
133 | ||
134 | return top; | |
135 | } | |
136 | ||
ae499cce MM |
137 | /* Finish the statement tree rooted at T. */ |
138 | ||
139 | void | |
2f6e4e97 | 140 | finish_stmt_tree (tree *t) |
ae499cce MM |
141 | { |
142 | tree stmt; | |
2f6e4e97 | 143 | |
ae499cce MM |
144 | /* Remove the fake extra statement added in begin_stmt_tree. */ |
145 | stmt = TREE_CHAIN (*t); | |
146 | *t = stmt; | |
147 | last_tree = NULL_TREE; | |
ae499cce MM |
148 | } |
149 | ||
0dfdeca6 BC |
150 | /* Build a generic statement based on the given type of node and |
151 | arguments. Similar to `build_nt', except that we set | |
6de9cd9a | 152 | EXPR_LOCUS to be the current source location. */ |
64094f6a RH |
153 | /* ??? This should be obsolete with the lineno_stmt productions |
154 | in the grammar. */ | |
0dfdeca6 BC |
155 | |
156 | tree | |
e34d07f2 | 157 | build_stmt (enum tree_code code, ...) |
0dfdeca6 | 158 | { |
6de9cd9a DN |
159 | tree ret; |
160 | int length, i; | |
e34d07f2 | 161 | va_list p; |
6de9cd9a | 162 | bool side_effects; |
2f6e4e97 | 163 | |
e34d07f2 | 164 | va_start (p, code); |
0dfdeca6 | 165 | |
6de9cd9a | 166 | ret = make_node (code); |
0dfdeca6 | 167 | length = TREE_CODE_LENGTH (code); |
6de9cd9a | 168 | annotate_with_locus (ret, input_location); |
0dfdeca6 | 169 | |
6de9cd9a DN |
170 | /* Most statements have implicit side effects all on their own, |
171 | such as control transfer. For those that do, we'll compute | |
172 | the real value of TREE_SIDE_EFFECTS from its arguments. */ | |
173 | switch (code) | |
174 | { | |
175 | case EXPR_STMT: | |
176 | side_effects = false; | |
177 | break; | |
178 | default: | |
179 | side_effects = true; | |
180 | break; | |
181 | } | |
f2c5f623 | 182 | |
6de9cd9a | 183 | for (i = 0; i < length; i++) |
f2c5f623 | 184 | { |
6de9cd9a DN |
185 | tree t = va_arg (p, tree); |
186 | if (t && IS_NON_TYPE_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (t)))) | |
187 | side_effects |= TREE_SIDE_EFFECTS (t); | |
188 | TREE_OPERAND (ret, i) = t; | |
f2c5f623 | 189 | } |
6de9cd9a DN |
190 | |
191 | TREE_SIDE_EFFECTS (ret) = side_effects; | |
192 | ||
193 | va_end (p); | |
194 | return ret; | |
f2c5f623 BC |
195 | } |
196 | ||
197 | /* Create RTL for the local static variable DECL. */ | |
198 | ||
199 | void | |
2f6e4e97 | 200 | make_rtl_for_local_static (tree decl) |
f2c5f623 BC |
201 | { |
202 | const char *asmspec = NULL; | |
203 | ||
204 | /* If we inlined this variable, we could see it's declaration | |
205 | again. */ | |
95ee998c | 206 | if (TREE_ASM_WRITTEN (decl)) |
f2c5f623 BC |
207 | return; |
208 | ||
2c21b247 MM |
209 | /* If the DECL_ASSEMBLER_NAME is not the same as the DECL_NAME, then |
210 | either we already created RTL for this DECL (and since it was a | |
0a7394bc | 211 | local variable, its DECL_ASSEMBLER_NAME got hacked up to prevent |
2c21b247 MM |
212 | clashes with other local statics with the same name by a previous |
213 | call to make_decl_rtl), or the user explicitly requested a | |
214 | particular assembly name for this variable, using the GNU | |
215 | extension for this purpose: | |
216 | ||
217 | int i asm ("j"); | |
218 | ||
219 | There's no way to know which case we're in, here. But, it turns | |
220 | out we're safe. If there's already RTL, then | |
221 | rest_of_decl_compilation ignores the ASMSPEC parameter, so we | |
222 | may as well not pass it in. If there isn't RTL, then we didn't | |
223 | already create RTL, which means that the modification to | |
224 | DECL_ASSEMBLER_NAME came only via the explicit extension. */ | |
225 | if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) | |
45dcf572 | 226 | && !DECL_RTL_SET_P (decl)) |
2c21b247 | 227 | asmspec = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); |
f2c5f623 BC |
228 | |
229 | rest_of_decl_compilation (decl, asmspec, /*top_level=*/0, /*at_end=*/0); | |
230 | } | |
231 | ||
232 | /* Let the back-end know about DECL. */ | |
233 | ||
234 | void | |
2f6e4e97 | 235 | emit_local_var (tree decl) |
f2c5f623 BC |
236 | { |
237 | /* Create RTL for this variable. */ | |
19e7881c | 238 | if (!DECL_RTL_SET_P (decl)) |
f2c5f623 | 239 | { |
6de9cd9a | 240 | if (DECL_HARD_REGISTER (decl)) |
3645c4dc RH |
241 | /* The user specified an assembler name for this variable. |
242 | Set that up now. */ | |
f2c5f623 BC |
243 | rest_of_decl_compilation |
244 | (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), | |
245 | /*top_level=*/0, /*at_end=*/0); | |
246 | else | |
247 | expand_decl (decl); | |
248 | } | |
249 | ||
03307888 JM |
250 | if (DECL_INITIAL (decl)) |
251 | { | |
252 | /* Actually do the initialization. */ | |
253 | if (stmts_are_full_exprs_p ()) | |
254 | expand_start_target_temps (); | |
f2c5f623 | 255 | |
03307888 | 256 | expand_decl_init (decl); |
f2c5f623 | 257 | |
03307888 JM |
258 | if (stmts_are_full_exprs_p ()) |
259 | expand_end_target_temps (); | |
260 | } | |
f2c5f623 BC |
261 | } |
262 | ||
ec5c56db | 263 | /* Build the node for a return statement and return it. */ |
0dfdeca6 BC |
264 | |
265 | tree | |
2f6e4e97 | 266 | build_return_stmt (tree expr) |
0dfdeca6 BC |
267 | { |
268 | return (build_stmt (RETURN_STMT, expr)); | |
269 | } | |
270 | ||
ec5c56db | 271 | /* Build a break statement node and return it. */ |
0dfdeca6 BC |
272 | |
273 | tree | |
2f6e4e97 | 274 | build_break_stmt (void) |
0dfdeca6 BC |
275 | { |
276 | return (build_stmt (BREAK_STMT)); | |
277 | } | |
278 | ||
ec5c56db | 279 | /* Build a continue statement node and return it. */ |
0dfdeca6 BC |
280 | |
281 | tree | |
2f6e4e97 | 282 | build_continue_stmt (void) |
0dfdeca6 BC |
283 | { |
284 | return (build_stmt (CONTINUE_STMT)); | |
285 | } | |
286 | ||
ec5c56db | 287 | /* Create a CASE_LABEL tree node and return it. */ |
0dfdeca6 BC |
288 | |
289 | tree | |
2f6e4e97 | 290 | build_case_label (tree low_value, tree high_value, tree label_decl) |
0dfdeca6 | 291 | { |
56cb9733 | 292 | return build_stmt (CASE_LABEL, low_value, high_value, label_decl); |
0dfdeca6 BC |
293 | } |
294 | ||
54f7877c MM |
295 | /* We're about to expand T, a statement. Set up appropriate context |
296 | for the substitution. */ | |
297 | ||
298 | void | |
2f6e4e97 | 299 | prep_stmt (tree t) |
54f7877c | 300 | { |
6de9cd9a DN |
301 | if (EXPR_LOCUS (t)) |
302 | input_location = *EXPR_LOCUS (t); | |
54f7877c MM |
303 | current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t); |
304 | } |