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