1 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
3 Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
4 Contributed by Jason Merrill <jason@redhat.com>
6 This file is part of GCC.
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
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
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
25 #include "coretypes.h"
31 #include "tree-gimple.h"
34 /* Genericize a TRY_BLOCK. */
37 genericize_try_block (tree
*stmt_p
)
39 tree body
= TRY_STMTS (*stmt_p
);
40 tree cleanup
= TRY_HANDLERS (*stmt_p
);
42 gimplify_stmt (&body
);
44 if (CLEANUP_P (*stmt_p
))
45 /* A cleanup is an expression, so it doesn't need to be genericized. */;
47 gimplify_stmt (&cleanup
);
49 *stmt_p
= build2 (TRY_CATCH_EXPR
, void_type_node
, body
, cleanup
);
52 /* Genericize a HANDLER by converting to a CATCH_EXPR. */
55 genericize_catch_block (tree
*stmt_p
)
57 tree type
= HANDLER_TYPE (*stmt_p
);
58 tree body
= HANDLER_BODY (*stmt_p
);
60 gimplify_stmt (&body
);
62 /* FIXME should the caught type go in TREE_TYPE? */
63 *stmt_p
= build2 (CATCH_EXPR
, void_type_node
, type
, body
);
66 /* Genericize an EH_SPEC_BLOCK by converting it to a
67 TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
70 genericize_eh_spec_block (tree
*stmt_p
)
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 (),
77 gimplify_stmt (&body
);
79 *stmt_p
= gimple_build_eh_filter (body
, allowed
, failure
);
82 /* Genericize an IF_STMT by turning it into a COND_EXPR. */
85 gimplify_if_stmt (tree
*stmt_p
)
87 tree stmt
, then_
, else_
;
90 then_
= THEN_CLAUSE (stmt
);
91 else_
= ELSE_CLAUSE (stmt
);
94 then_
= build_empty_stmt ();
96 else_
= build_empty_stmt ();
98 stmt
= build3 (COND_EXPR
, void_type_node
, IF_COND (stmt
), then_
, else_
);
102 /* Gimplify initialization from an AGGR_INIT_EXPR. */
105 cp_gimplify_init_expr (tree
*expr_p
, tree
*pre_p
, tree
*post_p
)
107 tree from
= TREE_OPERAND (*expr_p
, 1);
108 tree to
= TREE_OPERAND (*expr_p
, 0);
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);
122 /* Look through any COMPOUND_EXPRs. */
123 sub
= expr_last (from
);
125 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
126 replace the slot operand with our target.
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
)
132 gimplify_expr (&to
, pre_p
, post_p
, is_gimple_lvalue
, fb_lvalue
);
133 TREE_OPERAND (sub
, 2) = to
;
136 /* The initialization is now a side-effect, so the container can
139 TREE_TYPE (from
) = void_type_node
;
143 /* Gimplify a MUST_NOT_THROW_EXPR. */
146 gimplify_must_not_throw_expr (tree
*expr_p
, tree
*pre_p
)
149 tree temp
= voidify_wrapper_expr (stmt
, NULL
);
150 tree body
= TREE_OPERAND (stmt
, 0);
152 gimplify_stmt (&body
);
154 stmt
= gimple_build_eh_filter (body
, NULL_TREE
,
155 build_call (terminate_node
, NULL_TREE
));
159 append_to_statement_list (stmt
, pre_p
);
166 /* Do C++-specific gimplification. Args are as for gimplify_expr. */
169 cp_gimplify_expr (tree
*expr_p
, tree
*pre_p
, tree
*post_p
)
171 int saved_stmts_are_full_exprs_p
= 0;
172 enum tree_code code
= TREE_CODE (*expr_p
);
173 enum gimplify_status ret
;
175 if (STATEMENT_CODE_P (code
))
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
);
185 *expr_p
= cplus_expand_constant (*expr_p
);
190 simplify_aggr_init_expr (expr_p
);
195 /* FIXME communicate throw type to backend, probably by moving
196 THROW_EXPR into ../tree.def. */
197 *expr_p
= TREE_OPERAND (*expr_p
, 0);
201 case MUST_NOT_THROW_EXPR
:
202 gimplify_must_not_throw_expr (expr_p
, pre_p
);
208 cp_gimplify_init_expr (expr_p
, pre_p
, post_p
);
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);
219 *expr_p
= BASELINK_FUNCTIONS (*expr_p
);
224 genericize_try_block (expr_p
);
229 genericize_catch_block (expr_p
);
234 genericize_eh_spec_block (expr_p
);
239 /* Just ignore for now. Eventually we will want to pass this on to
241 *expr_p
= build_empty_stmt ();
246 gimplify_if_stmt (expr_p
);
251 ret
= c_gimplify_expr (expr_p
, pre_p
, post_p
);
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
;
264 is_invisiref_parm (tree t
)
266 return ((TREE_CODE (t
) == PARM_DECL
|| TREE_CODE (t
) == RESULT_DECL
)
267 && DECL_BY_REFERENCE (t
));
270 /* Perform any pre-gimplification lowering of C++ front end trees to
274 cp_genericize_r (tree
*stmt_p
, int *walk_subtrees
, void *data
)
277 htab_t htab
= (htab_t
) data
;
280 if (is_invisiref_parm (stmt
))
282 *stmt_p
= convert_from_reference (stmt
);
287 /* Other than invisiref parms, don't walk the same tree twice. */
288 slot
= htab_find_slot (htab
, stmt
, INSERT
);
295 if (TREE_CODE (stmt
) == ADDR_EXPR
296 && is_invisiref_parm (TREE_OPERAND (stmt
, 0)))
298 *stmt_p
= convert (TREE_TYPE (stmt
), TREE_OPERAND (stmt
, 0));
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. */
306 else if (IS_TYPE_OR_DECL_P (stmt
))
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
317 CLEANUP_EXPR (stmt
));
324 cp_genericize (tree fndecl
)
329 /* Fix up the types of parms passed by invisible reference. */
330 for (t
= DECL_ARGUMENTS (fndecl
); t
; t
= TREE_CHAIN (t
))
332 gcc_assert (!DECL_BY_REFERENCE (t
));
333 if (TREE_ADDRESSABLE (TREE_TYPE (t
)))
335 gcc_assert (DECL_ARG_TYPE (t
) != TREE_TYPE (t
));
336 TREE_TYPE (t
) = DECL_ARG_TYPE (t
);
337 DECL_BY_REFERENCE (t
) = 1;
338 TREE_ADDRESSABLE (t
) = 0;
343 /* Do the same for the return value. */
344 if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl
))))
346 t
= DECL_RESULT (fndecl
);
347 TREE_TYPE (t
) = build_reference_type (TREE_TYPE (t
));
348 DECL_BY_REFERENCE (t
) = 1;
349 TREE_ADDRESSABLE (t
) = 0;
353 /* If we're a clone, the body is already GIMPLE. */
354 if (DECL_CLONED_FUNCTION_P (fndecl
))
357 /* We do want to see every occurrence of the parms, so we can't just use
358 walk_tree's hash functionality. */
359 htab
= htab_create (37, htab_hash_pointer
, htab_eq_pointer
, NULL
);
360 walk_tree (&DECL_SAVED_TREE (fndecl
), cp_genericize_r
, htab
, NULL
);
363 /* Do everything else. */
364 c_genericize (fndecl
);