00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "config.h"
00027 #include "system.h"
00028 #include "coretypes.h"
00029 #include "tm.h"
00030 #include "tree.h"
00031 #include "cp-tree.h"
00032 #include "c-common.h"
00033 #include "toplev.h"
00034 #include "tree-gimple.h"
00035 #include "hashtab.h"
00036 #include "pointer-set.h"
00037
00038 #ifdef KEY
00039 #include "gspin-gcc-interface.h"
00040 #endif
00041
00042
00043
00044 static void
00045 genericize_try_block (tree *stmt_p)
00046 {
00047 tree body = TRY_STMTS (*stmt_p);
00048 tree cleanup = TRY_HANDLERS (*stmt_p);
00049
00050 gimplify_stmt (&body);
00051
00052 if (CLEANUP_P (*stmt_p))
00053 ;
00054 else
00055 gimplify_stmt (&cleanup);
00056
00057 *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
00058 }
00059
00060
00061
00062 static void
00063 genericize_catch_block (tree *stmt_p)
00064 {
00065 tree type = HANDLER_TYPE (*stmt_p);
00066 tree body = HANDLER_BODY (*stmt_p);
00067
00068 gimplify_stmt (&body);
00069
00070
00071 *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
00072 }
00073
00074
00075
00076
00077 static void
00078 genericize_eh_spec_block (tree *stmt_p)
00079 {
00080 tree body = EH_SPEC_STMTS (*stmt_p);
00081 tree allowed = EH_SPEC_RAISES (*stmt_p);
00082 tree failure = build_call (call_unexpected_node,
00083 tree_cons (NULL_TREE, build_exc_ptr (),
00084 NULL_TREE));
00085 gimplify_stmt (&body);
00086
00087 *stmt_p = gimple_build_eh_filter (body, allowed, failure);
00088 }
00089
00090
00091
00092 static void
00093 gimplify_if_stmt (tree *stmt_p)
00094 {
00095 tree stmt, cond, then_, else_;
00096
00097 stmt = *stmt_p;
00098 cond = IF_COND (stmt);
00099 then_ = THEN_CLAUSE (stmt);
00100 else_ = ELSE_CLAUSE (stmt);
00101
00102 if (!then_)
00103 then_ = build_empty_stmt ();
00104 if (!else_)
00105 else_ = build_empty_stmt ();
00106
00107 if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
00108 stmt = then_;
00109 else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
00110 stmt = else_;
00111 else
00112 stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
00113 *stmt_p = stmt;
00114 }
00115
00116
00117
00118 static void
00119 cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
00120 {
00121 tree from = TREE_OPERAND (*expr_p, 1);
00122 tree to = TREE_OPERAND (*expr_p, 0);
00123 tree sub;
00124
00125
00126
00127
00128
00129
00130
00131 if (TREE_CODE (from) == TARGET_EXPR)
00132 from = TARGET_EXPR_INITIAL (from);
00133 if (TREE_CODE (from) == CLEANUP_POINT_EXPR)
00134 from = TREE_OPERAND (from, 0);
00135
00136
00137 sub = expr_last (from);
00138
00139
00140
00141
00142
00143
00144 if (TREE_CODE (sub) == AGGR_INIT_EXPR)
00145 {
00146 gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
00147 TREE_OPERAND (sub, 2) = to;
00148 *expr_p = from;
00149
00150
00151
00152 if (from != sub)
00153 TREE_TYPE (from) = void_type_node;
00154 }
00155 }
00156
00157
00158
00159 static void
00160 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
00161 {
00162 tree stmt = *expr_p;
00163 tree temp = voidify_wrapper_expr (stmt, NULL);
00164 tree body = TREE_OPERAND (stmt, 0);
00165
00166 gimplify_stmt (&body);
00167
00168 stmt = gimple_build_eh_filter (body, NULL_TREE,
00169 build_call (terminate_node, NULL_TREE));
00170
00171 if (temp)
00172 {
00173 append_to_statement_list (stmt, pre_p);
00174 *expr_p = temp;
00175 }
00176 else
00177 *expr_p = stmt;
00178 }
00179
00180
00181
00182 int
00183 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
00184 {
00185 int saved_stmts_are_full_exprs_p = 0;
00186 enum tree_code code = TREE_CODE (*expr_p);
00187 enum gimplify_status ret;
00188
00189 if (STATEMENT_CODE_P (code))
00190 {
00191 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
00192 current_stmt_tree ()->stmts_are_full_exprs_p
00193 = STMT_IS_FULL_EXPR_P (*expr_p);
00194 }
00195
00196 switch (code)
00197 {
00198 case PTRMEM_CST:
00199 *expr_p = cplus_expand_constant (*expr_p);
00200 ret = GS_OK;
00201 break;
00202
00203 case AGGR_INIT_EXPR:
00204 simplify_aggr_init_expr (expr_p);
00205 ret = GS_OK;
00206 break;
00207
00208 case THROW_EXPR:
00209
00210
00211 *expr_p = TREE_OPERAND (*expr_p, 0);
00212 ret = GS_OK;
00213 break;
00214
00215 case MUST_NOT_THROW_EXPR:
00216 gimplify_must_not_throw_expr (expr_p, pre_p);
00217 ret = GS_OK;
00218 break;
00219
00220 case INIT_EXPR:
00221 case MODIFY_EXPR:
00222 cp_gimplify_init_expr (expr_p, pre_p, post_p);
00223 ret = GS_OK;
00224 break;
00225
00226 case EMPTY_CLASS_EXPR:
00227
00228 *expr_p = build_int_cst (TREE_TYPE (*expr_p), 0);
00229 ret = GS_OK;
00230 break;
00231
00232 case BASELINK:
00233 *expr_p = BASELINK_FUNCTIONS (*expr_p);
00234 ret = GS_OK;
00235 break;
00236
00237 case TRY_BLOCK:
00238 genericize_try_block (expr_p);
00239 ret = GS_OK;
00240 break;
00241
00242 case HANDLER:
00243 genericize_catch_block (expr_p);
00244 ret = GS_OK;
00245 break;
00246
00247 case EH_SPEC_BLOCK:
00248 genericize_eh_spec_block (expr_p);
00249 ret = GS_OK;
00250 break;
00251
00252 case USING_STMT:
00253
00254
00255 *expr_p = build_empty_stmt ();
00256 ret = GS_ALL_DONE;
00257 break;
00258
00259 case IF_STMT:
00260 gimplify_if_stmt (expr_p);
00261 ret = GS_OK;
00262 break;
00263
00264 default:
00265 ret = c_gimplify_expr (expr_p, pre_p, post_p);
00266 break;
00267 }
00268
00269
00270 if (STATEMENT_CODE_P (code))
00271 current_stmt_tree ()->stmts_are_full_exprs_p
00272 = saved_stmts_are_full_exprs_p;
00273
00274 return ret;
00275 }
00276
00277 static inline bool
00278 is_invisiref_parm (tree t)
00279 {
00280 return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
00281 && DECL_BY_REFERENCE (t));
00282 }
00283
00284
00285
00286
00287 static tree
00288 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
00289 {
00290 tree stmt = *stmt_p;
00291 struct pointer_set_t *p_set = (struct pointer_set_t*) data;
00292
00293 if (is_invisiref_parm (stmt))
00294 {
00295 *stmt_p = convert_from_reference (stmt);
00296 *walk_subtrees = 0;
00297 return NULL;
00298 }
00299
00300
00301 if (pointer_set_contains (p_set, stmt))
00302 {
00303 *walk_subtrees = 0;
00304 return NULL_TREE;
00305 }
00306
00307 if (TREE_CODE (stmt) == ADDR_EXPR
00308 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
00309 {
00310 *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
00311 *walk_subtrees = 0;
00312 }
00313 else if (TREE_CODE (stmt) == RETURN_EXPR
00314 && TREE_OPERAND (stmt, 0)
00315 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
00316
00317 *walk_subtrees = 0;
00318 else if (IS_TYPE_OR_DECL_P (stmt))
00319 *walk_subtrees = 0;
00320
00321
00322
00323
00324 else if (TREE_CODE (stmt) == CLEANUP_STMT)
00325 *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
00326 : TRY_FINALLY_EXPR,
00327 void_type_node,
00328 CLEANUP_BODY (stmt),
00329 CLEANUP_EXPR (stmt));
00330
00331 pointer_set_insert (p_set, *stmt_p);
00332
00333 return NULL;
00334 }
00335
00336 void
00337 cp_genericize (tree fndecl)
00338 {
00339 tree t;
00340 struct pointer_set_t *p_set;
00341
00342
00343 for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
00344 if (TREE_ADDRESSABLE (TREE_TYPE (t)))
00345 {
00346
00347
00348
00349
00350 gcc_assert (!DECL_BY_REFERENCE (t));
00351 gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
00352 TREE_TYPE (t) = DECL_ARG_TYPE (t);
00353 DECL_BY_REFERENCE (t) = 1;
00354 TREE_ADDRESSABLE (t) = 0;
00355 relayout_decl (t);
00356 }
00357
00358
00359 if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
00360 {
00361 t = DECL_RESULT (fndecl);
00362 TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
00363 DECL_BY_REFERENCE (t) = 1;
00364 TREE_ADDRESSABLE (t) = 0;
00365 relayout_decl (t);
00366 }
00367
00368 #ifdef KEY
00369
00370
00371
00372
00373 if (!flag_spin_file)
00374 #endif
00375
00376 if (DECL_CLONED_FUNCTION_P (fndecl))
00377 return;
00378
00379
00380
00381 p_set = pointer_set_create ();
00382 walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
00383 pointer_set_destroy (p_set);
00384
00385
00386 c_genericize (fndecl);
00387 }