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
00043
00044
00045 #include "config.h"
00046 #include "system.h"
00047 #include "rtl.h"
00048 #include "tree.h"
00049 #include "flags.h"
00050 #include "except.h"
00051 #include "function.h"
00052 #include "expr.h"
00053 #include "libfuncs.h"
00054 #include "regs.h"
00055 #include "hard-reg-set.h"
00056 #include "insn-config.h"
00057 #include "recog.h"
00058 #include "output.h"
00059 #include "basic-block.h"
00060 #include "toplev.h"
00061 #include "hashtab.h"
00062 #include "ggc.h"
00063 #include "tm_p.h"
00064 #include "integrate.h"
00065 #include "langhooks.h"
00066 #ifdef SGI_MONGOOSE
00067 #ifndef KEY // We should not use this file any more
00068 #include "MIPS/elf.h"
00069 #endif // !KEY
00070
00071 #include "defaults.h"
00072 #endif
00073
00074 #ifndef TRAMPOLINE_ALIGNMENT
00075 #define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
00076 #endif
00077
00078 #ifndef LOCAL_ALIGNMENT
00079 #define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
00080 #endif
00081
00082
00083
00084
00085
00086 #ifndef NAME__MAIN
00087 #define NAME__MAIN "__main"
00088 #endif
00089
00090
00091
00092
00093 #define FLOOR_ROUND(VALUE,ALIGN) ((VALUE) & ~((ALIGN) - 1))
00094
00095
00096
00097 #define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
00098
00099
00100
00101
00102
00103
00104
00105 #if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
00106 #define NEED_SEPARATE_AP
00107 #endif
00108
00109
00110
00111
00112
00113 int current_function_is_leaf;
00114
00115
00116
00117
00118 int current_function_nothrow;
00119
00120
00121
00122
00123 int current_function_sp_is_unchanging;
00124
00125
00126
00127
00128 int current_function_uses_only_leaf_regs;
00129
00130
00131
00132
00133
00134 int virtuals_instantiated;
00135
00136
00137 int trampolines_created;
00138
00139
00140 static int funcdef_no;
00141
00142
00143
00144 struct machine_function * (*init_machine_status) PARAMS ((void));
00145
00146
00147 tree inline_function_decl;
00148
00149
00150 struct function *cfun = 0;
00151
00152
00153 static GTY(()) varray_type prologue;
00154 static GTY(()) varray_type epilogue;
00155
00156
00157
00158 static GTY(()) varray_type sibcall_epilogue;
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 struct temp_slot GTY(())
00179 {
00180
00181 struct temp_slot *next;
00182
00183 rtx slot;
00184
00185
00186 rtx address;
00187
00188 unsigned int align;
00189
00190 HOST_WIDE_INT size;
00191
00192
00193
00194
00195 tree type;
00196
00197 tree rtl_expr;
00198
00199 char in_use;
00200
00201 char addr_taken;
00202
00203 int level;
00204
00205 int keep;
00206
00207
00208 HOST_WIDE_INT base_offset;
00209
00210
00211 HOST_WIDE_INT full_size;
00212 };
00213
00214
00215
00216
00217
00218
00219 struct fixup_replacement GTY(())
00220 {
00221 rtx old;
00222 rtx new;
00223 struct fixup_replacement *next;
00224 };
00225
00226 struct insns_for_mem_entry
00227 {
00228
00229 rtx key;
00230
00231 rtx insns;
00232 };
00233
00234
00235
00236 static rtx assign_stack_local_1 PARAMS ((enum machine_mode, HOST_WIDE_INT,
00237 int, struct function *));
00238 static struct temp_slot *find_temp_slot_from_address PARAMS ((rtx));
00239 static void put_reg_into_stack PARAMS ((struct function *, rtx, tree,
00240 enum machine_mode, enum machine_mode,
00241 int, unsigned int, int,
00242 htab_t));
00243 static void schedule_fixup_var_refs PARAMS ((struct function *, rtx, tree,
00244 enum machine_mode,
00245 htab_t));
00246 static void fixup_var_refs PARAMS ((rtx, enum machine_mode, int, rtx,
00247 htab_t));
00248 static struct fixup_replacement
00249 *find_fixup_replacement PARAMS ((struct fixup_replacement **, rtx));
00250 static void fixup_var_refs_insns PARAMS ((rtx, rtx, enum machine_mode,
00251 int, int, rtx));
00252 static void fixup_var_refs_insns_with_hash
00253 PARAMS ((htab_t, rtx,
00254 enum machine_mode, int, rtx));
00255 static void fixup_var_refs_insn PARAMS ((rtx, rtx, enum machine_mode,
00256 int, int, rtx));
00257 static void fixup_var_refs_1 PARAMS ((rtx, enum machine_mode, rtx *, rtx,
00258 struct fixup_replacement **, rtx));
00259 static rtx fixup_memory_subreg PARAMS ((rtx, rtx, enum machine_mode, int));
00260 static rtx walk_fixup_memory_subreg PARAMS ((rtx, rtx, enum machine_mode,
00261 int));
00262 static rtx fixup_stack_1 PARAMS ((rtx, rtx));
00263 static void optimize_bit_field PARAMS ((rtx, rtx, rtx *));
00264 static void instantiate_decls PARAMS ((tree, int));
00265 static void instantiate_decls_1 PARAMS ((tree, int));
00266 static void instantiate_decl PARAMS ((rtx, HOST_WIDE_INT, int));
00267 static rtx instantiate_new_reg PARAMS ((rtx, HOST_WIDE_INT *));
00268 static int instantiate_virtual_regs_1 PARAMS ((rtx *, rtx, int));
00269 static void delete_handlers PARAMS ((void));
00270 static void pad_to_arg_alignment PARAMS ((struct args_size *, int,
00271 struct args_size *));
00272 static void pad_below PARAMS ((struct args_size *, enum machine_mode,
00273 tree));
00274 static rtx round_trampoline_addr PARAMS ((rtx));
00275 static rtx adjust_trampoline_addr PARAMS ((rtx));
00276 static tree *identify_blocks_1 PARAMS ((rtx, tree *, tree *, tree *));
00277 static void reorder_blocks_0 PARAMS ((tree));
00278 static void reorder_blocks_1 PARAMS ((rtx, tree, varray_type *));
00279 static void reorder_fix_fragments PARAMS ((tree));
00280 static tree blocks_nreverse PARAMS ((tree));
00281 static int all_blocks PARAMS ((tree, tree *));
00282 static tree *get_block_vector PARAMS ((tree, int *));
00283 extern tree debug_find_var_in_block_tree PARAMS ((tree, tree));
00284
00285
00286 static void record_insns PARAMS ((rtx, varray_type *)) ATTRIBUTE_UNUSED;
00287 static int contains PARAMS ((rtx, varray_type));
00288 #ifdef HAVE_return
00289 static void emit_return_into_block PARAMS ((basic_block, rtx));
00290 #endif
00291 static void put_addressof_into_stack PARAMS ((rtx, htab_t));
00292 static bool purge_addressof_1 PARAMS ((rtx *, rtx, int, int,
00293 htab_t));
00294 static void purge_single_hard_subreg_set PARAMS ((rtx));
00295 #if defined(HAVE_epilogue) && defined(INCOMING_RETURN_ADDR_RTX)
00296 static rtx keep_stack_depressed PARAMS ((rtx));
00297 #endif
00298 static int is_addressof PARAMS ((rtx *, void *));
00299 static hashval_t insns_for_mem_hash PARAMS ((const void *));
00300 static int insns_for_mem_comp PARAMS ((const void *, const void *));
00301 static int insns_for_mem_walk PARAMS ((rtx *, void *));
00302 static void compute_insns_for_mem PARAMS ((rtx, rtx, htab_t));
00303 static void prepare_function_start PARAMS ((void));
00304 static void do_clobber_return_reg PARAMS ((rtx, void *));
00305 static void do_use_return_reg PARAMS ((rtx, void *));
00306 static void instantiate_virtual_regs_lossage PARAMS ((rtx));
00307
00308
00309 static GTY(()) struct function *outer_function_chain;
00310
00311
00312
00313
00314 struct function *
00315 find_function_data (decl)
00316 tree decl;
00317 {
00318 struct function *p;
00319
00320 for (p = outer_function_chain; p; p = p->outer)
00321 if (p->decl == decl)
00322 return p;
00323
00324 abort ();
00325 }
00326
00327
00328
00329
00330
00331
00332
00333 void
00334 push_function_context_to (context)
00335 tree context;
00336 {
00337 struct function *p;
00338
00339 if (context)
00340 {
00341 if (context == current_function_decl)
00342 cfun->contains_functions = 1;
00343 else
00344 {
00345 struct function *containing = find_function_data (context);
00346 containing->contains_functions = 1;
00347 }
00348 }
00349
00350 if (cfun == 0)
00351 init_dummy_function_start ();
00352 p = cfun;
00353
00354 p->outer = outer_function_chain;
00355 outer_function_chain = p;
00356 p->fixup_var_refs_queue = 0;
00357
00358 (*lang_hooks.function.enter_nested) (p);
00359
00360 cfun = 0;
00361 }
00362
00363 void
00364 push_function_context ()
00365 {
00366 push_function_context_to (current_function_decl);
00367 }
00368
00369
00370
00371
00372 void
00373 pop_function_context_from (context)
00374 tree context ATTRIBUTE_UNUSED;
00375 {
00376 struct function *p = outer_function_chain;
00377 struct var_refs_queue *queue;
00378
00379 cfun = p;
00380 outer_function_chain = p->outer;
00381
00382 current_function_decl = p->decl;
00383 reg_renumber = 0;
00384
00385 restore_emit_status (p);
00386
00387 (*lang_hooks.function.leave_nested) (p);
00388
00389
00390
00391
00392
00393 if (p->fixup_var_refs_queue == 0)
00394 ;
00395 else if (p->fixup_var_refs_queue->next == 0)
00396 fixup_var_refs (p->fixup_var_refs_queue->modified,
00397 p->fixup_var_refs_queue->promoted_mode,
00398 p->fixup_var_refs_queue->unsignedp,
00399 p->fixup_var_refs_queue->modified, 0);
00400 else
00401 {
00402 rtx list = 0;
00403
00404 for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
00405 list = gen_rtx_EXPR_LIST (VOIDmode, queue->modified, list);
00406
00407 for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
00408 fixup_var_refs (queue->modified, queue->promoted_mode,
00409 queue->unsignedp, list, 0);
00410
00411 }
00412
00413 p->fixup_var_refs_queue = 0;
00414
00415
00416 rtx_equal_function_value_matters = 1;
00417 virtuals_instantiated = 0;
00418 generating_concat_p = 1;
00419 }
00420
00421 void
00422 pop_function_context ()
00423 {
00424 pop_function_context_from (current_function_decl);
00425 }
00426
00427
00428
00429
00430
00431 void
00432 free_after_parsing (f)
00433 struct function *f;
00434 {
00435
00436
00437
00438
00439
00440 (*lang_hooks.function.final) (f);
00441 f->stmt = NULL;
00442 }
00443
00444
00445
00446
00447
00448 void
00449 free_after_compilation (f)
00450 struct function *f;
00451 {
00452 f->eh = NULL;
00453 f->expr = NULL;
00454 f->emit = NULL;
00455 f->varasm = NULL;
00456 f->machine = NULL;
00457
00458 f->x_temp_slots = NULL;
00459 f->arg_offset_rtx = NULL;
00460 f->return_rtx = NULL;
00461 f->internal_arg_pointer = NULL;
00462 f->x_nonlocal_labels = NULL;
00463 f->x_nonlocal_goto_handler_slots = NULL;
00464 f->x_nonlocal_goto_handler_labels = NULL;
00465 f->x_nonlocal_goto_stack_level = NULL;
00466 f->x_cleanup_label = NULL;
00467 f->x_return_label = NULL;
00468 f->computed_goto_common_label = NULL;
00469 f->computed_goto_common_reg = NULL;
00470 f->x_save_expr_regs = NULL;
00471 f->x_stack_slot_list = NULL;
00472 f->x_rtl_expr_chain = NULL;
00473 f->x_tail_recursion_label = NULL;
00474 f->x_tail_recursion_reentry = NULL;
00475 f->x_arg_pointer_save_area = NULL;
00476 f->x_clobber_return_insn = NULL;
00477 f->x_context_display = NULL;
00478 f->x_trampoline_list = NULL;
00479 f->x_parm_birth_insn = NULL;
00480 f->x_last_parm_insn = NULL;
00481 f->x_parm_reg_stack_loc = NULL;
00482 f->fixup_var_refs_queue = NULL;
00483 f->original_arg_vector = NULL;
00484 f->original_decl_initial = NULL;
00485 f->inl_last_parm_insn = NULL;
00486 f->epilogue_delay_list = NULL;
00487 }
00488
00489
00490
00491
00492
00493
00494
00495
00496 HOST_WIDE_INT
00497 get_func_frame_size (f)
00498 struct function *f;
00499 {
00500 #ifdef FRAME_GROWS_DOWNWARD
00501 return -f->x_frame_offset;
00502 #else
00503 return f->x_frame_offset;
00504 #endif
00505 }
00506
00507
00508
00509
00510 HOST_WIDE_INT
00511 get_frame_size ()
00512 {
00513 return get_func_frame_size (cfun);
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528 static rtx
00529 assign_stack_local_1 (mode, size, align, function)
00530 enum machine_mode mode;
00531 HOST_WIDE_INT size;
00532 int align;
00533 struct function *function;
00534 {
00535 rtx x, addr;
00536 int bigend_correction = 0;
00537 int alignment;
00538 int frame_off, frame_alignment, frame_phase;
00539
00540 if (align == 0)
00541 {
00542 tree type;
00543
00544 if (mode == BLKmode)
00545 alignment = BIGGEST_ALIGNMENT;
00546 else
00547 alignment = GET_MODE_ALIGNMENT (mode);
00548
00549
00550
00551 type = (*lang_hooks.types.type_for_mode) (mode, 0);
00552 if (type)
00553 alignment = LOCAL_ALIGNMENT (type, alignment);
00554
00555 alignment /= BITS_PER_UNIT;
00556 }
00557 else if (align == -1)
00558 {
00559 alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
00560 size = CEIL_ROUND (size, alignment);
00561 }
00562 else
00563 alignment = align / BITS_PER_UNIT;
00564
00565 #ifdef FRAME_GROWS_DOWNWARD
00566 function->x_frame_offset -= size;
00567 #endif
00568
00569
00570 if (alignment * BITS_PER_UNIT > PREFERRED_STACK_BOUNDARY)
00571 alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
00572
00573 if (function->stack_alignment_needed < alignment * BITS_PER_UNIT)
00574 function->stack_alignment_needed = alignment * BITS_PER_UNIT;
00575
00576
00577
00578 frame_alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
00579 frame_off = STARTING_FRAME_OFFSET % frame_alignment;
00580 frame_phase = frame_off ? frame_alignment - frame_off : 0;
00581
00582
00583
00584
00585
00586
00587 #ifdef FRAME_GROWS_DOWNWARD
00588 function->x_frame_offset = FLOOR_ROUND (function->x_frame_offset - frame_phase, alignment) + frame_phase;
00589 #else
00590 function->x_frame_offset = CEIL_ROUND (function->x_frame_offset - frame_phase, alignment) + frame_phase;
00591 #endif
00592
00593
00594
00595 if (BYTES_BIG_ENDIAN && mode != BLKmode)
00596 bigend_correction = size - GET_MODE_SIZE (mode);
00597
00598
00599
00600 if (function == cfun && virtuals_instantiated)
00601 addr = plus_constant (frame_pointer_rtx,
00602 (frame_offset + bigend_correction
00603 + STARTING_FRAME_OFFSET));
00604 else
00605 addr = plus_constant (virtual_stack_vars_rtx,
00606 function->x_frame_offset + bigend_correction);
00607
00608 #ifndef FRAME_GROWS_DOWNWARD
00609 function->x_frame_offset += size;
00610 #endif
00611
00612 x = gen_rtx_MEM (mode, addr);
00613
00614 function->x_stack_slot_list
00615 = gen_rtx_EXPR_LIST (VOIDmode, x, function->x_stack_slot_list);
00616
00617 return x;
00618 }
00619
00620
00621
00622
00623 rtx
00624 assign_stack_local (mode, size, align)
00625 enum machine_mode mode;
00626 HOST_WIDE_INT size;
00627 int align;
00628 {
00629 return assign_stack_local_1 (mode, size, align, cfun);
00630 }
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649 rtx
00650 assign_stack_temp_for_type (mode, size, keep, type)
00651 enum machine_mode mode;
00652 HOST_WIDE_INT size;
00653 int keep;
00654 tree type;
00655 {
00656 unsigned int align;
00657 struct temp_slot *p, *best_p = 0;
00658 rtx slot;
00659
00660
00661
00662 if (size == -1)
00663 abort ();
00664
00665 if (mode == BLKmode)
00666 align = BIGGEST_ALIGNMENT;
00667 else
00668 align = GET_MODE_ALIGNMENT (mode);
00669
00670 if (! type)
00671 type = (*lang_hooks.types.type_for_mode) (mode, 0);
00672
00673 if (type)
00674 align = LOCAL_ALIGNMENT (type, align);
00675
00676
00677
00678
00679 for (p = temp_slots; p; p = p->next)
00680 if (p->align >= align && p->size >= size && GET_MODE (p->slot) == mode
00681 && ! p->in_use
00682 && objects_must_conflict_p (p->type, type)
00683 && (best_p == 0 || best_p->size > p->size
00684 || (best_p->size == p->size && best_p->align > p->align)))
00685 {
00686 if (p->align == align && p->size == size)
00687 {
00688 best_p = 0;
00689 break;
00690 }
00691 best_p = p;
00692 }
00693
00694
00695 if (best_p)
00696 {
00697
00698
00699
00700 if (GET_MODE (best_p->slot) == BLKmode)
00701 {
00702 int alignment = best_p->align / BITS_PER_UNIT;
00703 HOST_WIDE_INT rounded_size = CEIL_ROUND (size, alignment);
00704
00705 if (best_p->size - rounded_size >= alignment)
00706 {
00707 p = (struct temp_slot *) ggc_alloc (sizeof (struct temp_slot));
00708 p->in_use = p->addr_taken = 0;
00709 p->size = best_p->size - rounded_size;
00710 p->base_offset = best_p->base_offset + rounded_size;
00711 p->full_size = best_p->full_size - rounded_size;
00712 p->slot = gen_rtx_MEM (BLKmode,
00713 plus_constant (XEXP (best_p->slot, 0),
00714 rounded_size));
00715 p->align = best_p->align;
00716 p->address = 0;
00717 p->rtl_expr = 0;
00718 p->type = best_p->type;
00719 p->next = temp_slots;
00720 temp_slots = p;
00721
00722 stack_slot_list = gen_rtx_EXPR_LIST (VOIDmode, p->slot,
00723 stack_slot_list);
00724
00725 best_p->size = rounded_size;
00726 best_p->full_size = rounded_size;
00727 }
00728 }
00729
00730 p = best_p;
00731 }
00732
00733
00734 if (p == 0)
00735 {
00736 HOST_WIDE_INT frame_offset_old = frame_offset;
00737
00738 p = (struct temp_slot *) ggc_alloc (sizeof (struct temp_slot));
00739
00740
00741
00742
00743
00744
00745
00746
00747 if (mode == BLKmode && align < BIGGEST_ALIGNMENT)
00748 abort ();
00749 p->slot = assign_stack_local (mode,
00750 (mode == BLKmode
00751 ? CEIL_ROUND (size, align / BITS_PER_UNIT)
00752 : size),
00753 align);
00754
00755 p->align = align;
00756
00757
00758
00759
00760
00761
00762
00763
00764 #ifdef FRAME_GROWS_DOWNWARD
00765 p->size = frame_offset_old - frame_offset;
00766 #else
00767 p->size = size;
00768 #endif
00769
00770
00771 #ifdef FRAME_GROWS_DOWNWARD
00772 p->base_offset = frame_offset;
00773 p->full_size = frame_offset_old - frame_offset;
00774 #else
00775 p->base_offset = frame_offset_old;
00776 p->full_size = frame_offset - frame_offset_old;
00777 #endif
00778 p->address = 0;
00779 p->next = temp_slots;
00780 temp_slots = p;
00781 }
00782
00783 p->in_use = 1;
00784 p->addr_taken = 0;
00785 p->rtl_expr = seq_rtl_expr;
00786 p->type = type;
00787
00788 if (keep == 2)
00789 {
00790 p->level = target_temp_slot_level;
00791 p->keep = 0;
00792 }
00793 else if (keep == 3)
00794 {
00795 p->level = var_temp_slot_level;
00796 p->keep = 0;
00797 }
00798 else
00799 {
00800 p->level = temp_slot_level;
00801 p->keep = keep;
00802 }
00803
00804
00805
00806 slot = gen_rtx_MEM (mode, XEXP (p->slot, 0));
00807 stack_slot_list = gen_rtx_EXPR_LIST (VOIDmode, slot, stack_slot_list);
00808
00809
00810
00811
00812 set_mem_alias_set (slot, type ? get_alias_set (type) : 0);
00813 set_mem_align (slot, align);
00814
00815
00816 if (type != 0)
00817 {
00818 RTX_UNCHANGING_P (slot) = (lang_hooks.honor_readonly
00819 && TYPE_READONLY (type));
00820 MEM_VOLATILE_P (slot) = TYPE_VOLATILE (type);
00821 MEM_SET_IN_STRUCT_P (slot, AGGREGATE_TYPE_P (type));
00822 }
00823
00824 return slot;
00825 }
00826
00827
00828
00829
00830 rtx
00831 assign_stack_temp (mode, size, keep)
00832 enum machine_mode mode;
00833 HOST_WIDE_INT size;
00834 int keep;
00835 {
00836 return assign_stack_temp_for_type (mode, size, keep, NULL_TREE);
00837 }
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849 rtx
00850 assign_temp (type_or_decl, keep, memory_required, dont_promote)
00851 tree type_or_decl;
00852 int keep;
00853 int memory_required;
00854 int dont_promote ATTRIBUTE_UNUSED;
00855 {
00856 tree type, decl;
00857 enum machine_mode mode;
00858 #ifndef PROMOTE_FOR_CALL_ONLY
00859 int unsignedp;
00860 #endif
00861
00862 if (DECL_P (type_or_decl))
00863 decl = type_or_decl, type = TREE_TYPE (decl);
00864 else
00865 decl = NULL, type = type_or_decl;
00866
00867 mode = TYPE_MODE (type);
00868 #ifndef PROMOTE_FOR_CALL_ONLY
00869 unsignedp = TREE_UNSIGNED (type);
00870 #endif
00871
00872 if (mode == BLKmode || memory_required)
00873 {
00874 HOST_WIDE_INT size = int_size_in_bytes (type);
00875 rtx tmp;
00876
00877
00878
00879 if (size == 0)
00880 size = 1;
00881
00882
00883
00884
00885
00886 if (size == -1 && TREE_CODE (type) == ARRAY_TYPE
00887 && TYPE_ARRAY_MAX_SIZE (type) != NULL_TREE
00888 && host_integerp (TYPE_ARRAY_MAX_SIZE (type), 1))
00889 size = tree_low_cst (TYPE_ARRAY_MAX_SIZE (type), 1);
00890
00891
00892
00893
00894
00895 if (decl && size == -1
00896 && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST)
00897 {
00898 error_with_decl (decl, "size of variable `%s' is too large");
00899 size = 1;
00900 }
00901
00902 tmp = assign_stack_temp_for_type (mode, size, keep, type);
00903 return tmp;
00904 }
00905
00906 #ifndef PROMOTE_FOR_CALL_ONLY
00907 if (! dont_promote)
00908 mode = promote_mode (type, mode, &unsignedp, 0);
00909 #endif
00910
00911 return gen_reg_rtx (mode);
00912 }
00913
00914
00915
00916
00917
00918
00919
00920 void
00921 combine_temp_slots ()
00922 {
00923 struct temp_slot *p, *q;
00924 struct temp_slot *prev_p, *prev_q;
00925 int num_slots;
00926
00927
00928
00929 if (flag_strict_aliasing)
00930 return;
00931
00932
00933
00934 if (! flag_expensive_optimizations)
00935 for (p = temp_slots, num_slots = 0; p; p = p->next, num_slots++)
00936 if (num_slots > 100 || (num_slots > 10 && optimize == 0))
00937 return;
00938
00939 for (p = temp_slots, prev_p = 0; p; p = prev_p ? prev_p->next : temp_slots)
00940 {
00941 int delete_p = 0;
00942
00943 if (! p->in_use && GET_MODE (p->slot) == BLKmode)
00944 for (q = p->next, prev_q = p; q; q = prev_q->next)
00945 {
00946 int delete_q = 0;
00947 if (! q->in_use && GET_MODE (q->slot) == BLKmode)
00948 {
00949 if (p->base_offset + p->full_size == q->base_offset)
00950 {
00951
00952 p->size += q->size;
00953 p->full_size += q->full_size;
00954 delete_q = 1;
00955 }
00956 else if (q->base_offset + q->full_size == p->base_offset)
00957 {
00958
00959 q->size += p->size;
00960 q->full_size += p->full_size;
00961 delete_p = 1;
00962 break;
00963 }
00964 }
00965
00966 if (delete_q)
00967 prev_q->next = q->next;
00968 else
00969 prev_q = q;
00970 }
00971
00972 if (delete_p)
00973 {
00974 if (prev_p)
00975 prev_p->next = p->next;
00976 else
00977 temp_slots = p->next;
00978 }
00979 else
00980 prev_p = p;
00981 }
00982 }
00983
00984
00985
00986 static struct temp_slot *
00987 find_temp_slot_from_address (x)
00988 rtx x;
00989 {
00990 struct temp_slot *p;
00991 rtx next;
00992
00993 for (p = temp_slots; p; p = p->next)
00994 {
00995 if (! p->in_use)
00996 continue;
00997
00998 else if (XEXP (p->slot, 0) == x
00999 || p->address == x
01000 || (GET_CODE (x) == PLUS
01001 && XEXP (x, 0) == virtual_stack_vars_rtx
01002 && GET_CODE (XEXP (x, 1)) == CONST_INT
01003 && INTVAL (XEXP (x, 1)) >= p->base_offset
01004 && INTVAL (XEXP (x, 1)) < p->base_offset + p->full_size))
01005 return p;
01006
01007 else if (p->address != 0 && GET_CODE (p->address) == EXPR_LIST)
01008 for (next = p->address; next; next = XEXP (next, 1))
01009 if (XEXP (next, 0) == x)
01010 return p;
01011 }
01012
01013
01014
01015 if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == REG
01016 && (p = find_temp_slot_from_address (XEXP (x, 0))) != 0)
01017 return p;
01018 else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == REG
01019 && (p = find_temp_slot_from_address (XEXP (x, 1))) != 0)
01020 return p;
01021
01022 return 0;
01023 }
01024
01025
01026
01027
01028 void
01029 update_temp_slot_address (old, new)
01030 rtx old, new;
01031 {
01032 struct temp_slot *p;
01033
01034 if (rtx_equal_p (old, new))
01035 return;
01036
01037 p = find_temp_slot_from_address (old);
01038
01039
01040
01041
01042
01043
01044 if (p == 0)
01045 {
01046 if (GET_CODE (old) != PLUS)
01047 return;
01048
01049 if (GET_CODE (new) == REG)
01050 {
01051 update_temp_slot_address (XEXP (old, 0), new);
01052 update_temp_slot_address (XEXP (old, 1), new);
01053 return;
01054 }
01055 else if (GET_CODE (new) != PLUS)
01056 return;
01057
01058 if (rtx_equal_p (XEXP (old, 0), XEXP (new, 0)))
01059 update_temp_slot_address (XEXP (old, 1), XEXP (new, 1));
01060 else if (rtx_equal_p (XEXP (old, 1), XEXP (new, 0)))
01061 update_temp_slot_address (XEXP (old, 0), XEXP (new, 1));
01062 else if (rtx_equal_p (XEXP (old, 0), XEXP (new, 1)))
01063 update_temp_slot_address (XEXP (old, 1), XEXP (new, 0));
01064 else if (rtx_equal_p (XEXP (old, 1), XEXP (new, 1)))
01065 update_temp_slot_address (XEXP (old, 0), XEXP (new, 0));
01066
01067 return;
01068 }
01069
01070
01071 else if (p->address == 0)
01072 p->address = new;
01073 else
01074 {
01075 if (GET_CODE (p->address) != EXPR_LIST)
01076 p->address = gen_rtx_EXPR_LIST (VOIDmode, p->address, NULL_RTX);
01077
01078 p->address = gen_rtx_EXPR_LIST (VOIDmode, new, p->address);
01079 }
01080 }
01081
01082
01083
01084
01085 void
01086 mark_temp_addr_taken (x)
01087 rtx x;
01088 {
01089 struct temp_slot *p;
01090
01091 if (x == 0)
01092 return;
01093
01094
01095
01096 if (GET_CODE (x) != MEM || CONSTANT_P (XEXP (x, 0)))
01097 return;
01098
01099 p = find_temp_slot_from_address (XEXP (x, 0));
01100 if (p != 0)
01101 p->addr_taken = 1;
01102 }
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113 void
01114 preserve_temp_slots (x)
01115 rtx x;
01116 {
01117 struct temp_slot *p = 0;
01118
01119
01120
01121 if (x == 0)
01122 {
01123 for (p = temp_slots; p; p = p->next)
01124 if (p->in_use && p->level == temp_slot_level && p->addr_taken)
01125 p->level--;
01126
01127 return;
01128 }
01129
01130
01131
01132
01133
01134 if (GET_CODE (x) == REG && REG_POINTER (x))
01135 p = find_temp_slot_from_address (x);
01136
01137
01138
01139
01140 if (p == 0 && (GET_CODE (x) != MEM || CONSTANT_P (XEXP (x, 0))))
01141 {
01142 for (p = temp_slots; p; p = p->next)
01143 if (p->in_use && p->level == temp_slot_level && p->addr_taken)
01144 p->level--;
01145
01146 return;
01147 }
01148
01149
01150 if (p == 0)
01151 p = find_temp_slot_from_address (XEXP (x, 0));
01152
01153 if (p != 0)
01154 {
01155
01156
01157 struct temp_slot *q;
01158
01159 if (p->level == temp_slot_level)
01160 {
01161 for (q = temp_slots; q; q = q->next)
01162 if (q != p && q->addr_taken && q->level == p->level)
01163 q->level--;
01164
01165 p->level--;
01166 p->addr_taken = 0;
01167 }
01168 return;
01169 }
01170
01171
01172 for (p = temp_slots; p; p = p->next)
01173 if (p->in_use && p->level == temp_slot_level && ! p->keep)
01174 p->level--;
01175 }
01176
01177
01178
01179
01180
01181
01182 void
01183 preserve_rtl_expr_result (x)
01184 rtx x;
01185 {
01186 struct temp_slot *p;
01187
01188
01189
01190 if (x == 0 || GET_CODE (x) != MEM || CONSTANT_P (XEXP (x, 0)))
01191 return;
01192
01193
01194
01195 p = find_temp_slot_from_address (XEXP (x, 0));
01196 if (p != 0)
01197 {
01198 p->level = MIN (p->level, temp_slot_level);
01199 p->rtl_expr = 0;
01200 }
01201
01202 return;
01203 }
01204
01205
01206
01207
01208
01209
01210
01211
01212 void
01213 free_temp_slots ()
01214 {
01215 struct temp_slot *p;
01216
01217 for (p = temp_slots; p; p = p->next)
01218 if (p->in_use && p->level == temp_slot_level && ! p->keep
01219 && p->rtl_expr == 0)
01220 p->in_use = 0;
01221
01222 combine_temp_slots ();
01223 }
01224
01225
01226
01227 void
01228 free_temps_for_rtl_expr (t)
01229 tree t;
01230 {
01231 struct temp_slot *p;
01232
01233 for (p = temp_slots; p; p = p->next)
01234 if (p->rtl_expr == t)
01235 {
01236
01237
01238
01239
01240 if (temp_slot_level <= p->level)
01241 p->in_use = 0;
01242 else
01243 p->rtl_expr = NULL_TREE;
01244 }
01245
01246 combine_temp_slots ();
01247 }
01248
01249
01250
01251
01252 void
01253 mark_all_temps_used ()
01254 {
01255 struct temp_slot *p;
01256
01257 for (p = temp_slots; p; p = p->next)
01258 {
01259 p->in_use = p->keep = 1;
01260 p->level = MIN (p->level, temp_slot_level);
01261 }
01262 }
01263
01264
01265
01266 void
01267 push_temp_slots ()
01268 {
01269 temp_slot_level++;
01270 }
01271
01272
01273
01274
01275 #if 0
01276 void
01277 push_temp_slots_for_block ()
01278 {
01279 push_temp_slots ();
01280
01281 var_temp_slot_level = temp_slot_level;
01282 }
01283
01284
01285
01286
01287 void
01288 push_temp_slots_for_target ()
01289 {
01290 push_temp_slots ();
01291
01292 target_temp_slot_level = temp_slot_level;
01293 }
01294
01295
01296
01297
01298 int
01299 get_target_temp_slot_level ()
01300 {
01301 return target_temp_slot_level;
01302 }
01303
01304 void
01305 set_target_temp_slot_level (level)
01306 int level;
01307 {
01308 target_temp_slot_level = level;
01309 }
01310 #endif
01311
01312
01313
01314
01315 void
01316 pop_temp_slots ()
01317 {
01318 struct temp_slot *p;
01319
01320 for (p = temp_slots; p; p = p->next)
01321 if (p->in_use && p->level == temp_slot_level && p->rtl_expr == 0)
01322 p->in_use = 0;
01323
01324 combine_temp_slots ();
01325
01326 temp_slot_level--;
01327 }
01328
01329
01330
01331 void
01332 init_temp_slots ()
01333 {
01334
01335 temp_slots = 0;
01336 temp_slot_level = 0;
01337 var_temp_slot_level = 0;
01338 target_temp_slot_level = 0;
01339 }
01340
01341
01342
01343
01344
01345
01346
01347 void
01348 put_var_into_stack (decl, rescan)
01349 tree decl;
01350 int rescan;
01351 {
01352 rtx reg;
01353 enum machine_mode promoted_mode, decl_mode;
01354 struct function *function = 0;
01355 tree context;
01356 int can_use_addressof;
01357 int volatilep = TREE_CODE (decl) != SAVE_EXPR && TREE_THIS_VOLATILE (decl);
01358 int usedp = (TREE_USED (decl)
01359 || (TREE_CODE (decl) != SAVE_EXPR && DECL_INITIAL (decl) != 0));
01360
01361 context = decl_function_context (decl);
01362
01363
01364 reg = (TREE_CODE (decl) == SAVE_EXPR
01365 ? SAVE_EXPR_RTL (decl)
01366 : DECL_RTL_IF_SET (decl));
01367
01368
01369
01370
01371 if (reg == 0)
01372 return;
01373
01374
01375 decl_mode = (TREE_CODE (decl) == SAVE_EXPR ? TYPE_MODE (TREE_TYPE (decl))
01376 : DECL_MODE (decl));
01377
01378 promoted_mode = GET_MODE (reg);
01379
01380
01381
01382
01383
01384
01385 if (context != current_function_decl && context != inline_function_decl)
01386 for (function = outer_function_chain; function; function = function->outer)
01387 if (function->decl == context)
01388 break;
01389
01390
01391
01392 if (TREE_CODE (decl) != SAVE_EXPR && DECL_NONLOCAL (decl)
01393 && GET_CODE (reg) == MEM
01394 && GET_CODE (XEXP (reg, 0)) == REG
01395 && REGNO (XEXP (reg, 0)) > LAST_VIRTUAL_REGISTER)
01396 {
01397 reg = XEXP (reg, 0);
01398 decl_mode = promoted_mode = GET_MODE (reg);
01399 }
01400
01401 can_use_addressof
01402 = (function == 0
01403 && optimize > 0
01404
01405 && decl_mode == promoted_mode
01406 #ifdef NON_SAVING_SETJMP
01407 && ! (NON_SAVING_SETJMP && current_function_calls_setjmp)
01408 #endif
01409 );
01410
01411
01412
01413 if (! can_use_addressof && GET_CODE (reg) == MEM
01414 && GET_CODE (XEXP (reg, 0)) == ADDRESSOF)
01415 reg = XEXP (XEXP (reg, 0), 0);
01416
01417
01418
01419 if (GET_CODE (reg) == REG)
01420 {
01421
01422
01423
01424 if (can_use_addressof)
01425 gen_mem_addressof (reg, decl, rescan);
01426 else
01427 put_reg_into_stack (function, reg, TREE_TYPE (decl), promoted_mode,
01428 decl_mode, volatilep, 0, usedp, 0);
01429 }
01430 else if (GET_CODE (reg) == CONCAT)
01431 {
01432
01433
01434
01435
01436
01437 enum machine_mode part_mode = GET_MODE (XEXP (reg, 0));
01438 tree part_type = (*lang_hooks.types.type_for_mode) (part_mode, 0);
01439 rtx lopart = XEXP (reg, 0);
01440 rtx hipart = XEXP (reg, 1);
01441 #ifdef FRAME_GROWS_DOWNWARD
01442
01443 put_reg_into_stack (function, hipart, part_type, part_mode,
01444 part_mode, volatilep, 0, 0, 0);
01445 put_reg_into_stack (function, lopart, part_type, part_mode,
01446 part_mode, volatilep, 0, 0, 0);
01447 #else
01448 put_reg_into_stack (function, lopart, part_type, part_mode,
01449 part_mode, volatilep, 0, 0, 0);
01450 put_reg_into_stack (function, hipart, part_type, part_mode,
01451 part_mode, volatilep, 0, 0, 0);
01452 #endif
01453
01454
01455 PUT_CODE (reg, MEM);
01456 MEM_ATTRS (reg) = 0;
01457
01458
01459
01460 if (DECL_P (decl))
01461 SET_DECL_RTL (decl, NULL);
01462 set_mem_attributes (reg, decl, 1);
01463 if (DECL_P (decl))
01464 SET_DECL_RTL (decl, reg);
01465
01466
01467
01468 XEXP (reg, 0) = XEXP (XEXP (reg, 0), 0);
01469
01470 if (GET_CODE (XEXP (reg, 0)) == PLUS)
01471 XEXP (reg, 0) = copy_rtx (XEXP (reg, 0));
01472 if (usedp && rescan)
01473 {
01474 schedule_fixup_var_refs (function, reg, TREE_TYPE (decl),
01475 promoted_mode, 0);
01476 schedule_fixup_var_refs (function, lopart, part_type, part_mode, 0);
01477 schedule_fixup_var_refs (function, hipart, part_type, part_mode, 0);
01478 }
01479 }
01480 else
01481 return;
01482 }
01483
01484
01485
01486
01487
01488
01489
01490
01491 static void
01492 put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
01493 original_regno, used_p, ht)
01494 struct function *function;
01495 rtx reg;
01496 tree type;
01497 enum machine_mode promoted_mode, decl_mode;
01498 int volatile_p;
01499 unsigned int original_regno;
01500 int used_p;
01501 htab_t ht;
01502 {
01503 struct function *func = function ? function : cfun;
01504 rtx new = 0;
01505 unsigned int regno = original_regno;
01506
01507 if (regno == 0)
01508 regno = REGNO (reg);
01509
01510 if (regno < func->x_max_parm_reg)
01511 new = func->x_parm_reg_stack_loc[regno];
01512
01513 if (new == 0)
01514 new = assign_stack_local_1 (decl_mode, GET_MODE_SIZE (decl_mode), 0, func);
01515
01516 PUT_CODE (reg, MEM);
01517 PUT_MODE (reg, decl_mode);
01518 XEXP (reg, 0) = XEXP (new, 0);
01519 MEM_ATTRS (reg) = 0;
01520
01521 MEM_VOLATILE_P (reg) = volatile_p;
01522
01523
01524
01525
01526
01527
01528 if (type)
01529 {
01530 MEM_SET_IN_STRUCT_P (reg,
01531 AGGREGATE_TYPE_P (type) || MEM_IN_STRUCT_P (new));
01532 set_mem_alias_set (reg, get_alias_set (type));
01533 }
01534
01535 if (used_p)
01536 schedule_fixup_var_refs (function, reg, type, promoted_mode, ht);
01537 }
01538
01539
01540
01541
01542
01543 static void
01544 schedule_fixup_var_refs (function, reg, type, promoted_mode, ht)
01545 struct function *function;
01546 rtx reg;
01547 tree type;
01548 enum machine_mode promoted_mode;
01549 htab_t ht;
01550 {
01551 int unsigned_p = type ? TREE_UNSIGNED (type) : 0;
01552
01553 if (function != 0)
01554 {
01555 struct var_refs_queue *temp;
01556
01557 temp
01558 = (struct var_refs_queue *) ggc_alloc (sizeof (struct var_refs_queue));
01559 temp->modified = reg;
01560 temp->promoted_mode = promoted_mode;
01561 temp->unsignedp = unsigned_p;
01562 temp->next = function->fixup_var_refs_queue;
01563 function->fixup_var_refs_queue = temp;
01564 }
01565 else
01566
01567 fixup_var_refs (reg, promoted_mode, unsigned_p, reg, ht);
01568 }
01569
01570 static void
01571 fixup_var_refs (var, promoted_mode, unsignedp, may_share, ht)
01572 rtx var;
01573 enum machine_mode promoted_mode;
01574 int unsignedp;
01575 htab_t ht;
01576 rtx may_share;
01577 {
01578 tree pending;
01579 rtx first_insn = get_insns ();
01580 struct sequence_stack *stack = seq_stack;
01581 tree rtl_exps = rtl_expr_chain;
01582
01583
01584 if (ht)
01585 {
01586 if (stack != 0)
01587 abort ();
01588 fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp,
01589 may_share);
01590 return;
01591 }
01592
01593 fixup_var_refs_insns (first_insn, var, promoted_mode, unsignedp,
01594 stack == 0, may_share);
01595
01596
01597 for (; stack; stack = stack->next)
01598 {
01599 push_to_full_sequence (stack->first, stack->last);
01600 fixup_var_refs_insns (stack->first, var, promoted_mode, unsignedp,
01601 stack->next != 0, may_share);
01602
01603
01604 stack->last = get_last_insn ();
01605 end_sequence ();
01606 }
01607
01608
01609 for (pending = rtl_exps; pending; pending = TREE_CHAIN (pending))
01610 {
01611 rtx seq = RTL_EXPR_SEQUENCE (TREE_VALUE (pending));
01612 if (seq != const0_rtx && seq != 0)
01613 {
01614 push_to_sequence (seq);
01615 fixup_var_refs_insns (seq, var, promoted_mode, unsignedp, 0,
01616 may_share);
01617 end_sequence ();
01618 }
01619 }
01620 }
01621
01622
01623
01624
01625
01626 static struct fixup_replacement *
01627 find_fixup_replacement (replacements, x)
01628 struct fixup_replacement **replacements;
01629 rtx x;
01630 {
01631 struct fixup_replacement *p;
01632
01633
01634 for (p = *replacements; p != 0 && ! rtx_equal_p (p->old, x); p = p->next)
01635 ;
01636
01637 if (p == 0)
01638 {
01639 p = (struct fixup_replacement *) xmalloc (sizeof (struct fixup_replacement));
01640 p->old = x;
01641 p->new = 0;
01642 p->next = *replacements;
01643 *replacements = p;
01644 }
01645
01646 return p;
01647 }
01648
01649
01650
01651
01652
01653
01654 static void
01655 fixup_var_refs_insns (insn, var, promoted_mode, unsignedp, toplevel, may_share)
01656 rtx insn;
01657 rtx var;
01658 enum machine_mode promoted_mode;
01659 int unsignedp;
01660 int toplevel;
01661 rtx may_share;
01662 {
01663 while (insn)
01664 {
01665
01666
01667 rtx next = NEXT_INSN (insn);
01668
01669
01670
01671
01672
01673 if (GET_CODE (insn) == CALL_INSN
01674 && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
01675 {
01676 int i;
01677
01678
01679
01680 for (i = 0; i < 3; i++)
01681 {
01682 rtx seq = XEXP (PATTERN (insn), i);
01683 if (seq)
01684 {
01685 push_to_sequence (seq);
01686 fixup_var_refs_insns (seq, var, promoted_mode, unsignedp, 0,
01687 may_share);
01688 XEXP (PATTERN (insn), i) = get_insns ();
01689 end_sequence ();
01690 }
01691 }
01692 }
01693
01694 else if (INSN_P (insn))
01695 fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel,
01696 may_share);
01697
01698 insn = next;
01699 }
01700 }
01701
01702
01703
01704
01705
01706
01707
01708
01709 static void
01710 fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp, may_share)
01711 htab_t ht;
01712 rtx var;
01713 enum machine_mode promoted_mode;
01714 int unsignedp;
01715 rtx may_share;
01716 {
01717 struct insns_for_mem_entry tmp;
01718 struct insns_for_mem_entry *ime;
01719 rtx insn_list;
01720
01721 tmp.key = var;
01722 ime = (struct insns_for_mem_entry *) htab_find (ht, &tmp);
01723 for (insn_list = ime->insns; insn_list != 0; insn_list = XEXP (insn_list, 1))
01724 if (INSN_P (XEXP (insn_list, 0)))
01725 fixup_var_refs_insn (XEXP (insn_list, 0), var, promoted_mode,
01726 unsignedp, 1, may_share);
01727 }
01728
01729
01730
01731
01732
01733
01734
01735
01736 static void
01737 fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel, no_share)
01738 rtx insn;
01739 rtx var;
01740 enum machine_mode promoted_mode;
01741 int unsignedp;
01742 int toplevel;
01743 rtx no_share;
01744 {
01745 rtx call_dest = 0;
01746 rtx set, prev, prev_set;
01747 rtx note;
01748
01749
01750 note = REG_NOTES (insn);
01751
01752
01753
01754
01755
01756 if (GET_CODE (PATTERN (insn)) == CLOBBER
01757 && (XEXP (PATTERN (insn), 0) == var
01758 || (GET_CODE (XEXP (PATTERN (insn), 0)) == CONCAT
01759 && (XEXP (XEXP (PATTERN (insn), 0), 0) == var
01760 || XEXP (XEXP (PATTERN (insn), 0), 1) == var))))
01761 {
01762 if ((note = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) != 0)
01763
01764
01765
01766 remove_note (XEXP (note, 0),
01767 find_reg_note (XEXP (note, 0), REG_RETVAL,
01768 NULL_RTX));
01769
01770 delete_insn (insn);
01771 }
01772
01773
01774
01775
01776
01777
01778 else if (toplevel
01779 && (set = single_set (insn)) != 0
01780 && SET_DEST (set) == var
01781
01782
01783 && find_reg_note (insn, REG_RETVAL, NULL_RTX) == 0
01784 && (rtx_equal_p (SET_SRC (set), var)
01785 || (GET_CODE (SET_SRC (set)) == REG
01786 && (prev = prev_nonnote_insn (insn)) != 0
01787 && (prev_set = single_set (prev)) != 0
01788 && SET_DEST (prev_set) == SET_SRC (set)
01789 && rtx_equal_p (SET_SRC (prev_set), var))))
01790 {
01791 delete_insn (insn);
01792 }
01793 else
01794 {
01795 struct fixup_replacement *replacements = 0;
01796 rtx next_insn = NEXT_INSN (insn);
01797
01798 if (SMALL_REGISTER_CLASSES)
01799 {
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813 if (call_dest != 0 && GET_CODE (insn) == INSN
01814 && reg_mentioned_p (var, PATTERN (insn))
01815 && reg_mentioned_p (call_dest, PATTERN (insn)))
01816 {
01817 rtx temp = gen_reg_rtx (GET_MODE (call_dest));
01818
01819 emit_insn_before (gen_move_insn (temp, call_dest), insn);
01820
01821 PATTERN (insn) = replace_rtx (PATTERN (insn),
01822 call_dest, temp);
01823 }
01824
01825 if (GET_CODE (insn) == CALL_INSN
01826 && GET_CODE (PATTERN (insn)) == SET)
01827 call_dest = SET_DEST (PATTERN (insn));
01828 else if (GET_CODE (insn) == CALL_INSN
01829 && GET_CODE (PATTERN (insn)) == PARALLEL
01830 && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
01831 call_dest = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
01832 else
01833 call_dest = 0;
01834 }
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847 fixup_var_refs_1 (var, promoted_mode, &PATTERN (insn), insn,
01848 &replacements, no_share);
01849
01850
01851
01852
01853 if (insn == last_parm_insn)
01854 last_parm_insn = PREV_INSN (next_insn);
01855
01856 while (replacements)
01857 {
01858 struct fixup_replacement *next;
01859
01860 if (GET_CODE (replacements->new) == REG)
01861 {
01862 rtx insert_before;
01863 rtx seq;
01864
01865
01866 if (GET_CODE (replacements->old) == SUBREG)
01867 replacements->old
01868 = fixup_memory_subreg (replacements->old, insn,
01869 promoted_mode, 0);
01870 else
01871 replacements->old
01872 = fixup_stack_1 (replacements->old, insn);
01873
01874 insert_before = insn;
01875
01876
01877
01878
01879
01880 if (GET_MODE (replacements->new)
01881 != GET_MODE (replacements->old))
01882 {
01883 start_sequence ();
01884 convert_move (replacements->new,
01885 replacements->old, unsignedp);
01886 seq = get_insns ();
01887 end_sequence ();
01888 }
01889 else
01890 seq = gen_move_insn (replacements->new,
01891 replacements->old);
01892
01893 emit_insn_before (seq, insert_before);
01894 }
01895
01896 next = replacements->next;
01897 free (replacements);
01898 replacements = next;
01899 }
01900 }
01901
01902
01903
01904
01905 while (note)
01906 {
01907 if (GET_CODE (note) != INSN_LIST)
01908 XEXP (note, 0)
01909 = walk_fixup_memory_subreg (XEXP (note, 0), insn,
01910 promoted_mode, 1);
01911 note = XEXP (note, 1);
01912 }
01913 }
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926 static void
01927 fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share)
01928 rtx var;
01929 enum machine_mode promoted_mode;
01930 rtx *loc;
01931 rtx insn;
01932 struct fixup_replacement **replacements;
01933 rtx no_share;
01934 {
01935 int i;
01936 rtx x = *loc;
01937 RTX_CODE code = GET_CODE (x);
01938 const char *fmt;
01939 rtx tem, tem1;
01940 struct fixup_replacement *replacement;
01941
01942 switch (code)
01943 {
01944 case ADDRESSOF:
01945 if (XEXP (x, 0) == var)
01946 {
01947
01948 rtx sub = copy_rtx (XEXP (var, 0));
01949
01950 if (! validate_change (insn, loc, sub, 0))
01951 {
01952 rtx y = gen_reg_rtx (GET_MODE (sub));
01953 rtx seq, new_insn;
01954
01955
01956
01957
01958 if (! validate_replace_rtx (*loc, y, insn))
01959 abort ();
01960
01961
01962
01963
01964
01965
01966 start_sequence ();
01967 new_insn = emit_insn (gen_rtx_SET (VOIDmode, y, sub));
01968 seq = get_insns ();
01969 end_sequence ();
01970
01971 if (recog_memoized (new_insn) < 0)
01972 {
01973
01974
01975 start_sequence ();
01976 sub = force_operand (sub, y);
01977 if (sub != y)
01978 emit_insn (gen_move_insn (y, sub));
01979 seq = get_insns ();
01980 end_sequence ();
01981 }
01982
01983 #ifdef HAVE_cc0
01984
01985 if (PREV_INSN (insn) && sets_cc0_p (PREV_INSN (insn)))
01986 insn = PREV_INSN (insn);
01987 #endif
01988
01989 emit_insn_before (seq, insn);
01990 }
01991 }
01992 return;
01993
01994 case MEM:
01995 if (var == x)
01996 {
01997
01998
01999
02000 replacement = find_fixup_replacement (replacements, var);
02001 if (replacement->new)
02002 {
02003 *loc = replacement->new;
02004 return;
02005 }
02006
02007 *loc = replacement->new = x = fixup_stack_1 (x, insn);
02008
02009
02010
02011
02012 INSN_CODE (insn) = -1;
02013 if (! flag_force_mem && GET_MODE (x) == promoted_mode
02014 && recog_memoized (insn) >= 0)
02015 return;
02016
02017 *loc = replacement->new = gen_reg_rtx (promoted_mode);
02018 return;
02019 }
02020
02021
02022
02023
02024
02025
02026 if (reg_mentioned_p (var, x))
02027 {
02028 replacement = find_fixup_replacement (replacements, x);
02029 if (replacement->new == 0)
02030 replacement->new = copy_most_rtx (x, no_share);
02031
02032 *loc = x = replacement->new;
02033 code = GET_CODE (x);
02034 }
02035 break;
02036
02037 case REG:
02038 case CC0:
02039 case PC:
02040 case CONST_INT:
02041 case CONST:
02042 case SYMBOL_REF:
02043 case LABEL_REF:
02044 case CONST_DOUBLE:
02045 case CONST_VECTOR:
02046 return;
02047
02048 case SIGN_EXTRACT:
02049 case ZERO_EXTRACT:
02050
02051
02052 if (XEXP (x, 0) == var
02053 || (GET_CODE (XEXP (x, 0)) == SUBREG
02054 && SUBREG_REG (XEXP (x, 0)) == var))
02055 {
02056
02057
02058
02059
02060
02061 tem = XEXP (x, 0);
02062 if (GET_CODE (tem) == SUBREG)
02063 {
02064 if (GET_MODE_BITSIZE (GET_MODE (tem))
02065 > GET_MODE_BITSIZE (GET_MODE (var)))
02066 {
02067 replacement = find_fixup_replacement (replacements, var);
02068 if (replacement->new == 0)
02069 replacement->new = gen_reg_rtx (GET_MODE (var));
02070 SUBREG_REG (tem) = replacement->new;
02071
02072
02073
02074
02075
02076
02077 XEXP (x, 0) = tem;
02078 return;
02079 }
02080 else
02081 tem = fixup_memory_subreg (tem, insn, promoted_mode, 0);
02082 }
02083 else
02084 tem = fixup_stack_1 (tem, insn);
02085
02086
02087
02088
02089
02090 if (! flag_force_mem && GET_CODE (XEXP (x, 1)) == CONST_INT
02091 && GET_CODE (XEXP (x, 2)) == CONST_INT
02092 && ! mode_dependent_address_p (XEXP (tem, 0))
02093 && ! MEM_VOLATILE_P (tem))
02094 {
02095 enum machine_mode wanted_mode = VOIDmode;
02096 enum machine_mode is_mode = GET_MODE (tem);
02097 HOST_WIDE_INT pos = INTVAL (XEXP (x, 2));
02098
02099 if (GET_CODE (x) == ZERO_EXTRACT)
02100 {
02101 enum machine_mode new_mode
02102 = mode_for_extraction (EP_extzv, 1);
02103 if (new_mode != MAX_MACHINE_MODE)
02104 wanted_mode = new_mode;
02105 }
02106 else if (GET_CODE (x) == SIGN_EXTRACT)
02107 {
02108 enum machine_mode new_mode
02109 = mode_for_extraction (EP_extv, 1);
02110 if (new_mode != MAX_MACHINE_MODE)
02111 wanted_mode = new_mode;
02112 }
02113
02114
02115 if (wanted_mode != VOIDmode
02116 && GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
02117 {
02118 HOST_WIDE_INT offset = pos / BITS_PER_UNIT;
02119 rtx old_pos = XEXP (x, 2);
02120 rtx newmem;
02121
02122
02123
02124 if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
02125 offset = (GET_MODE_SIZE (is_mode)
02126 - GET_MODE_SIZE (wanted_mode) - offset);
02127
02128 pos %= GET_MODE_BITSIZE (wanted_mode);
02129
02130 newmem = adjust_address_nv (tem, wanted_mode, offset);
02131
02132
02133 INSN_CODE (insn) = -1;
02134 XEXP (x, 0) = newmem;
02135 XEXP (x, 2) = GEN_INT (pos);
02136
02137 if (recog_memoized (insn) >= 0)
02138 return;
02139
02140
02141
02142 XEXP (x, 2) = old_pos;
02143 }
02144 }
02145
02146
02147
02148
02149 tem1 = gen_reg_rtx (GET_MODE (tem));
02150 emit_insn_before (gen_move_insn (tem1, tem), insn);
02151 XEXP (x, 0) = tem1;
02152 return;
02153 }
02154 break;
02155
02156 case SUBREG:
02157 if (SUBREG_REG (x) == var)
02158 {
02159
02160
02161
02162
02163
02164 if (SUBREG_PROMOTED_VAR_P (x))
02165 {
02166 *loc = var;
02167 fixup_var_refs_1 (var, GET_MODE (var), loc, insn, replacements,
02168 no_share);
02169 return;
02170 }
02171
02172
02173
02174
02175
02176 if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (var)))
02177 {
02178 replacement = find_fixup_replacement (replacements, var);
02179 if (replacement->new == 0)
02180 replacement->new = gen_reg_rtx (promoted_mode);
02181 SUBREG_REG (x) = replacement->new;
02182 return;
02183 }
02184
02185
02186
02187
02188
02189 replacement = find_fixup_replacement (replacements, x);
02190 if (replacement->new)
02191 {
02192 *loc = replacement->new;
02193 return;
02194 }
02195
02196 replacement->new = *loc = fixup_memory_subreg (x, insn,
02197 promoted_mode, 0);
02198
02199 INSN_CODE (insn) = -1;
02200 if (! flag_force_mem && recog_memoized (insn) >= 0)
02201 return;
02202
02203 *loc = replacement->new = gen_reg_rtx (GET_MODE (x));
02204 return;
02205 }
02206 break;
02207
02208 case SET:
02209
02210 if (GET_CODE (SET_DEST (x)) == SIGN_EXTRACT
02211 || GET_CODE (SET_DEST (x)) == ZERO_EXTRACT)
02212 optimize_bit_field (x, insn, 0);
02213 if (GET_CODE (SET_SRC (x)) == SIGN_EXTRACT
02214 || GET_CODE (SET_SRC (x)) == ZERO_EXTRACT)
02215 optimize_bit_field (x, insn, 0);
02216
02217
02218
02219 if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT
02220 && GET_CODE (XEXP (SET_DEST (x), 0)) == SUBREG
02221 && SUBREG_REG (XEXP (SET_DEST (x), 0)) == var
02222 && (GET_MODE_SIZE (GET_MODE (XEXP (SET_DEST (x), 0)))
02223 > GET_MODE_SIZE (GET_MODE (var))))
02224 {
02225 replacement = find_fixup_replacement (replacements, var);
02226 if (replacement->new == 0)
02227 replacement->new = gen_reg_rtx (GET_MODE (var));
02228
02229 SUBREG_REG (XEXP (SET_DEST (x), 0)) = replacement->new;
02230 emit_insn_after (gen_move_insn (var, replacement->new), insn);
02231 }
02232
02233
02234
02235 if (GET_CODE (SET_DEST (x)) == SUBREG
02236 && SUBREG_REG (SET_DEST (x)) == var
02237 && (GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
02238 > GET_MODE_SIZE (GET_MODE (var))))
02239 {
02240 SET_DEST (x) = tem = gen_reg_rtx (GET_MODE (SET_DEST (x)));
02241 emit_insn_after (gen_move_insn (var, gen_lowpart (GET_MODE (var),
02242 tem)),
02243 insn);
02244 break;
02245 }
02246
02247 {
02248 rtx dest = SET_DEST (x);
02249 rtx src = SET_SRC (x);
02250 rtx outerdest = dest;
02251
02252 while (GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART
02253 || GET_CODE (dest) == SIGN_EXTRACT
02254 || GET_CODE (dest) == ZERO_EXTRACT)
02255 dest = XEXP (dest, 0);
02256
02257 if (GET_CODE (src) == SUBREG)
02258 src = SUBREG_REG (src);
02259
02260
02261
02262
02263 if (src != var && dest != var)
02264 break;
02265
02266
02267 INSN_CODE (insn) = -1;
02268
02269 if (GET_CODE (outerdest) == ZERO_EXTRACT && dest == var
02270 && mode_for_extraction (EP_insv, -1) != MAX_MACHINE_MODE)
02271 {
02272
02273
02274 fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 1),
02275 insn, replacements, no_share);
02276 fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 2),
02277 insn, replacements, no_share);
02278 fixup_var_refs_1 (var, promoted_mode, &SET_SRC (x),
02279 insn, replacements, no_share);
02280
02281 tem = XEXP (outerdest, 0);
02282
02283
02284
02285
02286 if (GET_CODE (tem) == SUBREG
02287 && SUBREG_REG (tem) == var)
02288 tem = fixup_memory_subreg (tem, insn, promoted_mode, 0);
02289 else
02290 tem = fixup_stack_1 (tem, insn);
02291
02292 if (GET_CODE (XEXP (outerdest, 1)) == CONST_INT
02293 && GET_CODE (XEXP (outerdest, 2)) == CONST_INT
02294 && ! mode_dependent_address_p (XEXP (tem, 0))
02295 && ! MEM_VOLATILE_P (tem))
02296 {
02297 enum machine_mode wanted_mode;
02298 enum machine_mode is_mode = GET_MODE (tem);
02299 HOST_WIDE_INT pos = INTVAL (XEXP (outerdest, 2));
02300
02301 wanted_mode = mode_for_extraction (EP_insv, 0);
02302
02303
02304 if (GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
02305 {
02306 HOST_WIDE_INT offset = pos / BITS_PER_UNIT;
02307 rtx old_pos = XEXP (outerdest, 2);
02308 rtx newmem;
02309
02310 if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
02311 offset = (GET_MODE_SIZE (is_mode)
02312 - GET_MODE_SIZE (wanted_mode) - offset);
02313
02314 pos %= GET_MODE_BITSIZE (wanted_mode);
02315
02316 newmem = adjust_address_nv (tem, wanted_mode, offset);
02317
02318
02319 INSN_CODE (insn) = -1;
02320 XEXP (outerdest, 0) = newmem;
02321 XEXP (outerdest, 2) = GEN_INT (pos);
02322
02323 if (recog_memoized (insn) >= 0)
02324 return;
02325
02326
02327
02328 XEXP (outerdest, 2) = old_pos;
02329 }
02330 }
02331
02332
02333
02334
02335
02336 tem1 = gen_reg_rtx (GET_MODE (tem));
02337 emit_insn_before (gen_move_insn (tem1, tem), insn);
02338 emit_insn_after (gen_move_insn (tem, tem1), insn);
02339 XEXP (outerdest, 0) = tem1;
02340 return;
02341 }
02342
02343
02344
02345
02346
02347 if (dest == var && GET_CODE (SET_DEST (x)) == STRICT_LOW_PART)
02348 SET_DEST (x) = XEXP (SET_DEST (x), 0);
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361 if ((SET_SRC (x) == var
02362 || (GET_CODE (SET_SRC (x)) == SUBREG
02363 && SUBREG_REG (SET_SRC (x)) == var))
02364 && (GET_CODE (SET_DEST (x)) == REG
02365 || (GET_CODE (SET_DEST (x)) == SUBREG
02366 && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG))
02367 && GET_MODE (var) == promoted_mode
02368 && x == single_set (insn))
02369 {
02370 rtx pat, last;
02371
02372 if (GET_CODE (SET_SRC (x)) == SUBREG
02373 && (GET_MODE_SIZE (GET_MODE (SET_SRC (x)))
02374 > GET_MODE_SIZE (GET_MODE (var))))
02375 {
02376
02377
02378 replacement = find_fixup_replacement (replacements, var);
02379 if (replacement->new == NULL_RTX)
02380 replacement->new = gen_reg_rtx (GET_MODE (var));
02381 SUBREG_REG (SET_SRC (x)) = replacement->new;
02382 }
02383 else
02384 {
02385 replacement = find_fixup_replacement (replacements, SET_SRC (x));
02386 if (replacement->new)
02387 SET_SRC (x) = replacement->new;
02388 else if (GET_CODE (SET_SRC (x)) == SUBREG)
02389 SET_SRC (x) = replacement->new
02390 = fixup_memory_subreg (SET_SRC (x), insn, promoted_mode,
02391 0);
02392 else
02393 SET_SRC (x) = replacement->new
02394 = fixup_stack_1 (SET_SRC (x), insn);
02395 }
02396
02397 if (recog_memoized (insn) >= 0)
02398 return;
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408 pat = gen_move_insn (SET_DEST (x), SET_SRC (x));
02409 if (NEXT_INSN (pat) != NULL_RTX)
02410 {
02411 last = emit_insn_before (pat, insn);
02412
02413
02414
02415
02416
02417
02418 if (REG_NOTES (last) && REG_NOTES (insn))
02419 abort ();
02420 if (REG_NOTES (last))
02421 REG_NOTES (insn) = REG_NOTES (last);
02422 PATTERN (insn) = PATTERN (last);
02423
02424 delete_insn (last);
02425 }
02426 else
02427 PATTERN (insn) = PATTERN (pat);
02428
02429 return;
02430 }
02431
02432 if ((SET_DEST (x) == var
02433 || (GET_CODE (SET_DEST (x)) == SUBREG
02434 && SUBREG_REG (SET_DEST (x)) == var))
02435 && (GET_CODE (SET_SRC (x)) == REG
02436 || (GET_CODE (SET_SRC (x)) == SUBREG
02437 && GET_CODE (SUBREG_REG (SET_SRC (x))) == REG))
02438 && GET_MODE (var) == promoted_mode
02439 && x == single_set (insn))
02440 {
02441 rtx pat, last;
02442
02443 if (GET_CODE (SET_DEST (x)) == SUBREG)
02444 SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn,
02445 promoted_mode, 0);
02446 else
02447 SET_DEST (x) = fixup_stack_1 (SET_DEST (x), insn);
02448
02449 if (recog_memoized (insn) >= 0)
02450 return;
02451
02452 pat = gen_move_insn (SET_DEST (x), SET_SRC (x));
02453 if (NEXT_INSN (pat) != NULL_RTX)
02454 {
02455 last = emit_insn_before (pat, insn);
02456
02457
02458
02459
02460
02461
02462 if (REG_NOTES (last) && REG_NOTES (insn))
02463 abort ();
02464 if (REG_NOTES (last))
02465 REG_NOTES (insn) = REG_NOTES (last);
02466 PATTERN (insn) = PATTERN (last);
02467
02468 delete_insn (last);
02469 }
02470 else
02471 PATTERN (insn) = PATTERN (pat);
02472
02473 return;
02474 }
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486 if (dest == var)
02487 {
02488 rtx temp;
02489 rtx fixeddest = SET_DEST (x);
02490 enum machine_mode temp_mode;
02491
02492
02493 if (GET_CODE (fixeddest) == STRICT_LOW_PART)
02494 fixeddest = XEXP (fixeddest, 0);
02495
02496 if (GET_CODE (fixeddest) == SUBREG)
02497 {
02498 fixeddest = fixup_memory_subreg (fixeddest, insn,
02499 promoted_mode, 0);
02500 temp_mode = GET_MODE (fixeddest);
02501 }
02502 else
02503 {
02504 fixeddest = fixup_stack_1 (fixeddest, insn);
02505 temp_mode = promoted_mode;
02506 }
02507
02508 temp = gen_reg_rtx (temp_mode);
02509
02510 emit_insn_after (gen_move_insn (fixeddest,
02511 gen_lowpart (GET_MODE (fixeddest),
02512 temp)),
02513 insn);
02514
02515 SET_DEST (x) = temp;
02516 }
02517 }
02518
02519 default:
02520 break;
02521 }
02522
02523
02524
02525 fmt = GET_RTX_FORMAT (code);
02526 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
02527 {
02528 if (fmt[i] == 'e')
02529 fixup_var_refs_1 (var, promoted_mode, &XEXP (x, i), insn, replacements,
02530 no_share);
02531 else if (fmt[i] == 'E')
02532 {
02533 int j;
02534 for (j = 0; j < XVECLEN (x, i); j++)
02535 fixup_var_refs_1 (var, promoted_mode, &XVECEXP (x, i, j),
02536 insn, replacements, no_share);
02537 }
02538 }
02539 }
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551 static rtx
02552 fixup_memory_subreg (x, insn, promoted_mode, uncritical)
02553 rtx x;
02554 rtx insn;
02555 enum machine_mode promoted_mode;
02556 int uncritical;
02557 {
02558 int offset;
02559 rtx mem = SUBREG_REG (x);
02560 rtx addr = XEXP (mem, 0);
02561 enum machine_mode mode = GET_MODE (x);
02562 rtx result, seq;
02563
02564
02565 if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (mem)) && ! uncritical)
02566 abort ();
02567
02568 offset = SUBREG_BYTE (x);
02569 if (BYTES_BIG_ENDIAN)
02570
02571
02572
02573 offset -= (GET_MODE_SIZE (promoted_mode) - GET_MODE_SIZE (GET_MODE (mem)));
02574
02575 if (!flag_force_addr
02576 && memory_address_p (mode, plus_constant (addr, offset)))
02577
02578 return adjust_address (mem, mode, offset);
02579
02580 start_sequence ();
02581 result = adjust_address (mem, mode, offset);
02582 seq = get_insns ();
02583 end_sequence ();
02584
02585 emit_insn_before (seq, insn);
02586 return result;
02587 }
02588
02589
02590
02591
02592
02593
02594
02595
02596
02597 static rtx
02598 walk_fixup_memory_subreg (x, insn, promoted_mode, uncritical)
02599 rtx x;
02600 rtx insn;
02601 enum machine_mode promoted_mode;
02602 int uncritical;
02603 {
02604 enum rtx_code code;
02605 const char *fmt;
02606 int i;
02607
02608 if (x == 0)
02609 return 0;
02610
02611 code = GET_CODE (x);
02612
02613 if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM)
02614 return fixup_memory_subreg (x, insn, promoted_mode, uncritical);
02615
02616
02617
02618 fmt = GET_RTX_FORMAT (code);
02619 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
02620 {
02621 if (fmt[i] == 'e')
02622 XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn,
02623 promoted_mode, uncritical);
02624 else if (fmt[i] == 'E')
02625 {
02626 int j;
02627 for (j = 0; j < XVECLEN (x, i); j++)
02628 XVECEXP (x, i, j)
02629 = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn,
02630 promoted_mode, uncritical);
02631 }
02632 }
02633 return x;
02634 }
02635
02636
02637
02638
02639
02640
02641
02642 static rtx
02643 fixup_stack_1 (x, insn)
02644 rtx x;
02645 rtx insn;
02646 {
02647 int i;
02648 RTX_CODE code = GET_CODE (x);
02649 const char *fmt;
02650
02651 if (code == MEM)
02652 {
02653 rtx ad = XEXP (x, 0);
02654
02655
02656 if (GET_CODE (ad) == PLUS
02657 && GET_CODE (XEXP (ad, 0)) == REG
02658 && ((REGNO (XEXP (ad, 0)) >= FIRST_VIRTUAL_REGISTER
02659 && REGNO (XEXP (ad, 0)) <= LAST_VIRTUAL_REGISTER)
02660 || REGNO (XEXP (ad, 0)) == FRAME_POINTER_REGNUM
02661 #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
02662 || REGNO (XEXP (ad, 0)) == HARD_FRAME_POINTER_REGNUM
02663 #endif
02664 || REGNO (XEXP (ad, 0)) == STACK_POINTER_REGNUM
02665 || REGNO (XEXP (ad, 0)) == ARG_POINTER_REGNUM
02666 || XEXP (ad, 0) == current_function_internal_arg_pointer)
02667 && GET_CODE (XEXP (ad, 1)) == CONST_INT)
02668 {
02669 rtx temp, seq;
02670 if (memory_address_p (GET_MODE (x), ad))
02671 return x;
02672
02673 start_sequence ();
02674 temp = copy_to_reg (ad);
02675 seq = get_insns ();
02676 end_sequence ();
02677 emit_insn_before (seq, insn);
02678 return replace_equiv_address (x, temp);
02679 }
02680 return x;
02681 }
02682
02683 fmt = GET_RTX_FORMAT (code);
02684 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
02685 {
02686 if (fmt[i] == 'e')
02687 XEXP (x, i) = fixup_stack_1 (XEXP (x, i), insn);
02688 else if (fmt[i] == 'E')
02689 {
02690 int j;
02691 for (j = 0; j < XVECLEN (x, i); j++)
02692 XVECEXP (x, i, j) = fixup_stack_1 (XVECEXP (x, i, j), insn);
02693 }
02694 }
02695 return x;
02696 }
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709 static void
02710 optimize_bit_field (body, insn, equiv_mem)
02711 rtx body;
02712 rtx insn;
02713 rtx *equiv_mem;
02714 {
02715 #ifndef SGI_MONGOOSE
02716 rtx bitfield;
02717 int destflag;
02718 rtx seq = 0;
02719 enum machine_mode mode;
02720
02721 if (GET_CODE (SET_DEST (body)) == SIGN_EXTRACT
02722 || GET_CODE (SET_DEST (body)) == ZERO_EXTRACT)
02723 bitfield = SET_DEST (body), destflag = 1;
02724 else
02725 bitfield = SET_SRC (body), destflag = 0;
02726
02727
02728
02729
02730 if (GET_CODE (XEXP (bitfield, 1)) == CONST_INT
02731 && GET_CODE (XEXP (bitfield, 2)) == CONST_INT
02732 && ((mode = mode_for_size (INTVAL (XEXP (bitfield, 1)), MODE_INT, 1))
02733 != BLKmode)
02734 && INTVAL (XEXP (bitfield, 2)) % INTVAL (XEXP (bitfield, 1)) == 0)
02735 {
02736 rtx memref = 0;
02737
02738
02739
02740
02741 if (GET_CODE (XEXP (bitfield, 0)) == MEM)
02742 memref = XEXP (bitfield, 0);
02743 else if (GET_CODE (XEXP (bitfield, 0)) == REG
02744 && equiv_mem != 0)
02745 memref = equiv_mem[REGNO (XEXP (bitfield, 0))];
02746 else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG
02747 && GET_CODE (SUBREG_REG (XEXP (bitfield, 0))) == MEM)
02748 memref = SUBREG_REG (XEXP (bitfield, 0));
02749 else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG
02750 && equiv_mem != 0
02751 && GET_CODE (SUBREG_REG (XEXP (bitfield, 0))) == REG)
02752 memref = equiv_mem[REGNO (SUBREG_REG (XEXP (bitfield, 0)))];
02753
02754 if (memref
02755 && ! mode_dependent_address_p (XEXP (memref, 0))
02756 && ! MEM_VOLATILE_P (memref))
02757 {
02758
02759
02760
02761
02762 HOST_WIDE_INT offset = INTVAL (XEXP (bitfield, 2));
02763 rtx insns;
02764
02765
02766 if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
02767 offset = (GET_MODE_BITSIZE (GET_MODE (XEXP (bitfield, 0)))
02768 - offset - INTVAL (XEXP (bitfield, 1)));
02769
02770
02771 offset /= BITS_PER_UNIT;
02772 if (GET_CODE (XEXP (bitfield, 0)) == SUBREG)
02773 {
02774 offset += (SUBREG_BYTE (XEXP (bitfield, 0))
02775 / UNITS_PER_WORD) * UNITS_PER_WORD;
02776 if (BYTES_BIG_ENDIAN)
02777 offset -= (MIN (UNITS_PER_WORD,
02778 GET_MODE_SIZE (GET_MODE (XEXP (bitfield, 0))))
02779 - MIN (UNITS_PER_WORD,
02780 GET_MODE_SIZE (GET_MODE (memref))));
02781 }
02782
02783 start_sequence ();
02784 memref = adjust_address (memref, mode, offset);
02785 insns = get_insns ();
02786 end_sequence ();
02787 emit_insn_before (insns, insn);
02788
02789
02790
02791
02792 if (destflag)
02793 {
02794 validate_change (insn, &SET_DEST (body), memref, 1);
02795 if (! CONSTANT_ADDRESS_P (SET_SRC (body)))
02796 {
02797 rtx src = SET_SRC (body);
02798 while (GET_CODE (src) == SUBREG
02799 && SUBREG_BYTE (src) == 0)
02800 src = SUBREG_REG (src);
02801 if (GET_MODE (src) != GET_MODE (memref))
02802 src = gen_lowpart (GET_MODE (memref), SET_SRC (body));
02803 validate_change (insn, &SET_SRC (body), src, 1);
02804 }
02805 else if (GET_MODE (SET_SRC (body)) != VOIDmode
02806 && GET_MODE (SET_SRC (body)) != GET_MODE (memref))
02807
02808
02809
02810
02811
02812
02813 abort ();
02814 }
02815 else
02816 {
02817 rtx dest = SET_DEST (body);
02818
02819 while (GET_CODE (dest) == SUBREG
02820 && SUBREG_BYTE (dest) == 0
02821 && (GET_MODE_CLASS (GET_MODE (dest))
02822 == GET_MODE_CLASS (GET_MODE (SUBREG_REG (dest))))
02823 && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
02824 <= UNITS_PER_WORD))
02825 dest = SUBREG_REG (dest);
02826
02827 validate_change (insn, &SET_DEST (body), dest, 1);
02828
02829 if (GET_MODE (dest) == GET_MODE (memref))
02830 validate_change (insn, &SET_SRC (body), memref, 1);
02831 else
02832 {
02833
02834 rtx newreg = gen_reg_rtx (GET_MODE (dest));
02835
02836 start_sequence ();
02837 convert_move (newreg, memref,
02838 GET_CODE (SET_SRC (body)) == ZERO_EXTRACT);
02839 seq = get_insns ();
02840 end_sequence ();
02841
02842 validate_change (insn, &SET_SRC (body), newreg, 1);
02843 }
02844 }
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854 if (apply_change_group () && seq)
02855 emit_insn_before (seq, insn);
02856 }
02857 }
02858 #endif
02859 }
02860
02861
02862
02863
02864
02865
02866
02867
02868 static int in_arg_offset;
02869 static int var_offset;
02870 static int dynamic_offset;
02871 static int out_arg_offset;
02872 static int cfa_offset;
02873
02874
02875
02876
02877 #ifndef STACK_POINTER_OFFSET
02878 #define STACK_POINTER_OFFSET 0
02879 #endif
02880
02881
02882
02883
02884
02885 #ifndef STACK_DYNAMIC_OFFSET
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895 #if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)
02896 #define STACK_DYNAMIC_OFFSET(FNDECL) \
02897 ((ACCUMULATE_OUTGOING_ARGS \
02898 ? (current_function_outgoing_args_size + REG_PARM_STACK_SPACE (FNDECL)) : 0)\
02899 + (STACK_POINTER_OFFSET)) \
02900
02901 #else
02902 #define STACK_DYNAMIC_OFFSET(FNDECL) \
02903 ((ACCUMULATE_OUTGOING_ARGS ? current_function_outgoing_args_size : 0) \
02904 + (STACK_POINTER_OFFSET))
02905 #endif
02906 #endif
02907
02908
02909
02910 #ifndef ARG_POINTER_CFA_OFFSET
02911 #define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET (FNDECL)
02912 #endif
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922 rtx
02923 gen_mem_addressof (reg, decl, rescan)
02924 rtx reg;
02925 tree decl;
02926 int rescan;
02927 {
02928 rtx r = gen_rtx_ADDRESSOF (Pmode, gen_reg_rtx (GET_MODE (reg)),
02929 REGNO (reg), decl);
02930
02931
02932 HOST_WIDE_INT set = decl ? get_alias_set (decl) : 0;
02933
02934
02935
02936 REG_USERVAR_P (XEXP (r, 0)) = REG_USERVAR_P (reg);
02937 RTX_UNCHANGING_P (XEXP (r, 0)) = RTX_UNCHANGING_P (reg);
02938
02939 PUT_CODE (reg, MEM);
02940 MEM_ATTRS (reg) = 0;
02941 XEXP (reg, 0) = r;
02942
02943 if (decl)
02944 {
02945 tree type = TREE_TYPE (decl);
02946 enum machine_mode decl_mode
02947 = (DECL_P (decl) ? DECL_MODE (decl) : TYPE_MODE (TREE_TYPE (decl)));
02948 rtx decl_rtl = (TREE_CODE (decl) == SAVE_EXPR ? SAVE_EXPR_RTL (decl)
02949 : DECL_RTL_IF_SET (decl));
02950
02951 PUT_MODE (reg, decl_mode);
02952
02953
02954
02955 if (DECL_P (decl) && decl_rtl == reg)
02956 SET_DECL_RTL (decl, 0);
02957
02958 set_mem_attributes (reg, decl, 1);
02959 set_mem_alias_set (reg, set);
02960
02961 if (DECL_P (decl) && decl_rtl == reg)
02962 SET_DECL_RTL (decl, reg);
02963
02964 if (rescan
02965 && (TREE_USED (decl) || (DECL_P (decl) && DECL_INITIAL (decl) != 0)))
02966 fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type), reg, 0);
02967 }
02968 else if (rescan)
02969 fixup_var_refs (reg, GET_MODE (reg), 0, reg, 0);
02970
02971 return reg;
02972 }
02973
02974
02975
02976 void
02977 flush_addressof (decl)
02978 tree decl;
02979 {
02980 if ((TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == VAR_DECL)
02981 && DECL_RTL (decl) != 0
02982 && GET_CODE (DECL_RTL (decl)) == MEM
02983 && GET_CODE (XEXP (DECL_RTL (decl), 0)) == ADDRESSOF
02984 && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == REG)
02985 put_addressof_into_stack (XEXP (DECL_RTL (decl), 0), 0);
02986 }
02987
02988
02989
02990 static void
02991 put_addressof_into_stack (r, ht)
02992 rtx r;
02993 htab_t ht;
02994 {
02995 tree decl, type;
02996 int volatile_p, used_p;
02997
02998 rtx reg = XEXP (r, 0);
02999
03000 if (GET_CODE (reg) != REG)
03001 abort ();
03002
03003 decl = ADDRESSOF_DECL (r);
03004 if (decl)
03005 {
03006 type = TREE_TYPE (decl);
03007 volatile_p = (TREE_CODE (decl) != SAVE_EXPR
03008 && TREE_THIS_VOLATILE (decl));
03009 used_p = (TREE_USED (decl)
03010 || (DECL_P (decl) && DECL_INITIAL (decl) != 0));
03011 }
03012 else
03013 {
03014 type = NULL_TREE;
03015 volatile_p = 0;
03016 used_p = 1;
03017 }
03018
03019 put_reg_into_stack (0, reg, type, GET_MODE (reg), GET_MODE (reg),
03020 volatile_p, ADDRESSOF_REGNO (r), used_p, ht);
03021 }
03022
03023
03024
03025 static rtx purge_bitfield_addressof_replacements;
03026
03027
03028
03029
03030
03031
03032
03033 static rtx purge_addressof_replacements;
03034
03035
03036
03037
03038
03039
03040 static bool
03041 purge_addressof_1 (loc, insn, force, store, ht)
03042 rtx *loc;
03043 rtx insn;
03044 int force, store;
03045 htab_t ht;
03046 {
03047 rtx x;
03048 RTX_CODE code;
03049 int i, j;
03050 const char *fmt;
03051 bool result = true;
03052
03053
03054 restart:
03055
03056 x = *loc;
03057 if (x == 0)
03058 return true;
03059
03060 code = GET_CODE (x);
03061
03062
03063
03064
03065 if (code == SET)
03066 {
03067 result = purge_addressof_1 (&SET_DEST (x), insn, force, 1, ht);
03068 result &= purge_addressof_1 (&SET_SRC (x), insn, force, 0, ht);
03069 return result;
03070 }
03071 else if (code == ADDRESSOF)
03072 {
03073 rtx sub, insns;
03074
03075 if (GET_CODE (XEXP (x, 0)) != MEM)
03076 put_addressof_into_stack (x, ht);
03077
03078
03079
03080 sub = copy_rtx (XEXP (XEXP (x, 0), 0));
03081 if (validate_change (insn, loc, sub, 0)
03082 || validate_replace_rtx (x, sub, insn))
03083 return true;
03084
03085 start_sequence ();
03086 sub = force_operand (sub, NULL_RTX);
03087 if (! validate_change (insn, loc, sub, 0)
03088 && ! validate_replace_rtx (x, sub, insn))
03089 abort ();
03090
03091 insns = get_insns ();
03092 end_sequence ();
03093 emit_insn_before (insns, insn);
03094 return true;
03095 }
03096
03097 else if (code == MEM && GET_CODE (XEXP (x, 0)) == ADDRESSOF && ! force)
03098 {
03099 rtx sub = XEXP (XEXP (x, 0), 0);
03100
03101 if (GET_CODE (sub) == MEM)
03102 sub = adjust_address_nv (sub, GET_MODE (x), 0);
03103 else if (GET_CODE (sub) == REG
03104 && (MEM_VOLATILE_P (x) || GET_MODE (x) == BLKmode))
03105 ;
03106 else if (GET_CODE (sub) == REG && GET_MODE (x) != GET_MODE (sub))
03107 {
03108 int size_x, size_sub;
03109
03110 if (!insn)
03111 {
03112
03113
03114
03115 rtx tem;
03116
03117 for (tem = purge_bitfield_addressof_replacements;
03118 tem != NULL_RTX;
03119 tem = XEXP (XEXP (tem, 1), 1))
03120 if (rtx_equal_p (x, XEXP (tem, 0)))
03121 {
03122 *loc = XEXP (XEXP (tem, 1), 0);
03123 return true;
03124 }
03125
03126
03127 for (tem = purge_addressof_replacements;
03128 tem != NULL_RTX;
03129 tem = XEXP (XEXP (tem, 1), 1))
03130 if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0)))
03131 {
03132 rtx z = XEXP (XEXP (tem, 1), 0);
03133
03134 if (GET_MODE (x) == GET_MODE (z)
03135 || (GET_CODE (XEXP (XEXP (tem, 1), 0)) != REG
03136 && GET_CODE (XEXP (XEXP (tem, 1), 0)) != SUBREG))
03137 abort ();
03138
03139
03140
03141
03142
03143
03144 if (GET_CODE (z) == SUBREG && SUBREG_BYTE (z) == 0)
03145 z = SUBREG_REG (z);
03146
03147 if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
03148 && (GET_MODE_SIZE (GET_MODE (x))
03149 > GET_MODE_SIZE (GET_MODE (z))))
03150 {
03151
03152
03153
03154
03155
03156
03157 z = gen_rtx_SUBREG (GET_MODE (x), z, 0);
03158 }
03159 else
03160 z = gen_lowpart (GET_MODE (x), z);
03161
03162 *loc = z;
03163 return true;
03164 }
03165
03166
03167
03168
03169
03170
03171
03172
03173 return false;
03174 }
03175
03176 size_x = GET_MODE_BITSIZE (GET_MODE (x));
03177 size_sub = GET_MODE_BITSIZE (GET_MODE (sub));
03178
03179
03180
03181
03182 if (RTX_UNCHANGING_P (x) && size_x != size_sub)
03183 ;
03184
03185
03186
03187 else if (size_x <= size_sub
03188 && int_mode_for_mode (GET_MODE (sub)) != BLKmode)
03189 {
03190
03191
03192
03193 rtx val, seq;
03194
03195 if (store)
03196 {
03197 rtx p = PREV_INSN (insn);
03198
03199 start_sequence ();
03200 val = gen_reg_rtx (GET_MODE (x));
03201 if (! validate_change (insn, loc, val, 0))
03202 {
03203
03204
03205 end_sequence ();
03206 goto give_up;
03207 }
03208 seq = get_insns ();
03209 end_sequence ();
03210 emit_insn_before (seq, insn);
03211 compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (),
03212 insn, ht);
03213
03214 start_sequence ();
03215 store_bit_field (sub, size_x, 0, GET_MODE (x),
03216 val, GET_MODE_SIZE (GET_MODE (sub)));
03217
03218
03219
03220 unshare_all_rtl_again (get_insns ());
03221
03222 seq = get_insns ();
03223 end_sequence ();
03224 p = emit_insn_after (seq, insn);
03225 if (NEXT_INSN (insn))
03226 compute_insns_for_mem (NEXT_INSN (insn),
03227 p ? NEXT_INSN (p) : NULL_RTX,
03228 ht);
03229 }
03230 else
03231 {
03232 rtx p = PREV_INSN (insn);
03233
03234 start_sequence ();
03235 val = extract_bit_field (sub, size_x, 0, 1, NULL_RTX,
03236 GET_MODE (x), GET_MODE (x),
03237 GET_MODE_SIZE (GET_MODE (sub)));
03238
03239 if (! validate_change (insn, loc, val, 0))
03240 {
03241
03242
03243 end_sequence ();
03244 goto give_up;
03245 }
03246
03247 seq = get_insns ();
03248 end_sequence ();
03249 emit_insn_before (seq, insn);
03250 compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (),
03251 insn, ht);
03252 }
03253
03254
03255
03256 purge_bitfield_addressof_replacements
03257 = gen_rtx_EXPR_LIST (VOIDmode, x,
03258 gen_rtx_EXPR_LIST
03259 (VOIDmode, val,
03260 purge_bitfield_addressof_replacements));
03261
03262
03263 return true;
03264 }
03265 }
03266
03267 else if (validate_change (insn, loc, sub, 0))
03268 {
03269
03270
03271 if (GET_CODE (sub) == REG || GET_CODE (sub) == SUBREG)
03272 {
03273 rtx tem;
03274
03275 for (tem = purge_addressof_replacements;
03276 tem != NULL_RTX;
03277 tem = XEXP (XEXP (tem, 1), 1))
03278 if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0)))
03279 {
03280 XEXP (XEXP (tem, 1), 0) = sub;
03281 return true;
03282 }
03283 purge_addressof_replacements
03284 = gen_rtx (EXPR_LIST, VOIDmode, XEXP (x, 0),
03285 gen_rtx_EXPR_LIST (VOIDmode, sub,
03286 purge_addressof_replacements));
03287 return true;
03288 }
03289 goto restart;
03290 }
03291 }
03292
03293 give_up:
03294
03295 fmt = GET_RTX_FORMAT (code);
03296 for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
03297 {
03298 if (*fmt == 'e')
03299 result &= purge_addressof_1 (&XEXP (x, i), insn, force, 0, ht);
03300 else if (*fmt == 'E')
03301 for (j = 0; j < XVECLEN (x, i); j++)
03302 result &= purge_addressof_1 (&XVECEXP (x, i, j), insn, force, 0, ht);
03303 }
03304
03305 return result;
03306 }
03307
03308
03309
03310 static hashval_t
03311 insns_for_mem_hash (k)
03312 const void * k;
03313 {
03314
03315 struct insns_for_mem_entry *m = (struct insns_for_mem_entry *) k;
03316 return htab_hash_pointer (m->key);
03317 }
03318
03319
03320
03321 static int
03322 insns_for_mem_comp (k1, k2)
03323 const void * k1;
03324 const void * k2;
03325 {
03326 struct insns_for_mem_entry *m1 = (struct insns_for_mem_entry *) k1;
03327 struct insns_for_mem_entry *m2 = (struct insns_for_mem_entry *) k2;
03328 return m1->key == m2->key;
03329 }
03330
03331 struct insns_for_mem_walk_info
03332 {
03333
03334
03335 htab_t ht;
03336
03337
03338 rtx insn;
03339
03340
03341
03342 int pass;
03343 };
03344
03345
03346
03347
03348
03349
03350 static int
03351 insns_for_mem_walk (r, data)
03352 rtx *r;
03353 void *data;
03354 {
03355 struct insns_for_mem_walk_info *ifmwi
03356 = (struct insns_for_mem_walk_info *) data;
03357 struct insns_for_mem_entry tmp;
03358 tmp.insns = NULL_RTX;
03359
03360 if (ifmwi->pass == 0 && *r && GET_CODE (*r) == ADDRESSOF
03361 && GET_CODE (XEXP (*r, 0)) == REG)
03362 {
03363 PTR *e;
03364 tmp.key = XEXP (*r, 0);
03365 e = htab_find_slot (ifmwi->ht, &tmp, INSERT);
03366 if (*e == NULL)
03367 {
03368 *e = ggc_alloc (sizeof (tmp));
03369 memcpy (*e, &tmp, sizeof (tmp));
03370 }
03371 }
03372 else if (ifmwi->pass == 1 && *r && GET_CODE (*r) == REG)
03373 {
03374 struct insns_for_mem_entry *ifme;
03375 tmp.key = *r;
03376 ifme = (struct insns_for_mem_entry *) htab_find (ifmwi->ht, &tmp);
03377
03378
03379
03380
03381 if (ifme && (!ifme->insns || XEXP (ifme->insns, 0) != ifmwi->insn))
03382 ifme->insns = gen_rtx_EXPR_LIST (VOIDmode, ifmwi->insn,
03383 ifme->insns);
03384 }
03385
03386 return 0;
03387 }
03388
03389
03390
03391
03392 static void
03393 compute_insns_for_mem (insns, last_insn, ht)
03394 rtx insns;
03395 rtx last_insn;
03396 htab_t ht;
03397 {
03398 rtx insn;
03399 struct insns_for_mem_walk_info ifmwi;
03400 ifmwi.ht = ht;
03401
03402 for (ifmwi.pass = 0; ifmwi.pass < 2; ++ifmwi.pass)
03403 for (insn = insns; insn != last_insn; insn = NEXT_INSN (insn))
03404 if (INSN_P (insn))
03405 {
03406 ifmwi.insn = insn;
03407 for_each_rtx (&insn, insns_for_mem_walk, &ifmwi);
03408 }
03409 }
03410
03411
03412
03413
03414 static int
03415 is_addressof (rtl, data)
03416 rtx *rtl;
03417 void *data ATTRIBUTE_UNUSED;
03418 {
03419 return GET_CODE (*rtl) == ADDRESSOF;
03420 }
03421
03422
03423
03424
03425
03426 void
03427 purge_addressof (insns)
03428 rtx insns;
03429 {
03430 rtx insn;
03431 htab_t ht;
03432
03433
03434
03435
03436
03437
03438
03439
03440 ht = htab_create_ggc (1000, insns_for_mem_hash, insns_for_mem_comp, NULL);
03441 compute_insns_for_mem (insns, NULL_RTX, ht);
03442
03443 for (insn = insns; insn; insn = NEXT_INSN (insn))
03444 if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
03445 || GET_CODE (insn) == CALL_INSN)
03446 {
03447 if (! purge_addressof_1 (&PATTERN (insn), insn,
03448 asm_noperands (PATTERN (insn)) > 0, 0, ht))
03449
03450
03451 abort ();
03452
03453 if (! purge_addressof_1 (®_NOTES (insn), NULL_RTX, 0, 0, ht))
03454 {
03455
03456
03457 rtx note;
03458
03459 for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
03460 {
03461
03462
03463
03464
03465 if (REG_NOTE_KIND (note) == REG_RETVAL)
03466 abort ();
03467 if (for_each_rtx (¬e, is_addressof, NULL))
03468 remove_note (insn, note);
03469 }
03470 }
03471 }
03472
03473
03474 purge_bitfield_addressof_replacements = 0;
03475 purge_addressof_replacements = 0;
03476
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489 unshare_all_rtl_again (get_insns ());
03490 }
03491
03492
03493
03494
03495 static void
03496 purge_single_hard_subreg_set (pattern)
03497 rtx pattern;
03498 {
03499 rtx reg = SET_DEST (pattern);
03500 enum machine_mode mode = GET_MODE (SET_DEST (pattern));
03501 int offset = 0;
03502
03503 if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG
03504 && REGNO (SUBREG_REG (reg)) < FIRST_PSEUDO_REGISTER)
03505 {
03506 offset = subreg_regno_offset (REGNO (SUBREG_REG (reg)),
03507 GET_MODE (SUBREG_REG (reg)),
03508 SUBREG_BYTE (reg),
03509 GET_MODE (reg));
03510 reg = SUBREG_REG (reg);
03511 }
03512
03513
03514 if (GET_CODE (reg) == REG && REGNO (reg) < FIRST_PSEUDO_REGISTER)
03515 {
03516 reg = gen_rtx_REG (mode, REGNO (reg) + offset);
03517 SET_DEST (pattern) = reg;
03518 }
03519 }
03520
03521
03522
03523
03524
03525
03526
03527
03528 void
03529 purge_hard_subreg_sets (insn)
03530 rtx insn;
03531 {
03532 for (; insn; insn = NEXT_INSN (insn))
03533 {
03534 if (INSN_P (insn))
03535 {
03536 rtx pattern = PATTERN (insn);
03537 switch (GET_CODE (pattern))
03538 {
03539 case SET:
03540 if (GET_CODE (SET_DEST (pattern)) == SUBREG)
03541 purge_single_hard_subreg_set (pattern);
03542 break;
03543 case PARALLEL:
03544 {
03545 int j;
03546 for (j = XVECLEN (pattern, 0) - 1; j >= 0; j--)
03547 {
03548 rtx inner_pattern = XVECEXP (pattern, 0, j);
03549 if (GET_CODE (inner_pattern) == SET
03550 && GET_CODE (SET_DEST (inner_pattern)) == SUBREG)
03551 purge_single_hard_subreg_set (inner_pattern);
03552 }
03553 }
03554 break;
03555 default:
03556 break;
03557 }
03558 }
03559 }
03560 }
03561
03562
03563
03564
03565 void
03566 instantiate_virtual_regs (fndecl, insns)
03567 tree fndecl;
03568 rtx insns;
03569 {
03570 rtx insn;
03571 unsigned int i;
03572
03573
03574 in_arg_offset = FIRST_PARM_OFFSET (fndecl);
03575 var_offset = STARTING_FRAME_OFFSET;
03576 dynamic_offset = STACK_DYNAMIC_OFFSET (fndecl);
03577 out_arg_offset = STACK_POINTER_OFFSET;
03578 cfa_offset = ARG_POINTER_CFA_OFFSET (fndecl);
03579
03580
03581
03582
03583
03584 instantiate_decls (fndecl, 1);
03585
03586
03587 init_recog ();
03588
03589
03590
03591 for (insn = insns; insn; insn = NEXT_INSN (insn))
03592 if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
03593 || GET_CODE (insn) == CALL_INSN)
03594 {
03595 instantiate_virtual_regs_1 (&PATTERN (insn), insn, 1);
03596 if (INSN_DELETED_P (insn))
03597 continue;
03598 instantiate_virtual_regs_1 (®_NOTES (insn), NULL_RTX, 0);
03599
03600 if (GET_CODE (insn) == CALL_INSN)
03601 instantiate_virtual_regs_1 (&CALL_INSN_FUNCTION_USAGE (insn),
03602 NULL_RTX, 0);
03603
03604
03605
03606 if (asm_noperands (PATTERN (insn)) >= 0
03607 && ! check_asm_operands (PATTERN (insn)))
03608 instantiate_virtual_regs_lossage (insn);
03609 }
03610
03611
03612
03613 for (i = 0; i < max_parm_reg; ++i)
03614 if (parm_reg_stack_loc[i])
03615 instantiate_virtual_regs_1 (&parm_reg_stack_loc[i], NULL_RTX, 0);
03616
03617
03618
03619 instantiate_decls (fndecl, 0);
03620
03621
03622
03623 virtuals_instantiated = 1;
03624 }
03625
03626
03627
03628
03629
03630
03631
03632 static void
03633 instantiate_decls (fndecl, valid_only)
03634 tree fndecl;
03635 int valid_only;
03636 {
03637 tree decl;
03638
03639
03640 for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl))
03641 {
03642 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl));
03643 HOST_WIDE_INT size_rtl;
03644
03645 instantiate_decl (DECL_RTL (decl), size, valid_only);
03646
03647
03648
03649
03650 size_rtl = GET_MODE_SIZE (GET_MODE (DECL_INCOMING_RTL (decl)));
03651 size = MAX (size_rtl, size);
03652 instantiate_decl (DECL_INCOMING_RTL (decl), size, valid_only);
03653 }
03654
03655
03656 instantiate_decls_1 (DECL_INITIAL (fndecl), valid_only);
03657 }
03658
03659
03660
03661
03662 static void
03663 instantiate_decls_1 (let, valid_only)
03664 tree let;
03665 int valid_only;
03666 {
03667 tree t;
03668
03669 for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
03670 if (DECL_RTL_SET_P (t))
03671 instantiate_decl (DECL_RTL (t),
03672 int_size_in_bytes (TREE_TYPE (t)),
03673 valid_only);
03674
03675
03676 for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))
03677 instantiate_decls_1 (t, valid_only);
03678 }
03679
03680
03681
03682
03683
03684
03685
03686 static void
03687 instantiate_decl (x, size, valid_only)
03688 rtx x;
03689 HOST_WIDE_INT size;
03690 int valid_only;
03691 {
03692 enum machine_mode mode;
03693 rtx addr;
03694
03695
03696
03697
03698 if (x == 0 || GET_CODE (x) != MEM)
03699 return;
03700
03701 addr = XEXP (x, 0);
03702 if (CONSTANT_P (addr)
03703 || (GET_CODE (addr) == ADDRESSOF && GET_CODE (XEXP (addr, 0)) == REG)
03704 || (GET_CODE (addr) == REG
03705 && (REGNO (addr) < FIRST_VIRTUAL_REGISTER
03706 || REGNO (addr) > LAST_VIRTUAL_REGISTER)))
03707 return;
03708
03709
03710
03711
03712
03713
03714 if (valid_only)
03715 addr = copy_rtx (addr);
03716
03717 instantiate_virtual_regs_1 (&addr, NULL_RTX, 0);
03718
03719 if (valid_only && size >= 0)
03720 {
03721 unsigned HOST_WIDE_INT decl_size = size;
03722
03723
03724
03725
03726
03727
03728 for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
03729 mode != VOIDmode && GET_MODE_SIZE (mode) <= decl_size;
03730 mode = GET_MODE_WIDER_MODE (mode))
03731 if (! memory_address_p (mode, addr))
03732 return;
03733
03734 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
03735 mode != VOIDmode && GET_MODE_SIZE (mode) <= decl_size;
03736 mode = GET_MODE_WIDER_MODE (mode))
03737 if (! memory_address_p (mode, addr))
03738 return;
03739 }
03740
03741
03742
03743
03744 XEXP (x, 0) = addr;
03745 }
03746
03747
03748
03749
03750
03751 static rtx
03752 instantiate_new_reg (x, poffset)
03753 rtx x;
03754 HOST_WIDE_INT *poffset;
03755 {
03756 rtx new;
03757 HOST_WIDE_INT offset;
03758
03759 if (x == virtual_incoming_args_rtx)
03760 new = arg_pointer_rtx, offset = in_arg_offset;
03761 else if (x == virtual_stack_vars_rtx)
03762 new = frame_pointer_rtx, offset = var_offset;
03763 else if (x == virtual_stack_dynamic_rtx)
03764 new = stack_pointer_rtx, offset = dynamic_offset;
03765 else if (x == virtual_outgoing_args_rtx)
03766 new = stack_pointer_rtx, offset = out_arg_offset;
03767 else if (x == virtual_cfa_rtx)
03768 new = arg_pointer_rtx, offset = cfa_offset;
03769 else
03770 return 0;
03771
03772 *poffset = offset;
03773 return new;
03774 }
03775
03776
03777
03778
03779
03780 static void
03781 instantiate_virtual_regs_lossage (insn)
03782 rtx insn;
03783 {
03784 if (asm_noperands (PATTERN (insn)) >= 0)
03785 {
03786 error_for_asm (insn, "impossible constraint in `asm'");
03787 delete_insn (insn);
03788 }
03789 else
03790 abort ();
03791 }
03792
03793
03794
03795
03796
03797
03798
03799
03800
03801
03802
03803
03804
03805
03806 static int
03807 instantiate_virtual_regs_1 (loc, object, extra_insns)
03808 rtx *loc;
03809 rtx object;
03810 int extra_insns;
03811 {
03812 rtx x;
03813 RTX_CODE code;
03814 rtx new = 0;
03815 HOST_WIDE_INT offset = 0;
03816 rtx temp;
03817 rtx seq;
03818 int i, j;
03819 const char *fmt;
03820
03821
03822 restart:
03823
03824 x = *loc;
03825 if (x == 0)
03826 return 1;
03827
03828
03829 if (object && INSN_P (object) && INSN_DELETED_P (object))
03830 return 1;
03831
03832 code = GET_CODE (x);
03833
03834
03835 switch (code)
03836 {
03837 case CONST_INT:
03838 case CONST_DOUBLE:
03839 case CONST_VECTOR:
03840 case CONST:
03841 case SYMBOL_REF:
03842 case CODE_LABEL:
03843 case PC:
03844 case CC0:
03845 case ASM_INPUT:
03846 case ADDR_VEC:
03847 case ADDR_DIFF_VEC:
03848 case RETURN:
03849 return 1;
03850
03851 case SET:
03852
03853
03854
03855
03856 if ((new = instantiate_new_reg (SET_DEST (x), &offset)) != 0)
03857 {
03858 rtx src = SET_SRC (x);
03859
03860
03861
03862
03863 offset = - offset;
03864 instantiate_virtual_regs_1 (&src, NULL_RTX, 0);
03865
03866
03867
03868 if (GET_CODE (src) != REG && GET_CODE (src) != PLUS)
03869 {
03870 instantiate_virtual_regs_lossage (object);
03871 return 1;
03872 }
03873
03874 start_sequence ();
03875 if (GET_CODE (src) != REG)
03876 temp = force_operand (src, NULL_RTX);
03877 else
03878 temp = src;
03879 temp = force_operand (plus_constant (temp, offset), NULL_RTX);
03880 seq = get_insns ();
03881 end_sequence ();
03882
03883 emit_insn_before (seq, object);
03884 SET_DEST (x) = new;
03885
03886 if (! validate_change (object, &SET_SRC (x), temp, 0)
03887 || ! extra_insns)
03888 instantiate_virtual_regs_lossage (object);
03889
03890 return 1;
03891 }
03892
03893 instantiate_virtual_regs_1 (&SET_DEST (x), object, extra_insns);
03894 loc = &SET_SRC (x);
03895 goto restart;
03896
03897 case PLUS:
03898
03899 if (CONSTANT_P (XEXP (x, 1)))
03900 {
03901 rtx old, new_offset;
03902
03903
03904 if (GET_CODE (XEXP (x, 0)) == PLUS)
03905 {
03906 if ((new = instantiate_new_reg (XEXP (XEXP (x, 0), 0), &offset)))
03907 {
03908 instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 1), object,
03909 extra_insns);
03910 new = gen_rtx_PLUS (Pmode, new, XEXP (XEXP (x, 0), 1));
03911 }
03912 else
03913 {
03914 loc = &XEXP (x, 0);
03915 goto restart;
03916 }
03917 }
03918
03919 #ifdef POINTERS_EXTEND_UNSIGNED
03920
03921
03922
03923 else if (GET_CODE (XEXP (x, 0)) == SUBREG && GET_MODE (x) == ptr_mode
03924 && GET_CODE (XEXP (x, 1)) == CONST_INT
03925 && 0 != (new
03926 = instantiate_new_reg (SUBREG_REG (XEXP (x, 0)),
03927 &offset))
03928 && validate_change (object, loc,
03929 plus_constant (gen_lowpart (ptr_mode,
03930 new),
03931 offset
03932 + INTVAL (XEXP (x, 1))),
03933 0))
03934 return 1;
03935 #endif
03936 else if ((new = instantiate_new_reg (XEXP (x, 0), &offset)) == 0)
03937 {
03938
03939
03940
03941 if (GET_CODE (XEXP (x, 0)) != REG)
03942 {
03943 loc = &XEXP (x, 0);
03944 goto restart;
03945 }
03946 return 1;
03947 }
03948
03949 new_offset = plus_constant (XEXP (x, 1), offset);
03950
03951
03952
03953 if (new_offset == const0_rtx
03954 && validate_change (object, loc, new, 0))
03955 return 1;
03956
03957
03958
03959
03960
03961
03962
03963
03964 old = XEXP (x, 0);
03965 if (offset == 0
03966 ? ! validate_change (object, &XEXP (x, 0), new, 0)
03967 : (XEXP (x, 0) = new,
03968 ! validate_change (object, &XEXP (x, 1), new_offset, 0)))
03969 {
03970 if (! extra_insns)
03971 {
03972 XEXP (x, 0) = old;
03973 return 0;
03974 }
03975
03976
03977
03978 temp = gen_reg_rtx (Pmode);
03979 XEXP (x, 0) = new;
03980 if (validate_change (object, &XEXP (x, 1), temp, 0))
03981 emit_insn_before (gen_move_insn (temp, new_offset), object);
03982 else
03983 {
03984
03985
03986
03987 XEXP (x, 0) = old;
03988 new = gen_rtx_PLUS (Pmode, new, new_offset);
03989
03990 start_sequence ();
03991 temp = force_operand (new, NULL_RTX);
03992 seq = get_insns ();
03993 end_sequence ();
03994
03995 emit_insn_before (seq, object);
03996 if (! validate_change (object, loc, temp, 0)
03997 && ! validate_replace_rtx (x, temp, object))
03998 {
03999 instantiate_virtual_regs_lossage (object);
04000 return 1;
04001 }
04002 }
04003 }
04004
04005 return 1;
04006 }
04007
04008
04009 case EXPR_LIST:
04010 case CALL:
04011 case COMPARE:
04012 case MINUS:
04013 case MULT:
04014 case DIV: case UDIV:
04015 case MOD: case UMOD:
04016 case AND: case IOR: case XOR:
04017 case ROTATERT: case ROTATE:
04018 case ASHIFTRT: case LSHIFTRT: case ASHIFT:
04019 case NE: case EQ:
04020 case GE: case GT: case GEU: case GTU:
04021 case LE: case LT: case LEU: case LTU:
04022 if (XEXP (x, 1) && ! CONSTANT_P (XEXP (x, 1)))
04023 instantiate_virtual_regs_1 (&XEXP (x, 1), object, extra_insns);
04024 loc = &XEXP (x, 0);
04025 goto restart;
04026
04027 case MEM:
04028
04029
04030
04031
04032
04033
04034
04035
04036
04037
04038
04039
04040
04041
04042 temp = XEXP (x, 0);
04043 if (CONSTANT_ADDRESS_P (temp)
04044 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
04045 || temp == arg_pointer_rtx
04046 #endif
04047 #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
04048 || temp == hard_frame_pointer_rtx
04049 #endif
04050 || temp == frame_pointer_rtx)
04051 return 1;
04052
04053 if (GET_CODE (temp) == PLUS
04054 && CONSTANT_ADDRESS_P (XEXP (temp, 1))
04055 && (XEXP (temp, 0) == frame_pointer_rtx
04056 #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
04057 || XEXP (temp, 0) == hard_frame_pointer_rtx
04058 #endif
04059 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
04060 || XEXP (temp, 0) == arg_pointer_rtx
04061 #endif
04062 ))
04063 return 1;
04064
04065 if (temp == virtual_stack_vars_rtx
04066 || temp == virtual_incoming_args_rtx
04067 || (GET_CODE (temp) == PLUS
04068 && CONSTANT_ADDRESS_P (XEXP (temp, 1))
04069 && (XEXP (temp, 0) == virtual_stack_vars_rtx
04070 || XEXP (temp, 0) == virtual_incoming_args_rtx)))
04071 {
04072
04073
04074
04075
04076
04077
04078
04079
04080
04081
04082
04083
04084
04085
04086
04087
04088
04089
04090
04091 if (instantiate_virtual_regs_1 (&XEXP (x, 0),
04092 object ? object : x, 0))
04093 return 1;
04094
04095
04096
04097
04098 *loc = x = copy_rtx (x);
04099 }
04100
04101
04102 case PREFETCH:
04103 case SUBREG:
04104 case STRICT_LOW_PART:
04105 case NEG: case NOT:
04106 case PRE_DEC: case PRE_INC: case POST_DEC: case POST_INC:
04107 case SIGN_EXTEND: case ZERO_EXTEND:
04108 case TRUNCATE: case FLOAT_EXTEND: case FLOAT_TRUNCATE:
04109 case FLOAT: case FIX:
04110 case UNSIGNED_FIX: case UNSIGNED_FLOAT:
04111 case ABS:
04112 case SQRT:
04113 case FFS:
04114
04115
04116 loc = &XEXP (x, 0);
04117 goto restart;
04118
04119 case USE:
04120 case CLOBBER:
04121
04122
04123
04124
04125 if ((GET_CODE (XEXP (x, 0)) == MEM
04126 && instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 0), XEXP (x, 0),
04127 0))
04128 || (GET_CODE (XEXP (x, 0)) == REG
04129 && instantiate_virtual_regs_1 (&XEXP (x, 0), object, 0)))
04130 return 1;
04131
04132 XEXP (x, 0) = copy_rtx (XEXP (x, 0));
04133 loc = &XEXP (x, 0);
04134 goto restart;
04135
04136 case REG:
04137
04138
04139 if ((new = instantiate_new_reg (x, &offset)) != 0)
04140 {
04141 temp = plus_constant (new, offset);
04142 if (!validate_change (object, loc, temp, 0))
04143 {
04144 if (! extra_insns)
04145 return 0;
04146
04147 start_sequence ();
04148 temp = force_operand (temp, NULL_RTX);
04149 seq = get_insns ();
04150 end_sequence ();
04151
04152 emit_insn_before (seq, object);
04153 if (! validate_change (object, loc, temp, 0)
04154 && ! validate_replace_rtx (x, temp, object))
04155 instantiate_virtual_regs_lossage (object);
04156 }
04157 }
04158
04159 return 1;
04160
04161 case ADDRESSOF:
04162 if (GET_CODE (XEXP (x, 0)) == REG)
04163 return 1;
04164
04165 else if (GET_CODE (XEXP (x, 0)) == MEM)
04166 {
04167
04168
04169
04170 instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 0), NULL_RTX, 0);
04171 return 1;
04172 }
04173 break;
04174
04175 default:
04176 break;
04177 }
04178
04179
04180 fmt = GET_RTX_FORMAT (code);
04181 for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
04182 if (*fmt == 'e')
04183 {
04184 if (!instantiate_virtual_regs_1 (&XEXP (x, i), object, extra_insns))
04185 return 0;
04186 }
04187 else if (*fmt == 'E')
04188 for (j = 0; j < XVECLEN (x, i); j++)
04189 if (! instantiate_virtual_regs_1 (&XVECEXP (x, i, j), object,
04190 extra_insns))
04191 return 0;
04192
04193 return 1;
04194 }
04195
04196
04197
04198
04199
04200 static void
04201 delete_handlers ()
04202 {
04203 rtx insn;
04204 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
04205 {
04206
04207
04208
04209
04210 if (GET_CODE (insn) == CODE_LABEL)
04211 {
04212 tree t, last_t;
04213
04214 LABEL_PRESERVE_P (insn) = 0;
04215
04216
04217
04218 for (t = nonlocal_labels, last_t = 0; t;
04219 last_t = t, t = TREE_CHAIN (t))
04220 if (DECL_RTL (TREE_VALUE (t)) == insn)
04221 break;
04222 if (t)
04223 {
04224 if (! last_t)
04225 nonlocal_labels = TREE_CHAIN (nonlocal_labels);
04226 else
04227 TREE_CHAIN (last_t) = TREE_CHAIN (t);
04228 }
04229 }
04230 if (GET_CODE (insn) == INSN)
04231 {
04232 int can_delete = 0;
04233 rtx t;
04234 for (t = nonlocal_goto_handler_slots; t != 0; t = XEXP (t, 1))
04235 if (reg_mentioned_p (t, PATTERN (insn)))
04236 {
04237 can_delete = 1;
04238 break;
04239 }
04240 if (can_delete
04241 || (nonlocal_goto_stack_level != 0
04242 && reg_mentioned_p (nonlocal_goto_stack_level,
04243 PATTERN (insn))))
04244 delete_related_insns (insn);
04245 }
04246 }
04247 }
04248
04249 int
04250 max_parm_reg_num ()
04251 {
04252 return max_parm_reg;
04253 }
04254
04255
04256
04257 rtx
04258 get_first_nonparm_insn ()
04259 {
04260 if (last_parm_insn)
04261 return NEXT_INSN (last_parm_insn);
04262 return get_insns ();
04263 }
04264
04265
04266
04267
04268 rtx
04269 get_first_block_beg ()
04270 {
04271 rtx searcher;
04272 rtx insn = get_first_nonparm_insn ();
04273
04274 for (searcher = insn; searcher; searcher = NEXT_INSN (searcher))
04275 if (GET_CODE (searcher) == NOTE
04276 && NOTE_LINE_NUMBER (searcher) == NOTE_INSN_BLOCK_BEG)
04277 return searcher;
04278
04279 abort ();
04280 return NULL_RTX;
04281 }
04282
04283
04284
04285
04286
04287
04288 int
04289 aggregate_value_p (exp)
04290 tree exp;
04291 {
04292 int i, regno, nregs;
04293 rtx reg;
04294
04295 tree type = (TYPE_P (exp)) ? exp : TREE_TYPE (exp);
04296
04297 if (TREE_CODE (type) == VOID_TYPE)
04298 return 0;
04299 if (RETURN_IN_MEMORY (type))
04300 return 1;
04301
04302
04303 if (TREE_ADDRESSABLE (type))
04304 return 1;
04305 if (flag_pcc_struct_return && AGGREGATE_TYPE_P (type))
04306 return 1;
04307
04308
04309 reg = hard_function_value (type, 0, 0);
04310
04311
04312
04313 if (GET_CODE (reg) != REG)
04314 return 0;
04315
04316 regno = REGNO (reg);
04317 nregs = HARD_REGNO_NREGS (regno, TYPE_MODE (type));
04318 for (i = 0; i < nregs; i++)
04319 if (! call_used_regs[regno + i])
04320 return 1;
04321 return 0;
04322 }
04323
04324
04325
04326
04327
04328 void
04329 assign_parms (fndecl)
04330 tree fndecl;
04331 {
04332 tree parm;
04333 rtx entry_parm = 0;
04334 rtx stack_parm = 0;
04335 CUMULATIVE_ARGS args_so_far;
04336 enum machine_mode promoted_mode, passed_mode;
04337 enum machine_mode nominal_mode, promoted_nominal_mode;
04338 int unsignedp;
04339
04340
04341 struct args_size stack_args_size;
04342 tree fntype = TREE_TYPE (fndecl);
04343 tree fnargs = DECL_ARGUMENTS (fndecl);
04344
04345 rtx internal_arg_pointer;
04346
04347
04348 tree function_result_decl = 0;
04349 #ifdef SETUP_INCOMING_VARARGS
04350 int varargs_setup = 0;
04351 #endif
04352 rtx conversion_insns = 0;
04353 struct args_size alignment_pad;
04354
04355
04356
04357
04358 int stdarg
04359 = (TYPE_ARG_TYPES (fntype) != 0
04360 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
04361 != void_type_node));
04362
04363 current_function_stdarg = stdarg;
04364
04365
04366
04367
04368
04369
04370
04371
04372 if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM
04373 || ! (fixed_regs[ARG_POINTER_REGNUM]
04374 || ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM)))
04375 internal_arg_pointer = copy_to_reg (virtual_incoming_args_rtx);
04376 else
04377 internal_arg_pointer = virtual_incoming_args_rtx;
04378 current_function_internal_arg_pointer = internal_arg_pointer;
04379
04380 stack_args_size.constant = 0;
04381 stack_args_size.var = 0;
04382
04383
04384 if (aggregate_value_p (DECL_RESULT (fndecl))
04385 && ! current_function_returns_pcc_struct
04386 && struct_value_incoming_rtx == 0)
04387 {
04388 tree type = build_pointer_type (TREE_TYPE (fntype));
04389
04390 function_result_decl = build_decl (PARM_DECL, NULL_TREE, type);
04391
04392 DECL_ARG_TYPE (function_result_decl) = type;
04393 TREE_CHAIN (function_result_decl) = fnargs;
04394 fnargs = function_result_decl;
04395 }
04396
04397 max_parm_reg = LAST_VIRTUAL_REGISTER + 1;
04398 parm_reg_stack_loc = (rtx *) ggc_alloc_cleared (max_parm_reg * sizeof (rtx));
04399
04400 #ifdef INIT_CUMULATIVE_INCOMING_ARGS
04401 INIT_CUMULATIVE_INCOMING_ARGS (args_so_far, fntype, NULL_RTX);
04402 #else
04403 INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, 0);
04404 #endif
04405
04406
04407
04408 current_function_pretend_args_size = 0;
04409
04410 for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
04411 {
04412 struct args_size stack_offset;
04413 struct args_size arg_size;
04414 int passed_pointer = 0;
04415 int did_conversion = 0;
04416 tree passed_type = DECL_ARG_TYPE (parm);
04417 tree nominal_type = TREE_TYPE (parm);
04418 int pretend_named;
04419 int last_named = 0, named_arg;
04420
04421
04422
04423 if (stdarg)
04424 {
04425 tree tem;
04426
04427 for (tem = TREE_CHAIN (parm); tem; tem = TREE_CHAIN (tem))
04428 if (DECL_NAME (tem))
04429 break;
04430
04431 if (tem == 0)
04432 last_named = 1;
04433 }
04434
04435
04436
04437 named_arg = STRICT_ARGUMENT_NAMING ? 1 : ! last_named;
04438
04439 if (TREE_TYPE (parm) == error_mark_node
04440
04441
04442 || TREE_CODE (parm) != PARM_DECL
04443 || passed_type == NULL)
04444 {
04445 SET_DECL_RTL (parm, gen_rtx_MEM (BLKmode, const0_rtx));
04446 DECL_INCOMING_RTL (parm) = DECL_RTL (parm);
04447 TREE_USED (parm) = 1;
04448 continue;
04449 }
04450
04451
04452
04453 passed_mode = TYPE_MODE (passed_type);
04454 nominal_mode = TYPE_MODE (nominal_type);
04455
04456
04457
04458 if (nominal_mode == VOIDmode)
04459 {
04460 SET_DECL_RTL (parm, const0_rtx);
04461 DECL_INCOMING_RTL (parm) = DECL_RTL (parm);
04462 continue;
04463 }
04464
04465
04466
04467
04468 if (DECL_TRANSPARENT_UNION (parm)
04469 || (TREE_CODE (passed_type) == UNION_TYPE
04470 && TYPE_TRANSPARENT_UNION (passed_type)))
04471 passed_type = TREE_TYPE (TYPE_FIELDS (passed_type));
04472
04473
04474
04475
04476
04477
04478 if ((TREE_CODE (TYPE_SIZE (passed_type)) != INTEGER_CST
04479 && contains_placeholder_p (TYPE_SIZE (passed_type)))
04480 || TREE_ADDRESSABLE (passed_type)
04481 #ifdef FUNCTION_ARG_PASS_BY_REFERENCE
04482 || FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, passed_mode,
04483 passed_type, named_arg)
04484 #endif
04485 )
04486 {
04487 passed_type = nominal_type = build_pointer_type (passed_type);
04488 passed_pointer = 1;
04489 passed_mode = nominal_mode = Pmode;
04490 }
04491
04492 else if (passed_type != nominal_type
04493 && POINTER_TYPE_P (passed_type)
04494 && TREE_TYPE (passed_type) == nominal_type)
04495 {
04496 nominal_type = passed_type;
04497 passed_pointer = 1;
04498 passed_mode = nominal_mode = Pmode;
04499 }
04500
04501 promoted_mode = passed_mode;
04502
04503 #ifdef PROMOTE_FUNCTION_ARGS
04504
04505 unsignedp = TREE_UNSIGNED (passed_type);
04506 promoted_mode = promote_mode (passed_type, promoted_mode, &unsignedp, 1);
04507 #endif
04508
04509
04510
04511 #ifdef FUNCTION_INCOMING_ARG
04512 entry_parm = FUNCTION_INCOMING_ARG (args_so_far, promoted_mode,
04513 passed_type, named_arg);
04514 #else
04515 entry_parm = FUNCTION_ARG (args_so_far, promoted_mode,
04516 passed_type, named_arg);
04517 #endif
04518
04519 if (entry_parm == 0)
04520 promoted_mode = passed_mode;
04521
04522 #ifdef SETUP_INCOMING_VARARGS
04523
04524
04525
04526
04527
04528
04529
04530
04531
04532
04533 if (last_named && !varargs_setup)
04534 {
04535 SETUP_INCOMING_VARARGS (args_so_far, promoted_mode, passed_type,
04536 current_function_pretend_args_size, 0);
04537 varargs_setup = 1;
04538 }
04539 #endif
04540
04541
04542
04543
04544
04545
04546
04547
04548
04549
04550
04551
04552
04553
04554 pretend_named = named_arg || PRETEND_OUTGOING_VARARGS_NAMED;
04555 locate_and_pad_parm (promoted_mode, passed_type,
04556 #ifdef STACK_PARMS_IN_REG_PARM_AREA
04557 1,
04558 #else
04559 #ifdef FUNCTION_INCOMING_ARG
04560 FUNCTION_INCOMING_ARG (args_so_far, promoted_mode,
04561 passed_type,
04562 pretend_named) != 0,
04563 #else
04564 FUNCTION_ARG (args_so_far, promoted_mode,
04565 passed_type,
04566 pretend_named) != 0,
04567 #endif
04568 #endif
04569 fndecl, &stack_args_size, &stack_offset, &arg_size,
04570 &alignment_pad);
04571
04572 {
04573 rtx offset_rtx = ARGS_SIZE_RTX (stack_offset);
04574
04575 if (offset_rtx == const0_rtx)
04576 stack_parm = gen_rtx_MEM (promoted_mode, internal_arg_pointer);
04577 else
04578 stack_parm = gen_rtx_MEM (promoted_mode,
04579 gen_rtx_PLUS (Pmode,
04580 internal_arg_pointer,
04581 offset_rtx));
04582
04583 set_mem_attributes (stack_parm, parm, 1);
04584 }
04585
04586
04587
04588 if (MUST_PASS_IN_STACK (promoted_mode, passed_type))
04589 entry_parm = 0;
04590
04591 #ifdef FUNCTION_ARG_PARTIAL_NREGS
04592
04593
04594
04595
04596
04597
04598
04599
04600 if (entry_parm)
04601 {
04602 int nregs = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, promoted_mode,
04603 passed_type, named_arg);
04604
04605 if (nregs > 0)
04606 {
04607 #if defined (REG_PARM_STACK_SPACE) && !defined (MAYBE_REG_PARM_STACK_SPACE)
04608
04609
04610
04611 if (REG_PARM_STACK_SPACE (fndecl) == 0)
04612 #endif
04613 current_function_pretend_args_size
04614 = (((nregs * UNITS_PER_WORD) + (PARM_BOUNDARY / BITS_PER_UNIT) - 1)
04615 / (PARM_BOUNDARY / BITS_PER_UNIT)
04616 * (PARM_BOUNDARY / BITS_PER_UNIT));
04617
04618
04619
04620 if (GET_CODE (entry_parm) == PARALLEL)
04621 emit_group_store (validize_mem (stack_parm), entry_parm,
04622 int_size_in_bytes (TREE_TYPE (parm)));
04623
04624 else
04625 move_block_from_reg (REGNO (entry_parm),
04626 validize_mem (stack_parm), nregs,
04627 int_size_in_bytes (TREE_TYPE (parm)));
04628
04629 entry_parm = stack_parm;
04630 }
04631 }
04632 #endif
04633
04634
04635
04636 if (entry_parm == 0)
04637 entry_parm = stack_parm;
04638
04639
04640 DECL_INCOMING_RTL (parm) = entry_parm;
04641
04642
04643
04644
04645
04646 if (entry_parm == stack_parm
04647 || (GET_CODE (entry_parm) == PARALLEL
04648 && XEXP (XVECEXP (entry_parm, 0, 0), 0) == NULL_RTX)
04649 #if defined (REG_PARM_STACK_SPACE) && ! defined (MAYBE_REG_PARM_STACK_SPACE)
04650
04651
04652
04653
04654
04655
04656
04657
04658
04659 || REG_PARM_STACK_SPACE (fndecl) > 0
04660 #endif
04661 )
04662 {
04663 stack_args_size.constant += arg_size.constant;
04664 if (arg_size.var)
04665 ADD_PARM_SIZE (stack_args_size, arg_size.var);
04666 }
04667 else
04668
04669 stack_parm = 0;
04670
04671
04672
04673 FUNCTION_ARG_ADVANCE (args_so_far, promoted_mode,
04674 passed_type, named_arg);
04675
04676
04677
04678
04679 {
04680 unsigned int thisparm_boundary
04681 = FUNCTION_ARG_BOUNDARY (promoted_mode, passed_type);
04682
04683 if (GET_MODE_ALIGNMENT (nominal_mode) > thisparm_boundary)
04684 stack_parm = 0;
04685 }
04686
04687
04688
04689 if (entry_parm != 0
04690 && nominal_mode != BLKmode && nominal_mode != passed_mode)
04691 stack_parm = 0;
04692
04693
04694
04695
04696 if (GET_CODE (entry_parm) == PARALLEL
04697 && nominal_mode != BLKmode && passed_mode != BLKmode)
04698 {
04699 int i, len = XVECLEN (entry_parm, 0);
04700
04701 for (i = 0; i < len; i++)
04702 if (XEXP (XVECEXP (entry_parm, 0, i), 0) != NULL_RTX
04703 && GET_CODE (XEXP (XVECEXP (entry_parm, 0, i), 0)) == REG
04704 && (GET_MODE (XEXP (XVECEXP (entry_parm, 0, i), 0))
04705 == passed_mode)
04706 && INTVAL (XEXP (XVECEXP (entry_parm, 0, i), 1)) == 0)
04707 {
04708 entry_parm = XEXP (XVECEXP (entry_parm, 0, i), 0);
04709 DECL_INCOMING_RTL (parm) = entry_parm;
04710 break;
04711 }
04712 }
04713
04714
04715
04716
04717
04718
04719
04720
04721
04722
04723
04724
04725
04726
04727
04728 if (nominal_mode == BLKmode || GET_CODE (entry_parm) == PARALLEL)
04729 {
04730
04731
04732
04733 if (GET_CODE (entry_parm) == REG
04734 || GET_CODE (entry_parm) == PARALLEL)
04735 {
04736 int size_stored
04737 = CEIL_ROUND (int_size_in_bytes (TREE_TYPE (parm)),
04738 UNITS_PER_WORD);
04739
04740
04741
04742
04743
04744
04745
04746
04747
04748 if (stack_parm == 0)
04749 {
04750 stack_parm
04751 = assign_stack_local (GET_MODE (entry_parm),
04752 size_stored, 0);
04753 set_mem_attributes (stack_parm, parm, 1);
04754 }
04755
04756 else if (PARM_BOUNDARY % BITS_PER_WORD != 0)
04757 abort ();
04758
04759
04760
04761 if (GET_CODE (entry_parm) == PARALLEL)
04762 emit_group_store (validize_mem (stack_parm), entry_parm,
04763 int_size_in_bytes (TREE_TYPE (parm)));
04764 else
04765 move_block_from_reg (REGNO (entry_parm),
04766 validize_mem (stack_parm),
04767 size_stored / UNITS_PER_WORD,
04768 int_size_in_bytes (TREE_TYPE (parm)));
04769 }
04770 SET_DECL_RTL (parm, stack_parm);
04771 }
04772 else if (! ((! optimize
04773 && ! DECL_REGISTER (parm))
04774 || TREE_SIDE_EFFECTS (parm)
04775
04776
04777 || (flag_float_store
04778 && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE))
04779
04780
04781 || passed_pointer || parm == function_result_decl)
04782 {
04783
04784
04785
04786 rtx parmreg;
04787 unsigned int regno, regnoi = 0, regnor = 0;
04788
04789 unsignedp = TREE_UNSIGNED (TREE_TYPE (parm));
04790
04791 promoted_nominal_mode
04792 = promote_mode (TREE_TYPE (parm), nominal_mode, &unsignedp, 0);
04793
04794 parmreg = gen_reg_rtx (promoted_nominal_mode);
04795 mark_user_reg (parmreg);
04796
04797
04798
04799 if (passed_pointer)
04800 {
04801 rtx x = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (passed_type)),
04802 parmreg);
04803 set_mem_attributes (x, parm, 1);
04804 SET_DECL_RTL (parm, x);
04805 }
04806 else
04807 {
04808 SET_DECL_RTL (parm, parmreg);
04809 maybe_set_unchanging (DECL_RTL (parm), parm);
04810 }
04811
04812
04813 if (nominal_mode != passed_mode
04814 || promoted_nominal_mode != promoted_mode)
04815 {
04816 int save_tree_used;
04817
04818
04819
04820
04821
04822
04823
04824
04825
04826
04827
04828
04829
04830
04831
04832
04833
04834
04835
04836 rtx tempreg = gen_reg_rtx (GET_MODE (entry_parm));
04837
04838 emit_move_insn (tempreg, validize_mem (entry_parm));
04839
04840 push_to_sequence (conversion_insns);
04841 tempreg = convert_to_mode (nominal_mode, tempreg, unsignedp);
04842
04843 if (GET_CODE (tempreg) == SUBREG
04844 && GET_MODE (tempreg) == nominal_mode
04845 && GET_CODE (SUBREG_REG (tempreg)) == REG
04846 && nominal_mode == passed_mode
04847 && GET_MODE (SUBREG_REG (tempreg)) == GET_MODE (entry_parm)
04848 && GET_MODE_SIZE (GET_MODE (tempreg))
04849 < GET_MODE_SIZE (GET_MODE (entry_parm)))
04850 {
04851
04852
04853 SUBREG_PROMOTED_VAR_P (tempreg) = 1;
04854 SUBREG_PROMOTED_UNSIGNED_SET (tempreg, unsignedp);
04855 }
04856
04857
04858 save_tree_used = TREE_USED (parm);
04859 expand_assignment (parm,
04860 make_tree (nominal_type, tempreg), 0, 0);
04861 TREE_USED (parm) = save_tree_used;
04862 conversion_insns = get_insns ();
04863 did_conversion = 1;
04864 end_sequence ();
04865 }
04866 else
04867 emit_move_insn (parmreg, validize_mem (entry_parm));
04868
04869
04870
04871 if (passed_pointer && TYPE_MODE (TREE_TYPE (parm)) != BLKmode
04872
04873 && (TYPE_MODE (TREE_TYPE (parm)) != GET_MODE (DECL_RTL (parm))
04874 || ! ((! optimize
04875 && ! DECL_REGISTER (parm))
04876 || TREE_SIDE_EFFECTS (parm)
04877
04878
04879 || (flag_float_store
04880 && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE))))
04881 {
04882
04883
04884 parmreg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (parm)));
04885 mark_user_reg (parmreg);
04886 if (GET_MODE (parmreg) != GET_MODE (DECL_RTL (parm)))
04887 {
04888 rtx tempreg = gen_reg_rtx (GET_MODE (DECL_RTL (parm)));
04889 int unsigned_p = TREE_UNSIGNED (TREE_TYPE (parm));
04890 push_to_sequence (conversion_insns);
04891 emit_move_insn (tempreg, DECL_RTL (parm));
04892 SET_DECL_RTL (parm,
04893 convert_to_mode (GET_MODE (parmreg),
04894 tempreg,
04895 unsigned_p));
04896 emit_move_insn (parmreg, DECL_RTL (parm));
04897 conversion_insns = get_insns();
04898 did_conversion = 1;
04899 end_sequence ();
04900 }
04901 else
04902 emit_move_insn (parmreg, DECL_RTL (parm));
04903 SET_DECL_RTL (parm, parmreg);
04904
04905
04906 stack_parm = 0;
04907 }
04908 #ifdef FUNCTION_ARG_CALLEE_COPIES
04909
04910
04911
04912
04913
04914
04915
04916
04917 else if (passed_pointer
04918 && FUNCTION_ARG_CALLEE_COPIES (args_so_far,
04919 TYPE_MODE (DECL_ARG_TYPE (parm)),
04920 DECL_ARG_TYPE (parm),
04921 named_arg)
04922 && ! TREE_ADDRESSABLE (DECL_ARG_TYPE (parm)))
04923 {
04924 rtx copy;
04925 tree type = DECL_ARG_TYPE (parm);
04926
04927
04928
04929
04930 push_to_sequence (conversion_insns);
04931
04932 if (!COMPLETE_TYPE_P (type)
04933 || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
04934
04935 copy = gen_rtx_MEM (BLKmode,
04936 allocate_dynamic_stack_space
04937 (expr_size (parm), NULL_RTX,
04938 TYPE_ALIGN (type)));
04939 else
04940 copy = assign_stack_temp (TYPE_MODE (type),
04941 int_size_in_bytes (type), 1);
04942 set_mem_attributes (copy, parm, 1);
04943
04944 store_expr (parm, copy, 0);
04945 emit_move_insn (parmreg, XEXP (copy, 0));
04946 conversion_insns = get_insns ();
04947 did_conversion = 1;
04948 end_sequence ();
04949 }
04950 #endif
04951
04952
04953
04954
04955
04956
04957
04958 if (GET_CODE (parmreg) == CONCAT)
04959 regno = MAX (REGNO (XEXP (parmreg, 0)), REGNO (XEXP (parmreg, 1)));
04960 else
04961 regno = REGNO (parmreg);
04962
04963 if (regno >= max_parm_reg)
04964 {
04965 rtx *new;
04966 int old_max_parm_reg = max_parm_reg;
04967
04968
04969
04970
04971 max_parm_reg = regno + 1;
04972 new = (rtx *) ggc_realloc (parm_reg_stack_loc,
04973 max_parm_reg * sizeof (rtx));
04974 memset ((char *) (new + old_max_parm_reg), 0,
04975 (max_parm_reg - old_max_parm_reg) * sizeof (rtx));
04976 parm_reg_stack_loc = new;
04977 }
04978
04979 if (GET_CODE (parmreg) == CONCAT)
04980 {
04981 enum machine_mode submode = GET_MODE (XEXP (parmreg, 0));
04982
04983 regnor = REGNO (gen_realpart (submode, parmreg));
04984 regnoi = REGNO (gen_imagpart (submode, parmreg));
04985
04986 if (stack_parm != 0)
04987 {
04988 parm_reg_stack_loc[regnor]
04989 = gen_realpart (submode, stack_parm);
04990 parm_reg_stack_loc[regnoi]
04991 = gen_imagpart (submode, stack_parm);
04992 }
04993 else
04994 {
04995 parm_reg_stack_loc[regnor] = 0;
04996 parm_reg_stack_loc[regnoi] = 0;
04997 }
04998 }
04999 else
05000 parm_reg_stack_loc[REGNO (parmreg)] = stack_parm;
05001
05002
05003
05004
05005
05006
05007
05008 if (nominal_mode == passed_mode
05009 && ! did_conversion
05010 && stack_parm != 0
05011 && GET_CODE (stack_parm) == MEM
05012 && stack_offset.var == 0
05013 && reg_mentioned_p (virtual_incoming_args_rtx,
05014 XEXP (stack_parm, 0)))
05015 {
05016 rtx linsn = get_last_insn ();
05017 rtx sinsn, set;
05018
05019
05020 if (GET_CODE (parmreg) == CONCAT)
05021
05022
05023 for (sinsn = linsn; sinsn != 0;
05024 sinsn = prev_nonnote_insn (sinsn))
05025 {
05026 set = single_set (sinsn);
05027 if (set != 0
05028 && SET_DEST (set) == regno_reg_rtx [regnoi])
05029 REG_NOTES (sinsn)
05030 = gen_rtx_EXPR_LIST (REG_EQUIV,
05031 parm_reg_stack_loc[regnoi],
05032 REG_NOTES (sinsn));
05033 else if (set != 0
05034 && SET_DEST (set) == regno_reg_rtx [regnor])
05035 REG_NOTES (sinsn)
05036 = gen_rtx_EXPR_LIST (REG_EQUIV,
05037 parm_reg_stack_loc[regnor],
05038 REG_NOTES (sinsn));
05039 }
05040 else if ((set = single_set (linsn)) != 0
05041 && SET_DEST (set) == parmreg)
05042 REG_NOTES (linsn)
05043 = gen_rtx_EXPR_LIST (REG_EQUIV,
05044 stack_parm, REG_NOTES (linsn));
05045 }
05046
05047
05048 if (POINTER_TYPE_P (TREE_TYPE (parm)))
05049 mark_reg_pointer (parmreg,
05050 TYPE_ALIGN (TREE_TYPE (TREE_TYPE (parm))));
05051
05052
05053 if (TREE_ADDRESSABLE (parm))
05054 {
05055
05056
05057
05058
05059
05060
05061
05062 push_to_sequence (conversion_insns);
05063 put_var_into_stack (parm, true);
05064 conversion_insns = get_insns ();
05065 end_sequence ();
05066 }
05067 }
05068 else
05069 {
05070
05071
05072
05073 if (promoted_mode != nominal_mode)
05074 {
05075
05076 rtx tempreg = gen_reg_rtx (GET_MODE (entry_parm));
05077
05078 emit_move_insn (tempreg, validize_mem (entry_parm));
05079
05080 push_to_sequence (conversion_insns);
05081 entry_parm = convert_to_mode (nominal_mode, tempreg,
05082 TREE_UNSIGNED (TREE_TYPE (parm)));
05083 if (stack_parm)
05084
05085 stack_parm = adjust_address (stack_parm, nominal_mode, 0);
05086
05087 conversion_insns = get_insns ();
05088 did_conversion = 1;
05089 end_sequence ();
05090 }
05091
05092 if (entry_parm != stack_parm)
05093 {
05094 if (stack_parm == 0)
05095 {
05096 stack_parm
05097 = assign_stack_local (GET_MODE (entry_parm),
05098 GET_MODE_SIZE (GET_MODE (entry_parm)), 0);
05099 set_mem_attributes (stack_parm, parm, 1);
05100 }
05101
05102 if (promoted_mode != nominal_mode)
05103 {
05104 push_to_sequence (conversion_insns);
05105 emit_move_insn (validize_mem (stack_parm),
05106 validize_mem (entry_parm));
05107 conversion_insns = get_insns ();
05108 end_sequence ();
05109 }
05110 else
05111 emit_move_insn (validize_mem (stack_parm),
05112 validize_mem (entry_parm));
05113 }
05114
05115 SET_DECL_RTL (parm, stack_parm);
05116 }
05117
05118
05119
05120 if (parm == function_result_decl)
05121 {
05122 tree result = DECL_RESULT (fndecl);
05123 rtx addr = DECL_RTL (parm);
05124 rtx x;
05125
05126 #ifdef POINTERS_EXTEND_UNSIGNED
05127 if (GET_MODE (addr) != Pmode)
05128 addr = convert_memory_address (Pmode, addr);
05129 #endif
05130
05131 x = gen_rtx_MEM (DECL_MODE (result), addr);
05132 set_mem_attributes (x, result, 1);
05133 SET_DECL_RTL (result, x);
05134 }
05135
05136 if (GET_CODE (DECL_RTL (parm)) == REG)
05137 REGNO_DECL (REGNO (DECL_RTL (parm))) = parm;
05138 else if (GET_CODE (DECL_RTL (parm)) == CONCAT)
05139 {
05140 REGNO_DECL (REGNO (XEXP (DECL_RTL (parm), 0))) = parm;
05141 REGNO_DECL (REGNO (XEXP (DECL_RTL (parm), 1))) = parm;
05142 }
05143
05144 }
05145
05146
05147
05148 emit_insn (conversion_insns);
05149
05150 last_parm_insn = get_last_insn ();
05151
05152 current_function_args_size = stack_args_size.constant;
05153
05154
05155
05156
05157 #ifdef REG_PARM_STACK_SPACE
05158 #ifndef MAYBE_REG_PARM_STACK_SPACE
05159 current_function_args_size = MAX (current_function_args_size,
05160 REG_PARM_STACK_SPACE (fndecl));
05161 #endif
05162 #endif
05163
05164 #define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
05165
05166 current_function_args_size
05167 = ((current_function_args_size + STACK_BYTES - 1)
05168 / STACK_BYTES) * STACK_BYTES;
05169
05170 #ifdef ARGS_GROW_DOWNWARD
05171 current_function_arg_offset_rtx
05172 = (stack_args_size.var == 0 ? GEN_INT (-stack_args_size.constant)
05173 : expand_expr (size_diffop (stack_args_size.var,
05174 size_int (-stack_args_size.constant)),
05175 NULL_RTX, VOIDmode, 0));
05176 #else
05177 current_function_arg_offset_rtx = ARGS_SIZE_RTX (stack_args_size);
05178 #endif
05179
05180
05181
05182
05183 current_function_pops_args = RETURN_POPS_ARGS (fndecl, TREE_TYPE (fndecl),
05184 current_function_args_size);
05185
05186
05187
05188
05189 current_function_args_info = args_so_far;
05190
05191
05192
05193
05194
05195
05196 current_function_return_rtx
05197 = (DECL_RTL_SET_P (DECL_RESULT (fndecl))
05198 ? DECL_RTL (DECL_RESULT (fndecl)) : NULL_RTX);
05199
05200
05201
05202
05203 if (DECL_RTL_SET_P (DECL_RESULT (fndecl)))
05204 {
05205 tree decl_result = DECL_RESULT (fndecl);
05206 rtx decl_rtl = DECL_RTL (decl_result);
05207
05208 if (REG_P (decl_rtl)
05209 ? REGNO (decl_rtl) >= FIRST_PSEUDO_REGISTER
05210 : DECL_REGISTER (decl_result))
05211 {
05212 rtx real_decl_rtl;
05213
05214 #ifdef FUNCTION_OUTGOING_VALUE
05215 real_decl_rtl = FUNCTION_OUTGOING_VALUE (TREE_TYPE (decl_result),
05216 fndecl);
05217 #else
05218 real_decl_rtl = FUNCTION_VALUE (TREE_TYPE (decl_result),
05219 fndecl);
05220 #endif
05221 REG_FUNCTION_VALUE_P (real_decl_rtl) = 1;
05222
05223
05224
05225 current_function_return_rtx = real_decl_rtl;
05226 }
05227 }
05228 }
05229
05230
05231
05232
05233
05234
05235
05236 #ifdef PROMOTE_FUNCTION_ARGS
05237
05238 rtx
05239 promoted_input_arg (regno, pmode, punsignedp)
05240 unsigned int regno;
05241 enum machine_mode *pmode;
05242 int *punsignedp;
05243 {
05244 tree arg;
05245
05246 for (arg = DECL_ARGUMENTS (current_function_decl); arg;
05247 arg = TREE_CHAIN (arg))
05248 if (GET_CODE (DECL_INCOMING_RTL (arg)) == REG
05249 && REGNO (DECL_INCOMING_RTL (arg)) == regno
05250 && TYPE_MODE (DECL_ARG_TYPE (arg)) == TYPE_MODE (TREE_TYPE (arg)))
05251 {
05252 enum machine_mode mode = TYPE_MODE (TREE_TYPE (arg));
05253 int unsignedp = TREE_UNSIGNED (TREE_TYPE (arg));
05254
05255 mode = promote_mode (TREE_TYPE (arg), mode, &unsignedp, 1);
05256 if (mode == GET_MODE (DECL_INCOMING_RTL (arg))
05257 && mode != DECL_MODE (arg))
05258 {
05259 *pmode = DECL_MODE (arg);
05260 *punsignedp = unsignedp;
05261 return DECL_INCOMING_RTL (arg);
05262 }
05263 }
05264
05265 return 0;
05266 }
05267
05268 #endif
05269
05270
05271
05272
05273
05274
05275
05276
05277
05278
05279
05280
05281
05282
05283
05284
05285
05286
05287
05288
05289
05290
05291
05292
05293
05294
05295
05296
05297
05298
05299 void
05300 locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
05301 initial_offset_ptr, offset_ptr, arg_size_ptr,
05302 alignment_pad)
05303 enum machine_mode passed_mode;
05304 tree type;
05305 int in_regs ATTRIBUTE_UNUSED;
05306 tree fndecl ATTRIBUTE_UNUSED;
05307 struct args_size *initial_offset_ptr;
05308 struct args_size *offset_ptr;
05309 struct args_size *arg_size_ptr;
05310 struct args_size *alignment_pad;
05311
05312 {
05313 tree sizetree
05314 = type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode));
05315 enum direction where_pad = FUNCTION_ARG_PADDING (passed_mode, type);
05316 int boundary = FUNCTION_ARG_BOUNDARY (passed_mode, type);
05317 #ifdef ARGS_GROW_DOWNWARD
05318 tree s2 = sizetree;
05319 #endif
05320
05321 #ifdef REG_PARM_STACK_SPACE
05322
05323
05324 if (! in_regs)
05325 {
05326 int reg_parm_stack_space = 0;
05327
05328 #ifdef MAYBE_REG_PARM_STACK_SPACE
05329 reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
05330 #else
05331 reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
05332 #endif
05333 if (reg_parm_stack_space > 0)
05334 {
05335 if (initial_offset_ptr->var)
05336 {
05337 initial_offset_ptr->var
05338 = size_binop (MAX_EXPR, ARGS_SIZE_TREE (*initial_offset_ptr),
05339 ssize_int (reg_parm_stack_space));
05340 initial_offset_ptr->constant = 0;
05341 }
05342 else if (initial_offset_ptr->constant < reg_parm_stack_space)
05343 initial_offset_ptr->constant = reg_parm_stack_space;
05344 }
05345 }
05346 #endif
05347
05348 arg_size_ptr->var = 0;
05349 arg_size_ptr->constant = 0;
05350 alignment_pad->var = 0;
05351 alignment_pad->constant = 0;
05352
05353 #ifdef ARGS_GROW_DOWNWARD
05354 if (initial_offset_ptr->var)
05355 {
05356 offset_ptr->constant = 0;
05357 offset_ptr->var = size_binop (MINUS_EXPR, ssize_int (0),
05358 initial_offset_ptr->var);
05359 }
05360 else
05361 {
05362 offset_ptr->constant = -initial_offset_ptr->constant;
05363 offset_ptr->var = 0;
05364 }
05365
05366 if (where_pad != none
05367 && (!host_integerp (sizetree, 1)
05368 || (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % PARM_BOUNDARY))
05369 s2 = round_up (s2, PARM_BOUNDARY / BITS_PER_UNIT);
05370 SUB_PARM_SIZE (*offset_ptr, s2);
05371
05372 if (!in_regs
05373 #ifdef REG_PARM_STACK_SPACE
05374 || REG_PARM_STACK_SPACE (fndecl) > 0
05375 #endif
05376 )
05377 pad_to_arg_alignment (offset_ptr, boundary, alignment_pad);
05378
05379 if (initial_offset_ptr->var)
05380 arg_size_ptr->var = size_binop (MINUS_EXPR,
05381 size_binop (MINUS_EXPR,
05382 ssize_int (0),
05383 initial_offset_ptr->var),
05384 offset_ptr->var);
05385
05386 else
05387 arg_size_ptr->constant = (-initial_offset_ptr->constant
05388 - offset_ptr->constant);
05389
05390
05391
05392
05393 if (where_pad == downward
05394 && !in_regs)
05395 pad_below (offset_ptr, passed_mode, sizetree);
05396
05397 #else
05398 if (!in_regs
05399 #ifdef REG_PARM_STACK_SPACE
05400 || REG_PARM_STACK_SPACE (fndecl) > 0
05401 #endif
05402 )
05403 pad_to_arg_alignment (initial_offset_ptr, boundary, alignment_pad);
05404 *offset_ptr = *initial_offset_ptr;
05405
05406 #ifdef PUSH_ROUNDING
05407 if (passed_mode != BLKmode)
05408 sizetree = size_int (PUSH_ROUNDING (TREE_INT_CST_LOW (sizetree)));
05409 #endif
05410
05411
05412
05413 if (where_pad == downward
05414
05415
05416 && !(in_regs && passed_mode == BLKmode))
05417 pad_below (offset_ptr, passed_mode, sizetree);
05418
05419 if (where_pad != none
05420 && (!host_integerp (sizetree, 1)
05421 || (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % PARM_BOUNDARY))
05422 sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
05423
05424 ADD_PARM_SIZE (*arg_size_ptr, sizetree);
05425 #endif
05426 }
05427
05428
05429
05430
05431 static void
05432 pad_to_arg_alignment (offset_ptr, boundary, alignment_pad)
05433 struct args_size *offset_ptr;
05434 int boundary;
05435 struct args_size *alignment_pad;
05436 {
05437 tree save_var = NULL_TREE;
05438 HOST_WIDE_INT save_constant = 0;
05439
05440 int boundary_in_bytes = boundary / BITS_PER_UNIT;
05441
05442 if (boundary > PARM_BOUNDARY && boundary > STACK_BOUNDARY)
05443 {
05444 save_var = offset_ptr->var;
05445 save_constant = offset_ptr->constant;
05446 }
05447
05448 alignment_pad->var = NULL_TREE;
05449 alignment_pad->constant = 0;
05450
05451 if (boundary > BITS_PER_UNIT)
05452 {
05453 if (offset_ptr->var)
05454 {
05455 offset_ptr->var =
05456 #ifdef ARGS_GROW_DOWNWARD
05457 round_down
05458 #else
05459 round_up
05460 #endif
05461 (ARGS_SIZE_TREE (*offset_ptr),
05462 boundary / BITS_PER_UNIT);
05463 offset_ptr->constant = 0;
05464 if (boundary > PARM_BOUNDARY && boundary > STACK_BOUNDARY)
05465 alignment_pad->var = size_binop (MINUS_EXPR, offset_ptr->var,
05466 save_var);
05467 }
05468 else
05469 {
05470 offset_ptr->constant =
05471 #ifdef ARGS_GROW_DOWNWARD
05472 FLOOR_ROUND (offset_ptr->constant, boundary_in_bytes);
05473 #else
05474 CEIL_ROUND (offset_ptr->constant, boundary_in_bytes);
05475 #endif
05476 if (boundary > PARM_BOUNDARY && boundary > STACK_BOUNDARY)
05477 alignment_pad->constant = offset_ptr->constant - save_constant;
05478 }
05479 }
05480 }
05481
05482 static void
05483 pad_below (offset_ptr, passed_mode, sizetree)
05484 struct args_size *offset_ptr;
05485 enum machine_mode passed_mode;
05486 tree sizetree;
05487 {
05488 if (passed_mode != BLKmode)
05489 {
05490 if (GET_MODE_BITSIZE (passed_mode) % PARM_BOUNDARY)
05491 offset_ptr->constant
05492 += (((GET_MODE_BITSIZE (passed_mode) + PARM_BOUNDARY - 1)
05493 / PARM_BOUNDARY * PARM_BOUNDARY / BITS_PER_UNIT)
05494 - GET_MODE_SIZE (passed_mode));
05495 }
05496 else
05497 {
05498 if (TREE_CODE (sizetree) != INTEGER_CST
05499 || (TREE_INT_CST_LOW (sizetree) * BITS_PER_UNIT) % PARM_BOUNDARY)
05500 {
05501
05502 tree s2 = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
05503
05504 ADD_PARM_SIZE (*offset_ptr, s2);
05505 SUB_PARM_SIZE (*offset_ptr, sizetree);
05506 }
05507 }
05508 }
05509
05510
05511
05512
05513
05514
05515 void
05516 uninitialized_vars_warning (block)
05517 tree block;
05518 {
05519 tree decl, sub;
05520 for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
05521 {
05522 if (warn_uninitialized
05523 && TREE_CODE (decl) == VAR_DECL
05524
05525
05526
05527
05528 && ! AGGREGATE_TYPE_P (TREE_TYPE (decl))
05529 && DECL_RTL (decl) != 0
05530 && GET_CODE (DECL_RTL (decl)) == REG
05531
05532
05533
05534
05535
05536
05537
05538 && DECL_INITIAL (decl) == NULL_TREE
05539 && regno_uninitialized (REGNO (DECL_RTL (decl))))
05540 warning_with_decl (decl,
05541 "`%s' might be used uninitialized in this function");
05542 if (extra_warnings
05543 && TREE_CODE (decl) == VAR_DECL
05544 && DECL_RTL (decl) != 0
05545 && GET_CODE (DECL_RTL (decl)) == REG
05546 && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
05547 warning_with_decl (decl,
05548 "variable `%s' might be clobbered by `longjmp' or `vfork'");
05549 }
05550 for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub))
05551 uninitialized_vars_warning (sub);
05552 }
05553
05554
05555
05556
05557 void
05558 setjmp_args_warning ()
05559 {
05560 tree decl;
05561 for (decl = DECL_ARGUMENTS (current_function_decl);
05562 decl; decl = TREE_CHAIN (decl))
05563 if (DECL_RTL (decl) != 0
05564 && GET_CODE (DECL_RTL (decl)) == REG
05565 && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
05566 warning_with_decl (decl,
05567 "argument `%s' might be clobbered by `longjmp' or `vfork'");
05568 }
05569
05570
05571
05572
05573 void
05574 setjmp_protect (block)
05575 tree block;
05576 {
05577 tree decl, sub;
05578 for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
05579 if ((TREE_CODE (decl) == VAR_DECL
05580 || TREE_CODE (decl) == PARM_DECL)
05581 && DECL_RTL (decl) != 0
05582 && (GET_CODE (DECL_RTL (decl)) == REG
05583 || (GET_CODE (DECL_RTL (decl)) == MEM
05584 && GET_CODE (XEXP (DECL_RTL (decl), 0)) == ADDRESSOF))
05585
05586
05587
05588
05589
05590 && ! DECL_FROM_INLINE (decl)
05591 && (
05592 #ifdef NON_SAVING_SETJMP
05593
05594
05595 NON_SAVING_SETJMP
05596 ||
05597 #endif
05598 ! DECL_REGISTER (decl)))
05599 put_var_into_stack (decl, true);
05600 for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub))
05601 setjmp_protect (sub);
05602 }
05603
05604
05605
05606 void
05607 setjmp_protect_args ()
05608 {
05609 tree decl;
05610 for (decl = DECL_ARGUMENTS (current_function_decl);
05611 decl; decl = TREE_CHAIN (decl))
05612 if ((TREE_CODE (decl) == VAR_DECL
05613 || TREE_CODE (decl) == PARM_DECL)
05614 && DECL_RTL (decl) != 0
05615 && (GET_CODE (DECL_RTL (decl)) == REG
05616 || (GET_CODE (DECL_RTL (decl)) == MEM
05617 && GET_CODE (XEXP (DECL_RTL (decl), 0)) == ADDRESSOF))
05618 && (
05619
05620
05621 #ifdef NON_SAVING_SETJMP
05622 NON_SAVING_SETJMP
05623 ||
05624 #endif
05625 ! DECL_REGISTER (decl)))
05626 put_var_into_stack (decl, true);
05627 }
05628
05629
05630
05631
05632 rtx
05633 lookup_static_chain (decl)
05634 tree decl;
05635 {
05636 tree context = decl_function_context (decl);
05637 tree link;
05638
05639 if (context == 0
05640 || (TREE_CODE (decl) == FUNCTION_DECL && DECL_NO_STATIC_CHAIN (decl)))
05641 return 0;
05642
05643
05644
05645
05646
05647 if (context == current_function_decl || context == inline_function_decl)
05648 return virtual_stack_vars_rtx;
05649
05650 for (link = context_display; link; link = TREE_CHAIN (link))
05651 if (TREE_PURPOSE (link) == context)
05652 return RTL_EXPR_RTL (TREE_VALUE (link));
05653
05654 abort ();
05655 }
05656
05657
05658
05659
05660
05661 rtx
05662 fix_lexical_addr (addr, var)
05663 rtx addr;
05664 tree var;
05665 {
05666 rtx basereg;
05667 HOST_WIDE_INT displacement;
05668 tree context = decl_function_context (var);
05669 struct function *fp;
05670 rtx base = 0;
05671
05672
05673 if (context == current_function_decl || context == inline_function_decl)
05674 return addr;
05675
05676 fp = find_function_data (context);
05677
05678 if (GET_CODE (addr) == ADDRESSOF && GET_CODE (XEXP (addr, 0)) == MEM)
05679 addr = XEXP (XEXP (addr, 0), 0);
05680
05681
05682 if (GET_CODE (addr) == REG)
05683 basereg = addr, displacement = 0;
05684 else if (GET_CODE (addr) == PLUS && GET_CODE (XEXP (addr, 1)) == CONST_INT)
05685 basereg = XEXP (addr, 0), displacement = INTVAL (XEXP (addr, 1));
05686 else
05687 abort ();
05688
05689
05690
05691 if (basereg == fp->internal_arg_pointer)
05692 {
05693
05694
05695
05696
05697
05698
05699
05700
05701
05702 #ifdef NEED_SEPARATE_AP
05703 rtx addr;
05704
05705 addr = get_arg_pointer_save_area (fp);
05706 addr = fix_lexical_addr (XEXP (addr, 0), var);
05707 addr = memory_address (Pmode, addr);
05708
05709 base = gen_rtx_MEM (Pmode, addr);
05710 set_mem_alias_set (base, get_frame_alias_set ());
05711 base = copy_to_reg (base);
05712 #else
05713 displacement += (FIRST_PARM_OFFSET (context) - STARTING_FRAME_OFFSET);
05714 base = lookup_static_chain (var);
05715 #endif
05716 }
05717
05718 else if (basereg == virtual_stack_vars_rtx)
05719 {
05720
05721
05722 tree link;
05723
05724 for (link = context_display; link; link = TREE_CHAIN (link))
05725 if (TREE_PURPOSE (link) == context)
05726 {
05727 base = RTL_EXPR_RTL (TREE_VALUE (link));
05728 break;
05729 }
05730 }
05731
05732 if (base == 0)
05733 abort ();
05734
05735
05736
05737 return plus_constant (base, displacement);
05738 }
05739
05740
05741
05742
05743
05744 rtx
05745 trampoline_address (function)
05746 tree function;
05747 {
05748 tree link;
05749 tree rtlexp;
05750 rtx tramp;
05751 struct function *fp;
05752 tree fn_context;
05753
05754
05755 for (link = trampoline_list; link; link = TREE_CHAIN (link))
05756 if (TREE_PURPOSE (link) == function)
05757 return
05758 adjust_trampoline_addr (XEXP (RTL_EXPR_RTL (TREE_VALUE (link)), 0));
05759
05760 for (fp = outer_function_chain; fp; fp = fp->outer)
05761 for (link = fp->x_trampoline_list; link; link = TREE_CHAIN (link))
05762 if (TREE_PURPOSE (link) == function)
05763 {
05764 tramp = fix_lexical_addr (XEXP (RTL_EXPR_RTL (TREE_VALUE (link)), 0),
05765 function);
05766 return adjust_trampoline_addr (tramp);
05767 }
05768
05769
05770
05771
05772 fp = 0;
05773 fn_context = decl_function_context (function);
05774 if (fn_context != current_function_decl
05775 && fn_context != inline_function_decl)
05776 fp = find_function_data (fn_context);
05777
05778
05779
05780 #ifdef ALLOCATE_TRAMPOLINE
05781 tramp = ALLOCATE_TRAMPOLINE (fp);
05782 #else
05783
05784
05785 #define TRAMPOLINE_REAL_SIZE \
05786 (TRAMPOLINE_SIZE + (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT) - 1)
05787 tramp = assign_stack_local_1 (BLKmode, TRAMPOLINE_REAL_SIZE, 0,
05788 fp ? fp : cfun);
05789 #endif
05790
05791
05792
05793 if (fp != 0)
05794 {
05795 rtlexp = make_node (RTL_EXPR);
05796 RTL_EXPR_RTL (rtlexp) = tramp;
05797 fp->x_trampoline_list = tree_cons (function, rtlexp,
05798 fp->x_trampoline_list);
05799 }
05800 else
05801 {
05802
05803
05804 rtlexp = make_node (RTL_EXPR);
05805
05806 RTL_EXPR_RTL (rtlexp) = tramp;
05807 trampoline_list = tree_cons (function, rtlexp, trampoline_list);
05808 }
05809
05810 tramp = fix_lexical_addr (XEXP (tramp, 0), function);
05811 return adjust_trampoline_addr (tramp);
05812 }
05813
05814
05815
05816
05817 static rtx
05818 round_trampoline_addr (tramp)
05819 rtx tramp;
05820 {
05821
05822 rtx temp = gen_reg_rtx (Pmode);
05823 rtx addend = GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1);
05824 rtx mask = GEN_INT (-TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
05825
05826 temp = expand_simple_binop (Pmode, PLUS, tramp, addend,
05827 temp, 0, OPTAB_LIB_WIDEN);
05828 tramp = expand_simple_binop (Pmode, AND, temp, mask,
05829 temp, 0, OPTAB_LIB_WIDEN);
05830
05831 return tramp;
05832 }
05833
05834
05835
05836
05837
05838 static rtx
05839 adjust_trampoline_addr (tramp)
05840 rtx tramp;
05841 {
05842 tramp = round_trampoline_addr (tramp);
05843 #ifdef TRAMPOLINE_ADJUST_ADDRESS
05844 TRAMPOLINE_ADJUST_ADDRESS (tramp);
05845 #endif
05846 return tramp;
05847 }
05848
05849
05850
05851
05852
05853
05854
05855
05856 void
05857 identify_blocks ()
05858 {
05859 int n_blocks;
05860 tree *block_vector, *last_block_vector;
05861 tree *block_stack;
05862 tree block = DECL_INITIAL (current_function_decl);
05863
05864 if (block == 0)
05865 return;
05866
05867
05868
05869 block_vector = get_block_vector (block, &n_blocks);
05870 block_stack = (tree *) xmalloc (n_blocks * sizeof (tree));
05871
05872 last_block_vector = identify_blocks_1 (get_insns (),
05873 block_vector + 1,
05874 block_vector + n_blocks,
05875 block_stack);
05876
05877
05878
05879 if (0 && last_block_vector != block_vector + n_blocks)
05880 abort ();
05881
05882 free (block_vector);
05883 free (block_stack);
05884 }
05885
05886
05887
05888
05889
05890
05891
05892 static tree *
05893 identify_blocks_1 (insns, block_vector, end_block_vector, orig_block_stack)
05894 rtx insns;
05895 tree *block_vector;
05896 tree *end_block_vector;
05897 tree *orig_block_stack;
05898 {
05899 rtx insn;
05900 tree *block_stack = orig_block_stack;
05901
05902 for (insn = insns; insn; insn = NEXT_INSN (insn))
05903 {
05904 if (GET_CODE (insn) == NOTE)
05905 {
05906 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
05907 {
05908 tree b;
05909
05910
05911
05912 if (block_vector == end_block_vector)
05913 abort ();
05914
05915 b = *block_vector++;
05916 NOTE_BLOCK (insn) = b;
05917 *block_stack++ = b;
05918 }
05919 else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
05920 {
05921
05922
05923 if (block_stack == orig_block_stack)
05924 abort ();
05925
05926 NOTE_BLOCK (insn) = *--block_stack;
05927 }
05928 }
05929 else if (GET_CODE (insn) == CALL_INSN
05930 && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
05931 {
05932 rtx cp = PATTERN (insn);
05933
05934 block_vector = identify_blocks_1 (XEXP (cp, 0), block_vector,
05935 end_block_vector, block_stack);
05936 if (XEXP (cp, 1))
05937 block_vector = identify_blocks_1 (XEXP (cp, 1), block_vector,
05938 end_block_vector, block_stack);
05939 if (XEXP (cp, 2))
05940 block_vector = identify_blocks_1 (XEXP (cp, 2), block_vector,
05941 end_block_vector, block_stack);
05942 }
05943 }
05944
05945
05946
05947 if (block_stack != orig_block_stack)
05948 abort ();
05949
05950 return block_vector;
05951 }
05952
05953
05954
05955
05956
05957
05958
05959 void
05960 reorder_blocks ()
05961 {
05962 tree block = DECL_INITIAL (current_function_decl);
05963 varray_type block_stack;
05964
05965 if (block == NULL_TREE)
05966 return;
05967
05968 VARRAY_TREE_INIT (block_stack, 10, "block_stack");
05969
05970
05971 reorder_blocks_0 (block);
05972
05973
05974 BLOCK_SUBBLOCKS (block) = NULL_TREE;
05975 BLOCK_CHAIN (block) = NULL_TREE;
05976
05977
05978 reorder_blocks_1 (get_insns (), block, &block_stack);
05979 BLOCK_SUBBLOCKS (block) = blocks_nreverse (BLOCK_SUBBLOCKS (block));
05980
05981
05982 reorder_fix_fragments (block);
05983 }
05984
05985
05986
05987 static void
05988 reorder_blocks_0 (block)
05989 tree block;
05990 {
05991 while (block)
05992 {
05993 TREE_ASM_WRITTEN (block) = 0;
05994 reorder_blocks_0 (BLOCK_SUBBLOCKS (block));
05995 block = BLOCK_CHAIN (block);
05996 }
05997 }
05998
05999 static void
06000 reorder_blocks_1 (insns, current_block, p_block_stack)
06001 rtx insns;
06002 tree current_block;
06003 varray_type *p_block_stack;
06004 {
06005 rtx insn;
06006
06007 for (insn = insns; insn; insn = NEXT_INSN (insn))
06008 {
06009 if (GET_CODE (insn) == NOTE)
06010 {
06011 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
06012 {
06013 tree block = NOTE_BLOCK (insn);
06014
06015
06016
06017 if (TREE_ASM_WRITTEN (block))
06018 {
06019 tree new_block = copy_node (block);
06020 tree origin;
06021
06022 origin = (BLOCK_FRAGMENT_ORIGIN (block)
06023 ? BLOCK_FRAGMENT_ORIGIN (block)
06024 : block);
06025 BLOCK_FRAGMENT_ORIGIN (new_block) = origin;
06026 BLOCK_FRAGMENT_CHAIN (new_block)
06027 = BLOCK_FRAGMENT_CHAIN (origin);
06028 BLOCK_FRAGMENT_CHAIN (origin) = new_block;
06029
06030 NOTE_BLOCK (insn) = new_block;
06031 block = new_block;
06032 }
06033
06034 BLOCK_SUBBLOCKS (block) = 0;
06035 TREE_ASM_WRITTEN (block) = 1;
06036 BLOCK_SUPERCONTEXT (block) = current_block;
06037 BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block);
06038 BLOCK_SUBBLOCKS (current_block) = block;
06039 current_block = block;
06040 VARRAY_PUSH_TREE (*p_block_stack, block);
06041 }
06042 else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
06043 {
06044 NOTE_BLOCK (insn) = VARRAY_TOP_TREE (*p_block_stack);
06045 VARRAY_POP (*p_block_stack);
06046 BLOCK_SUBBLOCKS (current_block)
06047 = blocks_nreverse (BLOCK_SUBBLOCKS (current_block));
06048 current_block = BLOCK_SUPERCONTEXT (current_block);
06049 }
06050 }
06051 else if (GET_CODE (insn) == CALL_INSN
06052 && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
06053 {
06054 rtx cp = PATTERN (insn);
06055 reorder_blocks_1 (XEXP (cp, 0), current_block, p_block_stack);
06056 if (XEXP (cp, 1))
06057 reorder_blocks_1 (XEXP (cp, 1), current_block, p_block_stack);
06058 if (XEXP (cp, 2))
06059 reorder_blocks_1 (XEXP (cp, 2), current_block, p_block_stack);
06060 }
06061 }
06062 }
06063
06064
06065
06066
06067
06068 static void
06069 reorder_fix_fragments (block)
06070 tree block;
06071 {
06072 while (block)
06073 {
06074 tree dup_origin = BLOCK_FRAGMENT_ORIGIN (block);
06075 tree new_origin = NULL_TREE;
06076
06077 if (dup_origin)
06078 {
06079 if (! TREE_ASM_WRITTEN (dup_origin))
06080 {
06081 new_origin = BLOCK_FRAGMENT_CHAIN (dup_origin);
06082
06083
06084
06085 while (! TREE_ASM_WRITTEN (new_origin))
06086 new_origin = BLOCK_FRAGMENT_CHAIN (new_origin);
06087 BLOCK_FRAGMENT_ORIGIN (new_origin) = NULL_TREE;
06088 }
06089 }
06090 else if (! dup_origin)
06091 new_origin = block;
06092
06093
06094
06095
06096
06097 if (new_origin)
06098 {
06099 tree *pp = &BLOCK_FRAGMENT_CHAIN (new_origin);
06100 tree chain = *pp;
06101
06102 while (chain)
06103 {
06104 if (TREE_ASM_WRITTEN (chain))
06105 {
06106 BLOCK_FRAGMENT_ORIGIN (chain) = new_origin;
06107 *pp = chain;
06108 pp = &BLOCK_FRAGMENT_CHAIN (chain);
06109 }
06110 chain = BLOCK_FRAGMENT_CHAIN (chain);
06111 }
06112 *pp = NULL_TREE;
06113 }
06114
06115 reorder_fix_fragments (BLOCK_SUBBLOCKS (block));
06116 block = BLOCK_CHAIN (block);
06117 }
06118 }
06119
06120
06121
06122
06123 static tree
06124 blocks_nreverse (t)
06125 tree t;
06126 {
06127 tree prev = 0, decl, next;
06128 for (decl = t; decl; decl = next)
06129 {
06130 next = BLOCK_CHAIN (decl);
06131 BLOCK_CHAIN (decl) = prev;
06132 prev = decl;
06133 }
06134 return prev;
06135 }
06136
06137
06138
06139
06140
06141
06142 static int
06143 all_blocks (block, vector)
06144 tree block;
06145 tree *vector;
06146 {
06147 int n_blocks = 0;
06148
06149 while (block)
06150 {
06151 TREE_ASM_WRITTEN (block) = 0;
06152
06153
06154 if (vector)
06155 vector[n_blocks] = block;
06156
06157 ++n_blocks;
06158
06159
06160 n_blocks += all_blocks (BLOCK_SUBBLOCKS (block),
06161 vector ? vector + n_blocks : 0);
06162 block = BLOCK_CHAIN (block);
06163 }
06164
06165 return n_blocks;
06166 }
06167
06168
06169
06170
06171
06172
06173 static tree *
06174 get_block_vector (block, n_blocks_p)
06175 tree block;
06176 int *n_blocks_p;
06177 {
06178 tree *block_vector;
06179
06180 *n_blocks_p = all_blocks (block, NULL);
06181 block_vector = (tree *) xmalloc (*n_blocks_p * sizeof (tree));
06182 all_blocks (block, block_vector);
06183
06184 return block_vector;
06185 }
06186
06187 static int next_block_index = 2;
06188
06189
06190
06191 void
06192 number_blocks (fn)
06193 tree fn;
06194 {
06195 int i;
06196 int n_blocks;
06197 tree *block_vector;
06198
06199
06200
06201
06202 #if defined (SDB_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
06203 if (write_symbols == SDB_DEBUG || write_symbols == XCOFF_DEBUG)
06204 next_block_index = 1;
06205 #endif
06206
06207 block_vector = get_block_vector (DECL_INITIAL (fn), &n_blocks);
06208
06209
06210 for (i = 1; i < n_blocks; ++i)
06211
06212 BLOCK_NUMBER (block_vector[i]) = next_block_index++;
06213
06214 free (block_vector);
06215
06216 return;
06217 }
06218
06219
06220
06221 tree
06222 debug_find_var_in_block_tree (var, block)
06223 tree var;
06224 tree block;
06225 {
06226 tree t;
06227
06228 for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
06229 if (t == var)
06230 return block;
06231
06232 for (t = BLOCK_SUBBLOCKS (block); t; t = TREE_CHAIN (t))
06233 {
06234 tree ret = debug_find_var_in_block_tree (var, t);
06235 if (ret)
06236 return ret;
06237 }
06238
06239 return NULL_TREE;
06240 }
06241
06242
06243
06244 static void
06245 prepare_function_start ()
06246 {
06247 cfun = (struct function *) ggc_alloc_cleared (sizeof (struct function));
06248
06249 init_stmt_for_function ();
06250 init_eh_for_function ();
06251
06252 cse_not_expected = ! optimize;
06253
06254
06255 caller_save_needed = 0;
06256
06257
06258 stack_slot_list = 0;
06259
06260 current_function_has_nonlocal_label = 0;
06261 current_function_has_nonlocal_goto = 0;
06262
06263
06264 nonlocal_goto_handler_slots = 0;
06265 nonlocal_goto_stack_level = 0;
06266
06267
06268 nonlocal_labels = 0;
06269 nonlocal_goto_handler_labels = 0;
06270
06271
06272 function_call_count = 0;
06273
06274
06275
06276 max_parm_reg = LAST_VIRTUAL_REGISTER + 1;
06277
06278
06279 init_emit ();
06280
06281
06282
06283 init_expr ();
06284
06285
06286 reg_renumber = 0;
06287
06288 init_varasm_status (cfun);
06289
06290
06291 cfun->inlinable = 0;
06292 cfun->original_decl_initial = 0;
06293 cfun->original_arg_vector = 0;
06294
06295 cfun->stack_alignment_needed = STACK_BOUNDARY;
06296 cfun->preferred_stack_boundary = STACK_BOUNDARY;
06297
06298
06299 current_function_calls_setjmp = 0;
06300
06301
06302 current_function_calls_longjmp = 0;
06303
06304 current_function_calls_alloca = 0;
06305 current_function_contains_functions = 0;
06306 current_function_is_leaf = 0;
06307 current_function_nothrow = 0;
06308 current_function_sp_is_unchanging = 0;
06309 current_function_uses_only_leaf_regs = 0;
06310 current_function_has_computed_jump = 0;
06311 current_function_is_thunk = 0;
06312
06313 current_function_returns_pcc_struct = 0;
06314 current_function_returns_struct = 0;
06315 current_function_epilogue_delay_list = 0;
06316 current_function_uses_const_pool = 0;
06317 current_function_uses_pic_offset_table = 0;
06318 current_function_cannot_inline = 0;
06319
06320
06321 tail_recursion_label = 0;
06322
06323
06324 arg_pointer_save_area = 0;
06325
06326
06327 frame_offset = 0;
06328
06329
06330 save_expr_regs = 0;
06331
06332
06333 rtl_expr_chain = 0;
06334
06335
06336 init_temp_slots ();
06337
06338
06339
06340 rtx_equal_function_value_matters = 1;
06341
06342
06343 virtuals_instantiated = 0;
06344
06345
06346 generating_concat_p = 1;
06347
06348
06349 frame_pointer_needed = 0;
06350
06351
06352 current_function_stdarg = 0;
06353
06354
06355 trampoline_list = 0;
06356
06357 init_pending_stack_adjust ();
06358 inhibit_defer_pop = 0;
06359
06360 current_function_outgoing_args_size = 0;
06361
06362 current_function_funcdef_no = funcdef_no++;
06363
06364 cfun->arc_profile = profile_arc_flag || flag_test_coverage;
06365
06366 cfun->arc_profile = profile_arc_flag || flag_test_coverage;
06367
06368 cfun->function_frequency = FUNCTION_FREQUENCY_NORMAL;
06369
06370 cfun->max_jumptable_ents = 0;
06371
06372 (*lang_hooks.function.init) (cfun);
06373 if (init_machine_status)
06374 cfun->machine = (*init_machine_status) ();
06375 }
06376
06377
06378
06379
06380 void
06381 init_dummy_function_start ()
06382 {
06383 prepare_function_start ();
06384 }
06385
06386
06387
06388
06389
06390 void
06391 init_function_start (subr, filename, line)
06392 tree subr;
06393 const char *filename;
06394 int line;
06395 {
06396 prepare_function_start ();
06397
06398 current_function_name = (*lang_hooks.decl_printable_name) (subr, 2);
06399 cfun->decl = subr;
06400
06401
06402
06403 current_function_needs_context
06404 = (decl_function_context (current_function_decl) != 0
06405 && ! DECL_NO_STATIC_CHAIN (current_function_decl));
06406
06407
06408 immediate_size_expand++;
06409
06410
06411
06412
06413 if (line > 0)
06414 emit_line_note (filename, line);
06415
06416
06417
06418
06419 emit_note (NULL, NOTE_INSN_DELETED);
06420
06421
06422 if (aggregate_value_p (DECL_RESULT (subr)))
06423 {
06424 #ifdef PCC_STATIC_STRUCT_RETURN
06425 current_function_returns_pcc_struct = 1;
06426 #endif
06427 current_function_returns_struct = 1;
06428 }
06429
06430
06431
06432 if (warn_aggregate_return
06433 && AGGREGATE_TYPE_P (TREE_TYPE (DECL_RESULT (subr))))
06434 warning ("function returns an aggregate");
06435
06436 current_function_returns_pointer
06437 = POINTER_TYPE_P (TREE_TYPE (DECL_RESULT (subr)));
06438 }
06439
06440
06441
06442 void
06443 init_function_for_compilation ()
06444 {
06445 reg_renumber = 0;
06446
06447
06448 VARRAY_GROW (prologue, 0);
06449 VARRAY_GROW (epilogue, 0);
06450 VARRAY_GROW (sibcall_epilogue, 0);
06451 }
06452
06453
06454
06455 #if defined(INIT_SECTION_ASM_OP) && !defined(INVOKE__main)
06456 #undef HAS_INIT_SECTION
06457 #define HAS_INIT_SECTION
06458 #endif
06459
06460 void
06461 expand_main_function ()
06462 {
06463 #ifdef FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN
06464 if (FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN)
06465 {
06466 int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
06467 rtx tmp, seq;
06468
06469 start_sequence ();
06470
06471 #ifdef STACK_GROWS_DOWNWARD
06472 tmp = expand_simple_binop (Pmode, AND, stack_pointer_rtx, GEN_INT(-align),
06473 stack_pointer_rtx, 1, OPTAB_WIDEN);
06474 #else
06475 tmp = expand_simple_binop (Pmode, PLUS, stack_pointer_rtx,
06476 GEN_INT (align - 1), NULL_RTX, 1, OPTAB_WIDEN);
06477 tmp = expand_simple_binop (Pmode, AND, tmp, GEN_INT (-align),
06478 stack_pointer_rtx, 1, OPTAB_WIDEN);
06479 #endif
06480 if (tmp != stack_pointer_rtx)
06481 emit_move_insn (stack_pointer_rtx, tmp);
06482
06483
06484 tmp = force_reg (Pmode, const0_rtx);
06485 allocate_dynamic_stack_space (tmp, NULL_RTX, BIGGEST_ALIGNMENT);
06486 seq = get_insns ();
06487 end_sequence ();
06488
06489 for (tmp = get_last_insn (); tmp; tmp = PREV_INSN (tmp))
06490 if (NOTE_P (tmp) && NOTE_LINE_NUMBER (tmp) == NOTE_INSN_FUNCTION_BEG)
06491 break;
06492 if (tmp)
06493 emit_insn_before (seq, tmp);
06494 else
06495 emit_insn (seq);
06496 }
06497 #endif
06498
06499 #ifndef HAS_INIT_SECTION
06500 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, NAME__MAIN), LCT_NORMAL,
06501 VOIDmode, 0);
06502 #endif
06503 }
06504
06505
06506
06507
06508
06509
06510
06511 void
06512 expand_pending_sizes (pending_sizes)
06513 tree pending_sizes;
06514 {
06515 tree tem;
06516
06517
06518 for (tem = pending_sizes; tem; tem = TREE_CHAIN (tem))
06519 {
06520 expand_expr (TREE_VALUE (tem), const0_rtx, VOIDmode, 0);
06521
06522
06523 emit_queue ();
06524 }
06525 }
06526
06527
06528
06529
06530
06531
06532
06533 void
06534 expand_function_start (subr, parms_have_cleanups)
06535 tree subr;
06536 int parms_have_cleanups;
06537 {
06538 tree tem;
06539 rtx last_ptr = NULL_RTX;
06540
06541
06542
06543 init_recog_no_volatile ();
06544
06545 current_function_instrument_entry_exit
06546 = (flag_instrument_function_entry_exit
06547 && ! DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (subr));
06548
06549 current_function_profile
06550 = (profile_flag
06551 && ! DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (subr));
06552
06553 current_function_limit_stack
06554 = (stack_limit_rtx != NULL_RTX && ! DECL_NO_LIMIT_STACK (subr));
06555
06556
06557
06558 if (current_function_needs_context)
06559 {
06560 last_ptr = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
06561
06562
06563
06564 if (! SMALL_REGISTER_CLASSES
06565 || GET_CODE (static_chain_incoming_rtx) == REG)
06566 emit_move_insn (last_ptr, static_chain_incoming_rtx);
06567 }
06568
06569
06570
06571
06572 if (parms_have_cleanups)
06573 cleanup_label = gen_label_rtx ();
06574 else
06575 cleanup_label = 0;
06576
06577
06578
06579
06580 return_label = gen_label_rtx ();
06581
06582
06583
06584
06585
06586
06587 if (aggregate_value_p (DECL_RESULT (subr)))
06588 {
06589
06590 rtx value_address = 0;
06591
06592 #ifdef PCC_STATIC_STRUCT_RETURN
06593 if (current_function_returns_pcc_struct)
06594 {
06595 int size = int_size_in_bytes (TREE_TYPE (DECL_RESULT (subr)));
06596 value_address = assemble_static_space (size);
06597 }
06598 else
06599 #endif
06600 {
06601
06602
06603
06604 if (struct_value_incoming_rtx)
06605 {
06606 value_address = gen_reg_rtx (Pmode);
06607 emit_move_insn (value_address, struct_value_incoming_rtx);
06608 }
06609 }
06610 if (value_address)
06611 {
06612 rtx x = gen_rtx_MEM (DECL_MODE (DECL_RESULT (subr)), value_address);
06613 set_mem_attributes (x, DECL_RESULT (subr), 1);
06614 SET_DECL_RTL (DECL_RESULT (subr), x);
06615 }
06616 }
06617 else if (DECL_MODE (DECL_RESULT (subr)) == VOIDmode)
06618
06619 SET_DECL_RTL (DECL_RESULT (subr), NULL_RTX);
06620 else
06621 {
06622
06623
06624
06625
06626
06627
06628 rtx hard_reg
06629 = hard_function_value (TREE_TYPE (DECL_RESULT (subr)),
06630 subr, 1);
06631
06632
06633
06634 if (REG_P (hard_reg))
06635 SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (GET_MODE (hard_reg)));
06636 else if (GET_CODE (hard_reg) == PARALLEL)
06637 SET_DECL_RTL (DECL_RESULT (subr), gen_group_rtx (hard_reg));
06638 else
06639 abort ();
06640
06641
06642
06643 DECL_REGISTER (DECL_RESULT (subr)) = 1;
06644 }
06645
06646
06647
06648
06649 assign_parms (subr);
06650
06651
06652
06653
06654 if (SMALL_REGISTER_CLASSES && current_function_needs_context)
06655 if (GET_CODE (static_chain_incoming_rtx) != REG)
06656 emit_move_insn (last_ptr, static_chain_incoming_rtx);
06657
06658
06659
06660
06661
06662 emit_note (NULL, NOTE_INSN_FUNCTION_BEG);
06663
06664 if (GET_CODE (get_last_insn ()) != NOTE)
06665 emit_note (NULL, NOTE_INSN_DELETED);
06666 parm_birth_insn = get_last_insn ();
06667
06668 context_display = 0;
06669 if (current_function_needs_context)
06670 {
06671
06672 tem = decl_function_context (current_function_decl);
06673
06674
06675
06676 if (tem)
06677 {
06678
06679
06680
06681 if (SMALL_REGISTER_CLASSES
06682 && GET_CODE (static_chain_incoming_rtx) == REG)
06683 emit_move_insn (static_chain_incoming_rtx, last_ptr);
06684 last_ptr = copy_to_reg (static_chain_incoming_rtx);
06685 }
06686
06687 while (tem)
06688 {
06689 tree rtlexp = make_node (RTL_EXPR);
06690
06691 RTL_EXPR_RTL (rtlexp) = last_ptr;
06692 context_display = tree_cons (tem, rtlexp, context_display);
06693 tem = decl_function_context (tem);
06694 if (tem == 0)
06695 break;
06696
06697
06698 #ifdef FRAME_GROWS_DOWNWARD
06699 last_ptr = plus_constant (last_ptr,
06700 -(HOST_WIDE_INT) GET_MODE_SIZE (Pmode));
06701 #endif
06702 last_ptr = gen_rtx_MEM (Pmode, memory_address (Pmode, last_ptr));
06703 set_mem_alias_set (last_ptr, get_frame_alias_set ());
06704 last_ptr = copy_to_reg (last_ptr);
06705
06706
06707
06708 if (! optimize)
06709 save_expr_regs = gen_rtx_EXPR_LIST (VOIDmode, last_ptr,
06710 save_expr_regs);
06711 }
06712 }
06713
06714 if (current_function_instrument_entry_exit)
06715 {
06716 rtx fun = DECL_RTL (current_function_decl);
06717 if (GET_CODE (fun) == MEM)
06718 fun = XEXP (fun, 0);
06719 else
06720 abort ();
06721 emit_library_call (profile_function_entry_libfunc, LCT_NORMAL, VOIDmode,
06722 2, fun, Pmode,
06723 expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
06724 0,
06725 hard_frame_pointer_rtx),
06726 Pmode);
06727 }
06728
06729 if (current_function_profile)
06730 {
06731 #ifdef PROFILE_HOOK
06732 PROFILE_HOOK (current_function_funcdef_no);
06733 #endif
06734 }
06735
06736
06737
06738
06739 tail_recursion_reentry = emit_note (NULL, NOTE_INSN_DELETED);
06740
06741
06742 expand_pending_sizes (nreverse (get_pending_sizes ()));
06743
06744
06745 force_next_line_note ();
06746 }
06747
06748
06749 void
06750 expand_dummy_function_end ()
06751 {
06752
06753 while (in_sequence_p ())
06754 end_sequence ();
06755
06756
06757
06758
06759 free_after_parsing (cfun);
06760 free_after_compilation (cfun);
06761 cfun = 0;
06762 }
06763
06764
06765
06766
06767 void
06768 diddle_return_value (doit, arg)
06769 void (*doit) PARAMS ((rtx, void *));
06770 void *arg;
06771 {
06772 rtx outgoing = current_function_return_rtx;
06773
06774 if (! outgoing)
06775 return;
06776
06777 if (GET_CODE (outgoing) == REG)
06778 (*doit) (outgoing, arg);
06779 else if (GET_CODE (outgoing) == PARALLEL)
06780 {
06781 int i;
06782
06783 for (i = 0; i < XVECLEN (outgoing, 0); i++)
06784 {
06785 rtx x = XEXP (XVECEXP (outgoing, 0, i), 0);
06786
06787 if (GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
06788 (*doit) (x, arg);
06789 }
06790 }
06791 }
06792
06793 static void
06794 do_clobber_return_reg (reg, arg)
06795 rtx reg;
06796 void *arg ATTRIBUTE_UNUSED;
06797 {
06798 emit_insn (gen_rtx_CLOBBER (VOIDmode, reg));
06799 }
06800
06801 void
06802 clobber_return_register ()
06803 {
06804 diddle_return_value (do_clobber_return_reg, NULL);
06805
06806
06807 if (DECL_RTL_SET_P (DECL_RESULT (current_function_decl)))
06808 {
06809 tree decl_result = DECL_RESULT (current_function_decl);
06810 rtx decl_rtl = DECL_RTL (decl_result);
06811 if (REG_P (decl_rtl) && REGNO (decl_rtl) >= FIRST_PSEUDO_REGISTER)
06812 {
06813 do_clobber_return_reg (decl_rtl, NULL);
06814 }
06815 }
06816 }
06817
06818 static void
06819 do_use_return_reg (reg, arg)
06820 rtx reg;
06821 void *arg ATTRIBUTE_UNUSED;
06822 {
06823 emit_insn (gen_rtx_USE (VOIDmode, reg));
06824 }
06825
06826 void
06827 use_return_register ()
06828 {
06829 diddle_return_value (do_use_return_reg, NULL);
06830 }
06831
06832 static GTY(()) rtx initial_trampoline;
06833
06834
06835
06836
06837
06838
06839
06840 void
06841 expand_function_end (filename, line, end_bindings)
06842 const char *filename;
06843 int line;
06844 int end_bindings;
06845 {
06846 tree link;
06847 rtx clobber_after;
06848
06849 #ifdef SGI_MONGOOSE
06850 #ifdef KEY
06851
06852
06853
06854 immediate_size_expand--;
06855 #endif
06856
06857 return;
06858 #endif
06859
06860 finish_expr_for_function ();
06861
06862
06863
06864 if (arg_pointer_save_area && ! cfun->arg_pointer_save_area_init)
06865 get_arg_pointer_save_area (cfun);
06866
06867 #ifdef NON_SAVING_SETJMP
06868
06869
06870 if (NON_SAVING_SETJMP && current_function_calls_setjmp)
06871 {
06872 if (DECL_INITIAL (current_function_decl) != error_mark_node)
06873 setjmp_protect (DECL_INITIAL (current_function_decl));
06874
06875 setjmp_protect_args ();
06876 }
06877 #endif
06878
06879
06880 for (link = trampoline_list; link; link = TREE_CHAIN (link))
06881 {
06882 tree function = TREE_PURPOSE (link);
06883 rtx context ATTRIBUTE_UNUSED = lookup_static_chain (function);
06884 rtx tramp = RTL_EXPR_RTL (TREE_VALUE (link));
06885 #ifdef TRAMPOLINE_TEMPLATE
06886 rtx blktramp;
06887 #endif
06888 rtx seq;
06889
06890 #ifdef TRAMPOLINE_TEMPLATE
06891
06892
06893 if (initial_trampoline == 0)
06894 {
06895 initial_trampoline
06896 = gen_rtx_MEM (BLKmode, assemble_trampoline_template ());
06897 set_mem_align (initial_trampoline, TRAMPOLINE_ALIGNMENT);
06898 }
06899 #endif
06900
06901
06902 start_sequence ();
06903 tramp = round_trampoline_addr (XEXP (tramp, 0));
06904 #ifdef TRAMPOLINE_TEMPLATE
06905 blktramp = replace_equiv_address (initial_trampoline, tramp);
06906 emit_block_move (blktramp, initial_trampoline,
06907 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
06908 #endif
06909 trampolines_created = 1;
06910 INITIALIZE_TRAMPOLINE (tramp, XEXP (DECL_RTL (function), 0), context);
06911 seq = get_insns ();
06912 end_sequence ();
06913
06914
06915 emit_insn_before (seq, tail_recursion_reentry);
06916 }
06917
06918
06919
06920
06921 if (flag_stack_check && ! STACK_CHECK_BUILTIN)
06922 {
06923 rtx insn, seq;
06924
06925 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
06926 if (GET_CODE (insn) == CALL_INSN)
06927 {
06928 start_sequence ();
06929 probe_stack_range (STACK_CHECK_PROTECT,
06930 GEN_INT (STACK_CHECK_MAX_FRAME_SIZE));
06931 seq = get_insns ();
06932 end_sequence ();
06933 emit_insn_before (seq, tail_recursion_reentry);
06934 break;
06935 }
06936 }
06937
06938
06939
06940
06941
06942 if (warn_unused_parameter > 0
06943 || (warn_unused_parameter < 0 && extra_warnings))
06944 {
06945 tree decl;
06946
06947 for (decl = DECL_ARGUMENTS (current_function_decl);
06948 decl; decl = TREE_CHAIN (decl))
06949 if (! TREE_USED (decl) && TREE_CODE (decl) == PARM_DECL
06950 && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
06951 warning_with_decl (decl, "unused parameter `%s'");
06952 }
06953
06954
06955 if (nonlocal_goto_handler_slots != 0
06956 && ! current_function_has_nonlocal_label)
06957 delete_handlers ();
06958
06959
06960 while (in_sequence_p ())
06961 end_sequence ();
06962
06963
06964
06965 immediate_size_expand--;
06966
06967 clear_pending_stack_adjust ();
06968 do_pending_stack_adjust ();
06969
06970
06971
06972
06973 emit_note (NULL, NOTE_INSN_FUNCTION_END);
06974
06975
06976
06977
06978
06979
06980 if (flag_test_coverage)
06981 emit_note (NULL, NOTE_INSN_REPEATED_LINE_NUMBER);
06982
06983
06984
06985 emit_line_note_force (filename, line);
06986
06987
06988
06989
06990
06991
06992
06993
06994
06995 clobber_after = get_last_insn ();
06996
06997
06998
06999
07000
07001
07002 if (return_label)
07003 emit_label (return_label);
07004
07005
07006 if (end_bindings)
07007 expand_end_bindings (0, 0, 0);
07008
07009 if (current_function_instrument_entry_exit)
07010 {
07011 rtx fun = DECL_RTL (current_function_decl);
07012 if (GET_CODE (fun) == MEM)
07013 fun = XEXP (fun, 0);
07014 else
07015 abort ();
07016 emit_library_call (profile_function_exit_libfunc, LCT_NORMAL, VOIDmode,
07017 2, fun, Pmode,
07018 expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
07019 0,
07020 hard_frame_pointer_rtx),
07021 Pmode);
07022 }
07023
07024
07025
07026 if (flag_exceptions && USING_SJLJ_EXCEPTIONS)
07027 sjlj_emit_function_exit_after (get_last_insn ());
07028
07029
07030
07031
07032 #ifdef EXIT_IGNORE_STACK
07033 if (! EXIT_IGNORE_STACK)
07034 #endif
07035 if (current_function_calls_alloca)
07036 {
07037 rtx tem = 0;
07038
07039 emit_stack_save (SAVE_FUNCTION, &tem, parm_birth_insn);
07040 emit_stack_restore (SAVE_FUNCTION, tem, NULL_RTX);
07041 }
07042
07043
07044
07045
07046 if (DECL_RTL_SET_P (DECL_RESULT (current_function_decl)))
07047 {
07048 tree decl_result = DECL_RESULT (current_function_decl);
07049 rtx decl_rtl = DECL_RTL (decl_result);
07050
07051 if (REG_P (decl_rtl)
07052 ? REGNO (decl_rtl) >= FIRST_PSEUDO_REGISTER
07053 : DECL_REGISTER (decl_result))
07054 {
07055 rtx real_decl_rtl = current_function_return_rtx;
07056
07057
07058 if (! REG_FUNCTION_VALUE_P (real_decl_rtl))
07059 abort ();
07060
07061
07062
07063
07064
07065 if (GET_MODE (real_decl_rtl) == BLKmode)
07066 PUT_MODE (real_decl_rtl, GET_MODE (decl_rtl));
07067
07068
07069
07070
07071 if (GET_MODE (real_decl_rtl) != GET_MODE (decl_rtl))
07072 {
07073 int unsignedp = TREE_UNSIGNED (TREE_TYPE (decl_result));
07074
07075 #ifdef PROMOTE_FUNCTION_RETURN
07076 promote_mode (TREE_TYPE (decl_result), GET_MODE (decl_rtl),
07077 &unsignedp, 1);
07078 #endif
07079
07080 convert_move (real_decl_rtl, decl_rtl, unsignedp);
07081 }
07082 else if (GET_CODE (real_decl_rtl) == PARALLEL)
07083 {
07084
07085
07086
07087 if (GET_CODE (decl_rtl) == PARALLEL)
07088 emit_group_move (real_decl_rtl, decl_rtl);
07089 else
07090 emit_group_load (real_decl_rtl, decl_rtl,
07091 int_size_in_bytes (TREE_TYPE (decl_result)));
07092 }
07093 else
07094 emit_move_insn (real_decl_rtl, decl_rtl);
07095 }
07096 }
07097
07098
07099
07100
07101
07102
07103
07104 if (current_function_returns_struct
07105 || current_function_returns_pcc_struct)
07106 {
07107 rtx value_address
07108 = XEXP (DECL_RTL (DECL_RESULT (current_function_decl)), 0);
07109 tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
07110 #ifdef FUNCTION_OUTGOING_VALUE
07111 rtx outgoing
07112 = FUNCTION_OUTGOING_VALUE (build_pointer_type (type),
07113 current_function_decl);
07114 #else
07115 rtx outgoing
07116 = FUNCTION_VALUE (build_pointer_type (type), current_function_decl);
07117 #endif
07118
07119
07120
07121 REG_FUNCTION_VALUE_P (outgoing) = 1;
07122
07123 #ifdef POINTERS_EXTEND_UNSIGNED
07124
07125 if (GET_MODE (outgoing) != GET_MODE (value_address))
07126 value_address = convert_memory_address (GET_MODE (outgoing),
07127 value_address);
07128 #endif
07129
07130 emit_move_insn (outgoing, value_address);
07131
07132
07133
07134 current_function_return_rtx = outgoing;
07135 }
07136
07137
07138
07139 expand_eh_return ();
07140
07141
07142 {
07143 rtx seq, after;
07144
07145 start_sequence ();
07146 clobber_return_register ();
07147 seq = get_insns ();
07148 end_sequence ();
07149
07150 after = emit_insn_after (seq, clobber_after);
07151
07152 if (clobber_after != after)
07153 cfun->x_clobber_return_insn = after;
07154 }
07155
07156
07157
07158
07159
07160 use_return_register ();
07161
07162
07163
07164
07165
07166
07167
07168
07169 expand_fixups (get_insns ());
07170 }
07171
07172 rtx
07173 get_arg_pointer_save_area (f)
07174 struct function *f;
07175 {
07176 rtx ret = f->x_arg_pointer_save_area;
07177
07178 if (! ret)
07179 {
07180 ret = assign_stack_local_1 (Pmode, GET_MODE_SIZE (Pmode), 0, f);
07181 f->x_arg_pointer_save_area = ret;
07182 }
07183
07184 if (f == cfun && ! f->arg_pointer_save_area_init)
07185 {
07186 rtx seq;
07187
07188
07189
07190
07191 start_sequence ();
07192 emit_move_insn (validize_mem (ret), virtual_incoming_args_rtx);
07193 seq = get_insns ();
07194 end_sequence ();
07195
07196 push_topmost_sequence ();
07197 emit_insn_after (seq, get_insns ());
07198 pop_topmost_sequence ();
07199 }
07200
07201 return ret;
07202 }
07203
07204
07205
07206
07207 static void
07208 record_insns (insns, vecp)
07209 rtx insns;
07210 varray_type *vecp;
07211 {
07212 int i, len;
07213 rtx tmp;
07214
07215 tmp = insns;
07216 len = 0;
07217 while (tmp != NULL_RTX)
07218 {
07219 len++;
07220 tmp = NEXT_INSN (tmp);
07221 }
07222
07223 i = VARRAY_SIZE (*vecp);
07224 VARRAY_GROW (*vecp, i + len);
07225 tmp = insns;
07226 while (tmp != NULL_RTX)
07227 {
07228 VARRAY_INT (*vecp, i) = INSN_UID (tmp);
07229 i++;
07230 tmp = NEXT_INSN (tmp);
07231 }
07232 }
07233
07234
07235
07236
07237 static int
07238 contains (insn, vec)
07239 rtx insn;
07240 varray_type vec;
07241 {
07242 int i, j;
07243
07244 if (GET_CODE (insn) == INSN
07245 && GET_CODE (PATTERN (insn)) == SEQUENCE)
07246 {
07247 int count = 0;
07248 for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
07249 for (j = VARRAY_SIZE (vec) - 1; j >= 0; --j)
07250 if (INSN_UID (XVECEXP (PATTERN (insn), 0, i)) == VARRAY_INT (vec, j))
07251 count++;
07252 return count;
07253 }
07254 else
07255 {
07256 for (j = VARRAY_SIZE (vec) - 1; j >= 0; --j)
07257 if (INSN_UID (insn) == VARRAY_INT (vec, j))
07258 return 1;
07259 }
07260 return 0;
07261 }
07262
07263 int
07264 prologue_epilogue_contains (insn)
07265 rtx insn;
07266 {
07267 if (contains (insn, prologue))
07268 return 1;
07269 if (contains (insn, epilogue))
07270 return 1;
07271 return 0;
07272 }
07273
07274 int
07275 sibcall_epilogue_contains (insn)
07276 rtx insn;
07277 {
07278 if (sibcall_epilogue)
07279 return contains (insn, sibcall_epilogue);
07280 return 0;
07281 }
07282
07283 #ifdef HAVE_return
07284
07285
07286
07287 static void
07288 emit_return_into_block (bb, line_note)
07289 basic_block bb;
07290 rtx line_note;
07291 {
07292 rtx p, end;
07293
07294 p = NEXT_INSN (bb->end);
07295 end = emit_jump_insn_after (gen_return (), bb->end);
07296 if (line_note)
07297 emit_line_note_after (NOTE_SOURCE_FILE (line_note),
07298 NOTE_LINE_NUMBER (line_note), PREV_INSN (bb->end));
07299 }
07300 #endif
07301
07302 #if defined(HAVE_epilogue) && defined(INCOMING_RETURN_ADDR_RTX)
07303
07304
07305
07306
07307
07308
07309
07310
07311
07312
07313
07314
07315
07316
07317
07318
07319
07320
07321
07322
07323
07324
07325
07326
07327
07328
07329
07330
07331
07332
07333 struct epi_info
07334 {
07335 rtx sp_equiv_reg;
07336 HOST_WIDE_INT sp_offset;
07337 rtx new_sp_equiv_reg;
07338 HOST_WIDE_INT new_sp_offset;
07339 rtx equiv_reg_src;
07340
07341
07342 };
07343
07344 static void handle_epilogue_set PARAMS ((rtx, struct epi_info *));
07345 static void emit_equiv_load PARAMS ((struct epi_info *));
07346
07347
07348
07349
07350 static rtx
07351 keep_stack_depressed (insns)
07352 rtx insns;
07353 {
07354 int j;
07355 struct epi_info info;
07356 rtx insn, next;
07357
07358
07359
07360 if (NEXT_INSN (insns) == NULL_RTX)
07361 return insns;
07362
07363
07364
07365 start_sequence ();
07366
07367 info.sp_equiv_reg = stack_pointer_rtx;
07368 info.sp_offset = 0;
07369 info.equiv_reg_src = 0;
07370
07371 insn = insns;
07372 next = NULL_RTX;
07373 while (insn != NULL_RTX)
07374 {
07375 next = NEXT_INSN (insn);
07376
07377 if (!INSN_P (insn))
07378 {
07379 add_insn (insn);
07380 insn = next;
07381 continue;
07382 }
07383
07384
07385
07386
07387 if (info.equiv_reg_src != 0
07388 && reg_referenced_p (info.sp_equiv_reg, PATTERN (insn)))
07389 {
07390 emit_equiv_load (&info);
07391 info.sp_equiv_reg = 0;
07392 }
07393
07394 info.new_sp_equiv_reg = info.sp_equiv_reg;
07395 info.new_sp_offset = info.sp_offset;
07396
07397
07398
07399 if (GET_CODE (PATTERN (insn)) == RETURN
07400 || (GET_CODE (PATTERN (insn)) == PARALLEL
07401 && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == RETURN))
07402 {
07403 rtx retaddr = INCOMING_RETURN_ADDR_RTX;
07404 rtx base = 0;
07405 HOST_WIDE_INT offset = 0;
07406 rtx jump_insn, jump_set;
07407
07408
07409
07410
07411
07412 if (GET_CODE (retaddr) == REG)
07413 {
07414 emit_equiv_load (&info);
07415 add_insn (insn);
07416 insn = next;
07417 continue;
07418 }
07419 else if (GET_CODE (retaddr) == MEM
07420 && GET_CODE (XEXP (retaddr, 0)) == REG)
07421 base = gen_rtx_REG (Pmode, REGNO (XEXP (retaddr, 0))), offset = 0;
07422 else if (GET_CODE (retaddr) == MEM
07423 && GET_CODE (XEXP (retaddr, 0)) == PLUS
07424 && GET_CODE (XEXP (XEXP (retaddr, 0), 0)) == REG
07425 && GET_CODE (XEXP (XEXP (retaddr, 0), 1)) == CONST_INT)
07426 {
07427 base = gen_rtx_REG (Pmode, REGNO (XEXP (XEXP (retaddr, 0), 0)));
07428 offset = INTVAL (XEXP (XEXP (retaddr, 0), 1));
07429 }
07430 else
07431 abort ();
07432
07433
07434
07435
07436 retaddr = plus_constant (base, offset);
07437 if (base == stack_pointer_rtx)
07438 retaddr = simplify_replace_rtx (retaddr, stack_pointer_rtx,
07439 plus_constant (info.sp_equiv_reg,
07440 info.sp_offset));
07441
07442 retaddr = gen_rtx_MEM (Pmode, retaddr);
07443
07444
07445
07446
07447 if (info.equiv_reg_src
07448 && reg_overlap_mentioned_p (info.equiv_reg_src, retaddr))
07449 {
07450 unsigned int regno;
07451 rtx reg;
07452
07453 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
07454 if (HARD_REGNO_MODE_OK (regno, Pmode)
07455 && !fixed_regs[regno]
07456 && TEST_HARD_REG_BIT (regs_invalidated_by_call, regno)
07457 && !REGNO_REG_SET_P (EXIT_BLOCK_PTR->global_live_at_start,
07458 regno)
07459 && !refers_to_regno_p (regno,
07460 regno + HARD_REGNO_NREGS (regno,
07461 Pmode),
07462 info.equiv_reg_src, NULL))
07463 break;
07464
07465 if (regno == FIRST_PSEUDO_REGISTER)
07466 abort ();
07467
07468 reg = gen_rtx_REG (Pmode, regno);
07469 emit_move_insn (reg, retaddr);
07470 retaddr = reg;
07471 }
07472
07473 emit_equiv_load (&info);
07474 jump_insn = emit_jump_insn (gen_indirect_jump (retaddr));
07475
07476
07477 jump_set = single_set (jump_insn);
07478 if (jump_set == 0)
07479 abort ();
07480 else
07481 SET_IS_RETURN_P (jump_set) = 1;
07482 }
07483
07484
07485
07486
07487
07488 else if (!reg_mentioned_p (stack_pointer_rtx, PATTERN (insn))
07489 && (info.sp_equiv_reg == stack_pointer_rtx
07490 || !reg_set_p (info.sp_equiv_reg, insn)))
07491 add_insn (insn);
07492 else if (! reg_set_p (stack_pointer_rtx, insn)
07493 && (info.sp_equiv_reg == stack_pointer_rtx
07494 || !reg_set_p (info.sp_equiv_reg, insn)))
07495 {
07496 if (! validate_replace_rtx (stack_pointer_rtx,
07497 plus_constant (info.sp_equiv_reg,
07498 info.sp_offset),
07499 insn))
07500 abort ();
07501
07502 add_insn (insn);
07503 }
07504 else if (GET_CODE (PATTERN (insn)) == SET)
07505 handle_epilogue_set (PATTERN (insn), &info);
07506 else if (GET_CODE (PATTERN (insn)) == PARALLEL)
07507 {
07508 for (j = 0; j < XVECLEN (PATTERN (insn), 0); j++)
07509 if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == SET)
07510 handle_epilogue_set (XVECEXP (PATTERN (insn), 0, j), &info);
07511 }
07512 else
07513 add_insn (insn);
07514
07515 info.sp_equiv_reg = info.new_sp_equiv_reg;
07516 info.sp_offset = info.new_sp_offset;
07517
07518 insn = next;
07519 }
07520
07521 insns = get_insns ();
07522 end_sequence ();
07523 return insns;
07524 }
07525
07526
07527
07528
07529
07530
07531 static void
07532 handle_epilogue_set (set, p)
07533 rtx set;
07534 struct epi_info *p;
07535 {
07536
07537
07538 if (reg_set_p (stack_pointer_rtx, set))
07539 {
07540 if (SET_DEST (set) != stack_pointer_rtx)
07541 abort ();
07542
07543 if (GET_CODE (SET_SRC (set)) == PLUS
07544 && GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT)
07545 {
07546 p->new_sp_equiv_reg = XEXP (SET_SRC (set), 0);
07547 p->new_sp_offset = INTVAL (XEXP (SET_SRC (set), 1));
07548 }
07549 else
07550 p->new_sp_equiv_reg = SET_SRC (set), p->new_sp_offset = 0;
07551
07552
07553 if (p->new_sp_equiv_reg == stack_pointer_rtx)
07554 {
07555 p->new_sp_equiv_reg = p->sp_equiv_reg;
07556 p->new_sp_offset += p->sp_offset;
07557 }
07558
07559 if (p->new_sp_equiv_reg == 0 || GET_CODE (p->new_sp_equiv_reg) != REG)
07560 abort ();
07561
07562 return;
07563 }
07564
07565
07566
07567
07568
07569
07570
07571 else if (p->new_sp_equiv_reg != 0 && reg_set_p (p->new_sp_equiv_reg, set))
07572 {
07573 if (!rtx_equal_p (p->new_sp_equiv_reg, SET_DEST (set))
07574 || p->equiv_reg_src != 0)
07575 abort ();
07576 else
07577 p->equiv_reg_src
07578 = simplify_replace_rtx (SET_SRC (set), stack_pointer_rtx,
07579 plus_constant (p->sp_equiv_reg,
07580 p->sp_offset));
07581 }
07582
07583
07584
07585 else
07586 {
07587 SET_SRC (set) = simplify_replace_rtx (SET_SRC (set), stack_pointer_rtx,
07588 plus_constant (p->sp_equiv_reg,
07589 p->sp_offset));
07590 SET_DEST (set) = simplify_replace_rtx (SET_DEST (set), stack_pointer_rtx,
07591 plus_constant (p->sp_equiv_reg,
07592 p->sp_offset));
07593 emit_insn (set);
07594 }
07595 }
07596
07597
07598
07599 static void
07600 emit_equiv_load (p)
07601 struct epi_info *p;
07602 {
07603 if (p->equiv_reg_src != 0)
07604 emit_move_insn (p->sp_equiv_reg, p->equiv_reg_src);
07605
07606 p->equiv_reg_src = 0;
07607 }
07608 #endif
07609
07610
07611
07612
07613
07614 void
07615 thread_prologue_and_epilogue_insns (f)
07616 rtx f ATTRIBUTE_UNUSED;
07617 {
07618 int inserted = 0;
07619 edge e;
07620 #if defined (HAVE_sibcall_epilogue) || defined (HAVE_epilogue) || defined (HAVE_return) || defined (HAVE_prologue)
07621 rtx seq;
07622 #endif
07623 #ifdef HAVE_prologue
07624 rtx prologue_end = NULL_RTX;
07625 #endif
07626 #if defined (HAVE_epilogue) || defined(HAVE_return)
07627 rtx epilogue_end = NULL_RTX;
07628 #endif
07629
07630 #ifdef HAVE_prologue
07631 if (HAVE_prologue)
07632 {
07633 start_sequence ();
07634 seq = gen_prologue ();
07635 emit_insn (seq);
07636
07637
07638 record_insns (seq, &prologue);
07639 prologue_end = emit_note (NULL, NOTE_INSN_PROLOGUE_END);
07640
07641 seq = get_insns ();
07642 end_sequence ();
07643
07644
07645
07646
07647 if (!ENTRY_BLOCK_PTR->succ || ENTRY_BLOCK_PTR->succ->succ_next)
07648 abort ();
07649
07650 insert_insn_on_edge (seq, ENTRY_BLOCK_PTR->succ);
07651 inserted = 1;
07652 }
07653 #endif
07654
07655
07656
07657 for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
07658 if ((e->flags & EDGE_FAKE) == 0)
07659 break;
07660 if (e == NULL)
07661 goto epilogue_done;
07662
07663 #ifdef HAVE_return
07664 if (optimize && HAVE_return)
07665 {
07666
07667
07668
07669
07670
07671
07672 basic_block last;
07673 edge e_next;
07674 rtx label;
07675
07676 for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
07677 if (e->flags & EDGE_FALLTHRU)
07678 break;
07679 if (e == NULL)
07680 goto epilogue_done;
07681 last = e->src;
07682
07683
07684 label = last->end;
07685 while (label && GET_CODE (label) != CODE_LABEL)
07686 {
07687 if (active_insn_p (label))
07688 break;
07689 label = PREV_INSN (label);
07690 }
07691
07692 if (last->head == label && GET_CODE (label) == CODE_LABEL)
07693 {
07694 rtx epilogue_line_note = NULL_RTX;
07695
07696
07697
07698 for (seq = get_last_insn ();
07699 seq && ! active_insn_p (seq);
07700 seq = PREV_INSN (seq))
07701 if (GET_CODE (seq) == NOTE && NOTE_LINE_NUMBER (seq) > 0)
07702 {
07703 epilogue_line_note = seq;
07704 break;
07705 }
07706
07707 for (e = last->pred; e; e = e_next)
07708 {
07709 basic_block bb = e->src;
07710 rtx jump;
07711
07712 e_next = e->pred_next;
07713 if (bb == ENTRY_BLOCK_PTR)
07714 continue;
07715
07716 jump = bb->end;
07717 if ((GET_CODE (jump) != JUMP_INSN) || JUMP_LABEL (jump) != label)
07718 continue;
07719
07720
07721
07722 if (simplejump_p (jump))
07723 {
07724 emit_return_into_block (bb, epilogue_line_note);
07725 delete_insn (jump);
07726 }
07727
07728
07729
07730 else if (condjump_p (jump))
07731 {
07732 if (! redirect_jump (jump, 0, 0))
07733 continue;
07734
07735
07736
07737
07738 if (bb->succ->