]>
Commit | Line | Data |
---|---|---|
8d08fdba MS |
1 | /* Convert language-specific tree expression to rtl instructions, |
2 | for GNU compiler. | |
0b5be897 | 3 | Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc. |
8d08fdba MS |
4 | |
5 | This file is part of GNU CC. | |
6 | ||
7 | GNU CC is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GNU CC is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GNU CC; see the file COPYING. If not, write to | |
e9fa0c7c RK |
19 | the Free Software Foundation, 59 Temple Place - Suite 330, |
20 | Boston, MA 02111-1307, USA. */ | |
8d08fdba MS |
21 | |
22 | ||
23 | #include "config.h" | |
8d052bc7 | 24 | #include "system.h" |
8d08fdba MS |
25 | #include "rtl.h" |
26 | #include "tree.h" | |
27 | #include "flags.h" | |
28 | #include "expr.h" | |
29 | #include "cp-tree.h" | |
54f92bfb | 30 | #include "toplev.h" |
8d08fdba | 31 | |
1bbe34be | 32 | #if 0 |
994ac65b | 33 | static tree extract_aggr_init PROTO((tree, tree)); |
49c249e1 | 34 | static tree extract_scalar_init PROTO((tree, tree)); |
1bbe34be | 35 | #endif |
9f617717 L |
36 | static rtx cplus_expand_expr PROTO((tree, rtx, enum machine_mode, |
37 | enum expand_modifier)); | |
49c249e1 | 38 | |
8d08fdba MS |
39 | /* Hook used by expand_expr to expand language-specific tree codes. */ |
40 | ||
9f617717 | 41 | static rtx |
8d08fdba MS |
42 | cplus_expand_expr (exp, target, tmode, modifier) |
43 | tree exp; | |
44 | rtx target; | |
45 | enum machine_mode tmode; | |
46 | enum expand_modifier modifier; | |
47 | { | |
48 | tree type = TREE_TYPE (exp); | |
49 | register enum machine_mode mode = TYPE_MODE (type); | |
50 | register enum tree_code code = TREE_CODE (exp); | |
8d08fdba MS |
51 | int ignore = target == const0_rtx; |
52 | ||
53 | if (ignore) | |
de22184b | 54 | target = 0; |
8d08fdba MS |
55 | |
56 | /* No sense saving up arithmetic to be done | |
57 | if it's all in the wrong mode to form part of an address. | |
58 | And force_operand won't know whether to sign-extend or zero-extend. */ | |
59 | ||
60 | if (mode != Pmode && modifier == EXPAND_SUM) | |
61 | modifier = EXPAND_NORMAL; | |
62 | ||
63 | switch (code) | |
64 | { | |
02531345 | 65 | case AGGR_INIT_EXPR: |
8d08fdba MS |
66 | { |
67 | /* Something needs to be initialized, but we didn't know | |
68 | where that thing was when building the tree. For example, | |
69 | it could be the return value of a function, or a parameter | |
70 | to a function which lays down in the stack, or a temporary | |
71 | variable which must be passed by reference. | |
72 | ||
73 | Cleanups are handled in a language-specific way: they | |
74 | might be run by the called function (true in GNU C++ | |
75 | for parameters with cleanups), or they might be | |
76 | run by the caller, after the call (true in GNU C++ | |
77 | for other cleanup needs). */ | |
78 | ||
79 | tree func = TREE_OPERAND (exp, 0); | |
80 | tree args = TREE_OPERAND (exp, 1); | |
81 | tree type = TREE_TYPE (exp), slot; | |
8d08fdba MS |
82 | tree call_exp; |
83 | rtx call_target, return_target; | |
84 | int pcc_struct_return = 0; | |
85 | ||
86 | /* The expression `init' wants to initialize what | |
87 | `target' represents. SLOT holds the slot for TARGET. */ | |
88 | slot = TREE_OPERAND (exp, 2); | |
89 | ||
02531345 JM |
90 | /* Should always be called with a target. */ |
91 | my_friendly_assert (target != NULL_RTX, 205); | |
8d08fdba MS |
92 | |
93 | /* The target the initializer will initialize (CALL_TARGET) | |
94 | must now be directed to initialize the target we are | |
95 | supposed to initialize (TARGET). The semantics for | |
96 | choosing what CALL_TARGET is is language-specific, | |
97 | as is building the call which will perform the | |
98 | initialization. It is left here to show the choices that | |
99 | exist for C++. */ | |
100 | ||
101 | if (TREE_CODE (func) == ADDR_EXPR | |
102 | && TREE_CODE (TREE_OPERAND (func, 0)) == FUNCTION_DECL | |
103 | && DECL_CONSTRUCTOR_P (TREE_OPERAND (func, 0))) | |
104 | { | |
f30432d7 | 105 | type = build_pointer_type (type); |
8d08fdba MS |
106 | /* Don't clobber a value that might be part of a default |
107 | parameter value. */ | |
c19a8067 | 108 | mark_addressable (slot); |
8d08fdba | 109 | if (TREE_PERMANENT (args)) |
e66d884e | 110 | args = expr_tree_cons (0, build1 (ADDR_EXPR, type, slot), |
8d08fdba MS |
111 | TREE_CHAIN (args)); |
112 | else | |
113 | TREE_VALUE (args) = build1 (ADDR_EXPR, type, slot); | |
114 | call_target = 0; | |
115 | } | |
8d08fdba MS |
116 | else |
117 | { | |
8d08fdba | 118 | call_target = target; |
6b4e8391 JM |
119 | #ifdef PCC_STATIC_STRUCT_RETURN |
120 | if (aggregate_value_p (type)) | |
121 | { | |
122 | pcc_struct_return = 1; | |
123 | call_target = 0; | |
124 | } | |
8d08fdba MS |
125 | #endif |
126 | } | |
8d08fdba | 127 | |
4dabb379 | 128 | call_exp = build (CALL_EXPR, type, func, args, NULL_TREE); |
8d08fdba | 129 | TREE_SIDE_EFFECTS (call_exp) = 1; |
e8abc66f | 130 | return_target = expand_call (call_exp, call_target, ignore); |
8d08fdba | 131 | |
02531345 | 132 | if (call_target) |
56841f01 JM |
133 | /* Trust that the right thing has been done; it's too hard to |
134 | verify. */ | |
135 | return return_target; | |
8d08fdba | 136 | |
02531345 JM |
137 | /* If we're suffering under the ancient PCC_STATIC_STRUCT_RETURN |
138 | calling convention, we need to copy the return value out of | |
139 | the static return buffer into slot. */ | |
140 | if (pcc_struct_return) | |
8d08fdba | 141 | { |
02531345 JM |
142 | extern int flag_access_control; |
143 | int old_ac = flag_access_control; | |
8d08fdba | 144 | |
02531345 JM |
145 | tree init = build_decl (VAR_DECL, NULL_TREE, |
146 | build_reference_type (type)); | |
147 | DECL_RTL (init) = XEXP (return_target, 0); | |
2a66ec2b | 148 | init = convert_from_reference (init); |
8d08fdba | 149 | |
02531345 | 150 | flag_access_control = 0; |
b370501f | 151 | expand_aggr_init (slot, init, LOOKUP_ONLYCONVERTING); |
02531345 JM |
152 | flag_access_control = old_ac; |
153 | ||
154 | if (TYPE_NEEDS_DESTRUCTOR (type)) | |
155 | { | |
2a66ec2b | 156 | init = maybe_build_cleanup (init); |
02531345 JM |
157 | if (init != NULL_TREE) |
158 | expand_expr (init, const0_rtx, VOIDmode, 0); | |
159 | } | |
8d08fdba MS |
160 | } |
161 | ||
8d08fdba MS |
162 | return DECL_RTL (slot); |
163 | } | |
164 | ||
61a127b3 MM |
165 | case PTRMEM_CST: |
166 | { | |
167 | tree member; | |
168 | tree offset; | |
169 | ||
170 | /* Find the member. */ | |
171 | member = PTRMEM_CST_MEMBER (exp); | |
172 | ||
173 | if (TREE_CODE (member) == FIELD_DECL) | |
174 | { | |
175 | /* Find the offset for the field. */ | |
176 | offset = convert (sizetype, | |
177 | size_binop (EASY_DIV_EXPR, | |
178 | DECL_FIELD_BITPOS (member), | |
179 | size_int (BITS_PER_UNIT))); | |
180 | ||
181 | /* We offset all pointer to data members by 1 so that we | |
182 | can distinguish between a null pointer to data member | |
183 | and the first data member of a structure. */ | |
184 | offset = size_binop (PLUS_EXPR, offset, size_int (1)); | |
185 | ||
186 | return expand_expr (cp_convert (type, offset), target, tmode, | |
187 | modifier); | |
188 | } | |
189 | else | |
190 | { | |
e08a8f45 MM |
191 | tree delta; |
192 | tree idx; | |
193 | tree pfn; | |
194 | tree delta2; | |
195 | ||
196 | expand_ptrmemfunc_cst (exp, &delta, &idx, &pfn, &delta2); | |
197 | ||
198 | return expand_expr (build_ptrmemfunc1 (type, delta, idx, | |
199 | pfn, delta2), | |
200 | target, tmode, modifier); | |
61a127b3 MM |
201 | } |
202 | } | |
203 | ||
8d08fdba MS |
204 | case OFFSET_REF: |
205 | { | |
8d08fdba MS |
206 | return expand_expr (default_conversion (resolve_offset_ref (exp)), |
207 | target, tmode, EXPAND_NORMAL); | |
8d08fdba MS |
208 | } |
209 | ||
8926095f MS |
210 | case THUNK_DECL: |
211 | return DECL_RTL (exp); | |
212 | ||
8d2733ca MS |
213 | case THROW_EXPR: |
214 | expand_throw (TREE_OPERAND (exp, 0)); | |
215 | return NULL; | |
216 | ||
a80e4195 MS |
217 | case VEC_INIT_EXPR: |
218 | return expand_expr | |
219 | (expand_vec_init | |
220 | (NULL_TREE, TREE_OPERAND (exp, 0), | |
221 | build_binary_op (MINUS_EXPR, TREE_OPERAND (exp, 2), | |
337c90cc | 222 | integer_one_node), |
a80e4195 MS |
223 | TREE_OPERAND (exp, 1), 0), target, tmode, modifier); |
224 | ||
a0d5fba7 JM |
225 | case NEW_EXPR: |
226 | return expand_expr (build_new_1 (exp), target, tmode, modifier); | |
227 | ||
8d08fdba MS |
228 | default: |
229 | break; | |
230 | } | |
231 | my_friendly_abort (40); | |
232 | /* NOTREACHED */ | |
233 | return NULL; | |
234 | } | |
235 | ||
236 | void | |
237 | init_cplus_expand () | |
238 | { | |
239 | lang_expand_expr = cplus_expand_expr; | |
240 | } | |
241 | ||
242 | /* If DECL had its rtl moved from where callers expect it | |
243 | to be, fix it up. RESULT is the nominal rtl for the RESULT_DECL, | |
244 | which may be a pseudo instead of a hard register. */ | |
245 | ||
246 | void | |
247 | fixup_result_decl (decl, result) | |
248 | tree decl; | |
249 | rtx result; | |
250 | { | |
251 | if (REG_P (result)) | |
252 | { | |
253 | if (REGNO (result) >= FIRST_PSEUDO_REGISTER) | |
254 | { | |
255 | rtx real_decl_result; | |
256 | ||
257 | #ifdef FUNCTION_OUTGOING_VALUE | |
258 | real_decl_result | |
259 | = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl), current_function_decl); | |
260 | #else | |
261 | real_decl_result | |
262 | = FUNCTION_VALUE (TREE_TYPE (decl), current_function_decl); | |
263 | #endif | |
264 | REG_FUNCTION_VALUE_P (real_decl_result) = 1; | |
265 | result = real_decl_result; | |
266 | } | |
28cbf42c | 267 | store_expr (decl, result, 0); |
8d08fdba MS |
268 | emit_insn (gen_rtx (USE, VOIDmode, result)); |
269 | } | |
270 | } | |
271 | ||
994ac65b | 272 | #if 0 |
28cbf42c MS |
273 | /* Expand this initialization inline and see if it's simple enough that |
274 | it can be done at compile-time. */ | |
275 | ||
276 | static tree | |
277 | extract_aggr_init (decl, init) | |
278 | tree decl, init; | |
279 | { | |
280 | return 0; | |
281 | } | |
282 | ||
283 | static tree | |
284 | extract_scalar_init (decl, init) | |
285 | tree decl, init; | |
286 | { | |
287 | rtx value, insns, insn; | |
288 | extern struct obstack temporary_obstack; | |
289 | tree t = NULL_TREE; | |
290 | ||
291 | push_obstacks (&temporary_obstack, &temporary_obstack); | |
292 | start_sequence (); | |
293 | value = expand_expr (init, NULL_RTX, VOIDmode, 0); | |
294 | insns = get_insns (); | |
295 | end_sequence (); | |
296 | reg_scan (insns, max_reg_num (), 0); | |
297 | jump_optimize (insns, 0, 0, 1); | |
298 | pop_obstacks (); | |
299 | ||
300 | for (insn = insns; insn; insn = NEXT_INSN (insn)) | |
301 | { | |
302 | rtx r, to; | |
303 | ||
304 | if (GET_CODE (insn) == NOTE) | |
305 | continue; | |
306 | else if (GET_CODE (insn) != INSN) | |
307 | return 0; | |
308 | ||
309 | r = PATTERN (insn); | |
310 | if (GET_CODE (r) != SET) | |
311 | return 0; | |
312 | ||
313 | to = XEXP (r, 0); | |
314 | ||
beb53fb8 JM |
315 | if (! (to == value |
316 | || (GET_CODE (to) == SUBREG && XEXP (to, 0) == value))) | |
28cbf42c MS |
317 | return 0; |
318 | ||
319 | r = XEXP (r, 1); | |
320 | ||
321 | switch (GET_CODE (r)) | |
322 | { | |
323 | case CONST_INT: | |
324 | t = build_int_2 (XEXP (r, 0), 0); | |
325 | break; | |
326 | default: | |
327 | return 0; | |
328 | } | |
329 | } | |
330 | ||
331 | return t; | |
332 | } | |
1bbe34be | 333 | #endif |
28cbf42c MS |
334 | |
335 | int | |
336 | extract_init (decl, init) | |
b370501f | 337 | tree decl ATTRIBUTE_UNUSED, init ATTRIBUTE_UNUSED; |
28cbf42c MS |
338 | { |
339 | return 0; | |
340 | ||
9e9ff709 | 341 | #if 0 |
28cbf42c MS |
342 | if (IS_AGGR_TYPE (TREE_TYPE (decl)) |
343 | || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) | |
344 | init = extract_aggr_init (decl, init); | |
345 | else | |
346 | init = extract_scalar_init (decl, init); | |
347 | ||
348 | if (init == NULL_TREE) | |
349 | return 0; | |
350 | ||
351 | DECL_INITIAL (decl) = init; | |
352 | return 1; | |
9e9ff709 | 353 | #endif |
28cbf42c | 354 | } |
5566b478 MS |
355 | |
356 | void | |
357 | do_case (start, end) | |
358 | tree start, end; | |
359 | { | |
360 | tree value1 = NULL_TREE, value2 = NULL_TREE, label; | |
361 | ||
ce122a86 MS |
362 | if (start != NULL_TREE && TREE_TYPE (start) != NULL_TREE |
363 | && POINTER_TYPE_P (TREE_TYPE (start))) | |
8251199e | 364 | error ("pointers are not permitted as case values"); |
fc378698 | 365 | |
5566b478 | 366 | if (end && pedantic) |
8251199e | 367 | pedwarn ("ANSI C++ forbids range expressions in switch statement"); |
5566b478 | 368 | |
5156628f | 369 | if (processing_template_decl) |
5566b478 MS |
370 | { |
371 | add_tree (build_min_nt (CASE_LABEL, start, end)); | |
372 | return; | |
373 | } | |
374 | ||
375 | if (start) | |
376 | value1 = check_cp_case_value (start); | |
377 | if (end) | |
378 | value2 = check_cp_case_value (end); | |
379 | ||
380 | label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); | |
381 | ||
382 | if (value1 != error_mark_node | |
383 | && value2 != error_mark_node) | |
384 | { | |
385 | tree duplicate; | |
386 | int success; | |
387 | ||
388 | if (end) | |
389 | success = pushcase_range (value1, value2, convert_and_check, | |
390 | label, &duplicate); | |
391 | else if (start) | |
392 | success = pushcase (value1, convert_and_check, label, &duplicate); | |
393 | else | |
394 | success = pushcase (NULL_TREE, 0, label, &duplicate); | |
395 | ||
396 | if (success == 1) | |
397 | { | |
398 | if (end) | |
8251199e | 399 | error ("case label not within a switch statement"); |
5566b478 | 400 | else if (start) |
8251199e | 401 | cp_error ("case label `%E' not within a switch statement", start); |
5566b478 | 402 | else |
8251199e | 403 | error ("default label not within a switch statement"); |
5566b478 MS |
404 | } |
405 | else if (success == 2) | |
406 | { | |
407 | if (end) | |
408 | { | |
8251199e JM |
409 | error ("duplicate (or overlapping) case value"); |
410 | cp_error_at ("this is the first entry overlapping that value", | |
5566b478 MS |
411 | duplicate); |
412 | } | |
413 | else if (start) | |
414 | { | |
8251199e JM |
415 | cp_error ("duplicate case value `%E'", start); |
416 | cp_error_at ("previously used here", duplicate); | |
5566b478 MS |
417 | } |
418 | else | |
419 | { | |
8251199e JM |
420 | error ("multiple default labels in one switch"); |
421 | cp_error_at ("this is the first default label", duplicate); | |
5566b478 MS |
422 | } |
423 | } | |
424 | else if (success == 3) | |
8251199e | 425 | warning ("case value out of range"); |
5566b478 | 426 | else if (success == 4) |
8251199e | 427 | warning ("empty range specified"); |
5566b478 MS |
428 | else if (success == 5) |
429 | { | |
430 | if (end) | |
8251199e | 431 | error ("case label within scope of cleanup or variable array"); |
eb448459 | 432 | else if (! start) |
8251199e | 433 | error ("`default' label within scope of cleanup or variable array"); |
5566b478 | 434 | else |
8251199e | 435 | cp_error ("case label `%E' within scope of cleanup or variable array", start); |
5566b478 MS |
436 | } |
437 | } | |
b370501f | 438 | define_case_label (); |
5566b478 | 439 | } |