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
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "config.h"
00041 #include "system.h"
00042
00043 #include "rtl.h"
00044 #include "tree.h"
00045 #include "tm_p.h"
00046 #include "flags.h"
00047 #include "except.h"
00048 #include "function.h"
00049 #include "insn-config.h"
00050 #include "expr.h"
00051 #include "libfuncs.h"
00052 #include "hard-reg-set.h"
00053 #include "loop.h"
00054 #include "recog.h"
00055 #include "machmode.h"
00056 #include "toplev.h"
00057 #include "output.h"
00058 #include "ggc.h"
00059 #include "langhooks.h"
00060 #include "predict.h"
00061
00062 #ifdef SGI_MONGOOSE
00063 #include "defaults.h"
00064 #endif
00065
00066
00067 #ifndef CASE_VECTOR_PC_RELATIVE
00068 #define CASE_VECTOR_PC_RELATIVE 0
00069 #endif
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 struct case_node GTY(())
00096 {
00097 struct case_node *left;
00098 struct case_node *right;
00099 struct case_node *parent;
00100 tree low;
00101 tree high;
00102 tree code_label;
00103 int balance;
00104 };
00105
00106 typedef struct case_node case_node;
00107 typedef struct case_node *case_node_ptr;
00108
00109
00110
00111
00112 static short cost_table_[129];
00113 static int use_cost_table;
00114 static int cost_table_initialized;
00115
00116
00117
00118 #define COST_TABLE(I) cost_table_[(unsigned HOST_WIDE_INT) ((I) + 1)]
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 struct nesting GTY(())
00146 {
00147 struct nesting *all;
00148 struct nesting *next;
00149 int depth;
00150 rtx exit_label;
00151 enum nesting_desc {
00152 COND_NESTING,
00153 LOOP_NESTING,
00154 BLOCK_NESTING,
00155 CASE_NESTING
00156 } desc;
00157 union nesting_u
00158 {
00159
00160 struct nesting_cond
00161 {
00162
00163
00164
00165 rtx endif_label;
00166
00167
00168 rtx next_label;
00169 } GTY ((tag ("COND_NESTING"))) cond;
00170
00171 struct nesting_loop
00172 {
00173
00174 rtx start_label;
00175
00176 rtx end_label;
00177
00178
00179 rtx alt_end_label;
00180
00181
00182 rtx continue_label;
00183 } GTY ((tag ("LOOP_NESTING"))) loop;
00184
00185 struct nesting_block
00186 {
00187
00188
00189 int block_start_count;
00190
00191 rtx stack_level;
00192
00193
00194
00195 rtx first_insn;
00196
00197 struct nesting *innermost_stack_block;
00198
00199
00200
00201
00202 tree cleanups;
00203
00204
00205
00206
00207
00208
00209
00210
00211 tree outer_cleanups;
00212
00213
00214 struct label_chain *label_chain;
00215
00216 int n_function_calls;
00217
00218 int exception_region;
00219
00220
00221
00222
00223
00224 int block_target_temp_slot_level;
00225
00226
00227
00228
00229 int conditional_code;
00230
00231
00232
00233
00234 rtx last_unconditional_cleanup;
00235 } GTY ((tag ("BLOCK_NESTING"))) block;
00236
00237
00238 struct nesting_case
00239 {
00240
00241
00242 rtx start;
00243
00244
00245
00246 struct case_node *case_list;
00247
00248 tree default_label;
00249
00250 tree index_expr;
00251
00252 tree nominal_type;
00253
00254 const char *printname;
00255
00256
00257
00258 int line_number_status;
00259 } GTY ((tag ("CASE_NESTING"))) case_stmt;
00260 } GTY ((desc ("%1.desc"))) data;
00261 };
00262
00263
00264
00265 #define ALLOC_NESTING() \
00266 (struct nesting *) ggc_alloc (sizeof (struct nesting))
00267
00268
00269
00270
00271
00272
00273 #define POPSTACK(STACK) \
00274 do { struct nesting *target = STACK; \
00275 struct nesting *this; \
00276 do { this = nesting_stack; \
00277 if (loop_stack == this) \
00278 loop_stack = loop_stack->next; \
00279 if (cond_stack == this) \
00280 cond_stack = cond_stack->next; \
00281 if (block_stack == this) \
00282 block_stack = block_stack->next; \
00283 if (stack_block_stack == this) \
00284 stack_block_stack = stack_block_stack->next; \
00285 if (case_stack == this) \
00286 case_stack = case_stack->next; \
00287 nesting_depth = nesting_stack->depth - 1; \
00288 nesting_stack = this->all; } \
00289 while (this != target); } while (0)
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 struct goto_fixup GTY(())
00300 {
00301
00302 struct goto_fixup *next;
00303
00304
00305 rtx before_jump;
00306
00307
00308 tree target;
00309
00310 tree context;
00311
00312 rtx target_rtl;
00313
00314
00315 int block_start_count;
00316
00317
00318
00319 rtx stack_level;
00320
00321
00322
00323
00324
00325
00326
00327 tree cleanup_list_list;
00328 };
00329
00330
00331
00332
00333 struct label_chain GTY(())
00334 {
00335
00336 struct label_chain *next;
00337 tree label;
00338 };
00339
00340 struct stmt_status GTY(())
00341 {
00342
00343 struct nesting * x_block_stack;
00344
00345
00346
00347
00348
00349 struct nesting * x_stack_block_stack;
00350
00351
00352 struct nesting * x_cond_stack;
00353
00354
00355 struct nesting * x_loop_stack;
00356
00357
00358 struct nesting * x_case_stack;
00359
00360
00361
00362 struct nesting * x_nesting_stack;
00363
00364
00365 int x_nesting_depth;
00366
00367
00368 int x_block_start_count;
00369
00370
00371
00372 tree x_last_expr_type;
00373 rtx x_last_expr_value;
00374
00375
00376
00377 int x_expr_stmts_for_value;
00378
00379
00380
00381 const char *x_emit_filename;
00382 int x_emit_lineno;
00383
00384 struct goto_fixup *x_goto_fixup_chain;
00385 };
00386
00387 #define block_stack (cfun->stmt->x_block_stack)
00388 #define stack_block_stack (cfun->stmt->x_stack_block_stack)
00389 #define cond_stack (cfun->stmt->x_cond_stack)
00390 #define loop_stack (cfun->stmt->x_loop_stack)
00391 #define case_stack (cfun->stmt->x_case_stack)
00392 #define nesting_stack (cfun->stmt->x_nesting_stack)
00393 #define nesting_depth (cfun->stmt->x_nesting_depth)
00394 #define current_block_start_count (cfun->stmt->x_block_start_count)
00395 #define last_expr_type (cfun->stmt->x_last_expr_type)
00396 #define last_expr_value (cfun->stmt->x_last_expr_value)
00397 #define expr_stmts_for_value (cfun->stmt->x_expr_stmts_for_value)
00398 #define emit_filename (cfun->stmt->x_emit_filename)
00399 #define emit_lineno (cfun->stmt->x_emit_lineno)
00400 #define goto_fixup_chain (cfun->stmt->x_goto_fixup_chain)
00401
00402
00403 static int using_eh_for_cleanups_p = 0;
00404
00405 static int n_occurrences PARAMS ((int, const char *));
00406 static bool parse_input_constraint PARAMS ((const char **, int, int, int,
00407 int, const char * const *,
00408 bool *, bool *));
00409 static bool decl_conflicts_with_clobbers_p PARAMS ((tree, const HARD_REG_SET));
00410 static void expand_goto_internal PARAMS ((tree, rtx, rtx));
00411 static int expand_fixup PARAMS ((tree, rtx, rtx));
00412 static rtx expand_nl_handler_label PARAMS ((rtx, rtx));
00413 static void expand_nl_goto_receiver PARAMS ((void));
00414 static void expand_nl_goto_receivers PARAMS ((struct nesting *));
00415 static void fixup_gotos PARAMS ((struct nesting *, rtx, tree,
00416 rtx, int));
00417 static bool check_operand_nalternatives PARAMS ((tree, tree));
00418 static bool check_unique_operand_names PARAMS ((tree, tree));
00419 static tree resolve_operand_names PARAMS ((tree, tree, tree,
00420 const char **));
00421 static char *resolve_operand_name_1 PARAMS ((char *, tree, tree));
00422 static void expand_null_return_1 PARAMS ((rtx));
00423 static enum br_predictor return_prediction PARAMS ((rtx));
00424 static void expand_value_return PARAMS ((rtx));
00425 static int tail_recursion_args PARAMS ((tree, tree));
00426 static void expand_cleanups PARAMS ((tree, tree, int, int));
00427 static void check_seenlabel PARAMS ((void));
00428 static void do_jump_if_equal PARAMS ((rtx, rtx, rtx, int));
00429 static int estimate_case_costs PARAMS ((case_node_ptr));
00430 static void group_case_nodes PARAMS ((case_node_ptr));
00431 static void balance_case_nodes PARAMS ((case_node_ptr *,
00432 case_node_ptr));
00433 static int node_has_low_bound PARAMS ((case_node_ptr, tree));
00434 static int node_has_high_bound PARAMS ((case_node_ptr, tree));
00435 static int node_is_bounded PARAMS ((case_node_ptr, tree));
00436 static void emit_jump_if_reachable PARAMS ((rtx));
00437 static void emit_case_nodes PARAMS ((rtx, case_node_ptr, rtx, tree));
00438 static struct case_node *case_tree2list PARAMS ((case_node *, case_node *));
00439
00440 void
00441 using_eh_for_cleanups ()
00442 {
00443 using_eh_for_cleanups_p = 1;
00444 }
00445
00446 void
00447 init_stmt_for_function ()
00448 {
00449 cfun->stmt = ((struct stmt_status *)ggc_alloc (sizeof (struct stmt_status)));
00450
00451
00452 block_stack = 0;
00453 stack_block_stack = 0;
00454 loop_stack = 0;
00455 case_stack = 0;
00456 cond_stack = 0;
00457 nesting_stack = 0;
00458 nesting_depth = 0;
00459
00460 current_block_start_count = 0;
00461
00462
00463 goto_fixup_chain = 0;
00464
00465
00466 expr_stmts_for_value = 0;
00467 clear_last_expr ();
00468 }
00469
00470
00471
00472 int
00473 in_control_zone_p ()
00474 {
00475 return cond_stack || loop_stack || case_stack;
00476 }
00477
00478
00479 void
00480 set_file_and_line_for_stmt (file, line)
00481 const char *file;
00482 int line;
00483 {
00484
00485
00486
00487 if (cfun->stmt)
00488 {
00489 emit_filename = file;
00490 emit_lineno = line;
00491 }
00492 }
00493
00494
00495
00496 void
00497 emit_nop ()
00498 {
00499 rtx last_insn;
00500
00501 last_insn = get_last_insn ();
00502 if (!optimize
00503 && (GET_CODE (last_insn) == CODE_LABEL
00504 || (GET_CODE (last_insn) == NOTE
00505 && prev_real_insn (last_insn) == 0)))
00506 emit_insn (gen_nop ());
00507 }
00508
00509
00510
00511
00512 rtx
00513 label_rtx (label)
00514 tree label;
00515 {
00516 if (TREE_CODE (label) != LABEL_DECL)
00517 abort ();
00518
00519 if (!DECL_RTL_SET_P (label))
00520 SET_DECL_RTL (label, gen_label_rtx ());
00521
00522 return DECL_RTL (label);
00523 }
00524
00525
00526
00527
00528 void
00529 emit_jump (label)
00530 rtx label;
00531 {
00532 do_pending_stack_adjust ();
00533 emit_jump_insn (gen_jump (label));
00534 emit_barrier ();
00535 }
00536
00537
00538
00539
00540 void
00541 expand_computed_goto (exp)
00542 tree exp;
00543 {
00544 rtx x = expand_expr (exp, NULL_RTX, VOIDmode, 0);
00545
00546 #ifdef POINTERS_EXTEND_UNSIGNED
00547 if (GET_MODE (x) != Pmode)
00548 x = convert_memory_address (Pmode, x);
00549 #endif
00550
00551 emit_queue ();
00552
00553 if (! cfun->computed_goto_common_label)
00554 {
00555 cfun->computed_goto_common_reg = copy_to_mode_reg (Pmode, x);
00556 cfun->computed_goto_common_label = gen_label_rtx ();
00557 emit_label (cfun->computed_goto_common_label);
00558
00559 do_pending_stack_adjust ();
00560 emit_indirect_jump (cfun->computed_goto_common_reg);
00561
00562 current_function_has_computed_jump = 1;
00563 }
00564 else
00565 {
00566 emit_move_insn (cfun->computed_goto_common_reg, x);
00567 emit_jump (cfun->computed_goto_common_label);
00568 }
00569 }
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 void
00585 expand_label (label)
00586 tree label;
00587 {
00588 struct label_chain *p;
00589
00590 do_pending_stack_adjust ();
00591 emit_label (label_rtx (label));
00592 if (DECL_NAME (label))
00593 LABEL_NAME (DECL_RTL (label)) = IDENTIFIER_POINTER (DECL_NAME (label));
00594
00595 if (stack_block_stack != 0)
00596 {
00597 p = (struct label_chain *) ggc_alloc (sizeof (struct label_chain));
00598 p->next = stack_block_stack->data.block.label_chain;
00599 stack_block_stack->data.block.label_chain = p;
00600 p->label = label;
00601 }
00602 }
00603
00604
00605
00606
00607 void
00608 declare_nonlocal_label (label)
00609 tree label;
00610 {
00611 rtx slot = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
00612
00613 nonlocal_labels = tree_cons (NULL_TREE, label, nonlocal_labels);
00614 LABEL_PRESERVE_P (label_rtx (label)) = 1;
00615 if (nonlocal_goto_handler_slots == 0)
00616 {
00617 emit_stack_save (SAVE_NONLOCAL,
00618 &nonlocal_goto_stack_level,
00619 PREV_INSN (tail_recursion_reentry));
00620 }
00621 nonlocal_goto_handler_slots
00622 = gen_rtx_EXPR_LIST (VOIDmode, slot, nonlocal_goto_handler_slots);
00623 }
00624
00625
00626
00627
00628
00629 void
00630 expand_goto (label)
00631 tree label;
00632 {
00633 tree context;
00634
00635
00636 context = decl_function_context (label);
00637 if (context != 0 && context != current_function_decl)
00638 {
00639 struct function *p = find_function_data (context);
00640 rtx label_ref = gen_rtx_LABEL_REF (Pmode, label_rtx (label));
00641 rtx handler_slot, static_chain, save_area, insn;
00642 tree link;
00643
00644
00645 handler_slot = p->x_nonlocal_goto_handler_slots;
00646 for (link = p->x_nonlocal_labels; TREE_VALUE (link) != label;
00647 link = TREE_CHAIN (link))
00648 handler_slot = XEXP (handler_slot, 1);
00649 handler_slot = XEXP (handler_slot, 0);
00650
00651 p->has_nonlocal_label = 1;
00652 current_function_has_nonlocal_goto = 1;
00653 LABEL_REF_NONLOCAL_P (label_ref) = 1;
00654
00655
00656
00657
00658
00659 static_chain = copy_to_reg (lookup_static_chain (label));
00660
00661
00662
00663 handler_slot = copy_to_reg (replace_rtx (copy_rtx (handler_slot),
00664 virtual_stack_vars_rtx,
00665 static_chain));
00666
00667
00668 save_area = p->x_nonlocal_goto_stack_level;
00669 if (save_area)
00670 save_area = replace_rtx (copy_rtx (save_area),
00671 virtual_stack_vars_rtx, static_chain);
00672
00673 #if HAVE_nonlocal_goto
00674 if (HAVE_nonlocal_goto)
00675 emit_insn (gen_nonlocal_goto (static_chain, handler_slot,
00676 save_area, label_ref));
00677 else
00678 #endif
00679 {
00680
00681
00682
00683
00684
00685 emit_move_insn (hard_frame_pointer_rtx, static_chain);
00686 emit_stack_restore (SAVE_NONLOCAL, save_area, NULL_RTX);
00687
00688
00689
00690 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
00691 emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
00692 emit_indirect_jump (handler_slot);
00693 }
00694
00695
00696
00697 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
00698 {
00699 if (GET_CODE (insn) == JUMP_INSN)
00700 {
00701 REG_NOTES (insn) = alloc_EXPR_LIST (REG_NON_LOCAL_GOTO,
00702 const0_rtx, REG_NOTES (insn));
00703 break;
00704 }
00705 else if (GET_CODE (insn) == CALL_INSN)
00706 break;
00707 }
00708 }
00709 else
00710 expand_goto_internal (label, label_rtx (label), NULL_RTX);
00711 }
00712
00713
00714
00715
00716
00717
00718 static void
00719 expand_goto_internal (body, label, last_insn)
00720 tree body;
00721 rtx label;
00722 rtx last_insn;
00723 {
00724 struct nesting *block;
00725 rtx stack_level = 0;
00726
00727 if (GET_CODE (label) != CODE_LABEL)
00728 abort ();
00729
00730
00731
00732
00733 if (PREV_INSN (label) != 0)
00734 {
00735
00736
00737
00738
00739 for (block = block_stack; block; block = block->next)
00740 {
00741 if (INSN_UID (block->data.block.first_insn) < INSN_UID (label))
00742 break;
00743 if (block->data.block.stack_level != 0)
00744 stack_level = block->data.block.stack_level;
00745
00746 if (block->data.block.cleanups != 0)
00747 {
00748 expand_cleanups (block->data.block.cleanups, NULL_TREE, 1, 1);
00749 do_pending_stack_adjust ();
00750 }
00751 }
00752
00753 if (stack_level)
00754 {
00755
00756
00757
00758 clear_pending_stack_adjust ();
00759 do_pending_stack_adjust ();
00760
00761
00762
00763 if (label == return_label
00764 && (((TREE_CODE (TREE_TYPE (current_function_decl))
00765 == FUNCTION_TYPE)
00766 && (TYPE_RETURNS_STACK_DEPRESSED
00767 (TREE_TYPE (current_function_decl))))))
00768 ;
00769 else
00770 emit_stack_restore (SAVE_BLOCK, stack_level, NULL_RTX);
00771 }
00772
00773 if (body != 0 && DECL_TOO_LATE (body))
00774 error ("jump to `%s' invalidly jumps into binding contour",
00775 IDENTIFIER_POINTER (DECL_NAME (body)));
00776 }
00777
00778
00779 else if (! expand_fixup (body, label, last_insn))
00780 {
00781
00782
00783 if (body != 0)
00784 TREE_ADDRESSABLE (body) = 1;
00785 }
00786
00787 emit_jump (label);
00788 }
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805 static int
00806 expand_fixup (tree_label, rtl_label, last_insn)
00807 tree tree_label;
00808 rtx rtl_label;
00809 rtx last_insn;
00810 {
00811 struct nesting *block, *end_block;
00812
00813
00814
00815
00816
00817
00818 if (cond_stack
00819 && (rtl_label == cond_stack->data.cond.endif_label
00820 || rtl_label == cond_stack->data.cond.next_label))
00821 end_block = cond_stack;
00822
00823
00824
00825 else if (loop_stack
00826 && (rtl_label == loop_stack->data.loop.start_label
00827 || rtl_label == loop_stack->data.loop.end_label
00828 || rtl_label == loop_stack->data.loop.continue_label))
00829 end_block = loop_stack;
00830 else
00831 end_block = 0;
00832
00833
00834
00835 if (end_block)
00836 {
00837 struct nesting *next_block = end_block->all;
00838 block = block_stack;
00839
00840
00841
00842 while (next_block && next_block != block)
00843 next_block = next_block->all;
00844
00845 if (next_block)
00846 return 0;
00847
00848
00849
00850 next_block = block_stack->next;
00851 for (block = block_stack; block != end_block; block = block->all)
00852 if (block == next_block)
00853 next_block = next_block->next;
00854 end_block = next_block;
00855 }
00856
00857
00858
00859
00860 for (block = block_stack; block != end_block; block = block->next)
00861 if (block->data.block.stack_level != 0
00862 || block->data.block.cleanups != 0)
00863 break;
00864
00865 if (block != end_block)
00866 {
00867
00868 struct goto_fixup *fixup
00869 = (struct goto_fixup *) ggc_alloc (sizeof (struct goto_fixup));
00870
00871
00872
00873
00874
00875
00876 if (last_insn == 0)
00877 do_pending_stack_adjust ();
00878 fixup->target = tree_label;
00879 fixup->target_rtl = rtl_label;
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893 {
00894 rtx original_before_jump
00895 = last_insn ? last_insn : get_last_insn ();
00896 rtx start;
00897 rtx end;
00898 tree block;
00899
00900 block = make_node (BLOCK);
00901 TREE_USED (block) = 1;
00902
00903 if (!cfun->x_whole_function_mode_p)
00904 (*lang_hooks.decls.insert_block) (block);
00905 else
00906 {
00907 BLOCK_CHAIN (block)
00908 = BLOCK_CHAIN (DECL_INITIAL (current_function_decl));
00909 BLOCK_CHAIN (DECL_INITIAL (current_function_decl))
00910 = block;
00911 }
00912
00913 start_sequence ();
00914 start = emit_note (NULL, NOTE_INSN_BLOCK_BEG);
00915 if (cfun->x_whole_function_mode_p)
00916 NOTE_BLOCK (start) = block;
00917 fixup->before_jump = emit_note (NULL, NOTE_INSN_DELETED);
00918 end = emit_note (NULL, NOTE_INSN_BLOCK_END);
00919 if (cfun->x_whole_function_mode_p)
00920 NOTE_BLOCK (end) = block;
00921 fixup->context = block;
00922 end_sequence ();
00923 emit_insn_after (start, original_before_jump);
00924 }
00925
00926 fixup->block_start_count = current_block_start_count;
00927 fixup->stack_level = 0;
00928 fixup->cleanup_list_list
00929 = ((block->data.block.outer_cleanups
00930 || block->data.block.cleanups)
00931 ? tree_cons (NULL_TREE, block->data.block.cleanups,
00932 block->data.block.outer_cleanups)
00933 : 0);
00934 fixup->next = goto_fixup_chain;
00935 goto_fixup_chain = fixup;
00936 }
00937
00938 return block != 0;
00939 }
00940
00941
00942
00943
00944 void
00945 expand_fixups (first_insn)
00946 rtx first_insn;
00947 {
00948 fixup_gotos (NULL, NULL_RTX, NULL_TREE, first_insn, 0);
00949 }
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964 static void
00965 fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
00966 struct nesting *thisblock;
00967 rtx stack_level;
00968 tree cleanup_list;
00969 rtx first_insn;
00970 int dont_jump_in;
00971 {
00972 struct goto_fixup *f, *prev;
00973
00974
00975
00976
00977
00978
00979 for (prev = 0, f = goto_fixup_chain; f; prev = f, f = f->next)
00980 {
00981
00982 if (f->before_jump == 0)
00983 {
00984
00985 if (prev != 0)
00986 prev->next = f->next;
00987 }
00988
00989
00990 else if (PREV_INSN (f->target_rtl) != 0)
00991 {
00992 rtx cleanup_insns;
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003 if (f->target != 0
01004 && (dont_jump_in || stack_level || cleanup_list)
01005 && INSN_UID (first_insn) < INSN_UID (f->target_rtl)
01006 && INSN_UID (first_insn) > INSN_UID (f->before_jump)
01007 && ! DECL_ERROR_ISSUED (f->target))
01008 {
01009 error_with_decl (f->target,
01010 "label `%s' used before containing binding contour");
01011
01012 DECL_ERROR_ISSUED (f->target) = 1;
01013 }
01014
01015
01016
01017
01018
01019 start_sequence ();
01020
01021
01022
01023
01024
01025 (*lang_hooks.decls.pushlevel) (0);
01026 (*lang_hooks.decls.set_block) (f->context);
01027
01028
01029 if (f->cleanup_list_list)
01030 {
01031 tree lists;
01032 for (lists = f->cleanup_list_list; lists; lists = TREE_CHAIN (lists))
01033
01034
01035 if (TREE_ADDRESSABLE (lists)
01036 && TREE_VALUE (lists) != 0)
01037 {
01038 expand_cleanups (TREE_VALUE (lists), NULL_TREE, 1, 1);
01039
01040
01041 do_pending_stack_adjust ();
01042 }
01043 }
01044
01045
01046
01047 if (f->stack_level
01048 && ! (f->target_rtl == return_label
01049 && ((TREE_CODE (TREE_TYPE (current_function_decl))
01050 == FUNCTION_TYPE)
01051 && (TYPE_RETURNS_STACK_DEPRESSED
01052 (TREE_TYPE (current_function_decl))))))
01053 emit_stack_restore (SAVE_BLOCK, f->stack_level, f->before_jump);
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064 cleanup_insns = get_insns ();
01065 (*lang_hooks.decls.poplevel) (1, 0, 0);
01066
01067 end_sequence ();
01068 emit_insn_after (cleanup_insns, f->before_jump);
01069
01070 f->before_jump = 0;
01071 }
01072 }
01073
01074
01075
01076
01077 for (prev = 0, f = goto_fixup_chain; f; prev = f, f = f->next)
01078 if (f->before_jump != 0
01079 && PREV_INSN (f->target_rtl) == 0
01080
01081
01082
01083
01084 && thisblock != 0
01085
01086
01087 && (thisblock->data.block.block_start_count
01088 <= f->block_start_count))
01089 {
01090 tree lists = f->cleanup_list_list;
01091 rtx cleanup_insns;
01092
01093 for (; lists; lists = TREE_CHAIN (lists))
01094
01095
01096 if (TREE_CHAIN (lists) == thisblock->data.block.outer_cleanups)
01097 {
01098 start_sequence ();
01099 (*lang_hooks.decls.pushlevel) (0);
01100 (*lang_hooks.decls.set_block) (f->context);
01101 expand_cleanups (TREE_VALUE (lists), NULL_TREE, 1, 1);
01102 do_pending_stack_adjust ();
01103 cleanup_insns = get_insns ();
01104 (*lang_hooks.decls.poplevel) (1, 0, 0);
01105 end_sequence ();
01106 if (cleanup_insns != 0)
01107 f->before_jump
01108 = emit_insn_after (cleanup_insns, f->before_jump);
01109
01110 f->cleanup_list_list = TREE_CHAIN (lists);
01111 }
01112
01113 if (stack_level)
01114 f->stack_level = stack_level;
01115 }
01116 }
01117
01118
01119 static int
01120 n_occurrences (c, s)
01121 int c;
01122 const char *s;
01123 {
01124 int n = 0;
01125 while (*s)
01126 n += (*s++ == c);
01127 return n;
01128 }
01129
01130
01131
01132
01133
01134
01135 void
01136 expand_asm (string, vol)
01137 tree string;
01138 int vol;
01139 {
01140 rtx body;
01141
01142 if (TREE_CODE (string) == ADDR_EXPR)
01143 string = TREE_OPERAND (string, 0);
01144
01145 body = gen_rtx_ASM_INPUT (VOIDmode, TREE_STRING_POINTER (string));
01146
01147 MEM_VOLATILE_P (body) = vol;
01148
01149 emit_insn (body);
01150
01151 clear_last_expr ();
01152 }
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167 bool
01168 parse_output_constraint (constraint_p, operand_num, ninputs, noutputs,
01169 allows_mem, allows_reg, is_inout)
01170 const char **constraint_p;
01171 int operand_num;
01172 int ninputs;
01173 int noutputs;
01174 bool *allows_mem;
01175 bool *allows_reg;
01176 bool *is_inout;
01177 {
01178 const char *constraint = *constraint_p;
01179 const char *p;
01180
01181
01182
01183 *allows_mem = false;
01184 *allows_reg = false;
01185
01186
01187
01188
01189
01190 p = strchr (constraint, '=');
01191 if (!p)
01192 p = strchr (constraint, '+');
01193
01194
01195
01196 if (!p)
01197 {
01198 error ("output operand constraint lacks `='");
01199 return false;
01200 }
01201
01202
01203
01204 *is_inout = (*p == '+');
01205
01206
01207 if (p != constraint || is_inout)
01208 {
01209 char *buf;
01210 size_t c_len = strlen (constraint);
01211
01212 if (p != constraint)
01213 warning ("output constraint `%c' for operand %d is not at the beginning",
01214 *p, operand_num);
01215
01216
01217 buf = alloca (c_len + 1);
01218 strcpy (buf, constraint);
01219
01220 buf[p - constraint] = buf[0];
01221
01222
01223 buf[0] = '=';
01224
01225 *constraint_p = ggc_alloc_string (buf, c_len);
01226 constraint = *constraint_p;
01227 }
01228
01229
01230 for (p = constraint + 1; *p; ++p)
01231 switch (*p)
01232 {
01233 case '+':
01234 case '=':
01235 error ("operand constraint contains incorrectly positioned '+' or '='");
01236 return false;
01237
01238 case '%':
01239 if (operand_num + 1 == ninputs + noutputs)
01240 {
01241 error ("`%%' constraint used with last operand");
01242 return false;
01243 }
01244 break;
01245
01246 case 'V': case 'm': case 'o':
01247 *allows_mem = true;
01248 break;
01249
01250 case '?': case '!': case '*': case '&': case '#':
01251 case 'E': case 'F': case 'G': case 'H':
01252 case 's': case 'i': case 'n':
01253 case 'I': case 'J': case 'K': case 'L': case 'M':
01254 case 'N': case 'O': case 'P': case ',':
01255 break;
01256
01257 case '0': case '1': case '2': case '3': case '4':
01258 case '5': case '6': case '7': case '8': case '9':
01259 case '[':
01260 error ("matching constraint not valid in output operand");
01261 return false;
01262
01263 case '<': case '>':
01264
01265
01266
01267 *allows_mem = true;
01268 break;
01269
01270 case 'g': case 'X':
01271 *allows_reg = true;
01272 *allows_mem = true;
01273 break;
01274
01275 case 'p': case 'r':
01276 *allows_reg = true;
01277 break;
01278
01279 default:
01280 if (!ISALPHA (*p))
01281 break;
01282 if (REG_CLASS_FROM_LETTER (*p) != NO_REGS)
01283 *allows_reg = true;
01284 #ifdef EXTRA_CONSTRAINT
01285 else if (EXTRA_ADDRESS_CONSTRAINT (*p))
01286 *allows_reg = true;
01287 else if (EXTRA_MEMORY_CONSTRAINT (*p))
01288 *allows_mem = true;
01289 else
01290 {
01291
01292
01293
01294 *allows_reg = true;
01295 *allows_mem = true;
01296 }
01297 #endif
01298 break;
01299 }
01300
01301 return true;
01302 }
01303
01304
01305
01306 static bool
01307 parse_input_constraint (constraint_p, input_num, ninputs, noutputs, ninout,
01308 constraints, allows_mem, allows_reg)
01309 const char **constraint_p;
01310 int input_num;
01311 int ninputs;
01312 int noutputs;
01313 int ninout;
01314 const char * const * constraints;
01315 bool *allows_mem;
01316 bool *allows_reg;
01317 {
01318 const char *constraint = *constraint_p;
01319 const char *orig_constraint = constraint;
01320 size_t c_len = strlen (constraint);
01321 size_t j;
01322
01323
01324
01325 *allows_mem = false;
01326 *allows_reg = false;
01327
01328
01329
01330 for (j = 0; j < c_len; j++)
01331 switch (constraint[j])
01332 {
01333 case '+': case '=': case '&':
01334 if (constraint == orig_constraint)
01335 {
01336 error ("input operand constraint contains `%c'", constraint[j]);
01337 return false;
01338 }
01339 break;
01340
01341 case '%':
01342 if (constraint == orig_constraint
01343 && input_num + 1 == ninputs - ninout)
01344 {
01345 error ("`%%' constraint used with last operand");
01346 return false;
01347 }
01348 break;
01349
01350 case 'V': case 'm': case 'o':
01351 *allows_mem = true;
01352 break;
01353
01354 case '<': case '>':
01355 case '?': case '!': case '*': case '#':
01356 case 'E': case 'F': case 'G': case 'H':
01357 case 's': case 'i': case 'n':
01358 case 'I': case 'J': case 'K': case 'L': case 'M':
01359 case 'N': case 'O': case 'P': case ',':
01360 break;
01361
01362
01363
01364
01365
01366
01367 case '0': case '1': case '2': case '3': case '4':
01368 case '5': case '6': case '7': case '8': case '9':
01369 {
01370 char *end;
01371 unsigned long match;
01372
01373 match = strtoul (constraint + j, &end, 10);
01374 if (match >= (unsigned long) noutputs)
01375 {
01376 error ("matching constraint references invalid operand number");
01377 return false;
01378 }
01379
01380
01381
01382 if (*end == '\0'
01383 && (j == 0 || (j == 1 && constraint[0] == '%')))
01384 {
01385 constraint = constraints[match];
01386 *constraint_p = constraint;
01387 c_len = strlen (constraint);
01388 j = 0;
01389 break;
01390 }
01391 else
01392 j = end - constraint;
01393 }
01394
01395
01396 case 'p': case 'r':
01397 *allows_reg = true;
01398 break;
01399
01400 case 'g': case 'X':
01401 *allows_reg = true;
01402 *allows_mem = true;
01403 break;
01404
01405 default:
01406 if (! ISALPHA (constraint[j]))
01407 {
01408 error ("invalid punctuation `%c' in constraint", constraint[j]);
01409 return false;
01410 }
01411 if (REG_CLASS_FROM_LETTER (constraint[j]) != NO_REGS)
01412 *allows_reg = true;
01413 #ifdef EXTRA_CONSTRAINT
01414 else if (EXTRA_ADDRESS_CONSTRAINT (constraint[j]))
01415 *allows_reg = true;
01416 else if (EXTRA_MEMORY_CONSTRAINT (constraint[j]))
01417 *allows_mem = true;
01418 else
01419 {
01420
01421
01422
01423 *allows_reg = true;
01424 *allows_mem = true;
01425 }
01426 #endif
01427 break;
01428 }
01429
01430 return true;
01431 }
01432
01433
01434
01435
01436
01437 static bool
01438 decl_conflicts_with_clobbers_p (decl, clobbered_regs)
01439 tree decl;
01440 const HARD_REG_SET clobbered_regs;
01441 {
01442
01443
01444 if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
01445 && DECL_REGISTER (decl)
01446 && REG_P (DECL_RTL (decl))
01447 && REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
01448 {
01449 rtx reg = DECL_RTL (decl);
01450 unsigned int regno;
01451
01452 for (regno = REGNO (reg);
01453 regno < (REGNO (reg)
01454 + HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg)));
01455 regno++)
01456 if (TEST_HARD_REG_BIT (clobbered_regs, regno))
01457 {
01458 error ("asm-specifier for variable `%s' conflicts with asm clobber list",
01459 IDENTIFIER_POINTER (DECL_NAME (decl)));
01460
01461
01462
01463 DECL_REGISTER (decl) = 0;
01464 return true;
01465 }
01466 }
01467 return false;
01468 }
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487 void
01488 expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
01489 tree string, outputs, inputs, clobbers;
01490 int vol;
01491 const char *filename;
01492 int line;
01493 {
01494 rtvec argvec, constraintvec;
01495 rtx body;
01496 int ninputs = list_length (inputs);
01497 int noutputs = list_length (outputs);
01498 int ninout;
01499 int nclobbers;
01500 HARD_REG_SET clobbered_regs;
01501 int clobber_conflict_found = 0;
01502 tree tail;
01503 int i;
01504
01505 rtx *output_rtx = (rtx *) alloca (noutputs * sizeof (rtx));
01506 int *inout_opnum = (int *) alloca (noutputs * sizeof (int));
01507 rtx *real_output_rtx = (rtx *) alloca (noutputs * sizeof (rtx));
01508 enum machine_mode *inout_mode
01509 = (enum machine_mode *) alloca (noutputs * sizeof (enum machine_mode));
01510 const char **constraints
01511 = (const char **) alloca ((noutputs + ninputs) * sizeof (const char *));
01512
01513 rtx insn;
01514 int old_generating_concat_p = generating_concat_p;
01515
01516
01517 if (noutputs == 0)
01518 vol = 1;
01519
01520 if (! check_operand_nalternatives (outputs, inputs))
01521 return;
01522
01523 if (! check_unique_operand_names (outputs, inputs))
01524 return;
01525
01526 string = resolve_operand_names (string, outputs, inputs, constraints);
01527
01528 #ifdef MD_ASM_CLOBBERS
01529
01530
01531
01532
01533 MD_ASM_CLOBBERS (clobbers);
01534 #endif
01535
01536
01537
01538 nclobbers = 0;
01539 CLEAR_HARD_REG_SET (clobbered_regs);
01540 for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
01541 {
01542 const char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
01543
01544 i = decode_reg_name (regname);
01545 if (i >= 0 || i == -4)
01546 ++nclobbers;
01547 else if (i == -2)
01548 error ("unknown register name `%s' in `asm'", regname);
01549
01550
01551 if (i >= 0)
01552 SET_HARD_REG_BIT (clobbered_regs, i);
01553 }
01554
01555 clear_last_expr ();
01556
01557
01558
01559
01560 ninout = 0;
01561 for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
01562 {
01563 tree val = TREE_VALUE (tail);
01564 tree type = TREE_TYPE (val);
01565 const char *constraint;
01566 bool is_inout;
01567 bool allows_reg;
01568 bool allows_mem;
01569
01570
01571 if (type == error_mark_node)
01572 return;
01573
01574
01575
01576 constraint = constraints[i];
01577 if (!parse_output_constraint (&constraint, i, ninputs, noutputs,
01578 &allows_mem, &allows_reg, &is_inout))
01579 return;
01580
01581 if (! allows_reg
01582 && (allows_mem
01583 || is_inout
01584 || (DECL_P (val)
01585 && GET_CODE (DECL_RTL (val)) == REG
01586 && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type))))
01587 (*lang_hooks.mark_addressable) (val);
01588
01589 if (is_inout)
01590 ninout++;
01591 }
01592
01593 ninputs += ninout;
01594 if (ninputs + noutputs > MAX_RECOG_OPERANDS)
01595 {
01596 error ("more than %d operands in `asm'", MAX_RECOG_OPERANDS);
01597 return;
01598 }
01599
01600 for (i = 0, tail = inputs; tail; i++, tail = TREE_CHAIN (tail))
01601 {
01602 bool allows_reg, allows_mem;
01603 const char *constraint;
01604
01605
01606
01607 if (TREE_TYPE (TREE_VALUE (tail)) == error_mark_node)
01608 return;
01609
01610 constraint = constraints[i + noutputs];
01611 if (! parse_input_constraint (&constraint, i, ninputs, noutputs, ninout,
01612 constraints, &allows_mem, &allows_reg))
01613 return;
01614
01615 if (! allows_reg && allows_mem)
01616 (*lang_hooks.mark_addressable) (TREE_VALUE (tail));
01617 }
01618
01619
01620
01621 ninout = 0;
01622 for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
01623 {
01624 tree val = TREE_VALUE (tail);
01625 tree type = TREE_TYPE (val);
01626 bool is_inout;
01627 bool allows_reg;
01628 bool allows_mem;
01629 rtx op;
01630
01631 if (!parse_output_constraint (&constraints[i], i, ninputs,
01632 noutputs, &allows_mem, &allows_reg,
01633 &is_inout))
01634 abort ();
01635
01636
01637
01638
01639
01640
01641 generating_concat_p = 0;
01642
01643 real_output_rtx[i] = NULL_RTX;
01644 if ((TREE_CODE (val) == INDIRECT_REF
01645 && allows_mem)
01646 || (DECL_P (val)
01647 && (allows_mem || GET_CODE (DECL_RTL (val)) == REG)
01648 && ! (GET_CODE (DECL_RTL (val)) == REG
01649 && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))
01650 || ! allows_reg
01651 || is_inout)
01652 {
01653 op = expand_expr (val, NULL_RTX, VOIDmode, EXPAND_WRITE);
01654 if (GET_CODE (op) == MEM)
01655 op = validize_mem (op);
01656
01657 if (! allows_reg && GET_CODE (op) != MEM)
01658 error ("output number %d not directly addressable", i);
01659 if ((! allows_mem && GET_CODE (op) == MEM)
01660 || GET_CODE (op) == CONCAT)
01661 {
01662 real_output_rtx[i] = protect_from_queue (op, 1);
01663 op = gen_reg_rtx (GET_MODE (op));
01664 if (is_inout)
01665 emit_move_insn (op, real_output_rtx[i]);
01666 }
01667 }
01668 else
01669 {
01670 op = assign_temp (type, 0, 0, 1);
01671 op = validize_mem (op);
01672 TREE_VALUE (tail) = make_tree (type, op);
01673 }
01674 output_rtx[i] = op;
01675
01676 generating_concat_p = old_generating_concat_p;
01677
01678 if (is_inout)
01679 {
01680 inout_mode[ninout] = TYPE_MODE (type);
01681 inout_opnum[ninout++] = i;
01682 }
01683
01684 if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
01685 clobber_conflict_found = 1;
01686 }
01687
01688
01689
01690
01691 argvec = rtvec_alloc (ninputs);
01692 constraintvec = rtvec_alloc (ninputs);
01693
01694 body = gen_rtx_ASM_OPERANDS ((noutputs == 0 ? VOIDmode
01695 : GET_MODE (output_rtx[0])),
01696 TREE_STRING_POINTER (string),
01697 empty_string, 0, argvec, constraintvec,
01698 filename, line);
01699
01700 MEM_VOLATILE_P (body) = vol;
01701
01702
01703
01704
01705 for (i = 0, tail = inputs; tail; tail = TREE_CHAIN (tail), ++i)
01706 {
01707 bool allows_reg, allows_mem;
01708 const char *constraint;
01709 tree val, type;
01710 rtx op;
01711
01712 constraint = constraints[i + noutputs];
01713 if (! parse_input_constraint (&constraint, i, ninputs, noutputs, ninout,
01714 constraints, &allows_mem, &allows_reg))
01715 abort ();
01716
01717 generating_concat_p = 0;
01718
01719 val = TREE_VALUE (tail);
01720 type = TREE_TYPE (val);
01721 op = expand_expr (val, NULL_RTX, VOIDmode,
01722 (allows_mem && !allows_reg
01723 ? EXPAND_MEMORY : EXPAND_NORMAL));
01724
01725
01726 if (GET_CODE (op) == CONCAT)
01727 op = force_reg (GET_MODE (op), op);
01728 else if (GET_CODE (op) == MEM)
01729 op = validize_mem (op);
01730
01731 if (asm_operand_ok (op, constraint) <= 0)
01732 {
01733 if (allows_reg)
01734 op = force_reg (TYPE_MODE (type), op);
01735 else if (!allows_mem)
01736 warning ("asm operand %d probably doesn't match constraints",
01737 i + noutputs);
01738 else if (GET_CODE (op) == MEM)
01739 {
01740
01741
01742
01743 }
01744 else
01745 {
01746 warning ("use of memory input without lvalue in asm operand %d is deprecated",
01747 i + noutputs);
01748
01749 if (CONSTANT_P (op))
01750 {
01751 op = force_const_mem (TYPE_MODE (type), op);
01752 op = validize_mem (op);
01753 }
01754 else if (GET_CODE (op) == REG
01755 || GET_CODE (op) == SUBREG
01756 || GET_CODE (op) == ADDRESSOF
01757 || GET_CODE (op) == CONCAT)
01758 {
01759 tree qual_type = build_qualified_type (type,
01760 (TYPE_QUALS (type)
01761 | TYPE_QUAL_CONST));
01762 rtx memloc = assign_temp (qual_type, 1, 1, 1);
01763 memloc = validize_mem (memloc);
01764 emit_move_insn (memloc, op);
01765 op = memloc;
01766 }
01767 }
01768 }
01769
01770 generating_concat_p = old_generating_concat_p;
01771 ASM_OPERANDS_INPUT (body, i) = op;
01772
01773 ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, i)
01774 = gen_rtx_ASM_INPUT (TYPE_MODE (type), constraints[i + noutputs]);
01775
01776 if (decl_conflicts_with_clobbers_p (val, clobbered_regs))
01777 clobber_conflict_found = 1;
01778 }
01779
01780
01781
01782
01783 generating_concat_p = 0;
01784
01785 for (i = 0; i < ninputs - ninout; i++)
01786 ASM_OPERANDS_INPUT (body, i)
01787 = protect_from_queue (ASM_OPERANDS_INPUT (body, i), 0);
01788
01789 for (i = 0; i < noutputs; i++)
01790 output_rtx[i] = protect_from_queue (output_rtx[i], 1);
01791
01792
01793 for (i = 0; i < ninout; i++)
01794 {
01795 int j = inout_opnum[i];
01796 char buffer[16];
01797
01798 ASM_OPERANDS_INPUT (body, ninputs - ninout + i)
01799 = output_rtx[j];
01800
01801 sprintf (buffer, "%d", j);
01802 ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, ninputs - ninout + i)
01803 = gen_rtx_ASM_INPUT (inout_mode[i], ggc_alloc_string (buffer, -1));
01804 }
01805
01806 generating_concat_p = old_generating_concat_p;
01807
01808
01809
01810
01811
01812
01813 if (noutputs == 1 && nclobbers == 0)
01814 {
01815 ASM_OPERANDS_OUTPUT_CONSTRAINT (body) = constraints[0];
01816 insn = emit_insn (gen_rtx_SET (VOIDmode, output_rtx[0], body));
01817 }
01818
01819 else if (noutputs == 0 && nclobbers == 0)
01820 {
01821
01822 insn = emit_insn (body);
01823 }
01824
01825 else
01826 {
01827 rtx obody = body;
01828 int num = noutputs;
01829
01830 if (num == 0)
01831 num = 1;
01832
01833 body = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num + nclobbers));
01834
01835
01836 for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
01837 {
01838 XVECEXP (body, 0, i)
01839 = gen_rtx_SET (VOIDmode,
01840 output_rtx[i],
01841 gen_rtx_ASM_OPERANDS
01842 (GET_MODE (output_rtx[i]),
01843 TREE_STRING_POINTER (string),
01844 constraints[i], i, argvec, constraintvec,
01845 filename, line));
01846
01847 MEM_VOLATILE_P (SET_SRC (XVECEXP (body, 0, i))) = vol;
01848 }
01849
01850
01851
01852
01853 if (i == 0)
01854 XVECEXP (body, 0, i++) = obody;
01855
01856
01857
01858 for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
01859 {
01860 const char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
01861 int j = decode_reg_name (regname);
01862 rtx clobbered_reg;
01863
01864 if (j < 0)
01865 {
01866 if (j == -3)
01867 continue;
01868
01869 if (j == -4)
01870 {
01871 XVECEXP (body, 0, i++)
01872 = gen_rtx_CLOBBER (VOIDmode,
01873 gen_rtx_MEM
01874 (BLKmode,
01875 gen_rtx_SCRATCH (VOIDmode)));
01876 continue;
01877 }
01878
01879
01880 continue;
01881 }
01882
01883
01884 clobbered_reg = gen_rtx_REG (QImode, j);
01885
01886
01887
01888
01889 if (!clobber_conflict_found)
01890 {
01891 int opno;
01892
01893
01894
01895 for (opno = 0; opno < noutputs; opno++)
01896 if (reg_overlap_mentioned_p (clobbered_reg, output_rtx[opno]))
01897 internal_error ("asm clobber conflict with output operand");
01898
01899 for (opno = 0; opno < ninputs - ninout; opno++)
01900 if (reg_overlap_mentioned_p (clobbered_reg,
01901 ASM_OPERANDS_INPUT (obody, opno)))
01902 internal_error ("asm clobber conflict with input operand");
01903 }
01904
01905 XVECEXP (body, 0, i++)
01906 = gen_rtx_CLOBBER (VOIDmode, clobbered_reg);
01907 }
01908
01909 insn = emit_insn (body);
01910 }
01911
01912
01913
01914 for (i = 0; i < noutputs; ++i)
01915 if (real_output_rtx[i])
01916 emit_move_insn (real_output_rtx[i], output_rtx[i]);
01917
01918 free_temp_slots ();
01919 }
01920
01921
01922
01923
01924 static bool
01925 check_operand_nalternatives (outputs, inputs)
01926 tree outputs, inputs;
01927 {
01928 if (outputs || inputs)
01929 {
01930 tree tmp = TREE_PURPOSE (outputs ? outputs : inputs);
01931 int nalternatives
01932 = n_occurrences (',', TREE_STRING_POINTER (TREE_VALUE (tmp)));
01933 tree next = inputs;
01934
01935 if (nalternatives + 1 > MAX_RECOG_ALTERNATIVES)
01936 {
01937 error ("too many alternatives in `asm'");
01938 return false;
01939 }
01940
01941 tmp = outputs;
01942 while (tmp)
01943 {
01944 const char *constraint
01945 = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tmp)));
01946
01947 if (n_occurrences (',', constraint) != nalternatives)
01948 {
01949 error ("operand constraints for `asm' differ in number of alternatives");
01950 return false;
01951 }
01952
01953 if (TREE_CHAIN (tmp))
01954 tmp = TREE_CHAIN (tmp);
01955 else
01956 tmp = next, next = 0;
01957 }
01958 }
01959
01960 return true;
01961 }
01962
01963
01964
01965
01966
01967
01968 static bool
01969 check_unique_operand_names (outputs, inputs)
01970 tree outputs, inputs;
01971 {
01972 tree i, j;
01973
01974 for (i = outputs; i ; i = TREE_CHAIN (i))
01975 {
01976 tree i_name = TREE_PURPOSE (TREE_PURPOSE (i));
01977 if (! i_name)
01978 continue;
01979
01980 for (j = TREE_CHAIN (i); j ; j = TREE_CHAIN (j))
01981 if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
01982 goto failure;
01983 }
01984
01985 for (i = inputs; i ; i = TREE_CHAIN (i))
01986 {
01987 tree i_name = TREE_PURPOSE (TREE_PURPOSE (i));
01988 if (! i_name)
01989 continue;
01990
01991 for (j = TREE_CHAIN (i); j ; j = TREE_CHAIN (j))
01992 if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
01993 goto failure;
01994 for (j = outputs; j ; j = TREE_CHAIN (j))
01995 if (simple_cst_equal (i_name, TREE_PURPOSE (TREE_PURPOSE (j))))
01996 goto failure;
01997 }
01998
01999 return true;
02000
02001 failure:
02002 error ("duplicate asm operand name '%s'",
02003 TREE_STRING_POINTER (TREE_PURPOSE (TREE_PURPOSE (i))));
02004 return false;
02005 }
02006
02007
02008
02009
02010
02011 static tree
02012 resolve_operand_names (string, outputs, inputs, pconstraints)
02013 tree string;
02014 tree outputs, inputs;
02015 const char **pconstraints;
02016 {
02017 char *buffer = xstrdup (TREE_STRING_POINTER (string));
02018 char *p;
02019 tree t;
02020
02021
02022
02023
02024
02025 p = buffer;
02026 while ((p = strchr (p, '%')) != NULL)
02027 {
02028 if (p[1] == '[')
02029 p += 1;
02030 else if (ISALPHA (p[1]) && p[2] == '[')
02031 p += 2;
02032 else
02033 {
02034 p += 1;
02035 continue;
02036 }
02037
02038 p = resolve_operand_name_1 (p, outputs, inputs);
02039 }
02040
02041 string = build_string (strlen (buffer), buffer);
02042 free (buffer);
02043
02044
02045
02046
02047 for (t = outputs; t ; t = TREE_CHAIN (t), pconstraints++)
02048 *pconstraints = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
02049
02050
02051 for (t = inputs; t ; t = TREE_CHAIN (t), pconstraints++)
02052 {
02053 const char *c = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t)));
02054 if (strchr (c, '[') == NULL)
02055 *pconstraints = c;
02056 else
02057 {
02058 p = buffer = xstrdup (c);
02059 while ((p = strchr (p, '[')) != NULL)
02060 p = resolve_operand_name_1 (p, outputs, inputs);
02061
02062 *pconstraints = ggc_alloc_string (buffer, -1);
02063 free (buffer);
02064 }
02065 }
02066
02067 return string;
02068 }
02069
02070
02071
02072
02073
02074
02075 static char *
02076 resolve_operand_name_1 (p, outputs, inputs)
02077 char *p;
02078 tree outputs, inputs;
02079 {
02080 char *q;
02081 int op;
02082 tree t;
02083 size_t len;
02084
02085
02086 q = strchr (p, ']');
02087 if (!q)
02088 {
02089 error ("missing close brace for named operand");
02090 return strchr (p, '\0');
02091 }
02092 len = q - p - 1;
02093
02094
02095 for (op = 0, t = outputs; t ; t = TREE_CHAIN (t), op++)
02096 {
02097 tree name = TREE_PURPOSE (TREE_PURPOSE (t));
02098 if (name)
02099 {
02100 const char *c = TREE_STRING_POINTER (name);
02101 if (strncmp (c, p + 1, len) == 0 && c[len] == '\0')
02102 goto found;
02103 }
02104 }
02105 for (t = inputs; t ; t = TREE_CHAIN (t), op++)
02106 {
02107 tree name = TREE_PURPOSE (TREE_PURPOSE (t));
02108 if (name)
02109 {
02110 const char *c = TREE_STRING_POINTER (name);
02111 if (strncmp (c, p + 1, len) == 0 && c[len] == '\0')
02112 goto found;
02113 }
02114 }
02115
02116 *q = '\0';
02117 error ("undefined named operand '%s'", p + 1);
02118 op = 0;
02119 found:
02120
02121
02122
02123
02124 sprintf (p, "%d", op);
02125 p = strchr (p, '\0');
02126
02127
02128 if (p > q)
02129 abort ();
02130
02131
02132 memmove (p, q + 1, strlen (q + 1) + 1);
02133
02134 return p;
02135 }
02136
02137
02138
02139
02140
02141
02142 void
02143 expand_expr_stmt (exp)
02144 tree exp;
02145 {
02146 expand_expr_stmt_value (exp, -1, 1);
02147 }
02148
02149
02150
02151
02152
02153
02154 void
02155 expand_expr_stmt_value (exp, want_value, maybe_last)
02156 tree exp;
02157 int want_value, maybe_last;
02158 {
02159 rtx value;
02160 tree type;
02161
02162 if (want_value == -1)
02163 want_value = expr_stmts_for_value != 0;
02164
02165
02166
02167
02168 if (! want_value
02169 && (expr_stmts_for_value == 0 || ! maybe_last)
02170 && exp != error_mark_node)
02171 {
02172 if (! TREE_SIDE_EFFECTS (exp))
02173 {
02174 if ((extra_warnings || warn_unused_value)
02175 && !(TREE_CODE (exp) == CONVERT_EXPR
02176 && VOID_TYPE_P (TREE_TYPE (exp))))
02177 warning_with_file_and_line (emit_filename, emit_lineno,
02178 "statement with no effect");
02179 }
02180 else if (warn_unused_value)
02181 warn_if_unused_value (exp);
02182 }
02183
02184
02185
02186 if (want_value && TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE)
02187 exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);
02188
02189
02190
02191
02192 value = expand_expr (exp, want_value ? NULL_RTX : const0_rtx,
02193 VOIDmode, 0);
02194 type = TREE_TYPE (exp);
02195
02196
02197
02198 if (value && GET_CODE (value) == MEM && TREE_THIS_VOLATILE (exp))
02199 {
02200 if (TYPE_MODE (type) == VOIDmode)
02201 ;
02202 else if (TYPE_MODE (type) != BLKmode)
02203 value = copy_to_reg (value);
02204 else
02205 {
02206 rtx lab = gen_label_rtx ();
02207
02208
02209 emit_cmp_and_jump_insns (value, value, EQ,
02210 expand_expr (TYPE_SIZE (type),
02211 NULL_RTX, VOIDmode, 0),
02212 BLKmode, 0, lab);
02213 emit_label (lab);
02214 }
02215 }
02216
02217
02218
02219 preserve_temp_slots (value);
02220
02221
02222
02223
02224 free_temp_slots ();
02225
02226 if (want_value)
02227 {
02228 last_expr_value = value;
02229 last_expr_type = type;
02230 }
02231
02232 emit_queue ();
02233 }
02234
02235
02236
02237
02238 int
02239 warn_if_unused_value (exp)
02240 tree exp;
02241 {
02242 if (TREE_USED (exp))
02243 return 0;
02244
02245
02246
02247
02248 if (VOID_TYPE_P (TREE_TYPE (exp)))
02249 return 0;
02250
02251 switch (TREE_CODE (exp))
02252 {
02253 case PREINCREMENT_EXPR:
02254 case POSTINCREMENT_EXPR:
02255 case PREDECREMENT_EXPR:
02256 case POSTDECREMENT_EXPR:
02257 case MODIFY_EXPR:
02258 case INIT_EXPR:
02259 case TARGET_EXPR:
02260 case CALL_EXPR:
02261 case METHOD_CALL_EXPR:
02262 case RTL_EXPR:
02263 case TRY_CATCH_EXPR:
02264 case WITH_CLEANUP_EXPR:
02265 case EXIT_EXPR:
02266 return 0;
02267
02268 case BIND_EXPR:
02269
02270 return warn_if_unused_value (TREE_OPERAND (exp, 1));
02271
02272 case SAVE_EXPR:
02273 return warn_if_unused_value (TREE_OPERAND (exp, 1));
02274
02275 case TRUTH_ORIF_EXPR:
02276 case TRUTH_ANDIF_EXPR:
02277
02278 return warn_if_unused_value (TREE_OPERAND (exp, 1));
02279
02280 case COMPOUND_EXPR:
02281 if (TREE_NO_UNUSED_WARNING (exp))
02282 return 0;
02283 if (warn_if_unused_value (TREE_OPERAND (exp, 0)))
02284 return 1;
02285
02286 if (TREE_CONSTANT (TREE_OPERAND (exp, 1)))
02287 return 0;
02288 return warn_if_unused_value (TREE_OPERAND (exp, 1));
02289
02290 case NOP_EXPR:
02291 case CONVERT_EXPR:
02292 case NON_LVALUE_EXPR:
02293
02294 if (TREE_NO_UNUSED_WARNING (exp))
02295 return 0;
02296
02297
02298
02299
02300 {
02301 tree tem = TREE_OPERAND (exp, 0);
02302
02303 while (TREE_CODE (tem) == CONVERT_EXPR || TREE_CODE (tem) == NOP_EXPR)
02304 tem = TREE_OPERAND (tem, 0);
02305
02306 if (TREE_CODE (tem) == MODIFY_EXPR || TREE_CODE (tem) == INIT_EXPR
02307 || TREE_CODE (tem) == CALL_EXPR)
02308 return 0;
02309 }
02310 goto maybe_warn;
02311
02312 case INDIRECT_REF:
02313
02314
02315 if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE)
02316 return warn_if_unused_value (TREE_OPERAND (exp, 0));
02317
02318
02319 default:
02320
02321 if ((DECL_P (exp)
02322 || TREE_CODE_CLASS (TREE_CODE (exp)) == 'r')
02323 && TREE_THIS_VOLATILE (exp))
02324 return 0;
02325
02326
02327
02328
02329 if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'e'
02330 && TREE_CODE_LENGTH (TREE_CODE (exp)) == 0)
02331 return 0;
02332
02333 maybe_warn:
02334
02335 if (TREE_SIDE_EFFECTS (exp))
02336 return 0;
02337
02338 warning_with_file_and_line (emit_filename, emit_lineno,
02339 "value computed is not used");
02340 return 1;
02341 }
02342 }
02343
02344
02345
02346 void
02347 clear_last_expr ()
02348 {
02349 last_expr_type = NULL_TREE;
02350 last_expr_value = NULL_RTX;
02351 }
02352
02353
02354
02355
02356
02357
02358
02359
02360 tree
02361 expand_start_stmt_expr (has_scope)
02362 int has_scope;
02363 {
02364 tree t;
02365
02366
02367
02368 t = make_node (RTL_EXPR);
02369 do_pending_stack_adjust ();
02370 if (has_scope)
02371 start_sequence_for_rtl_expr (t);
02372 else
02373 start_sequence ();
02374 NO_DEFER_POP;
02375 expr_stmts_for_value++;
02376 return t;
02377 }
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391 tree
02392 expand_end_stmt_expr (t)
02393 tree t;
02394 {
02395 OK_DEFER_POP;
02396
02397 if (! last_expr_value || ! last_expr_type)
02398 {
02399 last_expr_value = const0_rtx;
02400 last_expr_type = void_type_node;
02401 }
02402 else if (GET_CODE (last_expr_value) != REG && ! CONSTANT_P (last_expr_value))
02403
02404 last_expr_value = protect_from_queue (last_expr_value, 0);
02405
02406 emit_queue ();
02407
02408 TREE_TYPE (t) = last_expr_type;
02409 RTL_EXPR_RTL (t) = last_expr_value;
02410 RTL_EXPR_SEQUENCE (t) = get_insns ();
02411
02412 rtl_expr_chain = tree_cons (NULL_TREE, t, rtl_expr_chain);
02413
02414 end_sequence ();
02415
02416
02417 TREE_SIDE_EFFECTS (t) = 1;
02418
02419 TREE_THIS_VOLATILE (t) = volatile_refs_p (last_expr_value);
02420
02421 clear_last_expr ();
02422 expr_stmts_for_value--;
02423
02424 return t;
02425 }
02426
02427
02428
02429
02430
02431
02432
02433 void
02434 expand_start_cond (cond, exitflag)
02435 tree cond;
02436 int exitflag;
02437 {
02438 struct nesting *thiscond = ALLOC_NESTING ();
02439
02440
02441
02442 thiscond->desc = COND_NESTING;
02443 thiscond->next = cond_stack;
02444 thiscond->all = nesting_stack;
02445 thiscond->depth = ++nesting_depth;
02446 thiscond->data.cond.next_label = gen_label_rtx ();
02447
02448
02449
02450 thiscond->exit_label = exitflag ? gen_label_rtx () : 0;
02451 thiscond->data.cond.endif_label = thiscond->exit_label;
02452 cond_stack = thiscond;
02453 nesting_stack = thiscond;
02454
02455 do_jump (cond, thiscond->data.cond.next_label, NULL_RTX);
02456 }
02457
02458
02459
02460
02461 void
02462 expand_start_elseif (cond)
02463 tree cond;
02464 {
02465 if (cond_stack->data.cond.endif_label == 0)
02466 cond_stack->data.cond.endif_label = gen_label_rtx ();
02467 emit_jump (cond_stack->data.cond.endif_label);
02468 emit_label (cond_stack->data.cond.next_label);
02469 cond_stack->data.cond.next_label = gen_label_rtx ();
02470 do_jump (cond, cond_stack->data.cond.next_label, NULL_RTX);
02471 }
02472
02473
02474
02475
02476 void
02477 expand_start_else ()
02478 {
02479 if (cond_stack->data.cond.endif_label == 0)
02480 cond_stack->data.cond.endif_label = gen_label_rtx ();
02481
02482 emit_jump (cond_stack->data.cond.endif_label);
02483 emit_label (cond_stack->data.cond.next_label);
02484 cond_stack->data.cond.next_label = 0;
02485 }
02486
02487
02488
02489
02490 void
02491 expand_elseif (cond)
02492 tree cond;
02493 {
02494 cond_stack->data.cond.next_label = gen_label_rtx ();
02495 do_jump (cond, cond_stack->data.cond.next_label, NULL_RTX);
02496 }
02497
02498
02499
02500
02501 void
02502 expand_end_cond ()
02503 {
02504 struct nesting *thiscond = cond_stack;
02505
02506 do_pending_stack_adjust ();
02507 if (thiscond->data.cond.next_label)
02508 emit_label (thiscond->data.cond.next_label);
02509 if (thiscond->data.cond.endif_label)
02510 emit_label (thiscond->data.cond.endif_label);
02511
02512 POPSTACK (cond_stack);
02513 clear_last_expr ();
02514 }
02515
02516
02517
02518
02519
02520
02521
02522
02523 struct nesting *
02524 expand_start_loop (exit_flag)
02525 int exit_flag;
02526 {
02527 struct nesting *thisloop = ALLOC_NESTING ();
02528
02529
02530
02531 thisloop->desc = LOOP_NESTING;
02532 thisloop->next = loop_stack;
02533 thisloop->all = nesting_stack;
02534 thisloop->depth = ++nesting_depth;
02535 thisloop->data.loop.start_label = gen_label_rtx ();
02536 thisloop->data.loop.end_label = gen_label_rtx ();
02537 thisloop->data.loop.alt_end_label = 0;
02538 thisloop->data.loop.continue_label = thisloop->data.loop.start_label;
02539 thisloop->exit_label = exit_flag ? thisloop->data.loop.end_label : 0;
02540 loop_stack = thisloop;
02541 nesting_stack = thisloop;
02542
02543 do_pending_stack_adjust ();
02544 emit_queue ();
02545 emit_note (NULL, NOTE_INSN_LOOP_BEG);
02546 emit_label (thisloop->data.loop.start_label);
02547
02548 return thisloop;
02549 }
02550
02551
02552
02553
02554 struct nesting *
02555 expand_start_loop_continue_elsewhere (exit_flag)
02556 int exit_flag;
02557 {
02558 struct nesting *thisloop = expand_start_loop (exit_flag);
02559 loop_stack->data.loop.continue_label = gen_label_rtx ();
02560 return thisloop;
02561 }
02562
02563
02564
02565
02566 struct nesting *
02567 expand_start_null_loop ()
02568 {
02569 struct nesting *thisloop = ALLOC_NESTING ();
02570
02571
02572
02573 thisloop->desc = LOOP_NESTING;
02574 thisloop->next = loop_stack;
02575 thisloop->all = nesting_stack;
02576 thisloop->depth = ++nesting_depth;
02577 thisloop->data.loop.start_label = emit_note (NULL, NOTE_INSN_DELETED);
02578 thisloop->data.loop.end_label = gen_label_rtx ();
02579 thisloop->data.loop.alt_end_label = NULL_RTX;
02580 thisloop->data.loop.continue_label = thisloop->data.loop.end_label;
02581 thisloop->exit_label = thisloop->data.loop.end_label;
02582 loop_stack = thisloop;
02583 nesting_stack = thisloop;
02584
02585 return thisloop;
02586 }
02587
02588
02589
02590
02591
02592
02593 void
02594 expand_loop_continue_here ()
02595 {
02596 do_pending_stack_adjust ();
02597 emit_note (NULL, NOTE_INSN_LOOP_CONT);
02598 emit_label (loop_stack->data.loop.continue_label);
02599 }
02600
02601
02602
02603
02604 void
02605 expand_end_loop ()
02606 {
02607 rtx start_label = loop_stack->data.loop.start_label;
02608 rtx etc_note;
02609 int eh_regions, debug_blocks;
02610
02611
02612 if (start_label == loop_stack->data.loop.continue_label)
02613 emit_note_before (NOTE_INSN_LOOP_CONT, start_label);
02614
02615 do_pending_stack_adjust ();
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653 eh_regions = debug_blocks = 0;
02654 for (etc_note = start_label; etc_note ; etc_note = NEXT_INSN (etc_note))
02655 if (GET_CODE (etc_note) == NOTE)
02656 {
02657 if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_LOOP_END_TOP_COND)
02658 break;
02659
02660
02661 else if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_LOOP_BEG)
02662 {
02663 etc_note = NULL_RTX;
02664 break;
02665 }
02666
02667
02668
02669 else if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_EH_REGION_BEG)
02670 eh_regions++;
02671 else if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_EH_REGION_END)
02672 {
02673 if (--eh_regions < 0)
02674
02675
02676
02677
02678
02679
02680
02681 abort ();
02682 }
02683
02684
02685
02686
02687
02688 else if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_BLOCK_BEG)
02689 debug_blocks++;
02690 else if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_BLOCK_END)
02691 debug_blocks--;
02692 }
02693
02694 if (etc_note
02695 && optimize
02696 && eh_regions == 0
02697 && (debug_blocks == 0 || optimize >= 2)
02698 && NEXT_INSN (etc_note) != NULL_RTX
02699 && ! any_condjump_p (get_last_insn ()))
02700 {
02701
02702
02703 rtx top_label = gen_label_rtx ();
02704 rtx start_move = start_label;
02705
02706
02707
02708 if (GET_CODE (PREV_INSN (start_move)) == NOTE
02709 && NOTE_LINE_NUMBER (PREV_INSN (start_move)) == NOTE_INSN_LOOP_CONT)
02710 start_move = PREV_INSN (start_move);
02711
02712 emit_label_before (top_label, start_move);
02713
02714
02715
02716
02717 if (debug_blocks == 0)
02718 reorder_insns (start_move, etc_note, get_last_insn ());
02719 else
02720 {
02721 rtx insn, next_insn;
02722 for (insn = start_move; insn; insn = next_insn)
02723 {
02724
02725
02726 next_insn = (insn == etc_note ? NULL : NEXT_INSN (insn));
02727
02728 if (GET_CODE (insn) == NOTE
02729 && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
02730 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END))
02731 continue;
02732
02733 reorder_insns (insn, insn, get_last_insn ());
02734 }
02735 }
02736
02737
02738 emit_jump_insn_before (gen_jump (start_label), top_label);
02739 emit_barrier_before (top_label);
02740 start_label = top_label;
02741 }
02742
02743 emit_jump (start_label);
02744 emit_note (NULL, NOTE_INSN_LOOP_END);
02745 emit_label (loop_stack->data.loop.end_label);
02746
02747 POPSTACK (loop_stack);
02748
02749 clear_last_expr ();
02750 }
02751
02752
02753
02754 void
02755 expand_end_null_loop ()
02756 {
02757 do_pending_stack_adjust ();
02758 emit_label (loop_stack->data.loop.end_label);
02759
02760 POPSTACK (loop_stack);
02761
02762 clear_last_expr ();
02763 }
02764
02765
02766
02767
02768
02769
02770 int
02771 expand_continue_loop (whichloop)
02772 struct nesting *whichloop;
02773 {
02774
02775 rtx note;
02776
02777 if (flag_guess_branch_prob)
02778 {
02779 note = emit_note (NULL, NOTE_INSN_PREDICTION);
02780 NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_CONTINUE, IS_TAKEN);
02781 }
02782 clear_last_expr ();
02783 if (whichloop == 0)
02784 whichloop = loop_stack;
02785 if (whichloop == 0)
02786 return 0;
02787 expand_goto_internal (NULL_TREE, whichloop->data.loop.continue_label,
02788 NULL_RTX);
02789 return 1;
02790 }
02791
02792
02793
02794
02795 int
02796 expand_exit_loop (whichloop)
02797 struct nesting *whichloop;
02798 {
02799 clear_last_expr ();
02800 if (whichloop == 0)
02801 whichloop = loop_stack;
02802 if (whichloop == 0)
02803 return 0;
02804 expand_goto_internal (NULL_TREE, whichloop->data.loop.end_label, NULL_RTX);
02805 return 1;
02806 }
02807
02808
02809
02810
02811
02812 int
02813 expand_exit_loop_if_false (whichloop, cond)
02814 struct nesting *whichloop;
02815 tree cond;
02816 {
02817 rtx label = gen_label_rtx ();
02818 rtx last_insn;
02819 clear_last_expr ();
02820
02821 if (whichloop == 0)
02822 whichloop = loop_stack;
02823 if (whichloop == 0)
02824 return 0;
02825
02826
02827
02828
02829 do_jump (cond, NULL_RTX, label);
02830 last_insn = get_last_insn ();
02831 if (GET_CODE (last_insn) == CODE_LABEL)
02832 whichloop->data.loop.alt_end_label = last_insn;
02833 expand_goto_internal (NULL_TREE, whichloop->data.loop.end_label,
02834 NULL_RTX);
02835 emit_label (label);
02836
02837 return 1;
02838 }
02839
02840
02841
02842
02843
02844 int
02845 expand_exit_loop_top_cond (whichloop, cond)
02846 struct nesting *whichloop;
02847 tree cond;
02848 {
02849 if (! expand_exit_loop_if_false (whichloop, cond))
02850 return 0;
02851
02852 emit_note (NULL, NOTE_INSN_LOOP_END_TOP_COND);
02853 return 1;
02854 }
02855
02856
02857
02858 int
02859 stmt_loop_nest_empty ()
02860 {
02861
02862
02863
02864 return (cfun->stmt == NULL || loop_stack == NULL);
02865 }
02866
02867
02868
02869
02870
02871
02872
02873
02874 int
02875 preserve_subexpressions_p ()
02876 {
02877 rtx insn;
02878
02879 if (flag_expensive_optimizations)
02880 return 1;
02881
02882 if (optimize == 0 || cfun == 0 || cfun->stmt == 0 || loop_stack == 0)
02883 return 0;
02884
02885 insn = get_last_insn_anywhere ();
02886
02887 return (insn
02888 && (INSN_UID (insn) - INSN_UID (loop_stack->data.loop.start_label)
02889 < n_non_fixed_regs * 3));
02890
02891 }
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902 int
02903 expand_exit_something ()
02904 {
02905 struct nesting *n;
02906 clear_last_expr ();
02907 for (n = nesting_stack; n; n = n->all)
02908 if (n->exit_label != 0)
02909 {
02910 expand_goto_internal (NULL_TREE, n->exit_label, NULL_RTX);
02911 return 1;
02912 }
02913
02914 return 0;
02915 }
02916
02917
02918
02919
02920 void
02921 expand_null_return ()
02922 {
02923 rtx last_insn;
02924
02925 last_insn = get_last_insn ();
02926
02927
02928
02929
02930 clobber_return_register ();
02931
02932 expand_null_return_1 (last_insn);
02933 }
02934
02935
02936 static enum br_predictor
02937 return_prediction (val)
02938 rtx val;
02939 {
02940
02941 if (POINTER_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
02942 {
02943
02944 if (val == const0_rtx)
02945 return PRED_NULL_RETURN;
02946 }
02947 else
02948 {
02949
02950
02951 if (GET_CODE (val) == CONST_INT
02952 && INTVAL (val) < 0)
02953 return PRED_NEGATIVE_RETURN;
02954
02955
02956
02957 if (CONSTANT_P (val)
02958 && (val != const0_rtx && val != const1_rtx))
02959 return PRED_CONST_RETURN;
02960 }
02961 return PRED_NO_PREDICTION;
02962 }
02963
02964
02965
02966 static void
02967 expand_value_return (val)
02968 rtx val;
02969 {
02970 rtx last_insn;
02971 rtx return_reg;
02972 enum br_predictor pred;
02973
02974 if (flag_guess_branch_prob
02975 && (pred = return_prediction (val)) != PRED_NO_PREDICTION)
02976 {
02977
02978 rtx note;
02979
02980 note = emit_note (NULL, NOTE_INSN_PREDICTION);
02981
02982 NOTE_PREDICTION (note) = NOTE_PREDICT (pred, NOT_TAKEN);
02983
02984 }
02985
02986 last_insn = get_last_insn ();
02987 return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
02988
02989
02990
02991
02992 if (return_reg != val)
02993 {
02994 tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
02995 #ifdef PROMOTE_FUNCTION_RETURN
02996 int unsignedp = TREE_UNSIGNED (type);
02997 enum machine_mode old_mode
02998 = DECL_MODE (DECL_RESULT (current_function_decl));
02999 enum machine_mode mode
03000 = promote_mode (type, old_mode, &unsignedp, 1);
03001
03002 if (mode != old_mode)
03003 val = convert_modes (mode, old_mode, val, unsignedp);
03004 #endif
03005 if (GET_CODE (return_reg) == PARALLEL)
03006 emit_group_load (return_reg, val, int_size_in_bytes (type));
03007 else
03008 emit_move_insn (return_reg, val);
03009 }
03010
03011 expand_null_return_1 (last_insn);
03012 }
03013
03014
03015
03016
03017 static void
03018 expand_null_return_1 (last_insn)
03019 rtx last_insn;
03020 {
03021 rtx end_label = cleanup_label ? cleanup_label : return_label;
03022
03023 clear_pending_stack_adjust ();
03024 do_pending_stack_adjust ();
03025 clear_last_expr ();
03026
03027 if (end_label == 0)
03028 end_label = return_label = gen_label_rtx ();
03029 expand_goto_internal (NULL_TREE, end_label, last_insn);
03030 }
03031
03032
03033
03034
03035 void
03036 expand_return (retval)
03037 tree retval;
03038 {
03039
03040
03041
03042
03043
03044
03045
03046
03047 rtx last_insn = 0;
03048 rtx result_rtl;
03049 rtx val = 0;
03050 tree retval_rhs;
03051
03052
03053 if (TREE_CODE (TREE_TYPE (TREE_TYPE (current_function_decl))) == VOID_TYPE)
03054 {
03055 expand_expr (retval, NULL_RTX, VOIDmode, 0);
03056 emit_queue ();
03057 expand_null_return ();
03058 return;
03059 }
03060
03061 if (retval == error_mark_node)
03062 {
03063
03064
03065 expand_null_return ();
03066 return;
03067 }
03068 else if (TREE_CODE (retval) == RESULT_DECL)
03069 retval_rhs = retval;
03070 else if ((TREE_CODE (retval) == MODIFY_EXPR || TREE_CODE (retval) == INIT_EXPR)
03071 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
03072 retval_rhs = TREE_OPERAND (retval, 1);
03073 else if (VOID_TYPE_P (TREE_TYPE (retval)))
03074
03075 retval_rhs = retval;
03076 else
03077 retval_rhs = NULL_TREE;
03078
03079 last_insn = get_last_insn ();
03080
03081 #ifndef SGI_MONGOOSE
03082
03083
03084
03085
03086
03087
03088 if (optimize && retval_rhs != 0
03089 && frame_offset == 0
03090 && TREE_CODE (retval_rhs) == COND_EXPR
03091 && (TREE_CODE (TREE_OPERAND (retval_rhs, 1)) == CALL_EXPR
03092 || TREE_CODE (TREE_OPERAND (retval_rhs, 2)) == CALL_EXPR))
03093 {
03094 rtx label = gen_label_rtx ();
03095 tree expr;
03096
03097 do_jump (TREE_OPERAND (retval_rhs, 0), label, NULL_RTX);
03098 start_cleanup_deferral ();
03099 expr = build (MODIFY_EXPR, TREE_TYPE (TREE_TYPE (current_function_decl)),
03100 DECL_RESULT (current_function_decl),
03101 TREE_OPERAND (retval_rhs, 1));
03102 TREE_SIDE_EFFECTS (expr) = 1;
03103 expand_return (expr);
03104 emit_label (label);
03105
03106 expr = build (MODIFY_EXPR, TREE_TYPE (TREE_TYPE (current_function_decl)),
03107 DECL_RESULT (current_function_decl),
03108 TREE_OPERAND (retval_rhs, 2));
03109 TREE_SIDE_EFFECTS (expr) = 1;
03110 expand_return (expr);
03111 end_cleanup_deferral ();
03112 return;
03113 }
03114 #endif
03115
03116 result_rtl = DECL_RTL (DECL_RESULT (current_function_decl));
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126 if (retval_rhs != 0
03127 && TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode
03128 && GET_CODE (result_rtl) == REG)
03129 {
03130 int i;
03131 unsigned HOST_WIDE_INT bitpos, xbitpos;
03132 unsigned HOST_WIDE_INT big_endian_correction = 0;
03133 unsigned HOST_WIDE_INT bytes
03134 = int_size_in_bytes (TREE_TYPE (retval_rhs));
03135 int n_regs = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
03136 unsigned int bitsize
03137 = MIN (TYPE_ALIGN (TREE_TYPE (retval_rhs)), BITS_PER_WORD);
03138 rtx *result_pseudos = (rtx *) alloca (sizeof (rtx) * n_regs);
03139 rtx result_reg, src = NULL_RTX, dst = NULL_RTX;
03140 rtx result_val = expand_expr (retval_rhs, NULL_RTX, VOIDmode, 0);
03141 enum machine_mode tmpmode, result_reg_mode;
03142
03143 if (bytes == 0)
03144 {
03145 expand_null_return ();
03146 return;
03147 }
03148
03149
03150
03151
03152
03153 if (BYTES_BIG_ENDIAN
03154 && bytes % UNITS_PER_WORD)
03155 big_endian_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD)
03156 * BITS_PER_UNIT));
03157
03158
03159 for (bitpos = 0, xbitpos = big_endian_correction;
03160 bitpos < bytes * BITS_PER_UNIT;
03161 bitpos += bitsize, xbitpos += bitsize)
03162 {
03163
03164
03165
03166 if (xbitpos % BITS_PER_WORD == 0
03167 || xbitpos == big_endian_correction)
03168 {
03169
03170 dst = gen_reg_rtx (word_mode);
03171 result_pseudos[xbitpos / BITS_PER_WORD] = dst;
03172
03173
03174 emit_move_insn (dst, CONST0_RTX (GET_MODE (dst)));
03175 }
03176
03177
03178
03179 if (bitpos % BITS_PER_WORD == 0)
03180 src = operand_subword_force (result_val,
03181 bitpos / BITS_PER_WORD,
03182 BLKmode);
03183
03184
03185
03186 store_bit_field (dst, bitsize, xbitpos % BITS_PER_WORD, word_mode,
03187 extract_bit_field (src, bitsize,
03188 bitpos % BITS_PER_WORD, 1,
03189 NULL_RTX, word_mode, word_mode,
03190 BITS_PER_WORD),
03191 BITS_PER_WORD);
03192 }
03193
03194
03195
03196
03197 for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
03198 tmpmode != VOIDmode;
03199 tmpmode = GET_MODE_WIDER_MODE (tmpmode))
03200
03201 if (GET_MODE_SIZE (tmpmode) >= bytes)
03202 break;
03203
03204
03205 if (tmpmode == VOIDmode)
03206 abort ();
03207
03208 PUT_MODE (result_rtl, tmpmode);
03209
03210 if (GET_MODE_SIZE (tmpmode) < GET_MODE_SIZE (word_mode))
03211 result_reg_mode = word_mode;
03212 else
03213 result_reg_mode = tmpmode;
03214 result_reg = gen_reg_rtx (result_reg_mode);
03215
03216 emit_queue ();
03217 for (i = 0; i < n_regs; i++)
03218 emit_move_insn (operand_subword (result_reg, i, 0, result_reg_mode),
03219 result_pseudos[i]);
03220
03221 if (tmpmode != result_reg_mode)
03222 result_reg = gen_lowpart (tmpmode, result_reg);
03223
03224 expand_value_return (result_reg);
03225 }
03226 else if (retval_rhs != 0
03227 && !VOID_TYPE_P (TREE_TYPE (retval_rhs))
03228 && (GET_CODE (result_rtl) == REG
03229 || (GET_CODE (result_rtl) == PARALLEL)))
03230 {
03231
03232
03233 tree ot = TREE_TYPE (DECL_RESULT (current_function_decl));
03234 tree nt = build_qualified_type (ot, TYPE_QUALS (ot) | TYPE_QUAL_CONST);
03235
03236 val = assign_temp (nt, 0, 0, 1);
03237 val = expand_expr (retval_rhs, val, GET_MODE (val), 0);
03238 val = force_not_mem (val);
03239 emit_queue ();
03240
03241 expand_value_return (val);
03242 }
03243 else
03244 {
03245
03246
03247 expand_expr (retval, const0_rtx, VOIDmode, 0);
03248 emit_queue ();
03249 expand_value_return (result_rtl);
03250 }
03251 }
03252
03253
03254
03255
03256 int
03257 drop_through_at_end_p ()
03258 {
03259 rtx insn = get_last_insn ();
03260 while (insn && GET_CODE (insn) == NOTE)
03261 insn = PREV_INSN (insn);
03262 return insn && GET_CODE (insn) != BARRIER;
03263 }
03264
03265
03266
03267
03268
03269
03270
03271 int
03272 optimize_tail_recursion (arguments, last_insn)
03273 tree arguments;
03274 rtx last_insn;
03275 {
03276
03277
03278 if (tail_recursion_args (arguments, DECL_ARGUMENTS (current_function_decl)))
03279 {
03280 if (tail_recursion_label == 0)
03281 {
03282 tail_recursion_label = gen_label_rtx ();
03283 emit_label_after (tail_recursion_label,
03284 tail_recursion_reentry);
03285 }
03286 emit_queue ();
03287 expand_goto_internal (NULL_TREE, tail_recursion_label, last_insn);
03288 emit_barrier ();
03289 return 1;
03290 }
03291 return 0;
03292 }
03293
03294
03295
03296
03297
03298
03299
03300 static int
03301 tail_recursion_args (actuals, formals)
03302 tree actuals, formals;
03303 {
03304 tree a = actuals, f = formals;
03305 int i;
03306 rtx *argvec;
03307
03308
03309
03310
03311
03312
03313
03314
03315 for (a = actuals, f = formals, i = 0; a && f; a = TREE_CHAIN (a), f = TREE_CHAIN (f), i++)
03316 {
03317 if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (a)))
03318 != TYPE_MAIN_VARIANT (TREE_TYPE (f)))
03319 return 0;
03320 if (GET_CODE (DECL_RTL (f)) != REG || DECL_MODE (f) == BLKmode)
03321 return 0;
03322 }
03323 if (a != 0 || f != 0)
03324 return 0;
03325
03326
03327
03328 argvec = (rtx *) alloca (i * sizeof (rtx));
03329
03330 for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++)
03331 argvec[i] = expand_expr (TREE_VALUE (a), NULL_RTX, VOIDmode, 0);
03332
03333
03334
03335
03336 for (a = actuals, i = 0; a; a = TREE_CHAIN (a), i++)
03337 {
03338 int copy = 0;
03339 int j;
03340 for (f = formals, j = 0; j < i; f = TREE_CHAIN (f), j++)
03341 if (reg_mentioned_p (DECL_RTL (f), argvec[i]))
03342 {
03343 copy = 1;
03344 break;
03345 }
03346 if (copy)
03347 argvec[i] = copy_to_reg (argvec[i]);
03348 }
03349
03350
03351
03352 for (f = formals, a = actuals, i = 0; f;
03353 f = TREE_CHAIN (f), a = TREE_CHAIN (a), i++)
03354 {
03355 if (GET_MODE (DECL_RTL (f)) == GET_MODE (argvec[i]))
03356 emit_move_insn (DECL_RTL (f), argvec[i]);
03357 else
03358 {
03359 rtx tmp = argvec[i];
03360 int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_VALUE (a)));
03361 promote_mode(TREE_TYPE (TREE_VALUE (a)), GET_MODE (tmp),
03362 &unsignedp, 0);
03363 if (DECL_MODE (f) != GET_MODE (DECL_RTL (f)))
03364 {
03365 tmp = gen_reg_rtx (DECL_MODE (f));
03366 convert_move (tmp, argvec[i], unsignedp);
03367 }
03368 convert_move (DECL_RTL (f), tmp, unsignedp);
03369 }
03370 }
03371
03372 free_temp_slots ();
03373 return 1;
03374 }
03375
03376
03377
03378
03379
03380
03381
03382
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396 void
03397 expand_start_bindings_and_block (flags, block)
03398 int flags;
03399 tree block;
03400 {
03401 struct nesting *thisblock = ALLOC_NESTING ();
03402 rtx note;
03403 int exit_flag = ((flags & 1) != 0);
03404 int block_flag = ((flags & 2) == 0);
03405
03406
03407
03408 if (!block_flag && block)
03409 abort ();
03410
03411
03412 if (block_flag)
03413 {
03414 note = emit_note (NULL, NOTE_INSN_BLOCK_BEG);
03415 NOTE_BLOCK (note) = block;
03416 }
03417 else
03418 note = emit_note (NULL, NOTE_INSN_DELETED);
03419
03420
03421
03422 thisblock->desc = BLOCK_NESTING;
03423 thisblock->next = block_stack;
03424 thisblock->all = nesting_stack;
03425 thisblock->depth = ++nesting_depth;
03426 thisblock->data.block.stack_level = 0;
03427 thisblock->data.block.cleanups = 0;
03428 thisblock->data.block.n_function_calls = 0;
03429 thisblock->data.block.exception_region = 0;
03430 thisblock->data.block.block_target_temp_slot_level = target_temp_slot_level;
03431
03432 thisblock->data.block.conditional_code = 0;
03433 thisblock->data.block.last_unconditional_cleanup = note;
03434
03435
03436
03437
03438
03439
03440 emit_note (NULL, NOTE_INSN_DELETED);
03441
03442 if (block_stack
03443 && !(block_stack->data.block.cleanups == NULL_TREE
03444 && block_stack->data.block.outer_cleanups == NULL_TREE))
03445 thisblock->data.block.outer_cleanups
03446 = tree_cons (NULL_TREE, block_stack->data.block.cleanups,
03447 block_stack->data.block.outer_cleanups);
03448 else
03449 thisblock->data.block.outer_cleanups = 0;
03450 thisblock->data.block.label_chain = 0;
03451 thisblock->data.block.innermost_stack_block = stack_block_stack;
03452 thisblock->data.block.first_insn = note;
03453 thisblock->data.block.block_start_count = ++current_block_start_count;
03454 thisblock->exit_label = exit_flag ? gen_label_rtx () : 0;
03455 block_stack = thisblock;
03456 nesting_stack = thisblock;
03457
03458
03459 push_temp_slots ();
03460 }
03461
03462
03463
03464
03465
03466
03467
03468 void
03469 expand_start_target_temps ()
03470 {
03471
03472
03473 push_temp_slots ();
03474
03475
03476
03477 expand_start_bindings (2);
03478
03479 target_temp_slot_level = temp_slot_level;
03480 }
03481
03482 void
03483 expand_end_target_temps ()
03484 {
03485 expand_end_bindings (NULL_TREE, 0, 0);
03486
03487
03488
03489 pop_temp_slots ();
03490 }
03491
03492
03493
03494
03495
03496
03497
03498
03499
03500
03501
03502 int
03503 is_body_block (stmt)
03504 tree stmt;
03505 {
03506 if (TREE_CODE (stmt) == BLOCK)
03507 {
03508 tree parent = BLOCK_SUPERCONTEXT (stmt);
03509
03510 if (parent && TREE_CODE (parent) == BLOCK)
03511 {
03512 tree grandparent = BLOCK_SUPERCONTEXT (parent);
03513
03514 if (grandparent && TREE_CODE (grandparent) == FUNCTION_DECL)
03515 return 1;
03516 }
03517 }
03518
03519 return 0;
03520 }
03521
03522
03523
03524
03525
03526 int
03527 conditional_context ()
03528 {
03529 return block_stack && block_stack->data.block.conditional_code;
03530 }
03531
03532
03533
03534
03535 struct nesting *
03536 current_nesting_level ()
03537 {
03538 return cfun ? block_stack : 0;
03539 }
03540
03541
03542
03543
03544 static rtx
03545 expand_nl_handler_label (slot, before_insn)
03546 rtx slot, before_insn;
03547 {
03548 rtx insns;
03549 rtx handler_label = gen_label_rtx ();
03550
03551
03552 LABEL_PRESERVE_P (handler_label) = 1;
03553
03554 start_sequence ();
03555 emit_move_insn (slot, gen_rtx_LABEL_REF (Pmode, handler_label));
03556 insns = get_insns ();
03557 end_sequence ();
03558 emit_insn_before (insns, before_insn);
03559
03560 emit_label (handler_label);
03561
03562 return handler_label;
03563 }
03564
03565
03566
03567 static void
03568 expand_nl_goto_receiver ()
03569 {
03570 #ifdef HAVE_nonlocal_goto
03571 if (! HAVE_nonlocal_goto)
03572 #endif
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584 emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx);
03585
03586 #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
03587 if (fixed_regs[ARG_POINTER_REGNUM])
03588 {
03589 #ifdef ELIMINABLE_REGS
03590
03591
03592
03593
03594
03595 static const struct elims {const int from, to;} elim_regs[] = ELIMINABLE_REGS;
03596 size_t i;
03597
03598 for (i = 0; i < ARRAY_SIZE (elim_regs); i++)
03599 if (elim_regs[i].from == ARG_POINTER_REGNUM
03600 && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM)
03601 break;
03602
03603 if (i == ARRAY_SIZE (elim_regs))
03604 #endif
03605 {
03606
03607
03608 emit_move_insn (virtual_incoming_args_rtx,
03609 copy_to_reg (get_arg_pointer_save_area (cfun)));
03610 }
03611 }
03612 #endif
03613
03614 #ifdef HAVE_nonlocal_goto_receiver
03615 if (HAVE_nonlocal_goto_receiver)
03616 emit_insn (gen_nonlocal_goto_receiver ());
03617 #endif
03618 }
03619
03620
03621
03622
03623 static void
03624 expand_nl_goto_receivers (thisblock)
03625 struct nesting *thisblock;
03626 {
03627 tree link;
03628 rtx afterward = gen_label_rtx ();
03629 rtx insns, slot;
03630 rtx label_list;
03631 int any_invalid;
03632
03633
03634
03635 if (thisblock->next != 0)
03636 for (slot = nonlocal_goto_handler_slots; slot; slot = XEXP (slot, 1))
03637 {
03638 rtx save_receiver = gen_reg_rtx (Pmode);
03639 emit_move_insn (XEXP (slot, 0), save_receiver);
03640
03641 start_sequence ();
03642 emit_move_insn (save_receiver, XEXP (slot, 0));
03643 insns = get_insns ();
03644 end_sequence ();
03645 emit_insn_before (insns, thisblock->data.block.first_insn);
03646 }
03647
03648
03649 emit_jump (afterward);
03650
03651
03652 link = nonlocal_labels;
03653 slot = nonlocal_goto_handler_slots;
03654 label_list = NULL_RTX;
03655 for (; link; link = TREE_CHAIN (link), slot = XEXP (slot, 1))
03656
03657
03658
03659 if (! DECL_TOO_LATE (TREE_VALUE (link)))
03660 {
03661 rtx lab;
03662 lab = expand_nl_handler_label (XEXP (slot, 0),
03663 thisblock->data.block.first_insn);
03664 label_list = gen_rtx_EXPR_LIST (VOIDmode, lab, label_list);
03665
03666 expand_nl_goto_receiver ();
03667
03668
03669 expand_goto (TREE_VALUE (link));
03670 }
03671
03672
03673
03674 link = nonlocal_labels;
03675 slot = nonlocal_goto_handler_slots;
03676 any_invalid = 0;
03677 for (; link; link = TREE_CHAIN (link), slot = XEXP (slot, 1))
03678 if (DECL_TOO_LATE (TREE_VALUE (link)))
03679 {
03680 rtx lab;
03681 lab = expand_nl_handler_label (XEXP (slot, 0),
03682 thisblock->data.block.first_insn);
03683 label_list = gen_rtx_EXPR_LIST (VOIDmode, lab, label_list);
03684 any_invalid = 1;
03685 }
03686
03687 if (any_invalid)
03688 {
03689 expand_nl_goto_receiver ();
03690 expand_builtin_trap ();
03691 }
03692
03693 nonlocal_goto_handler_labels = label_list;
03694 emit_label (afterward);
03695 }
03696
03697
03698
03699
03700
03701 void
03702 warn_about_unused_variables (vars)
03703 tree vars;
03704 {
03705 tree decl;
03706
03707 if (warn_unused_variable)
03708 for (decl = vars; decl; decl = TREE_CHAIN (decl))
03709 if (TREE_CODE (decl) == VAR_DECL
03710 && ! TREE_USED (decl)
03711 && ! DECL_IN_SYSTEM_HEADER (decl)
03712 && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
03713 warning_with_decl (decl, "unused variable `%s'");
03714 }
03715
03716
03717
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728 void
03729 expand_end_bindings (vars, mark_ends, dont_jump_in)
03730 tree vars;
03731 int mark_ends;
03732 int dont_jump_in;
03733 {
03734 struct nesting *thisblock = block_stack;
03735
03736
03737
03738 warn_about_unused_variables (vars);
03739
03740 if (thisblock->exit_label)
03741 {
03742 do_pending_stack_adjust ();
03743 emit_label (thisblock->exit_label);
03744 }
03745
03746
03747
03748 if (function_call_count != thisblock->data.block.n_function_calls
03749 && nonlocal_labels
03750
03751
03752 && (thisblock->next == 0 ? current_function_has_nonlocal_label
03753
03754
03755 : (thisblock->data.block.cleanups != 0
03756 || thisblock->data.block.stack_level != 0)))
03757 expand_nl_goto_receivers (thisblock);
03758
03759
03760
03761 if (dont_jump_in
03762 || thisblock->data.block.stack_level != 0)
03763 {
03764 struct label_chain *chain;
03765
03766
03767
03768 for (chain = thisblock->data.block.label_chain; chain; chain = chain->next)
03769 {
03770 DECL_TOO_LATE (chain->label) = 1;
03771
03772
03773
03774 if (TREE_ADDRESSABLE (chain->label))
03775 error_with_decl (chain->label,
03776 "label `%s' used before containing binding contour");
03777 }
03778 }
03779
03780
03781
03782
03783
03784 if (thisblock->data.block.stack_level != 0
03785 || thisblock->data.block.cleanups != 0)
03786 {
03787 int reachable;
03788 rtx insn;
03789
03790
03791 int old_expr_stmts_for_value = expr_stmts_for_value;
03792 rtx old_last_expr_value = last_expr_value;
03793 tree old_last_expr_type = last_expr_type;
03794 expr_stmts_for_value = 0;
03795
03796
03797 insn = get_last_insn ();
03798 if (GET_CODE (insn) == NOTE)
03799 insn = prev_nonnote_insn (insn);
03800 reachable = (! insn || GET_CODE (insn) != BARRIER);
03801
03802
03803 expand_cleanups (thisblock->data.block.cleanups, NULL_TREE, 0, reachable);
03804 if (reachable)
03805 do_pending_stack_adjust ();
03806
03807 expr_stmts_for_value = old_expr_stmts_for_value;
03808 last_expr_value = old_last_expr_value;
03809 last_expr_type = old_last_expr_type;
03810
03811
03812
03813 if (reachable && thisblock->data.block.stack_level != 0)
03814 {
03815 emit_stack_restore (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
03816 thisblock->data.block.stack_level, NULL_RTX);
03817 if (nonlocal_goto_handler_slots != 0)
03818 emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level,
03819 NULL_RTX);
03820 }
03821
03822
03823
03824
03825 fixup_gotos (thisblock,
03826 thisblock->data.block.stack_level,
03827 thisblock->data.block.cleanups,
03828 thisblock->data.block.first_insn,
03829 dont_jump_in);
03830 }
03831
03832
03833
03834
03835
03836 if (mark_ends)
03837 {
03838 rtx note = emit_note (NULL, NOTE_INSN_BLOCK_END);
03839 NOTE_BLOCK (note) = NOTE_BLOCK (thisblock->data.block.first_insn);
03840 }
03841 else
03842
03843 NOTE_LINE_NUMBER (thisblock->data.block.first_insn) = NOTE_INSN_DELETED;
03844
03845
03846 target_temp_slot_level = thisblock->data.block.block_target_temp_slot_level;
03847
03848
03849
03850 stack_block_stack = thisblock->data.block.innermost_stack_block;
03851 POPSTACK (block_stack);
03852
03853
03854 pop_temp_slots ();
03855 }
03856
03857
03858
03859
03860 void
03861 save_stack_pointer ()
03862 {
03863 struct nesting *thisblock = block_stack;
03864
03865 if (thisblock->data.block.stack_level == 0)
03866 {
03867 emit_stack_save (thisblock->next ? SAVE_BLOCK : SAVE_FUNCTION,
03868 &thisblock->data.block.stack_level,
03869 thisblock->data.block.first_insn);
03870 stack_block_stack = thisblock;
03871 }
03872 }
03873
03874
03875
03876
03877 void
03878 expand_decl (decl)
03879 tree decl;
03880 {
03881 struct nesting *thisblock;
03882 tree type;
03883
03884 type = TREE_TYPE (decl);
03885
03886
03887
03888 if (TREE_CODE (decl) == CONST_DECL)
03889 {
03890 DECL_MODE (decl) = TYPE_MODE (type);
03891 DECL_ALIGN (decl) = TYPE_ALIGN (type);
03892 DECL_SIZE (decl) = TYPE_SIZE (type);
03893 DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);
03894 return;
03895 }
03896
03897
03898
03899
03900
03901 if (TREE_CODE (decl) != VAR_DECL)
03902 return;
03903
03904 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
03905 return;
03906
03907 thisblock = block_stack;
03908
03909
03910
03911 if (type == error_mark_node)
03912 SET_DECL_RTL (decl, gen_rtx_MEM (BLKmode, const0_rtx));
03913
03914 else if (DECL_SIZE (decl) == 0)
03915
03916 {
03917 rtx x;
03918 if (DECL_INITIAL (decl) == 0)
03919
03920 x = gen_rtx_MEM (BLKmode, const0_rtx);
03921 else
03922
03923
03924 x = gen_rtx_MEM (BLKmode, gen_reg_rtx (Pmode));
03925
03926 set_mem_attributes (x, decl, 1);
03927 SET_DECL_RTL (decl, x);
03928 }
03929 else if (DECL_MODE (decl) != BLKmode
03930
03931
03932 && !(flag_float_store
03933 && TREE_CODE (type) == REAL_TYPE)
03934 && ! TREE_THIS_VOLATILE (decl)
03935 && ! DECL_NONLOCAL (decl)
03936 && (DECL_REGISTER (decl) || optimize))
03937 {
03938
03939 int unsignedp = TREE_UNSIGNED (type);
03940 enum machine_mode reg_mode
03941 = promote_mode (type, DECL_MODE (decl), &unsignedp, 0);
03942
03943 SET_DECL_RTL (decl, gen_reg_rtx (reg_mode));
03944
03945 if (GET_CODE (DECL_RTL (decl)) == REG)
03946 REGNO_DECL (REGNO (DECL_RTL (decl))) = decl;
03947 else if (GET_CODE (DECL_RTL (decl)) == CONCAT)
03948 {
03949 REGNO_DECL (REGNO (XEXP (DECL_RTL (decl), 0))) = decl;
03950 REGNO_DECL (REGNO (XEXP (DECL_RTL (decl), 1))) = decl;
03951 }
03952
03953 mark_user_reg (DECL_RTL (decl));
03954
03955 if (POINTER_TYPE_P (type))
03956 mark_reg_pointer (DECL_RTL (decl),
03957 TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
03958
03959 maybe_set_unchanging (DECL_RTL (decl), decl);
03960
03961
03962 if (TREE_ADDRESSABLE (decl))
03963 put_var_into_stack (decl, false);
03964 }
03965
03966 else if (TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST
03967 && ! (flag_stack_check && ! STACK_CHECK_BUILTIN
03968 && 0 < compare_tree_int (DECL_SIZE_UNIT (decl),
03969 STACK_CHECK_MAX_VAR_SIZE)))
03970 {
03971
03972 rtx oldaddr = 0;
03973 rtx addr;
03974 rtx x;
03975
03976
03977
03978
03979
03980 if (DECL_RTL_SET_P (decl))
03981 {
03982 if (GET_CODE (DECL_RTL (decl)) != MEM
03983 || GET_CODE (XEXP (DECL_RTL (decl), 0)) != REG)
03984 abort ();
03985 oldaddr = XEXP (DECL_RTL (decl), 0);
03986 }
03987
03988
03989 DECL_ALIGN (decl) = (DECL_MODE (decl) == BLKmode ? BIGGEST_ALIGNMENT
03990 : GET_MODE_BITSIZE (DECL_MODE (decl)));
03991 DECL_USER_ALIGN (decl) = 0;
03992
03993 x = assign_temp (decl, 1, 1, 1);
03994 set_mem_attributes (x, decl, 1);
03995 SET_DECL_RTL (decl, x);
03996
03997 if (oldaddr)
03998 {
03999 addr = force_operand (XEXP (DECL_RTL (decl), 0), oldaddr);
04000 if (addr != oldaddr)
04001 emit_move_insn (oldaddr, addr);
04002 }
04003 }
04004 else
04005
04006 {
04007 rtx address, size, x;
04008
04009
04010
04011 do_pending_stack_adjust ();
04012 save_stack_pointer ();
04013
04014
04015
04016 if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
04017 expand_expr (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
04018 const0_rtx, VOIDmode, 0);
04019
04020
04021 size = expand_expr (DECL_SIZE_UNIT (decl), NULL_RTX, VOIDmode, 0);
04022 free_temp_slots ();
04023
04024
04025
04026
04027
04028 address = allocate_dynamic_stack_space (size, NULL_RTX,
04029 TYPE_ALIGN (TREE_TYPE (decl)));
04030
04031
04032 x = gen_rtx_MEM (DECL_MODE (decl), address);
04033 set_mem_attributes (x, decl, 1);
04034 SET_DECL_RTL (decl, x);
04035
04036
04037
04038 #ifdef STACK_BOUNDARY
04039 DECL_ALIGN (decl) = STACK_BOUNDARY;
04040 #else
04041 DECL_ALIGN (decl) = BIGGEST_ALIGNMENT;
04042 #endif
04043 DECL_USER_ALIGN (decl) = 0;
04044 }
04045 }
04046
04047
04048
04049 void
04050 expand_decl_init (decl)
04051 tree decl;
04052 {
04053 int was_used = TREE_USED (decl);
04054
04055
04056
04057 if (TREE_CODE (decl) == CONST_DECL
04058 || TREE_STATIC (decl))
04059 return;
04060
04061
04062
04063 push_temp_slots ();
04064
04065 if (DECL_INITIAL (decl) == error_mark_node)
04066 {
04067 enum tree_code code = TREE_CODE (TREE_TYPE (decl));
04068
04069 if (code == INTEGER_TYPE || code == REAL_TYPE || code == ENUMERAL_TYPE
04070 || code == POINTER_TYPE || code == REFERENCE_TYPE)
04071 expand_assignment (decl, convert (TREE_TYPE (decl), integer_zero_node),
04072 0, 0);
04073 emit_queue ();
04074 }
04075 else if (DECL_INITIAL (decl) && TREE_CODE (DECL_INITIAL (decl)) != TREE_LIST)
04076 {
04077 emit_line_note (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
04078 expand_assignment (decl, DECL_INITIAL (decl), 0, 0);
04079 emit_queue ();
04080 }
04081
04082
04083 TREE_USED (decl) = was_used;
04084
04085
04086 preserve_temp_slots (NULL_RTX);
04087 free_temp_slots ();
04088 pop_temp_slots ();
04089 }
04090
04091
04092
04093
04094
04095
04096
04097
04098
04099
04100
04101
04102 int
04103 expand_decl_cleanup (decl, cleanup)
04104 tree decl, cleanup;
04105 {
04106 struct nesting *thisblock;
04107
04108
04109 if (cfun == 0 || block_stack == 0)
04110 return 0;
04111
04112 thisblock = block_stack;
04113
04114
04115
04116 if (cleanup != 0)
04117 {
04118 tree t;
04119 rtx seq;
04120 tree *cleanups = &thisblock->data.block.cleanups;
04121 int cond_context = conditional_context ();
04122
04123 if (cond_context)
04124 {
04125 rtx flag = gen_reg_rtx (word_mode);
04126 rtx set_flag_0;
04127 tree cond;
04128
04129 start_sequence ();
04130 emit_move_insn (flag, const0_rtx);
04131 set_flag_0 = get_insns ();
04132 end_sequence ();
04133
04134 thisblock->data.block.last_unconditional_cleanup
04135 = emit_insn_after (set_flag_0,
04136 thisblock->data.block.last_unconditional_cleanup);
04137
04138 emit_move_insn (flag, const1_rtx);
04139
04140 cond = build_decl (VAR_DECL, NULL_TREE,
04141 (*lang_hooks.types.type_for_mode) (word_mode, 1));
04142 SET_DECL_RTL (cond, flag);
04143
04144
04145 cleanup = build (COND_EXPR, void_type_node,
04146 (*lang_hooks.truthvalue_conversion) (cond),
04147 cleanup, integer_zero_node);
04148 cleanup = fold (cleanup);
04149
04150 cleanups = &thisblock->data.block.cleanups;
04151 }
04152
04153 cleanup = unsave_expr (cleanup);
04154
04155 t = *cleanups = tree_cons (decl, cleanup, *cleanups);
04156
04157 if (! cond_context)
04158
04159 stack_block_stack = thisblock;
04160
04161 if (cond_context)
04162 {
04163 start_sequence ();
04164 }
04165
04166 if (! using_eh_for_cleanups_p)
04167 TREE_ADDRESSABLE (t) = 1;
04168 else
04169 expand_eh_region_start ();
04170
04171 if (cond_context)
04172 {
04173 seq = get_insns ();
04174 end_sequence ();
04175 if (seq)
04176 thisblock->data.block.last_unconditional_cleanup
04177 = emit_insn_after (seq,
04178 thisblock->data.block.last_unconditional_cleanup);
04179 }
04180 else
04181 {
04182 thisblock->data.block.last_unconditional_cleanup
04183 = get_last_insn ();
04184
04185
04186
04187
04188
04189
04190 emit_note (NULL, NOTE_INSN_DELETED);
04191 }
04192 }
04193 return 1;
04194 }
04195
04196
04197
04198
04199 int
04200 expand_decl_cleanup_eh (decl, cleanup, eh_only)
04201 tree decl, cleanup;
04202 int eh_only;
04203 {
04204 int ret = expand_decl_cleanup (decl, cleanup);
04205 if (cleanup && ret)
04206 {
04207 tree node = block_stack->data.block.cleanups;
04208 CLEANUP_EH_ONLY (node) = eh_only;
04209 }
04210 return ret;
04211 }
04212
04213
04214
04215
04216
04217 void
04218 expand_anon_union_decl (decl, cleanup, decl_elts)
04219 tree decl, cleanup, decl_elts;
04220 {
04221 struct nesting *thisblock = cfun == 0 ? 0 : block_stack;
04222 rtx x;
04223 tree t;
04224
04225
04226 for (t = decl_elts; t; t = TREE_CHAIN (t))
04227 if (TREE_ADDRESSABLE (TREE_VALUE (t)))
04228 {
04229 TREE_ADDRESSABLE (decl) = 1;
04230 break;
04231 }
04232
04233 expand_decl (decl);
04234 expand_decl_cleanup (decl, cleanup);
04235 x = DECL_RTL (decl);
04236
04237
04238 for (t = decl_elts; t; t = TREE_CHAIN (t))
04239 {
04240 tree decl_elt = TREE_VALUE (t);
04241 tree cleanup_elt = TREE_PURPOSE (t);
04242 enum machine_mode mode = TYPE_MODE (TREE_TYPE (decl_elt));
04243
04244
04245
04246 if (TREE_USED (decl_elt))
04247 TREE_USED (decl) = 1;
04248
04249
04250 DECL_ALIGN (decl_elt) = DECL_ALIGN (decl);
04251 DECL_USER_ALIGN (decl_elt) = DECL_USER_ALIGN (decl);
04252
04253
04254
04255
04256 if (mode == BLKmode && DECL_MODE (decl) != BLKmode)
04257 DECL_MODE (decl_elt) = mode
04258 = mode_for_size_tree (DECL_SIZE (decl_elt), MODE_INT, 1);
04259
04260
04261
04262 if (GET_CODE (x) == MEM)
04263 {
04264 if (mode == GET_MODE (x))
04265 SET_DECL_RTL (decl_elt, x);
04266 else
04267 SET_DECL_RTL (decl_elt, adjust_address_nv (x, mode, 0));
04268 }
04269 else if (GET_CODE (x) == REG)
04270 {
04271 if (mode == GET_MODE (x))
04272 SET_DECL_RTL (decl_elt, x);
04273 else
04274 SET_DECL_RTL (decl_elt, gen_lowpart_SUBREG (mode, x));
04275 }
04276 else
04277 abort ();
04278
04279
04280
04281 if (cleanup != 0)
04282 thisblock->data.block.cleanups
04283 = tree_cons (decl_elt, cleanup_elt,
04284 thisblock->data.block.cleanups);
04285 }
04286 }
04287
04288
04289
04290
04291
04292
04293
04294
04295
04296
04297
04298
04299
04300
04301
04302 static void
04303 expand_cleanups (list, dont_do, in_fixup, reachable)
04304 tree list;
04305 tree dont_do;
04306 int in_fixup;
04307 int reachable;
04308 {
04309 tree tail;
04310 for (tail = list; tail; tail = TREE_CHAIN (tail))
04311 if (dont_do == 0 || TREE_PURPOSE (tail) != dont_do)
04312 {
04313 if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
04314 expand_cleanups (TREE_VALUE (tail), dont_do, in_fixup, reachable);
04315 else
04316 {
04317 if (! in_fixup && using_eh_for_cleanups_p)
04318 expand_eh_region_end_cleanup (TREE_VALUE (tail));
04319
04320 if (reachable && !CLEANUP_EH_ONLY (tail))
04321 {
04322
04323
04324
04325
04326
04327
04328
04329
04330
04331
04332 if (in_fixup && using_eh_for_cleanups_p)
04333 {
04334 expand_eh_region_start ();
04335
04336 expand_expr (TREE_VALUE (tail), const0_rtx, VOIDmode, 0);
04337
04338 expand_eh_region_end_fixup (TREE_VALUE (tail));
04339 }
04340 else
04341 expand_expr (TREE_VALUE (tail), const0_rtx, VOIDmode, 0);
04342
04343 free_temp_slots ();
04344 }
04345 }
04346 }
04347 }
04348
04349
04350
04351
04352
04353
04354
04355 void
04356 start_cleanup_deferral ()
04357 {
04358
04359
04360 if (block_stack)
04361 ++block_stack->data.block.conditional_code;
04362 }
04363
04364
04365
04366
04367
04368
04369 void
04370 end_cleanup_deferral ()
04371 {
04372
04373
04374 if (block_stack)
04375 --block_stack->data.block.conditional_code;
04376 }
04377
04378
04379
04380
04381
04382
04383
04384 void
04385 move_cleanups_up ()
04386 {
04387 struct nesting *block = block_stack;
04388 struct nesting *outer = block->next;
04389
04390 outer->data.block.cleanups
04391 = chainon (block->data.block.cleanups,
04392 outer->data.block.cleanups);
04393 block->data.block.cleanups = 0;
04394 }
04395
04396 tree
04397 last_cleanup_this_contour ()
04398 {
04399 if (block_stack == 0)
04400 return 0;
04401
04402 return block_stack->data.block.cleanups;
04403 }
04404
04405
04406
04407
04408
04409 int
04410 any_pending_cleanups (this_contour)
04411 int this_contour;
04412 {
04413 struct nesting *block;
04414
04415 if (cfun == NULL || cfun->stmt == NULL || block_stack == 0)
04416 return 0;
04417
04418 if (this_contour && block_stack->data.block.cleanups != NULL)
04419 return 1;
04420 if (block_stack->data.block.cleanups == 0
04421 && block_stack->data.block.outer_cleanups == 0)
04422 return 0;
04423
04424 for (block = block_stack->next; block; block = block->next)
04425 if (block->data.block.cleanups != 0)
04426 return 1;
04427
04428 return 0;
04429 }
04430
04431
04432
04433
04434
04435
04436
04437
04438
04439
04440
04441
04442
04443 void
04444 expand_start_case (exit_flag, expr, type, printname)
04445 int exit_flag;
04446 tree expr;
04447 tree type;
04448 const char *printname;
04449 {
04450 struct nesting *thiscase = ALLOC_NESTING ();
04451
04452
04453
04454 thiscase->desc = CASE_NESTING;
04455 thiscase->next = case_stack;
04456 thiscase->all = nesting_stack;
04457 thiscase->depth = ++nesting_depth;
04458 thiscase->exit_label = exit_flag ? gen_label_rtx () : 0;
04459 thiscase->data.case_stmt.case_list = 0;
04460 thiscase->data.case_stmt.index_expr = expr;
04461 thiscase->data.case_stmt.nominal_type = type;
04462 thiscase->data.case_stmt.default_label = 0;
04463 thiscase->data.case_stmt.printname = printname;
04464 thiscase->data.case_stmt.line_number_status = force_line_numbers ();
04465 case_stack = thiscase;
04466 nesting_stack = thiscase;
04467
04468 do_pending_stack_adjust ();
04469 emit_queue ();
04470
04471
04472
04473 if (GET_CODE (get_last_insn ()) != NOTE)
04474 emit_note (NULL, NOTE_INSN_DELETED);
04475
04476 thiscase->data.case_stmt.start = get_last_insn ();
04477
04478 start_cleanup_deferral ();
04479 }
04480
04481
04482
04483
04484
04485
04486 void
04487 expand_start_case_dummy ()
04488 {
04489 struct nesting *thiscase = ALLOC_NESTING ();
04490
04491
04492
04493 thiscase->desc = CASE_NESTING;
04494 thiscase->next = case_stack;
04495 thiscase->all = nesting_stack;
04496 thiscase->depth = ++nesting_depth;
04497 thiscase->exit_label = 0;
04498 thiscase->data.case_stmt.case_list = 0;
04499 thiscase->data.case_stmt.start = 0;
04500 thiscase->data.case_stmt.nominal_type = 0;
04501 thiscase->data.case_stmt.default_label = 0;
04502 case_stack = thiscase;
04503 nesting_stack = thiscase;
04504 start_cleanup_deferral ();
04505 }
04506
04507
04508
04509 void
04510 expand_end_case_dummy ()
04511 {
04512 end_cleanup_deferral ();
04513 POPSTACK (case_stack);
04514 }
04515
04516
04517
04518
04519 tree
04520 case_index_expr_type ()
04521 {
04522 if (case_stack)
04523 return TREE_TYPE (case_stack->data.case_stmt.index_expr);
04524 return 0;
04525 }
04526
04527 static void
04528 check_seenlabel ()
04529 {
04530
04531 if (case_stack->data.case_stmt.line_number_status >= 0)
04532 {
04533 rtx insn;
04534
04535 restore_line_number_status
04536 (case_stack->data.case_stmt.line_number_status);
04537 case_stack->data.case_stmt.line_number_status = -1;
04538
04539 for (insn = case_stack->data.case_stmt.start;
04540 insn;
04541 insn = NEXT_INSN (insn))
04542 {
04543 if (GET_CODE (insn) == CODE_LABEL)
04544 break;
04545 if (GET_CODE (insn) != NOTE
04546 && (GET_CODE (insn) != INSN || GET_CODE (PATTERN (insn)) != USE))
04547 {
04548 do
04549 insn = PREV_INSN (insn);
04550 while (insn && (GET_CODE (insn) != NOTE || NOTE_LINE_NUMBER (insn) < 0));
04551
04552
04553 if (insn)
04554 warning_with_file_and_line (NOTE_SOURCE_FILE (insn),
04555 NOTE_LINE_NUMBER (insn),
04556 "unreachable code at beginning of %s",
04557 case_stack->data.case_stmt.printname);
04558 break;
04559 }
04560 }
04561 }
04562 }
04563
04564
04565
04566
04567
04568
04569
04570
04571
04572
04573
04574
04575
04576
04577
04578
04579 int
04580 pushcase (value, converter, label, duplicate)
04581 tree value;
04582 tree (*converter) PARAMS ((tree, tree));
04583 tree label;
04584 tree *duplicate;
04585 {
04586 tree index_type;
04587 tree nominal_type;
04588
04589
04590 if (! (case_stack && case_stack->data.case_stmt.start))
04591 return 1;
04592
04593 if (stack_block_stack
04594 && stack_block_stack->depth > case_stack->depth)
04595 return 5;
04596
04597 index_type = TREE_TYPE (case_stack->data.case_stmt.index_expr);
04598 nominal_type = case_stack->data.case_stmt.nominal_type;
04599
04600
04601 if (index_type == error_mark_node)
04602 return 0;
04603
04604
04605 if (value != 0)
04606 value = (*converter) (nominal_type, value);
04607
04608 check_seenlabel ();
04609
04610
04611
04612 if (value != 0
04613 && (TREE_CONSTANT_OVERFLOW (value)
04614 || ! int_fits_type_p (value, index_type)))
04615 return 3;
04616
04617 return add_case_node (value, value, label, duplicate);
04618 }
04619
04620
04621
04622
04623
04624
04625
04626
04627
04628
04629 int
04630 pushcase_range (value1, value2, converter, label, duplicate)
04631 tree value1, value2;
04632 tree (*converter) PARAMS ((tree, tree));
04633 tree label;
04634 tree *duplicate;
04635 {
04636 tree index_type;
04637 tree nominal_type;
04638
04639
04640 if (! (case_stack && case_stack->data.case_stmt.start))
04641 return 1;
04642
04643 if (stack_block_stack
04644 && stack_block_stack->depth > case_stack->depth)
04645 return 5;
04646
04647 index_type = TREE_TYPE (case_stack->data.case_stmt.index_expr);
04648 nominal_type = case_stack->data.case_stmt.nominal_type;
04649
04650
04651 if (index_type == error_mark_node)
04652 return 0;
04653
04654 check_seenlabel ();
04655
04656
04657
04658 if (value1 == 0)
04659 value1 = TYPE_MIN_VALUE (index_type);
04660 if (value2 == 0)
04661 value2 = TYPE_MAX_VALUE (index_type);
04662
04663
04664
04665 if (value2 != 0 && tree_int_cst_lt (value2, value1))
04666 return 4;
04667
04668
04669
04670
04671 if (value2 == 0)
04672 value2 = TYPE_MAX_VALUE (nominal_type);
04673
04674 value1 = (*converter) (nominal_type, value1);
04675 value2 = (*converter) (nominal_type, value2);
04676
04677
04678 if (TREE_CONSTANT_OVERFLOW (value1)
04679 || ! int_fits_type_p (value1, index_type))
04680 return 3;
04681
04682 if (TREE_CONSTANT_OVERFLOW (value2)
04683 || ! int_fits_type_p (value2, index_type))
04684 return 3;
04685
04686 return add_case_node (value1, value2, label, duplicate);
04687 }
04688
04689
04690
04691
04692
04693 int
04694 add_case_node (low, high, label, duplicate)
04695 tree low, high;
04696 tree label;
04697 tree *duplicate;
04698 {
04699 struct case_node *p, **q, *r;
04700
04701
04702
04703
04704 if (!high)
04705 high = low;
04706
04707
04708 if (!high && !low)
04709 {
04710 if (case_stack->data.case_stmt.default_label != 0)
04711 {
04712 *duplicate = case_stack->data.case_stmt.default_label;
04713 return 2;
04714 }
04715 case_stack->data.case_stmt.default_label = label;
04716 expand_label (label);
04717 return 0;
04718 }
04719
04720 q = &case_stack->data.case_stmt.case_list;
04721 p = *q;
04722
04723 while ((r = *q))
04724 {
04725 p = r;
04726
04727
04728 if (tree_int_cst_lt (high, p->low))
04729 q = &p->left;
04730
04731
04732 else if (tree_int_cst_lt (p->high, low))
04733 q = &p->right;
04734
04735 else
04736 {
04737
04738 *duplicate = p->code_label;
04739 return 2;
04740 }
04741 }
04742
04743
04744
04745 r = (struct case_node *) ggc_alloc (sizeof (struct case_node));
04746 r->low = low;
04747
04748
04749 if (tree_int_cst_equal (low, high))
04750 r->high = r->low;
04751 else
04752 r->high = high;
04753
04754 r->code_label = label;
04755 expand_label (label);
04756
04757 *q = r;
04758 r->parent = p;
04759 r->left = 0;
04760 r->right = 0;
04761 r->balance = 0;
04762
04763 while (p)
04764 {
04765 struct case_node *s;
04766
04767 if (r == p->left)
04768 {
04769 int b;
04770
04771 if (! (b = p->balance))
04772
04773 p->balance = -1;
04774 else if (b < 0)
04775 {
04776 if (r->balance < 0)
04777 {
04778
04779 if ((p->left = s = r->right))
04780 s->parent = p;
04781
04782 r->right = p;
04783 p->balance = 0;
04784 r->balance = 0;
04785 s = p->parent;
04786 p->parent = r;
04787
04788 if ((r->parent = s))
04789 {
04790 if (s->left == p)
04791 s->left = r;
04792 else
04793 s->right = r;
04794 }
04795 else
04796 case_stack->data.case_stmt.case_list = r;
04797 }
04798 else
04799
04800 {
04801
04802
04803 int b2;
04804 struct case_node *t = r->right;
04805
04806 if ((p->left = s = t->right))
04807 s->parent = p;
04808
04809 t->right = p;
04810 if ((r->right = s = t->left))
04811 s->parent = r;
04812
04813 t->left = r;
04814 b = t->balance;
04815 b2 = b < 0;
04816 p->balance = b2;
04817 b2 = -b2 - b;
04818 r->balance = b2;
04819 t->balance = 0;
04820 s = p->parent;
04821 p->parent = t;
04822 r->parent = t;
04823
04824 if ((t->parent = s))
04825 {
04826 if (s->left == p)
04827 s->left = t;
04828 else
04829 s->right = t;
04830 }
04831 else
04832 case_stack->data.case_stmt.case_list = t;
04833 }
04834 break;
04835 }
04836
04837 else
04838 {
04839
04840 p->balance = 0;
04841 break;
04842 }
04843 }
04844 else
04845
04846 {
04847 int b;
04848
04849 if (! (b = p->balance))
04850
04851 p->balance++;
04852 else if (b > 0)
04853 {
04854 if (r->balance > 0)
04855 {
04856
04857
04858 if ((p->right = s = r->left))
04859 s->parent = p;
04860
04861 r->left = p;
04862 p->balance = 0;
04863 r->balance = 0;
04864 s = p->parent;
04865 p->parent = r;
04866 if ((r->parent = s))
04867 {
04868 if (s->left == p)
04869 s->left = r;
04870 else
04871 s->right = r;
04872 }
04873
04874 else
04875 case_stack->data.case_stmt.case_list = r;
04876 }
04877
04878 else
04879
04880 {
04881
04882 int b2;
04883 struct case_node *t = r->left;
04884
04885 if ((p->right = s = t->left))
04886 s->parent = p;
04887
04888 t->left = p;
04889
04890 if ((r->left = s = t->right))
04891 s->parent = r;
04892
04893 t->right = r;
04894 b = t->balance;
04895 b2 = b < 0;
04896 r->balance = b2;
04897 b2 = -b2 - b;
04898 p->balance = b2;
04899 t->balance = 0;
04900 s = p->parent;
04901 p->parent = t;
04902 r->parent = t;
04903
04904 if ((t->parent = s))
04905 {
04906 if (s->left == p)
04907 s->left = t;
04908 else
04909 s->right = t;
04910 }
04911
04912 else
04913 case_stack->data.case_stmt.case_list = t;
04914 }
04915 break;
04916 }
04917 else
04918 {
04919
04920 p->balance = 0;
04921 break;
04922 }
04923 }
04924
04925 r = p;
04926 p = p->parent;
04927 }
04928
04929 return 0;
04930 }
04931
04932
04933
04934
04935
04936
04937
04938
04939
04940 HOST_WIDE_INT
04941 all_cases_count (type, sparseness)
04942 tree type;
04943 int *sparseness;
04944 {
04945 tree t;
04946 HOST_WIDE_INT count, minval, lastval;
04947
04948 *sparseness = 0;
04949
04950 switch (TREE_CODE (type))
04951 {
04952 case BOOLEAN_TYPE:
04953 count = 2;
04954 break;
04955
04956 case CHAR_TYPE:
04957 count = 1 << BITS_PER_UNIT;
04958 break;
04959
04960 default:
04961 case INTEGER_TYPE:
04962 if (TYPE_MAX_VALUE (type) != 0
04963 && 0 != (t = fold (build (MINUS_EXPR, type, TYPE_MAX_VALUE (type),
04964 TYPE_MIN_VALUE (type))))
04965 && 0 != (t = fold (build (PLUS_EXPR, type, t,
04966 convert (type, integer_zero_node))))
04967 && host_integerp (t, 1))
04968 count = tree_low_cst (t, 1);
04969 else
04970 return -1;
04971 break;
04972
04973 case ENUMERAL_TYPE:
04974
04975 if (! host_integerp (TYPE_MIN_VALUE (type), 0)
04976 || TYPE_MAX_VALUE (type) == 0
04977 || ! host_integerp (TYPE_MAX_VALUE (type), 0))
04978 return -1;
04979
04980 lastval = minval = tree_low_cst (TYPE_MIN_VALUE (type), 0);
04981 count = 0;
04982
04983 for (t = TYPE_VALUES (type); t != NULL_TREE; t = TREE_CHAIN (t))
04984 {
04985 HOST_WIDE_INT thisval = tree_low_cst (TREE_VALUE (t), 0);
04986
04987 if (*sparseness == 2 || thisval <= lastval)
04988 *sparseness = 2;
04989 else if (thisval != minval + count)
04990 *sparseness = 1;
04991
04992 lastval = thisval;
04993 count++;
04994 }
04995 }
04996
04997 return count;
04998 }
04999
05000 #define BITARRAY_TEST(ARRAY, INDEX) \
05001 ((ARRAY)[(unsigned) (INDEX) / HOST_BITS_PER_CHAR]\
05002 & (1 << ((unsigned) (INDEX) % HOST_BITS_PER_CHAR)))
05003 #define BITARRAY_SET(ARRAY, INDEX) \
05004 ((ARRAY)[(unsigned) (INDEX) / HOST_BITS_PER_CHAR]\
05005 |= 1 << ((unsigned) (INDEX) % HOST_BITS_PER_CHAR))
05006
05007
05008
05009
05010
05011
05012
05013
05014
05015 void
05016 mark_seen_cases (type, cases_seen, count, sparseness)
05017 tree type;
05018 unsigned char *cases_seen;
05019 HOST_WIDE_INT count;
05020 int sparseness;
05021 {
05022 tree next_node_to_try = NULL_TREE;
05023 HOST_WIDE_INT next_node_offset = 0;
05024
05025 struct case_node *n, *root = case_stack->data.case_stmt.case_list;
05026 tree val = make_node (INTEGER_CST);
05027
05028 TREE_TYPE (val) = type;
05029 if (! root)
05030
05031 ;
05032 else if (sparseness == 2)
05033 {
05034 tree t;
05035 unsigned HOST_WIDE_INT xlo;
05036
05037
05038
05039
05040 TREE_TYPE (val) = TREE_TYPE (root->low);
05041 for (t = TYPE_VALUES (type), xlo = 0; t != NULL_TREE;
05042 t = TREE_CHAIN (t), xlo++)
05043 {
05044 TREE_INT_CST_LOW (val) = TREE_INT_CST_LOW (TREE_VALUE (t));
05045 TREE_INT_CST_HIGH (val) = TREE_INT_CST_HIGH (TREE_VALUE (t));
05046 n = root;
05047 do
05048 {
05049
05050 if (tree_int_cst_lt (val, n->low))
05051 n = n->left;
05052
05053
05054 else if (tree_int_cst_lt (n->high, val))
05055 n = n->right;
05056
05057 else
05058 {
05059
05060 BITARRAY_SET (cases_seen, xlo);
05061 break;
05062 }
05063 }
05064 while (n);
05065 }
05066 }
05067 else
05068 {
05069 if (root->left)
05070 case_stack->data.case_stmt.case_list = root = case_tree2list (root, 0);
05071
05072 for (n = root; n; n = n->right)
05073 {
05074 TREE_INT_CST_LOW (val) = TREE_INT_CST_LOW (n->low);
05075 TREE_INT_CST_HIGH (val) = TREE_INT_CST_HIGH (n->low);
05076 while (! tree_int_cst_lt (n->high, val))
05077 {
05078
05079
05080
05081
05082 unsigned HOST_WIDE_INT xlo;
05083 HOST_WIDE_INT xhi;
05084 tree t;
05085
05086 if (sparseness && TYPE_VALUES (type) != NULL_TREE)
05087 {
05088
05089
05090 t = next_node_to_try;
05091 xlo = next_node_offset;
05092 xhi = 0;
05093 for (;;)
05094 {
05095 if (t == NULL_TREE)
05096 {
05097 t = TYPE_VALUES (type);
05098 xlo = 0;
05099 }
05100 if (tree_int_cst_equal (val, TREE_VALUE (t)))
05101 {
05102 next_node_to_try = TREE_CHAIN (t);
05103 next_node_offset = xlo + 1;
05104 break;
05105 }
05106 xlo++;
05107 t = TREE_CHAIN (t);
05108 if (t == next_node_to_try)
05109 {
05110 xlo = -1;
05111 break;
05112 }
05113 }
05114 }
05115 else
05116 {
05117 t = TYPE_MIN_VALUE (type);
05118 if (t)
05119 neg_double (TREE_INT_CST_LOW (t), TREE_INT_CST_HIGH (t),
05120 &xlo, &xhi);
05121 else
05122 xlo = xhi = 0;
05123 add_double (xlo, xhi,
05124 TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val),
05125 &xlo, &xhi);
05126 }
05127
05128 if (xhi == 0 && xlo < (unsigned HOST_WIDE_INT) count)
05129 BITARRAY_SET (cases_seen, xlo);
05130
05131 add_double (TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val),
05132 1, 0,
05133 &TREE_INT_CST_LOW (val), &TREE_INT_CST_HIGH (val));
05134 }
05135 }
05136 }
05137 }
05138
05139
05140
05141
05142
05143
05144
05145
05146
05147
05148
05149
05150
05151
05152
05153
05154
05155
05156
05157 void
05158 check_for_full_enumeration_handling (type)
05159 tree type;
05160 {
05161 struct case_node *n;
05162 tree chain;
05163
05164
05165 int sparseness = 0;
05166
05167
05168 HOST_WIDE_INT size;
05169
05170
05171
05172 unsigned char *cases_seen;
05173
05174
05175 HOST_WIDE_INT bytes_needed;
05176
05177 size = all_cases_count (type, &sparseness);
05178 bytes_needed = (size + HOST_BITS_PER_CHAR) / HOST_BITS_PER_CHAR;
05179
05180 if (size > 0 && size < 600000
05181
05182
05183
05184 && (cases_seen =
05185 (unsigned char *) really_call_calloc (bytes_needed, 1)) != NULL)
05186 {
05187 HOST_WIDE_INT i;
05188 tree v = TYPE_VALUES (type);
05189
05190
05191
05192
05193
05194
05195 mark_seen_cases (type, cases_seen, size, sparseness);
05196
05197 for (i = 0; v != NULL_TREE && i < size; i++, v = TREE_CHAIN (v))
05198 if (BITARRAY_TEST (cases_seen, i) == 0)
05199 warning ("enumeration value `%s' not handled in switch",
05200 IDENTIFIER_POINTER (TREE_PURPOSE (v)));
05201
05202 free (cases_seen);
05203 }
05204
05205
05206
05207
05208
05209
05210 if (case_stack->data.case_stmt.case_list
05211 && case_stack->data.case_stmt.case_list->left)
05212 case_stack->data.case_stmt.case_list
05213 = case_tree2list (case_stack->data.case_stmt.case_list, 0);
05214 for (n = case_stack->data.case_stmt.case_list; n; n = n->right)
05215 {
05216 for (chain = TYPE_VALUES (type);
05217 chain && !tree_int_cst_equal (n->low, TREE_VALUE (chain));
05218 chain = TREE_CHAIN (chain))
05219 ;
05220
05221 if (!chain)
05222 {
05223 if (TYPE_NAME (type) == 0)
05224 warning ("case value `%ld' not in enumerated type",
05225 (long) TREE_INT_CST_LOW (n->low));
05226 else
05227 warning ("case value `%ld' not in enumerated type `%s'",
05228 (long) TREE_INT_CST_LOW (n->low),
05229 IDENTIFIER_POINTER ((TREE_CODE (TYPE_NAME (type))
05230 == IDENTIFIER_NODE)
05231 ? TYPE_NAME (type)
05232 : DECL_NAME (TYPE_NAME (type))));
05233 }
05234 if (!tree_int_cst_equal (n->low, n->high))
05235 {
05236 for (chain = TYPE_VALUES (type);
05237 chain && !tree_int_cst_equal (n->high, TREE_VALUE (chain));
05238 chain = TREE_CHAIN (chain))
05239 ;
05240
05241 if (!chain)
05242 {
05243 if (TYPE_NAME (type) == 0)
05244 warning ("case value `%ld' not in enumerated type",
05245 (long) TREE_INT_CST_LOW (n->high));
05246 else
05247 warning ("case value `%ld' not in enumerated type `%s'",
05248 (long) TREE_INT_CST_LOW (n->high),
05249 IDENTIFIER_POINTER ((TREE_CODE (TYPE_NAME (type))
05250 == IDENTIFIER_NODE)
05251 ? TYPE_NAME (type)
05252 : DECL_NAME (TYPE_NAME (type))));
05253 }
05254 }
05255 }
05256 }
05257
05258
05259
05260
05261
05262
05263
05264
05265
05266 void
05267 expand_end_case_type (orig_index, orig_type)
05268 tree orig_index, orig_type;
05269 {
05270 tree minval = NULL_TREE, maxval = NULL_TREE, range = NULL_TREE;
05271 rtx default_label = 0;
05272 struct case_node *n;
05273 unsigned int count;
05274 rtx index;
05275 rtx table_label;
05276 int ncases;
05277 rtx *labelvec;
05278 int i;
05279 rtx before_case, end;
05280 struct nesting *thiscase = case_stack;
05281 tree index_expr, index_type;
05282 int unsignedp;
05283
05284
05285 if (thiscase == NULL)
05286 return;
05287
05288 table_label = gen_label_rtx ();
05289 index_expr = thiscase->data.case_stmt.index_expr;
05290 index_type = TREE_TYPE (index_expr);
05291 unsignedp = TREE_UNSIGNED (index_type);
05292 if (orig_type == NULL)
05293 orig_type = TREE_TYPE (orig_index);
05294
05295 do_pending_stack_adjust ();
05296
05297
05298
05299
05300
05301
05302
05303
05304 check_seenlabel ();
05305
05306
05307 if (index_type != error_mark_node)
05308 {
05309
05310
05311
05312
05313 if (((warn_switch && !thiscase->data.case_stmt.default_label)
05314 || warn_switch_enum)
05315 && TREE_CODE (orig_type) == ENUMERAL_TYPE
05316 && TREE_CODE (index_expr) != INTEGER_CST)
05317 check_for_full_enumeration_handling (orig_type);
05318
05319 if (warn_switch_default && !thiscase->data.case_stmt.default_label)
05320 warning ("switch missing default case");
05321
05322
05323
05324 if (thiscase->data.case_stmt.default_label == 0)
05325 {
05326 thiscase->data.case_stmt.default_label
05327 = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
05328 expand_label (thiscase->data.case_stmt.default_label);
05329 }
05330 default_label = label_rtx (thiscase->data.case_stmt.default_label);
05331
05332 before_case = get_last_insn ();
05333
05334 if (thiscase->data.case_stmt.case_list
05335 && thiscase->data.case_stmt.case_list->left)
05336 thiscase->data.case_stmt.case_list
05337 = case_tree2list (thiscase->data.case_stmt.case_list, 0);
05338
05339
05340 group_case_nodes (thiscase->data.case_stmt.case_list);
05341
05342
05343
05344
05345 count = 0;
05346 for (n = thiscase->data.case_stmt.case_list; n; n = n->right)
05347 {
05348
05349 if (TREE_CODE (n->low) != INTEGER_CST)
05350 abort ();
05351 if (TREE_CODE (n->high) != INTEGER_CST)
05352 abort ();
05353
05354 n->low = convert (index_type, n->low);
05355 n->high = convert (index_type, n->high);
05356
05357
05358
05359 if (count++ == 0)
05360 {
05361 minval = n->low;
05362 maxval = n->high;
05363 }
05364 else
05365 {
05366 if (INT_CST_LT (n->low, minval))
05367 minval = n->low;
05368 if (INT_CST_LT (maxval, n->high))
05369 maxval = n->high;
05370 }
05371
05372 if (! tree_int_cst_equal (n->low, n->high))
05373 count++;
05374 }
05375
05376
05377 if (count != 0)
05378 range = fold (build (MINUS_EXPR, index_type, maxval, minval));
05379
05380 end_cleanup_deferral ();
05381
05382 if (count == 0)
05383 {
05384 expand_expr (index_expr, const0_rtx, VOIDmode, 0);
05385 emit_queue ();
05386 emit_jump (default_label);
05387 }
05388
05389
05390
05391
05392
05393
05394 else if (count < case_values_threshold ()
05395 || compare_tree_int (range, 10 * count) > 0
05396
05397
05398 || compare_tree_int (range, 0) < 0
05399 #ifndef ASM_OUTPUT_ADDR_DIFF_ELT
05400 || flag_pic
05401 #endif
05402 || TREE_CODE (index_expr) == INTEGER_CST
05403 || (TREE_CODE (index_expr) == COMPOUND_EXPR
05404 && TREE_CODE (TREE_OPERAND (index_expr, 1)) == INTEGER_CST))
05405 {
05406 index = expand_expr (index_expr, NULL_RTX, VOIDmode, 0);
05407
05408
05409
05410
05411
05412
05413 if (GET_MODE_CLASS (GET_MODE (index)) == MODE_INT
05414 && ! have_insn_for (COMPARE, GET_MODE (index)))
05415 {
05416 enum machine_mode wider_mode;
05417 for (wider_mode = GET_MODE (index); wider_mode != VOIDmode;
05418 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
05419 if (have_insn_for (COMPARE, wider_mode))
05420 {
05421 index = convert_to_mode (wider_mode, index, unsignedp);
05422 break;
05423 }
05424 }
05425
05426 emit_queue ();
05427 do_pending_stack_adjust ();
05428
05429 index = protect_from_queue (index, 0);
05430 if (GET_CODE (index) == MEM)
05431 index = copy_to_reg (index);
05432 if (GET_CODE (index) == CONST_INT
05433 || TREE_CODE (index_expr) == INTEGER_CST)
05434 {
05435
05436
05437 if (TREE_CODE (index_expr) != INTEGER_CST)
05438 {
05439 index_expr
05440 = build_int_2 (INTVAL (index),
05441 unsignedp || INTVAL (index) >= 0 ? 0 : -1);
05442 index_expr = convert (index_type, index_expr);
05443 }
05444
05445
05446
05447
05448
05449
05450 for (n = thiscase->data.case_stmt.case_list; n; n = n->right)
05451 if (! tree_int_cst_lt (index_expr, n->low)
05452 && ! tree_int_cst_lt (n->high, index_expr))
05453 break;
05454
05455 if (n)
05456 emit_jump (label_rtx (n->code_label));
05457 else
05458 emit_jump (default_label);
05459 }
05460 else
05461 {
05462
05463
05464
05465
05466
05467
05468
05469
05470
05471
05472
05473
05474
05475
05476 use_cost_table
05477 = (TREE_CODE (orig_type) != ENUMERAL_TYPE
05478 && estimate_case_costs (thiscase->data.case_stmt.case_list));
05479 balance_case_nodes (&thiscase->data.case_stmt.case_list, NULL);
05480 emit_case_nodes (index, thiscase->data.case_stmt.case_list,
05481 default_label, index_type);
05482 emit_jump_if_reachable (default_label);
05483 }
05484 }
05485 else
05486 {
05487 if (! try_casesi (index_type, index_expr, minval, range,
05488 table_label, default_label))
05489 {
05490 index_type = thiscase->data.case_stmt.nominal_type;
05491
05492
05493
05494 if (! optimize_size
05495 && compare_tree_int (minval, 0) > 0
05496 && compare_tree_int (minval, 3) < 0)
05497 {
05498 minval = integer_zero_node;
05499 range = maxval;
05500 }
05501
05502 if (! try_tablejump (index_type, index_expr, minval, range,
05503 table_label, default_label))
05504 abort ();
05505 }
05506
05507
05508
05509 ncases = tree_low_cst (range, 0) + 1;
05510 labelvec = (rtx *) alloca (ncases * sizeof (rtx));
05511 memset ((char *) labelvec, 0, ncases * sizeof (rtx));
05512
05513 for (n = thiscase->data.case_stmt.case_list; n; n = n->right)
05514 {
05515
05516
05517
05518 HOST_WIDE_INT i_low
05519 = tree_low_cst (fold (build (MINUS_EXPR, index_type,
05520 n->low, minval)), 1);
05521 HOST_WIDE_INT i_high
05522 = tree_low_cst (fold (build (MINUS_EXPR, index_type,
05523 n->high, minval)), 1);
05524 HOST_WIDE_INT i;
05525
05526 for (i = i_low; i <= i_high; i ++)
05527 labelvec[i]
05528 = gen_rtx_LABEL_REF (Pmode, label_rtx (n->code_label));
05529 }
05530
05531
05532 for (i = 0; i < ncases; i++)
05533 if (labelvec[i] == 0)
05534 labelvec[i] = gen_rtx_LABEL_REF (Pmode, default_label);
05535
05536
05537 emit_label (table_label);
05538
05539 if (CASE_VECTOR_PC_RELATIVE || flag_pic)
05540 emit_jump_insn (gen_rtx_ADDR_DIFF_VEC (CASE_VECTOR_MODE,
05541 gen_rtx_LABEL_REF (Pmode, table_label),
05542 gen_rtvec_v (ncases, labelvec),
05543 const0_rtx, const0_rtx));
05544 else
05545 emit_jump_insn (gen_rtx_ADDR_VEC (CASE_VECTOR_MODE,
05546 gen_rtvec_v (ncases, labelvec)));
05547
05548
05549
05550
05551 #ifdef CASE_DROPS_THROUGH
05552 emit_jump (default_label);
05553 #else
05554 emit_barrier ();
05555 #endif
05556 }
05557
05558 before_case = NEXT_INSN (before_case);
05559 end = get_last_insn ();
05560 if (squeeze_notes (&before_case, &end))
05561 abort ();
05562 reorder_insns (before_case, end,
05563 thiscase->data.case_stmt.start);
05564 }
05565 else
05566 end_cleanup_deferral ();
05567
05568 if (thiscase->exit_label)
05569 emit_label (thiscase->exit_label);
05570
05571 POPSTACK (case_stack);
05572
05573 free_temp_slots ();
05574 }
05575
05576
05577
05578
05579
05580 static struct case_node *
05581 case_tree2list (node, right)
05582 struct case_node *node, *right;
05583 {
05584 struct case_node *left;
05585
05586 if (node->right)
05587 right = case_tree2list (node->right, right);
05588
05589 node->right = right;
05590 if ((left = node->left))
05591 {
05592 node->left = 0;
05593 return case_tree2list (left, node);
05594 }
05595
05596 return node;
05597 }
05598
05599
05600
05601 static void
05602 do_jump_if_equal (op1, op2, label, unsignedp)
05603 rtx op1, op2, label;
05604 int unsignedp;
05605 {
05606 if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT)
05607 {
05608 if (INTVAL (op1) == INTVAL (op2))
05609 emit_jump (label);
05610 }
05611 else
05612 emit_cmp_and_jump_insns (op1, op2, EQ, NULL_RTX,
05613 (GET_MODE (op1) == VOIDmode
05614 ? GET_MODE (op2) : GET_MODE (op1)),
05615 unsignedp, label);
05616 }
05617
05618
05619
05620
05621
05622
05623
05624
05625
05626
05627
05628
05629
05630
05631
05632
05633
05634
05635
05636
05637
05638
05639
05640
05641 static int
05642 estimate_case_costs (node)
05643 case_node_ptr node;
05644 {
05645 tree min_ascii = integer_minus_one_node;
05646 tree max_ascii = convert (TREE_TYPE (node->high), build_int_2 (127, 0));
05647 case_node_ptr n;
05648 int i;
05649
05650
05651
05652
05653 if (! cost_table_initialized)
05654 {
05655 cost_table_initialized = 1;
05656
05657 for (i = 0; i < 128; i++)
05658 {
05659 if (ISALNUM (i))
05660 COST_TABLE (i) = 16;
05661 else if (ISPUNCT (i))
05662 COST_TABLE (i) = 8;
05663 else if (ISCNTRL (i))
05664 COST_TABLE (i) = -1;
05665 }
05666
05667 COST_TABLE (' ') = 8;
05668 COST_TABLE ('\t') = 4;
05669 COST_TABLE ('\0') = 4;
05670 COST_TABLE ('\n') = 2;
05671 COST_TABLE ('\f') = 1;
05672 COST_TABLE ('\v') = 1;
05673 COST_TABLE ('\b') = 1;
05674 }
05675
05676
05677
05678
05679
05680
05681
05682 for (n = node; n; n = n->right)
05683 {
05684 if ((INT_CST_LT (n->low, min_ascii)) || INT_CST_LT (max_ascii, n->high))
05685 return 0;
05686
05687 for (i = (HOST_WIDE_INT) TREE_INT_CST_LOW (n->low);
05688 i <= (HOST_WIDE_INT) TREE_INT_CST_LOW (n->high); i++)
05689 if (COST_TABLE (i) < 0)
05690 return 0;
05691 }
05692
05693
05694
05695 return 1;
05696 }
05697
05698
05699
05700
05701
05702
05703 static void
05704 group_case_nodes (head)
05705 case_node_ptr head;
05706 {
05707 case_node_ptr node = head;
05708
05709 while (node)
05710 {
05711 rtx lb = next_real_insn (label_rtx (node->code_label));
05712 rtx lb2;
05713 case_node_ptr np = node;
05714
05715
05716 while (((np = np->right) != 0)
05717
05718 && ((lb2 = next_real_insn (label_rtx (np->code_label))) == lb
05719 || (lb != 0 && lb2 != 0
05720 && simplejump_p (lb)
05721 && simplejump_p (lb2)
05722 && rtx_equal_p (SET_SRC (PATTERN (lb)),
05723 SET_SRC (PATTERN (lb2)))))
05724
05725 && tree_int_cst_equal (np->low,
05726 fold (build (PLUS_EXPR,
05727 TREE_TYPE (node->high),
05728 node->high,
05729 integer_one_node)))
05730
05731 && tree_int_cst_lt (node->high,
05732 fold (build (PLUS_EXPR,
05733 TREE_TYPE (node->high),
05734 node->high,
05735 integer_one_node))))
05736 {
05737 node->high = np->high;
05738 }
05739
05740
05741 node->right = np;
05742 node = np;
05743 }
05744 }
05745
05746
05747
05748
05749
05750
05751
05752
05753
05754
05755
05756 static void
05757 balance_case_nodes (head, parent)
05758 case_node_ptr *head;
05759 case_node_ptr parent;
05760 {
05761 case_node_ptr np;
05762
05763 np = *head;
05764 if (np)
05765 {
05766 int cost = 0;
05767 int i = 0;
05768 int ranges = 0;
05769 case_node_ptr *npp;
05770 case_node_ptr left;
05771
05772
05773
05774 while (np)
05775 {
05776 if (!tree_int_cst_equal (np->low, np->high))
05777 {
05778 ranges++;
05779 if (use_cost_table)
05780 cost += COST_TABLE (TREE_INT_CST_LOW (np->high));
05781 }
05782
05783 if (use_cost_table)
05784 cost += COST_TABLE (TREE_INT_CST_LOW (np->low));
05785
05786 i++;
05787 np = np->right;
05788 }
05789
05790 if (i > 2)
05791 {
05792
05793 npp = head;
05794 left = *npp;
05795 if (use_cost_table)
05796 {
05797
05798
05799 int n_moved = 0;
05800 i = (cost + 1) / 2;
05801 while (1)
05802 {
05803
05804 if (!tree_int_cst_equal ((*npp)->low, (*npp)->high))
05805 i -= COST_TABLE (TREE_INT_CST_LOW ((*npp)->high));
05806 i -= COST_TABLE (TREE_INT_CST_LOW ((*npp)->low));
05807 if (i <= 0)
05808 break;
05809 npp = &(*npp)->right;
05810 n_moved += 1;
05811 }
05812 if (n_moved == 0)
05813 {
05814
05815
05816 np = *head;
05817 np->parent = parent;
05818 balance_case_nodes (&np->left, np);
05819 for (; np->right; np = np->right)
05820 np->right->parent = np;
05821 return;
05822 }
05823 }
05824
05825 else if (i == 3)
05826 npp = &(*npp)->right;
05827 else
05828 {
05829
05830
05831
05832 i = (i + ranges + 1) / 2;
05833 while (1)
05834 {
05835
05836 if (!tree_int_cst_equal ((*npp)->low, (*npp)->high))
05837 i--;
05838 i--;
05839 if (i <= 0)
05840 break;
05841 npp = &(*npp)->right;
05842 }
05843 }
05844 *head = np = *npp;
05845 *npp = 0;
05846 np->parent = parent;
05847 np->left = left;
05848
05849
05850 balance_case_nodes (&np->left, np);
05851 balance_case_nodes (&np->right, np);
05852 }
05853 else
05854 {
05855
05856
05857 np = *head;
05858 np->parent = parent;
05859 for (; np->right; np = np->right)
05860 np->right->parent = np;
05861 }
05862 }
05863 }
05864
05865
05866
05867
05868
05869
05870
05871
05872
05873
05874
05875 static int
05876 node_has_low_bound (node, index_type)
05877 case_node_ptr node;
05878 tree index_type;
05879 {
05880 tree low_minus_one;
05881 case_node_ptr pnode;
05882
05883
05884
05885
05886 if (tree_int_cst_equal (node->low, TYPE_MIN_VALUE (index_type)))
05887 return 1;
05888
05889
05890
05891
05892
05893 if (node->left)
05894 return 0;
05895
05896 low_minus_one = fold (build (MINUS_EXPR, TREE_TYPE (node->low),
05897 node->low, integer_one_node));
05898
05899
05900
05901
05902 if (! tree_int_cst_lt (low_minus_one, node->low))
05903 return 0;
05904
05905 for (pnode = node->parent; pnode; pnode = pnode->parent)
05906 if (tree_int_cst_equal (low_minus_one, pnode->high))
05907 return 1;
05908
05909 return 0;
05910 }
05911
05912
05913
05914
05915
05916
05917
05918
05919
05920
05921
05922 static int
05923 node_has_high_bound (node, index_type)
05924 case_node_ptr node;
05925 tree index_type;
05926 {
05927 tree high_plus_one;
05928 case_node_ptr pnode;
05929
05930
05931
05932 if (TYPE_MAX_VALUE (index_type) == NULL)
05933 return 1;
05934
05935
05936
05937
05938 if (tree_int_cst_equal (node->high, TYPE_MAX_VALUE (index_type)))
05939 return 1;
05940
05941
05942
05943
05944
05945 if (node->right)
05946 return 0;
05947
05948 high_plus_one = fold (build (PLUS_EXPR, TREE_TYPE (node->high),
05949 node->high, integer_one_node));
05950
05951
05952
05953
05954 if (! tree_int_cst_lt (node->high, high_plus_one))
05955 return 0;
05956
05957 for (pnode = node->parent; pnode; pnode = pnode->parent)
05958 if (tree_int_cst_equal (high_plus_one, pnode->low))
05959 return 1;
05960
05961 return 0;
05962 }
05963
05964
05965
05966
05967
05968 static int
05969 node_is_bounded (node, index_type)
05970 case_node_ptr node;
05971 tree index_type;
05972 {
05973 return (node_has_low_bound (node, index_type)
05974 && node_has_high_bound (node, index_type));
05975 }
05976
05977
05978
05979 static void
05980 emit_jump_if_reachable (label)
05981 rtx label;
05982 {
05983 if (GET_CODE (get_last_insn ()) != BARRIER)
05984 emit_jump (label);
05985 }
05986
05987
05988
05989
05990
05991
05992
05993
05994
05995
05996
05997
05998
05999
06000
06001
06002
06003
06004
06005
06006
06007
06008
06009
06010
06011
06012
06013 static void
06014 emit_case_nodes (index, node, default_label, index_type)
06015 rtx index;
06016 case_node_ptr node;
06017 rtx default_label;
06018 tree index_type;
06019 {
06020
06021 int unsignedp = TREE_UNSIGNED (index_type);
06022 enum machine_mode mode = GET_MODE (index);
06023 enum machine_mode imode = TYPE_MODE (index_type);
06024
06025
06026
06027 if (node_is_bounded (node, index_type))
06028 emit_jump (label_rtx (node->code_label));
06029
06030 else if (tree_int_cst_equal (node->low, node->high))
06031 {
06032
06033
06034
06035 do_jump_if_equal (index,
06036 convert_modes (mode, imode,
06037 expand_expr (node->low, NULL_RTX,
06038 VOIDmode, 0),
06039 unsignedp),
06040 label_rtx (node->code_label), unsignedp);
06041
06042 if (node->right != 0 && node->left != 0)
06043 {
06044
06045
06046
06047
06048
06049
06050 if (node_is_bounded (node->right, index_type))
06051 {
06052 emit_cmp_and_jump_insns (index,
06053 convert_modes
06054 (mode, imode,
06055 expand_expr (node->high, NULL_RTX,
06056 VOIDmode, 0),
06057 unsignedp),
06058 GT, NULL_RTX, mode, unsignedp,
06059 label_rtx (node->right->code_label));
06060 emit_case_nodes (index, node->left, default_label, index_type);
06061 }
06062
06063 else if (node_is_bounded (node->left, index_type))
06064 {
06065 emit_cmp_and_jump_insns (index,
06066 convert_modes
06067 (mode, imode,
06068 expand_expr (node->high, NULL_RTX,
06069 VOIDmode, 0),
06070 unsignedp),
06071 LT, NULL_RTX, mode, unsignedp,
06072 label_rtx (node->left->code_label));
06073 emit_case_nodes (index, node->right, default_label, index_type);
06074 }
06075
06076 else
06077 {
06078
06079
06080
06081 tree test_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
06082
06083
06084 emit_cmp_and_jump_insns (index,
06085 convert_modes
06086 (mode, imode,
06087 expand_expr (node->high, NULL_RTX,
06088 VOIDmode, 0),
06089 unsignedp),
06090 GT, NULL_RTX, mode, unsignedp,
06091 label_rtx (test_label));
06092
06093
06094
06095 emit_case_nodes (index, node->left, default_label, index_type);
06096
06097
06098 emit_jump_if_reachable (default_label);
06099
06100
06101 expand_label (test_label);
06102 emit_case_nodes (index, node->right, default_label, index_type);
06103 }
06104 }
06105
06106 else if (node->right != 0 && node->left == 0)
06107 {
06108
06109
06110
06111
06112
06113
06114 if (node->right->right || node->right->left
06115 || !tree_int_cst_equal (node->right->low, node->right->high))
06116 {
06117 if (!node_has_low_bound (node, index_type))
06118 {
06119 emit_cmp_and_jump_insns (index,
06120 convert_modes
06121 (mode, imode,
06122 expand_expr (node->high, NULL_RTX,
06123 VOIDmode, 0),
06124 unsignedp),
06125 LT, NULL_RTX, mode, unsignedp,
06126 default_label);
06127 }
06128
06129 emit_case_nodes (index, node->right, default_label, index_type);
06130 }
06131 else
06132
06133
06134
06135 do_jump_if_equal (index,
06136 convert_modes
06137 (mode, imode,
06138 expand_expr (node->right->low, NULL_RTX,
06139 VOIDmode, 0),
06140 unsignedp),
06141 label_rtx (node->right->code_label), unsignedp);
06142 }
06143
06144 else if (node->right == 0 && node->left != 0)
06145 {
06146
06147 if (node->left->left || node->left->right
06148 || !tree_int_cst_equal (node->left->low, node->left->high))
06149 {
06150 if (!node_has_high_bound (node, index_type))
06151 {
06152 emit_cmp_and_jump_insns (index,
06153 convert_modes
06154 (mode, imode,
06155 expand_expr (node->high, NULL_RTX,
06156 VOIDmode, 0),
06157 unsignedp),
06158 GT, NULL_RTX, mode, unsignedp,
06159 default_label);
06160 }
06161
06162 emit_case_nodes (index, node->left, default_label, index_type);
06163 }
06164 else
06165
06166
06167
06168 do_jump_if_equal (index,
06169 convert_modes
06170 (mode, imode,
06171 expand_expr (node->left->low, NULL_RTX,
06172 VOIDmode, 0),
06173 unsignedp),
06174 label_rtx (node->left->code_label), unsignedp);
06175 }
06176 }
06177 else
06178 {
06179
06180
06181
06182
06183 if (node->right != 0 && node->left != 0)
06184 {
06185
06186
06187
06188
06189
06190 tree test_label = 0;
06191
06192 if (node_is_bounded (node->right, index_type))
06193
06194
06195 emit_cmp_and_jump_insns (index,
06196 convert_modes
06197 (mode, imode,
06198 expand_expr (node->high, NULL_RTX,
06199 VOIDmode, 0),
06200 unsignedp),
06201 GT, NULL_RTX, mode, unsignedp,
06202 label_rtx (node->right->code_label));
06203 else
06204 {
06205
06206
06207
06208 test_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
06209 emit_cmp_and_jump_insns (index,
06210 convert_modes
06211 (mode, imode,
06212 expand_expr (node->high, NULL_RTX,
06213 VOIDmode, 0),
06214 unsignedp),
06215 GT, NULL_RTX, mode, unsignedp,
06216 label_rtx (test_label));
06217 }
06218
06219
06220
06221 emit_cmp_and_jump_insns (index,
06222 convert_modes
06223 (mode, imode,
06224 expand_expr (node->low, NULL_RTX,
06225 VOIDmode, 0),
06226 unsignedp),
06227 GE, NULL_RTX, mode, unsignedp,
06228 label_rtx (node->code_label));
06229
06230
06231 emit_case_nodes (index, node->left, default_label, index_type);
06232
06233
06234
06235 if (test_label)
06236 {
06237
06238
06239 emit_jump_if_reachable (default_label);
06240
06241 expand_label (test_label);
06242 emit_case_nodes (index, node->right, default_label, index_type);
06243 }
06244 }
06245
06246 else if (node->right != 0 && node->left == 0)
06247 {
06248
06249
06250 if (!node_has_low_bound (node, index_type))
06251 {
06252 emit_cmp_and_jump_insns (index,
06253 convert_modes
06254 (mode, imode,
06255 expand_expr (node->low, NULL_RTX,
06256 VOIDmode, 0),
06257 unsignedp),
06258 LT, NULL_RTX, mode, unsignedp,
06259 default_label);
06260 }
06261
06262
06263
06264 emit_cmp_and_jump_insns (index,
06265 convert_modes
06266 (mode, imode,
06267 expand_expr (node->high, NULL_RTX,
06268 VOIDmode, 0),
06269 unsignedp),
06270 LE, NULL_RTX, mode, unsignedp,
06271 label_rtx (node->code_label));
06272
06273 emit_case_nodes (index, node->right, default_label, index_type);
06274 }
06275
06276 else if (node->right == 0 && node->left != 0)
06277 {
06278
06279
06280 if (!node_has_high_bound (node, index_type))
06281 {
06282 emit_cmp_and_jump_insns (index,
06283 convert_modes
06284 (mode, imode,
06285 expand_expr (node->high, NULL_RTX,
06286 VOIDmode, 0),
06287 unsignedp),
06288 GT, NULL_RTX, mode, unsignedp,
06289 default_label);
06290 }
06291
06292
06293
06294 emit_cmp_and_jump_insns (index,
06295 convert_modes
06296 (mode, imode,
06297 expand_expr (node->low, NULL_RTX,
06298 VOIDmode, 0),
06299 unsignedp),
06300 GE, NULL_RTX, mode, unsignedp,
06301 label_rtx (node->code_label));
06302
06303 emit_case_nodes (index, node->left, default_label, index_type);
06304 }
06305
06306 else
06307 {
06308
06309
06310
06311 int high_bound = node_has_high_bound (node, index_type);
06312 int low_bound = node_has_low_bound (node, index_type);
06313
06314 if (!high_bound && low_bound)
06315 {
06316 emit_cmp_and_jump_insns (index,
06317 convert_modes
06318 (mode, imode,
06319 expand_expr (node->high, NULL_RTX,
06320 VOIDmode, 0),
06321 unsignedp),
06322 GT, NULL_RTX, mode, unsignedp,
06323 default_label);
06324 }
06325
06326 else if (!low_bound && high_bound)
06327 {
06328 emit_cmp_and_jump_insns (index,
06329 convert_modes
06330 (mode, imode,
06331 expand_expr (node->low, NULL_RTX,
06332 VOIDmode, 0),
06333 unsignedp),
06334 LT, NULL_RTX, mode, unsignedp,
06335 default_label);
06336 }
06337 else if (!low_bound && !high_bound)
06338 {
06339
06340 tree type = (*lang_hooks.types.type_for_mode) (mode, unsignedp);
06341 tree low = build1 (CONVERT_EXPR, type, node->low);
06342 tree high = build1 (CONVERT_EXPR, type, node->high);
06343 rtx low_rtx, new_index, new_bound;
06344
06345
06346
06347 low_rtx = expand_expr (low, NULL_RTX, mode, 0);
06348 new_index = expand_simple_binop (mode, MINUS, index, low_rtx,
06349 NULL_RTX, unsignedp,
06350 OPTAB_WIDEN);
06351 new_bound = expand_expr (fold (build (MINUS_EXPR, type,
06352 high, low)),
06353 NULL_RTX, mode, 0);
06354
06355 emit_cmp_and_jump_insns (new_index, new_bound, GT, NULL_RTX,
06356 mode, 1, default_label);
06357 }
06358
06359 emit_jump (label_rtx (node->code_label));
06360 }
06361 }
06362 }
06363
06364 #include "gt-stmt.h"