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
00028 #include "config.h"
00029 #include "system.h"
00030 #ifdef SGI_MONGOOSE
00031
00032 #include "rtl.h"
00033 #endif
00034 #include "tree.h"
00035 #include "function.h"
00036 #include "splay-tree.h"
00037 #include "varray.h"
00038 #include "c-common.h"
00039 #include "except.h"
00040 #include "toplev.h"
00041 #include "flags.h"
00042 #include "ggc.h"
00043 #ifndef SGI_MONGOOSE
00044 #include "rtl.h"
00045 #endif
00046 #include "expr.h"
00047 #include "output.h"
00048 #include "timevar.h"
00049 #include "predict.h"
00050
00051
00052
00053 void (*lang_expand_stmt) PARAMS ((tree));
00054
00055
00056
00057
00058
00059
00060 void (*lang_expand_decl_stmt) PARAMS ((tree));
00061
00062
00063
00064 void
00065 begin_stmt_tree (t)
00066 tree *t;
00067 {
00068
00069
00070
00071 *t = build_nt (EXPR_STMT, void_zero_node);
00072 last_tree = *t;
00073 last_expr_type = NULL_TREE;
00074 last_expr_filename = input_filename;
00075 }
00076
00077
00078
00079 tree
00080 add_stmt (t)
00081 tree t;
00082 {
00083 if (input_filename != last_expr_filename)
00084 {
00085
00086
00087 int add = (strcmp (input_filename, last_expr_filename) != 0);
00088 last_expr_filename = input_filename;
00089 if (add)
00090 {
00091 tree pos = build_nt (FILE_STMT, get_identifier (input_filename));
00092 add_stmt (pos);
00093 }
00094 }
00095
00096
00097 TREE_CHAIN (last_tree) = t;
00098 last_tree = t;
00099
00100
00101
00102 STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p ();
00103
00104
00105 if (current_function_decl)
00106 ++DECL_NUM_STMTS (current_function_decl);
00107
00108 return t;
00109 }
00110
00111
00112
00113
00114 void
00115 add_decl_stmt (decl)
00116 tree decl;
00117 {
00118 tree decl_stmt;
00119
00120
00121 decl_stmt = build_stmt (DECL_STMT, decl);
00122 add_stmt (decl_stmt);
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 tree
00136 add_scope_stmt (begin_p, partial_p)
00137 int begin_p;
00138 int partial_p;
00139 {
00140 tree *stack_ptr = current_scope_stmt_stack ();
00141 tree ss;
00142 tree top = *stack_ptr;
00143
00144
00145 ss = build_stmt (SCOPE_STMT, NULL_TREE);
00146 SCOPE_BEGIN_P (ss) = begin_p;
00147 SCOPE_PARTIAL_P (ss) = partial_p;
00148
00149
00150 if (begin_p)
00151 {
00152 top = tree_cons (ss, NULL_TREE, top);
00153 *stack_ptr = top;
00154 }
00155 else
00156 {
00157 TREE_VALUE (top) = ss;
00158 *stack_ptr = TREE_CHAIN (top);
00159 }
00160
00161
00162 add_stmt (ss);
00163
00164 return top;
00165 }
00166
00167
00168
00169 void
00170 finish_stmt_tree (t)
00171 tree *t;
00172 {
00173 tree stmt;
00174
00175
00176 stmt = TREE_CHAIN (*t);
00177 *t = stmt;
00178 last_tree = NULL_TREE;
00179
00180 if (cfun && stmt)
00181 {
00182
00183
00184 STMT_LINENO (stmt) = lineno;
00185 STMT_LINENO_FOR_FN_P (stmt) = 1;
00186 }
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 tree
00196 build_stmt VPARAMS ((enum tree_code code, ...))
00197 {
00198 tree t;
00199 int length;
00200 int i;
00201
00202 VA_OPEN (p, code);
00203 VA_FIXEDARG (p, enum tree_code, code);
00204
00205 t = make_node (code);
00206 length = TREE_CODE_LENGTH (code);
00207 STMT_LINENO (t) = lineno;
00208
00209 for (i = 0; i < length; i++)
00210 TREE_OPERAND (t, i) = va_arg (p, tree);
00211
00212 VA_CLOSE (p);
00213 return t;
00214 }
00215
00216
00217
00218
00219
00220
00221 tree
00222 expand_cond (t)
00223 tree t;
00224 {
00225 if (t && TREE_CODE (t) == TREE_LIST)
00226 {
00227 expand_stmt (TREE_PURPOSE (t));
00228 return TREE_VALUE (t);
00229 }
00230 else
00231 return t;
00232 }
00233
00234
00235
00236 void
00237 make_rtl_for_local_static (decl)
00238 tree decl;
00239 {
00240 const char *asmspec = NULL;
00241
00242
00243
00244 if (TREE_ASM_WRITTEN (decl))
00245 return;
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)
00264 && !DECL_RTL_SET_P (decl))
00265 asmspec = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
00266
00267 rest_of_decl_compilation (decl, asmspec, 0, 0);
00268 }
00269
00270
00271
00272 void
00273 emit_local_var (decl)
00274 tree decl;
00275 {
00276
00277 if (!DECL_RTL_SET_P (decl))
00278 {
00279 if (DECL_C_HARD_REGISTER (decl))
00280
00281
00282 rest_of_decl_compilation
00283 (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
00284 0, 0);
00285 else
00286 expand_decl (decl);
00287 }
00288
00289
00290 if (stmts_are_full_exprs_p ())
00291 expand_start_target_temps ();
00292
00293 expand_decl_init (decl);
00294
00295 if (stmts_are_full_exprs_p ())
00296 expand_end_target_temps ();
00297 }
00298
00299
00300
00301 void
00302 genrtl_do_pushlevel ()
00303 {
00304 emit_line_note (input_filename, lineno);
00305 clear_last_expr ();
00306 }
00307
00308
00309
00310 void
00311 genrtl_goto_stmt (destination)
00312 tree destination;
00313 {
00314 if (TREE_CODE (destination) == IDENTIFIER_NODE)
00315 abort ();
00316
00317
00318
00319 if (TREE_CODE (destination) == LABEL_DECL)
00320 TREE_USED (destination) = 1;
00321
00322 emit_line_note (input_filename, lineno);
00323
00324 if (TREE_CODE (destination) == LABEL_DECL)
00325 {
00326 label_rtx (destination);
00327 expand_goto (destination);
00328 }
00329 else
00330 expand_computed_goto (destination);
00331 }
00332
00333
00334
00335
00336
00337 void
00338 genrtl_expr_stmt (expr)
00339 tree expr;
00340 {
00341 genrtl_expr_stmt_value (expr, -1, 1);
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351 void
00352 genrtl_expr_stmt_value (expr, want_value, maybe_last)
00353 tree expr;
00354 int want_value, maybe_last;
00355 {
00356 if (expr != NULL_TREE)
00357 {
00358 emit_line_note (input_filename, lineno);
00359
00360 if (stmts_are_full_exprs_p ())
00361 expand_start_target_temps ();
00362
00363 if (expr != error_mark_node)
00364 expand_expr_stmt_value (expr, want_value, maybe_last);
00365
00366 if (stmts_are_full_exprs_p ())
00367 expand_end_target_temps ();
00368 }
00369 }
00370
00371
00372
00373 void
00374 genrtl_decl_stmt (t)
00375 tree t;
00376 {
00377 tree decl;
00378 emit_line_note (input_filename, lineno);
00379 decl = DECL_STMT_DECL (t);
00380
00381
00382
00383
00384
00385
00386 if (TREE_CODE (decl) == VAR_DECL
00387 && !TREE_STATIC (decl)
00388 && !DECL_EXTERNAL (decl))
00389 {
00390
00391 if (!anon_aggr_type_p (TREE_TYPE (decl)))
00392 emit_local_var (decl);
00393 else
00394 expand_anon_union_decl (decl, NULL_TREE,
00395 DECL_ANON_UNION_ELEMS (decl));
00396 }
00397 else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
00398 make_rtl_for_local_static (decl);
00399 else if (TREE_CODE (decl) == LABEL_DECL
00400 && C_DECLARED_LABEL_FLAG (decl))
00401 declare_nonlocal_label (decl);
00402 else if (lang_expand_decl_stmt)
00403 (*lang_expand_decl_stmt) (t);
00404 }
00405
00406
00407
00408 void
00409 genrtl_if_stmt (t)
00410 tree t;
00411 {
00412 tree cond;
00413 genrtl_do_pushlevel ();
00414 cond = expand_cond (IF_COND (t));
00415 emit_line_note (input_filename, lineno);
00416 expand_start_cond (cond, 0);
00417 if (THEN_CLAUSE (t))
00418 expand_stmt (THEN_CLAUSE (t));
00419 if (ELSE_CLAUSE (t))
00420 {
00421 expand_start_else ();
00422 expand_stmt (ELSE_CLAUSE (t));
00423 }
00424 expand_end_cond ();
00425 }
00426
00427
00428
00429 void
00430 genrtl_while_stmt (t)
00431 tree t;
00432 {
00433 tree cond;
00434 emit_nop ();
00435 emit_line_note (input_filename, lineno);
00436 expand_start_loop (1);
00437 genrtl_do_pushlevel ();
00438
00439 cond = expand_cond (WHILE_COND (t));
00440 emit_line_note (input_filename, lineno);
00441 expand_exit_loop_top_cond (0, cond);
00442 genrtl_do_pushlevel ();
00443
00444 expand_stmt (WHILE_BODY (t));
00445
00446 expand_end_loop ();
00447 }
00448
00449
00450
00451 void
00452 genrtl_do_stmt (t)
00453 tree t;
00454 {
00455 tree cond = DO_COND (t);
00456
00457
00458
00459
00460
00461
00462 if (!cond || integer_zerop (cond))
00463 {
00464 expand_start_null_loop ();
00465 expand_stmt (DO_BODY (t));
00466 expand_end_null_loop ();
00467 }
00468 else
00469 {
00470 emit_nop ();
00471 emit_line_note (input_filename, lineno);
00472 expand_start_loop_continue_elsewhere (1);
00473
00474 expand_stmt (DO_BODY (t));
00475
00476 expand_loop_continue_here ();
00477 cond = expand_cond (cond);
00478 emit_line_note (input_filename, lineno);
00479 expand_exit_loop_if_false (0, cond);
00480 expand_end_loop ();
00481 }
00482 }
00483
00484
00485
00486 tree
00487 build_return_stmt (expr)
00488 tree expr;
00489 {
00490 return (build_stmt (RETURN_STMT, expr));
00491 }
00492
00493
00494
00495 void
00496 genrtl_return_stmt (stmt)
00497 tree stmt;
00498 {
00499 tree expr;
00500
00501 expr = RETURN_STMT_EXPR (stmt);
00502
00503 emit_line_note (input_filename, lineno);
00504 if (!expr)
00505 expand_null_return ();
00506 else
00507 {
00508 expand_start_target_temps ();
00509 expand_return (expr);
00510 expand_end_target_temps ();
00511 }
00512 }
00513
00514
00515
00516 void
00517 genrtl_for_stmt (t)
00518 tree t;
00519 {
00520 tree cond;
00521 const char *saved_filename;
00522 int saved_lineno;
00523
00524 if (NEW_FOR_SCOPE_P (t))
00525 genrtl_do_pushlevel ();
00526
00527 expand_stmt (FOR_INIT_STMT (t));
00528
00529
00530 emit_nop ();
00531 emit_line_note (input_filename, lineno);
00532 expand_start_loop_continue_elsewhere (1);
00533 genrtl_do_pushlevel ();
00534 cond = expand_cond (FOR_COND (t));
00535
00536
00537
00538 saved_filename = input_filename;
00539 saved_lineno = lineno;
00540
00541
00542 emit_line_note (input_filename, lineno);
00543 if (cond)
00544 expand_exit_loop_top_cond (0, cond);
00545
00546
00547 genrtl_do_pushlevel ();
00548 expand_stmt (FOR_BODY (t));
00549
00550
00551 input_filename = saved_filename;
00552 lineno = saved_lineno;
00553 emit_line_note (input_filename, lineno);
00554 expand_loop_continue_here ();
00555 if (FOR_EXPR (t))
00556 genrtl_expr_stmt (FOR_EXPR (t));
00557 expand_end_loop ();
00558 }
00559
00560
00561
00562 tree
00563 build_break_stmt ()
00564 {
00565 return (build_stmt (BREAK_STMT));
00566 }
00567
00568
00569
00570 void
00571 genrtl_break_stmt ()
00572 {
00573 emit_line_note (input_filename, lineno);
00574 if ( ! expand_exit_something ())
00575 error ("break statement not within loop or switch");
00576 }
00577
00578
00579
00580 tree
00581 build_continue_stmt ()
00582 {
00583 return (build_stmt (CONTINUE_STMT));
00584 }
00585
00586 #ifdef KEY
00587
00588 tree
00589 build_omp_stmt (enum omp_tree_type c, void * p)
00590 {
00591 tree t = build_stmt (OMP_MARKER_STMT);
00592 t->omp.choice = c;
00593 t->omp.omp_clause_list = p;
00594
00595 return t;
00596 }
00597 #endif
00598
00599
00600
00601 void
00602 genrtl_continue_stmt ()
00603 {
00604 emit_line_note (input_filename, lineno);
00605 if (! expand_continue_loop (0))
00606 error ("continue statement not within a loop");
00607 }
00608
00609
00610
00611 void
00612 genrtl_scope_stmt (t)
00613 tree t;
00614 {
00615 tree block = SCOPE_STMT_BLOCK (t);
00616
00617 if (!SCOPE_NO_CLEANUPS_P (t))
00618 {
00619 if (SCOPE_BEGIN_P (t))
00620 expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t), block);
00621 else if (SCOPE_END_P (t))
00622 expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), 0);
00623 }
00624 else if (!SCOPE_NULLIFIED_P (t))
00625 {
00626 rtx note = emit_note (NULL,
00627 (SCOPE_BEGIN_P (t)
00628 ? NOTE_INSN_BLOCK_BEG
00629 : NOTE_INSN_BLOCK_END));
00630 NOTE_BLOCK (note) = block;
00631 }
00632
00633
00634
00635 if (block && SCOPE_END_P (t))
00636 {
00637 tree fn;
00638
00639 for (fn = BLOCK_VARS (block); fn; fn = TREE_CHAIN (fn))
00640 {
00641 if (TREE_CODE (fn) == FUNCTION_DECL
00642 && DECL_CONTEXT (fn) == current_function_decl
00643 && DECL_SAVED_INSNS (fn)
00644 && !TREE_ASM_WRITTEN (fn)
00645 && TREE_ADDRESSABLE (fn))
00646 {
00647 push_function_context ();
00648 output_inline_function (fn);
00649 pop_function_context ();
00650 }
00651 }
00652 }
00653 }
00654
00655
00656
00657 void
00658 genrtl_switch_stmt (t)
00659 tree t;
00660 {
00661 tree cond;
00662 genrtl_do_pushlevel ();
00663
00664 cond = expand_cond (SWITCH_COND (t));
00665 if (cond == error_mark_node)
00666
00667
00668 cond = boolean_false_node;
00669
00670 emit_line_note (input_filename, lineno);
00671 expand_start_case (1, cond, TREE_TYPE (cond), "switch statement");
00672 expand_stmt (SWITCH_BODY (t));
00673 expand_end_case_type (cond, SWITCH_TYPE (t));
00674 }
00675
00676
00677
00678 tree
00679 build_case_label (low_value, high_value, label_decl)
00680 tree low_value;
00681 tree high_value;
00682 tree label_decl;
00683 {
00684 return build_stmt (CASE_LABEL, low_value, high_value, label_decl);
00685 }
00686
00687
00688
00689
00690 void
00691 genrtl_case_label (case_label)
00692 tree case_label;
00693 {
00694 tree duplicate;
00695 tree cleanup;
00696
00697 cleanup = last_cleanup_this_contour ();
00698 if (cleanup)
00699 {
00700 static int explained = 0;
00701 warning ("destructor needed for `%#D'", (TREE_PURPOSE (cleanup)));
00702 warning ("where case label appears here");
00703 if (!explained)
00704 {
00705 warning ("(enclose actions of previous case statements requiring destructors in their own scope.)");
00706 explained = 1;
00707 }
00708 }
00709
00710 add_case_node (CASE_LOW (case_label), CASE_HIGH (case_label),
00711 CASE_LABEL_DECL (case_label), &duplicate);
00712 }
00713
00714
00715
00716 void
00717 genrtl_compound_stmt (t)
00718 tree t;
00719 {
00720 #ifdef ENABLE_CHECKING
00721 struct nesting *n = current_nesting_level ();
00722 #endif
00723
00724 expand_stmt (COMPOUND_BODY (t));
00725
00726 #ifdef ENABLE_CHECKING
00727
00728 if (!COMPOUND_STMT_NO_SCOPE (t) && n != current_nesting_level ())
00729 abort ();
00730 #endif
00731 }
00732
00733
00734
00735 void
00736 genrtl_asm_stmt (cv_qualifier, string, output_operands,
00737 input_operands, clobbers, asm_input_p)
00738 tree cv_qualifier;
00739 tree string;
00740 tree output_operands;
00741 tree input_operands;
00742 tree clobbers;
00743 int asm_input_p;
00744 {
00745 if (cv_qualifier != NULL_TREE
00746 && cv_qualifier != ridpointers[(int) RID_VOLATILE])
00747 {
00748 warning ("%s qualifier ignored on asm",
00749 IDENTIFIER_POINTER (cv_qualifier));
00750 cv_qualifier = NULL_TREE;
00751 }
00752
00753 emit_line_note (input_filename, lineno);
00754 if (asm_input_p)
00755 expand_asm (string, cv_qualifier != NULL_TREE);
00756 else
00757 c_expand_asm_operands (string, output_operands, input_operands,
00758 clobbers, cv_qualifier != NULL_TREE,
00759 input_filename, lineno);
00760 }
00761
00762
00763
00764 void
00765 genrtl_decl_cleanup (t)
00766 tree t;
00767 {
00768 tree decl = CLEANUP_DECL (t);
00769 if (!decl || (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node))
00770 expand_decl_cleanup_eh (decl, CLEANUP_EXPR (t), CLEANUP_EH_ONLY (t));
00771 }
00772
00773
00774
00775
00776 void
00777 prep_stmt (t)
00778 tree t;
00779 {
00780 if (!STMT_LINENO_FOR_FN_P (t))
00781 lineno = STMT_LINENO (t);
00782 current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
00783 }
00784
00785
00786
00787
00788 void
00789 expand_stmt (t)
00790 tree t;
00791 {
00792 while (t && t != error_mark_node)
00793 {
00794 int saved_stmts_are_full_exprs_p;
00795
00796
00797 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
00798 prep_stmt (t);
00799
00800 switch (TREE_CODE (t))
00801 {
00802 case FILE_STMT:
00803 input_filename = FILE_STMT_FILENAME (t);
00804 break;
00805
00806 case RETURN_STMT:
00807 genrtl_return_stmt (t);
00808 break;
00809
00810 case EXPR_STMT:
00811 genrtl_expr_stmt_value (EXPR_STMT_EXPR (t), TREE_ADDRESSABLE (t),
00812 TREE_CHAIN (t) == NULL
00813 || (TREE_CODE (TREE_CHAIN (t)) == SCOPE_STMT
00814 && TREE_CHAIN (TREE_CHAIN (t)) == NULL));
00815 break;
00816
00817 case DECL_STMT:
00818 genrtl_decl_stmt (t);
00819 break;
00820
00821 case FOR_STMT:
00822 genrtl_for_stmt (t);
00823 break;
00824
00825 case WHILE_STMT:
00826 genrtl_while_stmt (t);
00827 break;
00828
00829 case DO_STMT:
00830 genrtl_do_stmt (t);
00831 break;
00832
00833 case IF_STMT:
00834 genrtl_if_stmt (t);
00835 break;
00836
00837 case COMPOUND_STMT:
00838 genrtl_compound_stmt (t);
00839 break;
00840
00841 case BREAK_STMT:
00842 genrtl_break_stmt ();
00843 break;
00844
00845 case CONTINUE_STMT:
00846 genrtl_continue_stmt ();
00847 break;
00848
00849 case SWITCH_STMT:
00850 genrtl_switch_stmt (t);
00851 break;
00852
00853 case CASE_LABEL:
00854 genrtl_case_label (t);
00855 break;
00856
00857 case LABEL_STMT:
00858 expand_label (LABEL_STMT_LABEL (t));
00859 break;
00860
00861 case GOTO_STMT:
00862
00863 if (!GOTO_FAKE_P (t)
00864 && TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL
00865 && flag_guess_branch_prob)
00866 {
00867 rtx note = emit_note (NULL, NOTE_INSN_PREDICTION);
00868
00869 NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_GOTO, NOT_TAKEN);
00870 }
00871 genrtl_goto_stmt (GOTO_DESTINATION (t));
00872 break;
00873
00874 case ASM_STMT:
00875 genrtl_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t),
00876 ASM_OUTPUTS (t), ASM_INPUTS (t),
00877 ASM_CLOBBERS (t), ASM_INPUT_P (t));
00878 break;
00879
00880 case SCOPE_STMT:
00881 genrtl_scope_stmt (t);
00882 break;
00883
00884 case CLEANUP_STMT:
00885 genrtl_decl_cleanup (t);
00886 break;
00887
00888 #ifdef KEY
00889 case OMP_MARKER_STMT:
00890 break;
00891 #endif
00892
00893 default:
00894 if (lang_expand_stmt)
00895 (*lang_expand_stmt) (t);
00896 else
00897 abort ();
00898 break;
00899 }
00900
00901
00902 current_stmt_tree ()->stmts_are_full_exprs_p
00903 = saved_stmts_are_full_exprs_p;
00904
00905
00906 t = TREE_CHAIN (t);
00907 }
00908 }