OSDN Git Service

e066f7b0f0b044f0784306a54e0299109f87ec2c
[pf3gnuchains/gcc-fork.git] / gcc / cp / cp-gimplify.c
1 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
2
3    Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
4    Contributed by Jason Merrill <jason@redhat.com>
5
6 This file is part of GCC.
7
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.
12
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.
17
18 You should have received a copy of the GNU General Public License
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.  */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "tree.h"
28 #include "cp-tree.h"
29 #include "c-common.h"
30 #include "toplev.h"
31 #include "tree-gimple.h"
32 #include "hashtab.h"
33
34 /* Genericize a TRY_BLOCK.  */
35
36 static void
37 genericize_try_block (tree *stmt_p)
38 {
39   tree body = TRY_STMTS (*stmt_p);
40   tree cleanup = TRY_HANDLERS (*stmt_p);
41
42   gimplify_stmt (&body);
43
44   if (CLEANUP_P (*stmt_p))
45     /* A cleanup is an expression, so it doesn't need to be genericized.  */;
46   else
47     gimplify_stmt (&cleanup);
48
49   *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
50 }
51
52 /* Genericize a HANDLER by converting to a CATCH_EXPR.  */
53
54 static void
55 genericize_catch_block (tree *stmt_p)
56 {
57   tree type = HANDLER_TYPE (*stmt_p);
58   tree body = HANDLER_BODY (*stmt_p);
59
60   gimplify_stmt (&body);
61
62   /* FIXME should the caught type go in TREE_TYPE?  */
63   *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
64 }
65
66 /* Genericize an EH_SPEC_BLOCK by converting it to a
67    TRY_CATCH_EXPR/EH_FILTER_EXPR pair.  */
68
69 static void
70 genericize_eh_spec_block (tree *stmt_p)
71 {
72   tree body = EH_SPEC_STMTS (*stmt_p);
73   tree allowed = EH_SPEC_RAISES (*stmt_p);
74   tree failure = build_call (call_unexpected_node,
75                              tree_cons (NULL_TREE, build_exc_ptr (),
76                                         NULL_TREE));
77   gimplify_stmt (&body);
78
79   *stmt_p = gimple_build_eh_filter (body, allowed, failure);
80 }
81
82 /* Genericize an IF_STMT by turning it into a COND_EXPR.  */
83
84 static void
85 gimplify_if_stmt (tree *stmt_p)
86 {
87   tree stmt, then_, else_;
88
89   stmt = *stmt_p;
90   then_ = THEN_CLAUSE (stmt);
91   else_ = ELSE_CLAUSE (stmt);
92
93   if (!then_)
94     then_ = build_empty_stmt ();
95   if (!else_)
96     else_ = build_empty_stmt ();
97
98   stmt = build3 (COND_EXPR, void_type_node, IF_COND (stmt), then_, else_);
99   *stmt_p = stmt;
100 }
101
102 /* Gimplify initialization from an AGGR_INIT_EXPR.  */
103
104 static void
105 cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
106 {
107   tree from = TREE_OPERAND (*expr_p, 1);
108   tree to = TREE_OPERAND (*expr_p, 0);
109   tree sub;
110
111   /* If we are initializing something from a TARGET_EXPR, strip the
112      TARGET_EXPR and initialize it directly.  */
113   /* What about code that pulls out the temp and uses it elsewhere?  I
114      think that such code never uses the TARGET_EXPR as an initializer.  If
115      I'm wrong, we'll abort because the temp won't have any RTL.  In that
116      case, I guess we'll need to replace references somehow.  */
117   if (TREE_CODE (from) == TARGET_EXPR)
118     from = TARGET_EXPR_INITIAL (from);
119   if (TREE_CODE (from) == CLEANUP_POINT_EXPR)
120     from = TREE_OPERAND (from, 0);
121
122   /* Look through any COMPOUND_EXPRs.  */
123   sub = expr_last (from);
124
125   /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
126      replace the slot operand with our target.
127
128      Should we add a target parm to gimplify_expr instead?  No, as in this
129      case we want to replace the INIT_EXPR.  */
130   if (TREE_CODE (sub) == AGGR_INIT_EXPR)
131     {
132       gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
133       TREE_OPERAND (sub, 2) = to;
134       *expr_p = from;
135
136       /* The initialization is now a side-effect, so the container can
137          become void.  */
138       if (from != sub)
139         TREE_TYPE (from) = void_type_node;
140     }
141 }
142
143 /* Gimplify a MUST_NOT_THROW_EXPR.  */
144
145 static void
146 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
147 {
148   tree stmt = *expr_p;
149   tree temp = voidify_wrapper_expr (stmt, NULL);
150   tree body = TREE_OPERAND (stmt, 0);
151
152   gimplify_stmt (&body);
153
154   stmt = gimple_build_eh_filter (body, NULL_TREE,
155                                  build_call (terminate_node, NULL_TREE));
156
157   if (temp)
158     {
159       append_to_statement_list (stmt, pre_p);
160       *expr_p = temp;
161     }
162   else
163     *expr_p = stmt;
164 }
165
166 /* Do C++-specific gimplification.  Args are as for gimplify_expr.  */
167
168 int
169 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
170 {
171   int saved_stmts_are_full_exprs_p = 0;
172   enum tree_code code = TREE_CODE (*expr_p);
173   enum gimplify_status ret;
174
175   if (STATEMENT_CODE_P (code))
176     {
177       saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
178       current_stmt_tree ()->stmts_are_full_exprs_p
179         = STMT_IS_FULL_EXPR_P (*expr_p);
180     }
181
182   switch (code)
183     {
184     case PTRMEM_CST:
185       *expr_p = cplus_expand_constant (*expr_p);
186       ret = GS_OK;
187       break;
188
189     case AGGR_INIT_EXPR:
190       simplify_aggr_init_expr (expr_p);
191       ret = GS_OK;
192       break;
193
194     case THROW_EXPR:
195       /* FIXME communicate throw type to backend, probably by moving
196          THROW_EXPR into ../tree.def.  */
197       *expr_p = TREE_OPERAND (*expr_p, 0);
198       ret = GS_OK;
199       break;
200
201     case MUST_NOT_THROW_EXPR:
202       gimplify_must_not_throw_expr (expr_p, pre_p);
203       ret = GS_OK;
204       break;
205
206     case INIT_EXPR:
207     case MODIFY_EXPR:
208       cp_gimplify_init_expr (expr_p, pre_p, post_p);
209       ret = GS_OK;
210       break;
211
212     case EMPTY_CLASS_EXPR:
213       /* We create an INTEGER_CST with RECORD_TYPE and value zero.  */
214       *expr_p = build_int_cst (TREE_TYPE (*expr_p), 0, 0);
215       ret = GS_OK;
216       break;
217
218     case BASELINK:
219       *expr_p = BASELINK_FUNCTIONS (*expr_p);
220       ret = GS_OK;
221       break;
222
223     case TRY_BLOCK:
224       genericize_try_block (expr_p);
225       ret = GS_OK;
226       break;
227
228     case HANDLER:
229       genericize_catch_block (expr_p);
230       ret = GS_OK;
231       break;
232
233     case EH_SPEC_BLOCK:
234       genericize_eh_spec_block (expr_p);
235       ret = GS_OK;
236       break;
237
238     case USING_STMT:
239       /* Just ignore for now.  Eventually we will want to pass this on to
240          the debugger.  */
241       *expr_p = build_empty_stmt ();
242       ret = GS_ALL_DONE;
243       break;
244
245     case IF_STMT:
246       gimplify_if_stmt (expr_p);
247       ret = GS_OK;
248       break;
249
250     default:
251       ret = c_gimplify_expr (expr_p, pre_p, post_p);
252       break;
253     }
254
255   /* Restore saved state.  */
256   if (STATEMENT_CODE_P (code))
257     current_stmt_tree ()->stmts_are_full_exprs_p
258       = saved_stmts_are_full_exprs_p;
259
260   return ret;
261 }
262
263 static inline bool
264 is_invisiref_parm (tree t)
265 {
266   return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
267           && DECL_BY_REFERENCE (t));
268 }
269
270 /* Perform any pre-gimplification lowering of C++ front end trees to
271    GENERIC.  */
272
273 static tree
274 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
275 {
276   tree stmt = *stmt_p;
277   htab_t htab = (htab_t) data;
278   void **slot;
279
280   if (is_invisiref_parm (stmt))
281     {
282       *stmt_p = convert_from_reference (stmt);
283       *walk_subtrees = 0;
284       return NULL;
285     }
286
287   /* Other than invisiref parms, don't walk the same tree twice.  */
288   slot = htab_find_slot (htab, stmt, INSERT);
289   if (*slot)
290     {
291       *walk_subtrees = 0;
292       return NULL_TREE;
293     }
294
295   if (TREE_CODE (stmt) == ADDR_EXPR
296       && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
297     {
298       *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
299       *walk_subtrees = 0;
300     }
301   else if (TREE_CODE (stmt) == RETURN_EXPR
302            && TREE_OPERAND (stmt, 0)
303            && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
304     /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR.  */
305     *walk_subtrees = 0;
306   else if (DECL_P (stmt) || TYPE_P (stmt))
307     *walk_subtrees = 0;
308
309   /* Due to the way voidify_wrapper_expr is written, we don't get a chance
310      to lower this construct before scanning it, so we need to lower these
311      before doing anything else.  */
312   else if (TREE_CODE (stmt) == CLEANUP_STMT)
313     *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
314                                              : TRY_FINALLY_EXPR,
315                       void_type_node,
316                       CLEANUP_BODY (stmt),
317                       CLEANUP_EXPR (stmt));
318
319   *slot = *stmt_p;
320   return NULL;
321 }
322
323 void
324 cp_genericize (tree fndecl)
325 {
326   tree t;
327   htab_t htab;
328
329   /* Fix up the types of parms passed by invisible reference.  */
330   for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
331     {
332       if (DECL_BY_REFERENCE (t))
333         abort ();
334       if (TREE_ADDRESSABLE (TREE_TYPE (t)))
335         {
336           if (DECL_ARG_TYPE (t) == TREE_TYPE (t))
337             abort ();
338           TREE_TYPE (t) = DECL_ARG_TYPE (t);
339           DECL_BY_REFERENCE (t) = 1;
340           TREE_ADDRESSABLE (t) = 0;
341           relayout_decl (t);
342         }
343     }
344
345   /* Do the same for the return value.  */
346   if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
347     {
348       t = DECL_RESULT (fndecl);
349       TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
350       DECL_BY_REFERENCE (t) = 1;
351       TREE_ADDRESSABLE (t) = 0;
352       relayout_decl (t);
353     }
354
355   /* If we're a clone, the body is already GIMPLE.  */
356   if (DECL_CLONED_FUNCTION_P (fndecl))
357     return;
358
359   /* We do want to see every occurrence of the parms, so we can't just use
360      walk_tree's hash functionality.  */
361   htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
362   walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, htab, NULL);
363   htab_delete (htab);
364
365   /* Do everything else.  */
366   c_genericize (fndecl);
367 }