OSDN Git Service

59th Cygnus<->FSF merge
[pf3gnuchains/gcc-fork.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_expr (call_exp, call_target, mode, 0);
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 (RTL_EXPR, type, 0, return_target);
155                 TREE_ADDRESSABLE (init) = 1;
156
157                 flag_access_control = 0;
158                 expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
159                 flag_access_control = old_ac;
160
161                 if (TYPE_NEEDS_DESTRUCTOR (type))
162                   {
163                     init = build (RTL_EXPR, build_reference_type (type), 0,
164                                   XEXP (return_target, 0));
165                     init = maybe_build_cleanup (convert_from_reference (init));
166                     if (init != NULL_TREE)
167                       expand_expr (init, 0, 0, 0);
168                   }
169                 call_target = return_target = DECL_RTL (slot);
170               }
171             else
172               call_target = return_target;
173           }
174
175         if (call_target != return_target)
176           {
177             my_friendly_assert (! TYPE_NEEDS_CONSTRUCTING (type), 317);
178             if (GET_MODE (return_target) == BLKmode)
179               emit_block_move (call_target, return_target, expr_size (exp),
180                                TYPE_ALIGN (type) / BITS_PER_UNIT);
181             else
182               emit_move_insn (call_target, return_target);
183           }
184
185         if (TREE_CODE (return_type) == REFERENCE_TYPE)
186           {
187             tree init;
188
189             if (GET_CODE (call_target) == REG
190                 && REGNO (call_target) < FIRST_PSEUDO_REGISTER)
191               my_friendly_abort (39);
192
193             type = TREE_TYPE (exp);
194
195             init = build (RTL_EXPR, return_type, 0, call_target);
196             /* We got back a reference to the type we want.  Now initialize
197                target with that.  */
198             expand_aggr_init (slot, init, 0, LOOKUP_ONLYCONVERTING);
199           }
200
201         if (DECL_RTL (slot) != target)
202           emit_move_insn (DECL_RTL (slot), target);
203         return DECL_RTL (slot);
204       }
205
206     case OFFSET_REF:
207       {
208 #if 1
209         return expand_expr (default_conversion (resolve_offset_ref (exp)),
210                             target, tmode, EXPAND_NORMAL);
211 #else
212         /* This is old crusty code, and does not handle all that the
213            resolve_offset_ref function does.  (mrs) */
214         tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0);
215         tree offset = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
216         return expand_expr (build (PLUS_EXPR, TREE_TYPE (exp), base, offset),
217                             target, tmode, EXPAND_NORMAL);
218 #endif
219       }
220
221     case THUNK_DECL:
222       return DECL_RTL (exp);
223
224     case THROW_EXPR:
225       expand_throw (TREE_OPERAND (exp, 0));
226       return NULL;
227
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         }
267       store_expr (decl, result, 0);
268       emit_insn (gen_rtx (USE, VOIDmode, result));
269     }
270 }
271
272 /* Return nonzero iff DECL is memory-based.  The DECL_RTL of
273    certain const variables might be a CONST_INT, or a REG
274    in some cases.  We cannot use `memory_operand' as a test
275    here because on most RISC machines, a variable's address
276    is not, by itself, a legitimate address.  */
277
278 int
279 decl_in_memory_p (decl)
280      tree decl;
281 {
282   return DECL_RTL (decl) != 0 && GET_CODE (DECL_RTL (decl)) == MEM;
283 }
284
285 /* Expand this initialization inline and see if it's simple enough that
286    it can be done at compile-time.  */
287
288 static tree
289 extract_aggr_init (decl, init)
290      tree decl, init;
291 {
292   return 0;
293 }
294
295 static tree
296 extract_scalar_init (decl, init)
297      tree decl, init;
298 {
299   rtx value, insns, insn;
300   extern struct obstack temporary_obstack;
301   tree t = NULL_TREE;
302
303   push_obstacks (&temporary_obstack, &temporary_obstack);
304   start_sequence ();
305   value = expand_expr (init, NULL_RTX, VOIDmode, 0);
306   insns = get_insns ();
307   end_sequence ();
308   reg_scan (insns, max_reg_num (), 0);
309   jump_optimize (insns, 0, 0, 1);
310   pop_obstacks ();
311
312   for (insn = insns; insn; insn = NEXT_INSN (insn))
313     {
314       rtx r, to;
315
316       if (GET_CODE (insn) == NOTE)
317         continue;
318       else if (GET_CODE (insn) != INSN)
319         return 0;
320
321       r = PATTERN (insn);
322       if (GET_CODE (r) != SET)
323         return 0;
324
325       to = XEXP (r, 0);
326
327       if (! (to == value ||
328              (GET_CODE (to) == SUBREG && XEXP (to, 0) == value)))
329         return 0;
330
331       r = XEXP (r, 1);
332
333       switch (GET_CODE (r))
334         {
335         case CONST_INT:
336           t = build_int_2 (XEXP (r, 0), 0);
337           break;
338         default:
339           return 0;
340         }
341     }
342
343   return t; 
344 }
345
346 int
347 extract_init (decl, init)
348      tree decl, init;
349 {
350   return 0;
351
352   if (IS_AGGR_TYPE (TREE_TYPE (decl))
353       || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
354     init = extract_aggr_init (decl, init);
355   else
356     init = extract_scalar_init (decl, init);
357
358   if (init == NULL_TREE)
359     return 0;
360
361   DECL_INITIAL (decl) = init;
362   return 1;
363 }