68th Cygnus<->FSF merge
[gcc.git] / gcc / cp / expr.c
1 /* Convert language-specific tree expression to rtl instructions,
2 for GNU compiler.
3 Copyright (C) 1988, 1992, 1993 Free Software Foundation, Inc.
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
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21
22 #include "config.h"
23 #include "rtl.h"
24 #include "tree.h"
25 #include "flags.h"
26 #include "expr.h"
27 #include "cp-tree.h"
28
29 #undef NULL
30 #define NULL 0
31
32 /* Hook used by expand_expr to expand language-specific tree codes. */
33
34 rtx
35 cplus_expand_expr (exp, target, tmode, modifier)
36 tree exp;
37 rtx target;
38 enum machine_mode tmode;
39 enum expand_modifier modifier;
40 {
41 tree type = TREE_TYPE (exp);
42 register enum machine_mode mode = TYPE_MODE (type);
43 register enum tree_code code = TREE_CODE (exp);
44 rtx original_target = target;
45 int ignore = target == const0_rtx;
46
47 if (ignore)
48 target = 0, original_target = 0;
49
50 /* No sense saving up arithmetic to be done
51 if it's all in the wrong mode to form part of an address.
52 And force_operand won't know whether to sign-extend or zero-extend. */
53
54 if (mode != Pmode && modifier == EXPAND_SUM)
55 modifier = EXPAND_NORMAL;
56
57 switch (code)
58 {
59 case NEW_EXPR:
60 {
61 /* Something needs to be initialized, but we didn't know
62 where that thing was when building the tree. For example,
63 it could be the return value of a function, or a parameter
64 to a function which lays down in the stack, or a temporary
65 variable which must be passed by reference.
66
67 Cleanups are handled in a language-specific way: they
68 might be run by the called function (true in GNU C++
69 for parameters with cleanups), or they might be
70 run by the caller, after the call (true in GNU C++
71 for other cleanup needs). */
72
73 tree func = TREE_OPERAND (exp, 0);
74 tree args = TREE_OPERAND (exp, 1);
75 tree type = TREE_TYPE (exp), slot;
76 tree fn_type = TREE_TYPE (TREE_TYPE (func));
77 tree return_type = TREE_TYPE (fn_type);
78 tree call_exp;
79 rtx call_target, return_target;
80 int pcc_struct_return = 0;
81
82 /* The expression `init' wants to initialize what
83 `target' represents. SLOT holds the slot for TARGET. */
84 slot = TREE_OPERAND (exp, 2);
85
86 if (target == 0)
87 {
88 /* Should always be called with a target in BLKmode case. */
89 my_friendly_assert (mode != BLKmode, 205);
90 my_friendly_assert (DECL_RTL (slot) != 0, 206);
91
92 target = gen_reg_rtx (mode);
93 }
94
95 /* The target the initializer will initialize (CALL_TARGET)
96 must now be directed to initialize the target we are
97 supposed to initialize (TARGET). The semantics for
98 choosing what CALL_TARGET is is language-specific,
99 as is building the call which will perform the
100 initialization. It is left here to show the choices that
101 exist for C++. */
102
103 if (TREE_CODE (func) == ADDR_EXPR
104 && TREE_CODE (TREE_OPERAND (func, 0)) == FUNCTION_DECL
105 && DECL_CONSTRUCTOR_P (TREE_OPERAND (func, 0)))
106 {
107 type = TYPE_POINTER_TO (type);
108 /* Don't clobber a value that might be part of a default
109 parameter value. */
110 if (TREE_PERMANENT (args))
111 args = tree_cons (0, build1 (ADDR_EXPR, type, slot),
112 TREE_CHAIN (args));
113 else
114 TREE_VALUE (args) = build1 (ADDR_EXPR, type, slot);
115 call_target = 0;
116 }
117 else if (TREE_CODE (return_type) == REFERENCE_TYPE)
118 {
119 type = return_type;
120 call_target = 0;
121 }
122 else
123 {
124 #ifdef PCC_STATIC_STRUCT_RETURN
125 pcc_struct_return = 1;
126 call_target = 0;
127 #else
128 call_target = target;
129 #endif
130 }
131 if (call_target)
132 {
133 preserve_temp_slots (call_target);
134
135 /* Make this a valid memory address now. The code below assumes
136 that it can compare rtx and make assumptions based on the
137 result. The assumptions are true only if the address was
138 valid to begin with. */
139 call_target = validize_mem (call_target);
140 }
141
142 preserve_temp_slots (DECL_RTL (slot));
143 call_exp = build (CALL_EXPR, type, func, args, 0);
144 TREE_SIDE_EFFECTS (call_exp) = 1;
145 return_target = expand_call (call_exp, call_target, ignore);
146 free_temp_slots ();
147 if (call_target == 0)
148 {
149 if (pcc_struct_return)
150 {
151 extern int flag_access_control;
152 int old_ac = flag_access_control;
153
154 tree init = build_decl (VAR_DECL, 0, type);
155 TREE_ADDRESSABLE (init) = 1;
156 DECL_RTL (init) = return_target;
157
158 flag_access_control = 0;
159 expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
160 flag_access_control = old_ac;
161
162 if (TYPE_NEEDS_DESTRUCTOR (type))
163 {
164 init = build_decl (VAR_DECL, 0,
165 build_reference_type (type));
166 DECL_RTL (init) = XEXP (return_target, 0);
167
168 init = maybe_build_cleanup (convert_from_reference (init));
169 if (init != NULL_TREE)
170 expand_expr (init, 0, 0, 0);
171 }
172 call_target = return_target = DECL_RTL (slot);
173 }
174 else
175 call_target = return_target;
176 }
177
178 if (call_target != return_target)
179 {
180 my_friendly_assert (TYPE_HAS_TRIVIAL_INIT_REF (type), 317);
181 if (GET_MODE (return_target) == BLKmode)
182 emit_block_move (call_target, return_target, expr_size (exp),
183 TYPE_ALIGN (type) / BITS_PER_UNIT);
184 else
185 emit_move_insn (call_target, return_target);
186 }
187
188 if (TREE_CODE (return_type) == REFERENCE_TYPE)
189 {
190 tree init;
191
192 if (GET_CODE (call_target) == REG
193 && REGNO (call_target) < FIRST_PSEUDO_REGISTER)
194 my_friendly_abort (39);
195
196 type = TREE_TYPE (exp);
197
198 init = build (RTL_EXPR, return_type, 0, call_target);
199 /* We got back a reference to the type we want. Now initialize
200 target with that. */
201 expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
202 }
203
204 if (DECL_RTL (slot) != target)
205 emit_move_insn (DECL_RTL (slot), target);
206 return DECL_RTL (slot);
207 }
208
209 case OFFSET_REF:
210 {
211 #if 1
212 return expand_expr (default_conversion (resolve_offset_ref (exp)),
213 target, tmode, EXPAND_NORMAL);
214 #else
215 /* This is old crusty code, and does not handle all that the
216 resolve_offset_ref function does. (mrs) */
217 tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0);
218 tree offset = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
219 return expand_expr (build (PLUS_EXPR, TREE_TYPE (exp), base, offset),
220 target, tmode, EXPAND_NORMAL);
221 #endif
222 }
223
224 case THUNK_DECL:
225 return DECL_RTL (exp);
226
227 case THROW_EXPR:
228 expand_throw (TREE_OPERAND (exp, 0));
229 return NULL;
230
231 default:
232 break;
233 }
234 my_friendly_abort (40);
235 /* NOTREACHED */
236 return NULL;
237 }
238
239 void
240 init_cplus_expand ()
241 {
242 lang_expand_expr = cplus_expand_expr;
243 }
244
245 /* If DECL had its rtl moved from where callers expect it
246 to be, fix it up. RESULT is the nominal rtl for the RESULT_DECL,
247 which may be a pseudo instead of a hard register. */
248
249 void
250 fixup_result_decl (decl, result)
251 tree decl;
252 rtx result;
253 {
254 if (REG_P (result))
255 {
256 if (REGNO (result) >= FIRST_PSEUDO_REGISTER)
257 {
258 rtx real_decl_result;
259
260 #ifdef FUNCTION_OUTGOING_VALUE
261 real_decl_result
262 = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl), current_function_decl);
263 #else
264 real_decl_result
265 = FUNCTION_VALUE (TREE_TYPE (decl), current_function_decl);
266 #endif
267 REG_FUNCTION_VALUE_P (real_decl_result) = 1;
268 result = real_decl_result;
269 }
270 store_expr (decl, result, 0);
271 emit_insn (gen_rtx (USE, VOIDmode, result));
272 }
273 }
274
275 /* Return nonzero iff DECL is memory-based. The DECL_RTL of
276 certain const variables might be a CONST_INT, or a REG
277 in some cases. We cannot use `memory_operand' as a test
278 here because on most RISC machines, a variable's address
279 is not, by itself, a legitimate address. */
280
281 int
282 decl_in_memory_p (decl)
283 tree decl;
284 {
285 return DECL_RTL (decl) != 0 && GET_CODE (DECL_RTL (decl)) == MEM;
286 }
287
288 /* Expand this initialization inline and see if it's simple enough that
289 it can be done at compile-time. */
290
291 static tree
292 extract_aggr_init (decl, init)
293 tree decl, init;
294 {
295 return 0;
296 }
297
298 static tree
299 extract_scalar_init (decl, init)
300 tree decl, init;
301 {
302 rtx value, insns, insn;
303 extern struct obstack temporary_obstack;
304 tree t = NULL_TREE;
305
306 push_obstacks (&temporary_obstack, &temporary_obstack);
307 start_sequence ();
308 value = expand_expr (init, NULL_RTX, VOIDmode, 0);
309 insns = get_insns ();
310 end_sequence ();
311 reg_scan (insns, max_reg_num (), 0);
312 jump_optimize (insns, 0, 0, 1);
313 pop_obstacks ();
314
315 for (insn = insns; insn; insn = NEXT_INSN (insn))
316 {
317 rtx r, to;
318
319 if (GET_CODE (insn) == NOTE)
320 continue;
321 else if (GET_CODE (insn) != INSN)
322 return 0;
323
324 r = PATTERN (insn);
325 if (GET_CODE (r) != SET)
326 return 0;
327
328 to = XEXP (r, 0);
329
330 if (! (to == value ||
331 (GET_CODE (to) == SUBREG && XEXP (to, 0) == value)))
332 return 0;
333
334 r = XEXP (r, 1);
335
336 switch (GET_CODE (r))
337 {
338 case CONST_INT:
339 t = build_int_2 (XEXP (r, 0), 0);
340 break;
341 default:
342 return 0;
343 }
344 }
345
346 return t;
347 }
348
349 int
350 extract_init (decl, init)
351 tree decl, init;
352 {
353 return 0;
354
355 if (IS_AGGR_TYPE (TREE_TYPE (decl))
356 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
357 init = extract_aggr_init (decl, init);
358 else
359 init = extract_scalar_init (decl, init);
360
361 if (init == NULL_TREE)
362 return 0;
363
364 DECL_INITIAL (decl) = init;
365 return 1;
366 }