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
00027 #include "config.h"
00028 #include "system.h"
00029 #include "coretypes.h"
00030 #include "tm.h"
00031 #include "tree.h"
00032 #include "errors.h"
00033 #include "varray.h"
00034 #include "c-tree.h"
00035 #include "c-common.h"
00036 #include "tree-gimple.h"
00037 #include "hard-reg-set.h"
00038 #include "basic-block.h"
00039 #include "tree-flow.h"
00040 #include "tree-inline.h"
00041 #include "diagnostic.h"
00042 #include "langhooks.h"
00043 #include "langhooks-def.h"
00044 #include "flags.h"
00045 #include "rtl.h"
00046 #include "toplev.h"
00047 #include "tree-dump.h"
00048 #include "c-pretty-print.h"
00049 #include "cgraph.h"
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 enum bc_t { bc_break = 0, bc_continue = 1 };
00076
00077 static struct c_gimplify_ctx
00078 {
00079
00080 tree current_bc_label;
00081 tree bc_id[2];
00082 } *ctxp;
00083
00084 static void
00085 push_context (void)
00086 {
00087 gcc_assert (!ctxp);
00088 ctxp = (struct c_gimplify_ctx *) xcalloc (1, sizeof (struct c_gimplify_ctx));
00089 ctxp->bc_id[bc_continue] = get_identifier ("continue");
00090 ctxp->bc_id[bc_break] = get_identifier ("break");
00091 }
00092
00093 static void
00094 pop_context (void)
00095 {
00096 gcc_assert (ctxp && !ctxp->current_bc_label);
00097 free (ctxp);
00098 ctxp = NULL;
00099 }
00100
00101
00102
00103
00104
00105
00106 void
00107 c_genericize (tree fndecl)
00108 {
00109 FILE *dump_file;
00110 int local_dump_flags;
00111 struct cgraph_node *cgn;
00112
00113
00114 dump_file = dump_begin (TDI_original, &local_dump_flags);
00115 if (dump_file)
00116 {
00117 fprintf (dump_file, "\n;; Function %s",
00118 lang_hooks.decl_printable_name (fndecl, 2));
00119 fprintf (dump_file, " (%s)\n",
00120 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
00121 fprintf (dump_file, ";; enabled by -%s\n", dump_flag_name (TDI_original));
00122 fprintf (dump_file, "\n");
00123
00124 if (local_dump_flags & TDF_RAW)
00125 dump_node (DECL_SAVED_TREE (fndecl),
00126 TDF_SLIM | local_dump_flags, dump_file);
00127 else
00128 print_c_tree (dump_file, DECL_SAVED_TREE (fndecl));
00129 fprintf (dump_file, "\n");
00130
00131 dump_end (TDI_original, dump_file);
00132 }
00133
00134
00135 push_context ();
00136 gimplify_function_tree (fndecl);
00137 pop_context ();
00138
00139
00140 dump_function (TDI_generic, fndecl);
00141
00142
00143
00144
00145 cgn = cgraph_node (fndecl);
00146 for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
00147 c_genericize (cgn->decl);
00148 }
00149
00150 static void
00151 add_block_to_enclosing (tree block)
00152 {
00153 tree enclosing;
00154
00155 for (enclosing = gimple_current_bind_expr ();
00156 enclosing; enclosing = TREE_CHAIN (enclosing))
00157 if (BIND_EXPR_BLOCK (enclosing))
00158 break;
00159
00160 enclosing = BIND_EXPR_BLOCK (enclosing);
00161 BLOCK_SUBBLOCKS (enclosing) = chainon (BLOCK_SUBBLOCKS (enclosing), block);
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171 tree
00172 c_build_bind_expr (tree block, tree body)
00173 {
00174 tree decls, bind;
00175
00176 if (block == NULL_TREE)
00177 decls = NULL_TREE;
00178 else if (TREE_CODE (block) == BLOCK)
00179 decls = BLOCK_VARS (block);
00180 else
00181 {
00182 decls = block;
00183 if (DECL_ARTIFICIAL (decls))
00184 block = NULL_TREE;
00185 else
00186 {
00187 block = make_node (BLOCK);
00188 BLOCK_VARS (block) = decls;
00189 add_block_to_enclosing (block);
00190 }
00191 }
00192
00193 if (!body)
00194 body = build_empty_stmt ();
00195 if (decls || block)
00196 {
00197 bind = build3 (BIND_EXPR, void_type_node, decls, body, block);
00198 TREE_SIDE_EFFECTS (bind) = 1;
00199 }
00200 else
00201 bind = body;
00202
00203 return bind;
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 static enum gimplify_status
00217 gimplify_expr_stmt (tree *stmt_p)
00218 {
00219 tree stmt = EXPR_STMT_EXPR (*stmt_p);
00220
00221 if (stmt == error_mark_node)
00222 stmt = NULL;
00223
00224
00225
00226
00227
00228
00229
00230 if (stmt && (extra_warnings || warn_unused_value))
00231 {
00232 if (!TREE_SIDE_EFFECTS (stmt))
00233 {
00234 if (!IS_EMPTY_STMT (stmt)
00235 && !VOID_TYPE_P (TREE_TYPE (stmt))
00236 && !TREE_NO_WARNING (stmt))
00237 warning ("statement with no effect");
00238 }
00239 else if (warn_unused_value)
00240 warn_if_unused_value (stmt, input_location);
00241 }
00242
00243 if (stmt == NULL_TREE)
00244 stmt = alloc_stmt_list ();
00245
00246 *stmt_p = stmt;
00247
00248 return GS_OK;
00249 }
00250
00251
00252
00253
00254
00255
00256 static tree
00257 begin_bc_block (enum bc_t bc)
00258 {
00259 tree label = create_artificial_label ();
00260 DECL_NAME (label) = ctxp->bc_id[bc];
00261 TREE_CHAIN (label) = ctxp->current_bc_label;
00262 ctxp->current_bc_label = label;
00263 return label;
00264 }
00265
00266
00267
00268
00269
00270
00271
00272
00273 static tree
00274 finish_bc_block (tree label, tree body)
00275 {
00276 gcc_assert (label == ctxp->current_bc_label);
00277
00278 if (TREE_USED (label))
00279 {
00280 tree t, sl = NULL;
00281
00282
00283 DECL_NAME (label) = NULL_TREE;
00284 t = build1 (LABEL_EXPR, void_type_node, label);
00285
00286 append_to_statement_list (body, &sl);
00287 append_to_statement_list (t, &sl);
00288 body = sl;
00289 }
00290
00291 ctxp->current_bc_label = TREE_CHAIN (label);
00292 TREE_CHAIN (label) = NULL_TREE;
00293 return body;
00294 }
00295
00296
00297
00298
00299 static tree
00300 build_bc_goto (enum bc_t bc)
00301 {
00302 tree label;
00303 tree target_name = ctxp->bc_id[bc];
00304
00305
00306 for (label = ctxp->current_bc_label;
00307 label;
00308 label = TREE_CHAIN (label))
00309 if (DECL_NAME (label) == target_name)
00310 break;
00311
00312 if (label == NULL_TREE)
00313 {
00314 if (bc == bc_break)
00315 error ("break statement not within loop or switch");
00316 else
00317 error ("continue statement not within loop or switch");
00318
00319 return NULL_TREE;
00320 }
00321
00322
00323 TREE_USED (label) = 1;
00324 return build1 (GOTO_EXPR, void_type_node, label);
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334 static tree
00335 gimplify_c_loop (tree cond, tree body, tree incr, bool cond_is_first)
00336 {
00337 tree top, entry, exit, cont_block, break_block, stmt_list, t;
00338 location_t stmt_locus;
00339
00340 stmt_locus = input_location;
00341 stmt_list = NULL_TREE;
00342 entry = NULL_TREE;
00343
00344 break_block = begin_bc_block (bc_break);
00345 cont_block = begin_bc_block (bc_continue);
00346
00347
00348 if (cond && integer_zerop (cond))
00349 {
00350 top = NULL_TREE;
00351 exit = NULL_TREE;
00352 if (cond_is_first)
00353 {
00354 t = build_bc_goto (bc_break);
00355 append_to_statement_list (t, &stmt_list);
00356 }
00357 }
00358 else
00359 {
00360
00361
00362
00363
00364 top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
00365
00366
00367
00368
00369 exit = build_and_jump (&LABEL_EXPR_LABEL (top));
00370 if (cond && !integer_nonzerop (cond))
00371 {
00372 t = build_bc_goto (bc_break);
00373 exit = build3 (COND_EXPR, void_type_node, cond, exit, t);
00374 exit = fold (exit);
00375 gimplify_stmt (&exit);
00376
00377 if (cond_is_first)
00378 {
00379 if (incr)
00380 {
00381 entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
00382 t = build_and_jump (&LABEL_EXPR_LABEL (entry));
00383 }
00384 else
00385 t = build_bc_goto (bc_continue);
00386 append_to_statement_list (t, &stmt_list);
00387 }
00388 }
00389 }
00390
00391 gimplify_stmt (&body);
00392 gimplify_stmt (&incr);
00393
00394 body = finish_bc_block (cont_block, body);
00395
00396 append_to_statement_list (top, &stmt_list);
00397 append_to_statement_list (body, &stmt_list);
00398 append_to_statement_list (incr, &stmt_list);
00399 append_to_statement_list (entry, &stmt_list);
00400 append_to_statement_list (exit, &stmt_list);
00401
00402 annotate_all_with_locus (&stmt_list, stmt_locus);
00403
00404 return finish_bc_block (break_block, stmt_list);
00405 }
00406
00407
00408
00409
00410 static enum gimplify_status
00411 gimplify_for_stmt (tree *stmt_p, tree *pre_p)
00412 {
00413 tree stmt = *stmt_p;
00414
00415 if (FOR_INIT_STMT (stmt))
00416 gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
00417
00418 *stmt_p = gimplify_c_loop (FOR_COND (stmt), FOR_BODY (stmt),
00419 FOR_EXPR (stmt), 1);
00420
00421 return GS_ALL_DONE;
00422 }
00423
00424
00425
00426 static enum gimplify_status
00427 gimplify_while_stmt (tree *stmt_p)
00428 {
00429 tree stmt = *stmt_p;
00430 *stmt_p = gimplify_c_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
00431 NULL_TREE, 1);
00432 return GS_ALL_DONE;
00433 }
00434
00435
00436
00437 static enum gimplify_status
00438 gimplify_do_stmt (tree *stmt_p)
00439 {
00440 tree stmt = *stmt_p;
00441 *stmt_p = gimplify_c_loop (DO_COND (stmt), DO_BODY (stmt),
00442 NULL_TREE, 0);
00443 return GS_ALL_DONE;
00444 }
00445
00446
00447
00448 static enum gimplify_status
00449 gimplify_switch_stmt (tree *stmt_p)
00450 {
00451 tree stmt = *stmt_p;
00452 tree break_block, body;
00453 location_t stmt_locus = input_location;
00454
00455 break_block = begin_bc_block (bc_break);
00456
00457 body = SWITCH_STMT_BODY (stmt);
00458 if (!body)
00459 body = build_empty_stmt ();
00460
00461 *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
00462 SWITCH_STMT_COND (stmt), body, NULL_TREE);
00463 SET_EXPR_LOCATION (*stmt_p, stmt_locus);
00464 gimplify_stmt (stmt_p);
00465
00466 *stmt_p = finish_bc_block (break_block, *stmt_p);
00467 return GS_ALL_DONE;
00468 }
00469
00470
00471
00472
00473
00474
00475
00476 static enum gimplify_status
00477 gimplify_compound_literal_expr (tree *expr_p, tree *pre_p)
00478 {
00479 tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (*expr_p);
00480 tree decl = DECL_EXPR_DECL (decl_s);
00481
00482
00483
00484
00485 if (DECL_NAME (decl) == NULL_TREE)
00486 gimple_add_tmp_var (decl);
00487
00488 gimplify_and_add (decl_s, pre_p);
00489 *expr_p = decl;
00490 return GS_OK;
00491 }
00492
00493
00494
00495 int
00496 c_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED)
00497 {
00498 enum tree_code code = TREE_CODE (*expr_p);
00499
00500 switch (code)
00501 {
00502 case DECL_EXPR:
00503
00504
00505
00506 if (TREE_CODE (DECL_EXPR_DECL (*expr_p)) == VAR_DECL
00507 && !DECL_EXTERNAL (DECL_EXPR_DECL (*expr_p))
00508 && !TREE_STATIC (DECL_EXPR_DECL (*expr_p))
00509 && (DECL_INITIAL (DECL_EXPR_DECL (*expr_p))
00510 == DECL_EXPR_DECL (*expr_p))
00511 && !warn_init_self)
00512 TREE_NO_WARNING (DECL_EXPR_DECL (*expr_p)) = 1;
00513 return GS_UNHANDLED;
00514
00515 case COMPOUND_LITERAL_EXPR:
00516 return gimplify_compound_literal_expr (expr_p, pre_p);
00517
00518 case FOR_STMT:
00519 return gimplify_for_stmt (expr_p, pre_p);
00520
00521 case WHILE_STMT:
00522 return gimplify_while_stmt (expr_p);
00523
00524 case DO_STMT:
00525 return gimplify_do_stmt (expr_p);
00526
00527 case SWITCH_STMT:
00528 return gimplify_switch_stmt (expr_p);
00529
00530 case EXPR_STMT:
00531 return gimplify_expr_stmt (expr_p);
00532
00533 case CONTINUE_STMT:
00534 *expr_p = build_bc_goto (bc_continue);
00535 return GS_ALL_DONE;
00536
00537 case BREAK_STMT:
00538 *expr_p = build_bc_goto (bc_break);
00539 return GS_ALL_DONE;
00540
00541 default:
00542 return GS_UNHANDLED;
00543 }
00544 }