00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "tree.h"
00027 #include "rtl.h"
00028 #include "errors.h"
00029 #include "varray.h"
00030 #include "tree-gimple.h"
00031 #include "tree-inline.h"
00032 #include "diagnostic.h"
00033 #include "langhooks.h"
00034 #include "langhooks-def.h"
00035 #include "tree-flow.h"
00036 #include "timevar.h"
00037 #include "except.h"
00038 #include "hashtab.h"
00039 #include "flags.h"
00040 #include "function.h"
00041 #include "expr.h"
00042 #include "toplev.h"
00043 #include "tree-pass.h"
00044
00045 struct lower_data
00046 {
00047
00048 tree block;
00049
00050
00051
00052 tree return_statements;
00053 };
00054
00055 static void lower_stmt (tree_stmt_iterator *, struct lower_data *);
00056 static void lower_bind_expr (tree_stmt_iterator *, struct lower_data *);
00057 static void lower_cond_expr (tree_stmt_iterator *, struct lower_data *);
00058 static void lower_return_expr (tree_stmt_iterator *, struct lower_data *);
00059 static bool expand_var_p (tree);
00060
00061
00062
00063 static void
00064 lower_function_body (void)
00065 {
00066 struct lower_data data;
00067 tree *body_p = &DECL_SAVED_TREE (current_function_decl);
00068 tree bind = *body_p;
00069 tree_stmt_iterator i;
00070 tree t, x;
00071
00072 gcc_assert (TREE_CODE (bind) == BIND_EXPR);
00073
00074 data.block = DECL_INITIAL (current_function_decl);
00075 BLOCK_SUBBLOCKS (data.block) = NULL_TREE;
00076 BLOCK_CHAIN (data.block) = NULL_TREE;
00077 TREE_ASM_WRITTEN (data.block) = 1;
00078
00079 data.return_statements = NULL_TREE;
00080
00081 *body_p = alloc_stmt_list ();
00082 i = tsi_start (*body_p);
00083 tsi_link_after (&i, bind, TSI_NEW_STMT);
00084 lower_bind_expr (&i, &data);
00085
00086 i = tsi_last (*body_p);
00087
00088
00089
00090
00091 if (block_may_fallthru (*body_p)
00092 && (data.return_statements == NULL
00093 || TREE_OPERAND (TREE_VALUE (data.return_statements), 0) != NULL))
00094 {
00095 x = build (RETURN_EXPR, void_type_node, NULL);
00096 SET_EXPR_LOCATION (x, cfun->function_end_locus);
00097 tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
00098 }
00099
00100
00101
00102 for (t = data.return_statements ; t ; t = TREE_CHAIN (t))
00103 {
00104 x = build (LABEL_EXPR, void_type_node, TREE_PURPOSE (t));
00105 tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
00106
00107
00108
00109
00110 x = TREE_VALUE (t);
00111 #ifdef USE_MAPPED_LOCATION
00112 SET_EXPR_LOCATION (x, UNKNOWN_LOCATION);
00113 #else
00114 SET_EXPR_LOCUS (x, NULL);
00115 #endif
00116 tsi_link_after (&i, x, TSI_CONTINUE_LINKING);
00117 }
00118
00119 gcc_assert (data.block == DECL_INITIAL (current_function_decl));
00120 BLOCK_SUBBLOCKS (data.block)
00121 = blocks_nreverse (BLOCK_SUBBLOCKS (data.block));
00122
00123 clear_block_marks (data.block);
00124 }
00125
00126 struct tree_opt_pass pass_lower_cf =
00127 {
00128 "lower",
00129 NULL,
00130 lower_function_body,
00131 NULL,
00132 NULL,
00133 0,
00134 0,
00135 PROP_gimple_any,
00136 PROP_gimple_lcf,
00137 PROP_gimple_any,
00138 0,
00139 TODO_dump_func,
00140 0
00141 };
00142
00143
00144
00145
00146
00147
00148 void
00149 lower_stmt_body (tree expr, struct lower_data *data)
00150 {
00151 tree_stmt_iterator tsi;
00152
00153 for (tsi = tsi_start (expr); !tsi_end_p (tsi); )
00154 lower_stmt (&tsi, data);
00155 }
00156
00157
00158
00159 static void
00160 lower_stmt (tree_stmt_iterator *tsi, struct lower_data *data)
00161 {
00162 tree stmt = tsi_stmt (*tsi);
00163
00164 if (EXPR_HAS_LOCATION (stmt) && data)
00165 TREE_BLOCK (stmt) = data->block;
00166
00167 switch (TREE_CODE (stmt))
00168 {
00169 case BIND_EXPR:
00170 lower_bind_expr (tsi, data);
00171 return;
00172 case COND_EXPR:
00173 lower_cond_expr (tsi, data);
00174 return;
00175 case RETURN_EXPR:
00176 lower_return_expr (tsi, data);
00177 return;
00178
00179 case TRY_FINALLY_EXPR:
00180 case TRY_CATCH_EXPR:
00181 lower_stmt_body (TREE_OPERAND (stmt, 0), data);
00182 lower_stmt_body (TREE_OPERAND (stmt, 1), data);
00183 break;
00184 case CATCH_EXPR:
00185 lower_stmt_body (CATCH_BODY (stmt), data);
00186 break;
00187 case EH_FILTER_EXPR:
00188 lower_stmt_body (EH_FILTER_FAILURE (stmt), data);
00189 break;
00190
00191 case NOP_EXPR:
00192 case ASM_EXPR:
00193 case MODIFY_EXPR:
00194 case CALL_EXPR:
00195 case GOTO_EXPR:
00196 case LABEL_EXPR:
00197 case SWITCH_EXPR:
00198 break;
00199
00200 default:
00201 #ifdef ENABLE_CHECKING
00202 print_node_brief (stderr, "", stmt, 0);
00203 internal_error ("unexpected node");
00204 #endif
00205 case COMPOUND_EXPR:
00206 gcc_unreachable ();
00207 }
00208
00209 tsi_next (tsi);
00210 }
00211
00212
00213
00214 static void
00215 lower_bind_expr (tree_stmt_iterator *tsi, struct lower_data *data)
00216 {
00217 tree old_block = data->block;
00218 tree stmt = tsi_stmt (*tsi);
00219 tree new_block = BIND_EXPR_BLOCK (stmt);
00220
00221 if (new_block)
00222 {
00223 if (new_block == old_block)
00224 {
00225
00226
00227
00228 gcc_assert (new_block == DECL_INITIAL (current_function_decl));
00229 new_block = NULL;
00230 }
00231 else
00232 {
00233
00234 gcc_assert (!TREE_ASM_WRITTEN (new_block));
00235 TREE_ASM_WRITTEN (new_block) = 1;
00236
00237
00238
00239
00240 BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (old_block);
00241 BLOCK_SUBBLOCKS (old_block) = new_block;
00242 BLOCK_SUBBLOCKS (new_block) = NULL_TREE;
00243 BLOCK_SUPERCONTEXT (new_block) = old_block;
00244
00245 data->block = new_block;
00246 }
00247 }
00248
00249 record_vars (BIND_EXPR_VARS (stmt));
00250 lower_stmt_body (BIND_EXPR_BODY (stmt), data);
00251
00252 if (new_block)
00253 {
00254 gcc_assert (data->block == new_block);
00255
00256 BLOCK_SUBBLOCKS (new_block)
00257 = blocks_nreverse (BLOCK_SUBBLOCKS (new_block));
00258 data->block = old_block;
00259 }
00260
00261
00262 tsi_link_before (tsi, BIND_EXPR_BODY (stmt), TSI_SAME_STMT);
00263 tsi_delink (tsi);
00264 }
00265
00266
00267
00268
00269 static bool
00270 try_catch_may_fallthru (tree stmt)
00271 {
00272 tree_stmt_iterator i;
00273
00274
00275
00276 if (block_may_fallthru (TREE_OPERAND (stmt, 0)))
00277 return true;
00278
00279 i = tsi_start (TREE_OPERAND (stmt, 1));
00280 switch (TREE_CODE (tsi_stmt (i)))
00281 {
00282 case CATCH_EXPR:
00283
00284
00285
00286 for (; !tsi_end_p (i); tsi_next (&i))
00287 {
00288 if (block_may_fallthru (CATCH_BODY (tsi_stmt (i))))
00289 return true;
00290 }
00291 return false;
00292
00293 case EH_FILTER_EXPR:
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 return block_may_fallthru (EH_FILTER_FAILURE (tsi_stmt (i)));
00304
00305 default:
00306
00307
00308
00309
00310 return false;
00311 }
00312 }
00313
00314
00315
00316
00317
00318
00319 bool
00320 block_may_fallthru (tree block)
00321 {
00322 tree stmt = expr_last (block);
00323
00324 switch (stmt ? TREE_CODE (stmt) : ERROR_MARK)
00325 {
00326 case GOTO_EXPR:
00327 case RETURN_EXPR:
00328 case RESX_EXPR:
00329
00330
00331 return false;
00332
00333 case SWITCH_EXPR:
00334
00335
00336
00337
00338 return SWITCH_LABELS (stmt) == NULL_TREE;
00339
00340 case COND_EXPR:
00341 if (block_may_fallthru (COND_EXPR_THEN (stmt)))
00342 return true;
00343 return block_may_fallthru (COND_EXPR_ELSE (stmt));
00344
00345 case BIND_EXPR:
00346 return block_may_fallthru (BIND_EXPR_BODY (stmt));
00347
00348 case TRY_CATCH_EXPR:
00349 return try_catch_may_fallthru (stmt);
00350
00351 case TRY_FINALLY_EXPR:
00352
00353
00354
00355
00356
00357
00358
00359 return (block_may_fallthru (TREE_OPERAND (stmt, 0))
00360 && block_may_fallthru (TREE_OPERAND (stmt, 1)));
00361
00362 case MODIFY_EXPR:
00363 if (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR)
00364 stmt = TREE_OPERAND (stmt, 1);
00365 else
00366 return true;
00367
00368
00369 case CALL_EXPR:
00370
00371 return (call_expr_flags (stmt) & ECF_NORETURN) == 0;
00372
00373 case CLEANUP_POINT_EXPR:
00374 return block_may_fallthru (TREE_OPERAND (stmt, 0));
00375
00376 default:
00377 return true;
00378 }
00379 }
00380
00381
00382
00383 static void
00384 lower_cond_expr (tree_stmt_iterator *tsi, struct lower_data *data)
00385 {
00386 tree stmt = tsi_stmt (*tsi);
00387 bool then_is_goto, else_is_goto;
00388 tree then_branch, else_branch;
00389 tree then_goto, else_goto;
00390
00391 then_branch = COND_EXPR_THEN (stmt);
00392 else_branch = COND_EXPR_ELSE (stmt);
00393
00394 lower_stmt_body (then_branch, data);
00395 lower_stmt_body (else_branch, data);
00396
00397 then_goto = expr_only (then_branch);
00398 then_is_goto = then_goto && simple_goto_p (then_goto);
00399
00400 else_goto = expr_only (else_branch);
00401 else_is_goto = else_goto && simple_goto_p (else_goto);
00402
00403 if (!then_is_goto || !else_is_goto)
00404 {
00405 tree then_label, else_label, end_label, t;
00406
00407 then_label = NULL_TREE;
00408 else_label = NULL_TREE;
00409 end_label = NULL_TREE;
00410
00411
00412 if (!then_is_goto)
00413 {
00414 t = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
00415 if (TREE_SIDE_EFFECTS (then_branch))
00416 then_label = t;
00417 else
00418 end_label = t;
00419 then_goto = build_and_jump (&LABEL_EXPR_LABEL (t));
00420 }
00421
00422 if (!else_is_goto)
00423 {
00424 t = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
00425 if (TREE_SIDE_EFFECTS (else_branch))
00426 else_label = t;
00427 else
00428 {
00429
00430
00431
00432
00433
00434 if (end_label)
00435 {
00436 tsi_delink (tsi);
00437 return;
00438 }
00439 else
00440 end_label = t;
00441 }
00442 else_goto = build_and_jump (&LABEL_EXPR_LABEL (t));
00443 }
00444
00445 if (then_label)
00446 {
00447 bool may_fallthru = block_may_fallthru (then_branch);
00448
00449 tsi_link_after (tsi, then_label, TSI_CONTINUE_LINKING);
00450 tsi_link_after (tsi, then_branch, TSI_CONTINUE_LINKING);
00451
00452 if (else_label && may_fallthru)
00453 {
00454 end_label = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
00455 t = build_and_jump (&LABEL_EXPR_LABEL (end_label));
00456 tsi_link_after (tsi, t, TSI_CONTINUE_LINKING);
00457 }
00458 }
00459
00460 if (else_label)
00461 {
00462 tsi_link_after (tsi, else_label, TSI_CONTINUE_LINKING);
00463 tsi_link_after (tsi, else_branch, TSI_CONTINUE_LINKING);
00464 }
00465
00466 if (end_label)
00467 tsi_link_after (tsi, end_label, TSI_CONTINUE_LINKING);
00468 }
00469
00470 COND_EXPR_THEN (stmt) = then_goto;
00471 COND_EXPR_ELSE (stmt) = else_goto;
00472
00473 tsi_next (tsi);
00474 }
00475
00476 static void
00477 lower_return_expr (tree_stmt_iterator *tsi, struct lower_data *data)
00478 {
00479 tree stmt = tsi_stmt (*tsi);
00480 tree value, t, label;
00481
00482
00483 value = TREE_OPERAND (stmt, 0);
00484 if (value && TREE_CODE (value) == MODIFY_EXPR)
00485 value = TREE_OPERAND (value, 1);
00486
00487
00488 for (t = data->return_statements; t ; t = TREE_CHAIN (t))
00489 {
00490 tree tvalue = TREE_OPERAND (TREE_VALUE (t), 0);
00491 if (tvalue && TREE_CODE (tvalue) == MODIFY_EXPR)
00492 tvalue = TREE_OPERAND (tvalue, 1);
00493
00494 if (value == tvalue)
00495 {
00496 label = TREE_PURPOSE (t);
00497 goto found;
00498 }
00499 }
00500
00501
00502 label = create_artificial_label ();
00503 data->return_statements = tree_cons (label, stmt, data->return_statements);
00504
00505
00506 found:
00507 t = build (GOTO_EXPR, void_type_node, label);
00508 SET_EXPR_LOCUS (t, EXPR_LOCUS (stmt));
00509 tsi_link_before (tsi, t, TSI_SAME_STMT);
00510 tsi_delink (tsi);
00511 }
00512
00513
00514
00515
00516 void
00517 record_vars (tree vars)
00518 {
00519 for (; vars; vars = TREE_CHAIN (vars))
00520 {
00521 tree var = vars;
00522
00523
00524 if (DECL_EXTERNAL (var))
00525 continue;
00526 if (TREE_CODE (var) == FUNCTION_DECL)
00527 continue;
00528
00529
00530 cfun->unexpanded_var_list = tree_cons (NULL_TREE, var,
00531 cfun->unexpanded_var_list);
00532 }
00533 }
00534
00535
00536
00537 static bool
00538 expand_var_p (tree var)
00539 {
00540 struct var_ann_d *ann;
00541
00542 if (TREE_CODE (var) != VAR_DECL)
00543 return true;
00544
00545
00546 if (TREE_STATIC (var) || DECL_EXTERNAL (var))
00547 return true;
00548
00549
00550 ann = var_ann (var);
00551 if (!ann || !ann->used)
00552 return false;
00553
00554 return true;
00555 }
00556
00557
00558
00559 static void
00560 remove_useless_vars (void)
00561 {
00562 tree var, *cell;
00563 FILE *df = NULL;
00564
00565 if (dump_file && (dump_flags & TDF_DETAILS))
00566 {
00567 df = dump_file;
00568 fputs ("Discarding as unused:\n", df);
00569 }
00570
00571 for (cell = &cfun->unexpanded_var_list; *cell; )
00572 {
00573 var = TREE_VALUE (*cell);
00574
00575 if (!expand_var_p (var))
00576 {
00577 if (df)
00578 {
00579 fputs (" ", df);
00580 print_generic_expr (df, var, dump_flags);
00581 fputc ('\n', df);
00582 }
00583
00584 *cell = TREE_CHAIN (*cell);
00585 continue;
00586 }
00587
00588 cell = &TREE_CHAIN (*cell);
00589 }
00590
00591 if (df)
00592 fputc ('\n', df);
00593 }
00594
00595 struct tree_opt_pass pass_remove_useless_vars =
00596 {
00597 "vars",
00598 NULL,
00599 remove_useless_vars,
00600 NULL,
00601 NULL,
00602 0,
00603 0,
00604 0,
00605 0,
00606 0,
00607 0,
00608 TODO_dump_func,
00609 0
00610 };
00611
00612
00613
00614
00615 static void
00616 mark_blocks_with_used_vars (tree block)
00617 {
00618 tree var;
00619 tree subblock;
00620
00621 if (!TREE_USED (block))
00622 {
00623 for (var = BLOCK_VARS (block);
00624 var;
00625 var = TREE_CHAIN (var))
00626 {
00627 if (TREE_USED (var))
00628 {
00629 TREE_USED (block) = true;
00630 break;
00631 }
00632 }
00633 }
00634 for (subblock = BLOCK_SUBBLOCKS (block);
00635 subblock;
00636 subblock = BLOCK_CHAIN (subblock))
00637 mark_blocks_with_used_vars (subblock);
00638 }
00639
00640
00641
00642 static void
00643 mark_used_blocks (void)
00644 {
00645 mark_blocks_with_used_vars (DECL_INITIAL (current_function_decl));
00646 }
00647
00648
00649 struct tree_opt_pass pass_mark_used_blocks =
00650 {
00651 "blocks",
00652 NULL,
00653 mark_used_blocks,
00654 NULL,
00655 NULL,
00656 0,
00657 0,
00658 0,
00659 0,
00660 0,
00661 0,
00662 TODO_dump_func,
00663 0
00664 };