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 #include "config.h"
00038 #include "system.h"
00039 #include "coretypes.h"
00040 #include "tm.h"
00041 #include "rtl.h"
00042 #include "tree.h"
00043 #include "flags.h"
00044 #include "except.h"
00045 #include "function.h"
00046 #include "expr.h"
00047 #include "optabs.h"
00048 #include "libfuncs.h"
00049 #include "regs.h"
00050 #include "hard-reg-set.h"
00051 #include "insn-config.h"
00052 #include "recog.h"
00053 #include "output.h"
00054 #include "basic-block.h"
00055 #include "toplev.h"
00056 #include "hashtab.h"
00057 #include "ggc.h"
00058 #include "tm_p.h"
00059 #include "integrate.h"
00060 #include "langhooks.h"
00061 #include "target.h"
00062 #include "cfglayout.h"
00063 #include "tree-gimple.h"
00064 #include "tree-pass.h"
00065 #include "predict.h"
00066 #include "vecprim.h"
00067
00068 #ifndef LOCAL_ALIGNMENT
00069 #define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
00070 #endif
00071
00072 #ifndef STACK_ALIGNMENT_NEEDED
00073 #define STACK_ALIGNMENT_NEEDED 1
00074 #endif
00075
00076 #define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
00077
00078
00079
00080
00081
00082 #ifndef NAME__MAIN
00083 #define NAME__MAIN "__main"
00084 #endif
00085
00086
00087
00088
00089 #define FLOOR_ROUND(VALUE,ALIGN) ((VALUE) & ~((ALIGN) - 1))
00090
00091
00092
00093 #define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
00094
00095
00096
00097
00098
00099 int current_function_is_leaf;
00100
00101
00102
00103
00104 int current_function_sp_is_unchanging;
00105
00106
00107
00108
00109 int current_function_uses_only_leaf_regs;
00110
00111
00112
00113
00114
00115 int virtuals_instantiated;
00116
00117
00118 static GTY(()) int funcdef_no;
00119
00120
00121
00122 struct machine_function * (*init_machine_status) (void);
00123
00124
00125 struct function *cfun = 0;
00126
00127
00128 static VEC(int,heap) *prologue;
00129 static VEC(int,heap) *epilogue;
00130
00131
00132
00133 static VEC(int,heap) *sibcall_epilogue;
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 struct temp_slot GTY(())
00154 {
00155
00156 struct temp_slot *next;
00157
00158 struct temp_slot *prev;
00159
00160
00161 rtx slot;
00162
00163
00164 rtx address;
00165
00166 unsigned int align;
00167
00168 HOST_WIDE_INT size;
00169
00170
00171
00172
00173 tree type;
00174
00175 char in_use;
00176
00177 char addr_taken;
00178
00179 int level;
00180
00181 int keep;
00182
00183
00184 HOST_WIDE_INT base_offset;
00185
00186
00187 HOST_WIDE_INT full_size;
00188 };
00189
00190
00191
00192 static rtx assign_stack_local_1 (enum machine_mode, HOST_WIDE_INT, int,
00193 struct function *);
00194 static struct temp_slot *find_temp_slot_from_address (rtx);
00195 static void pad_to_arg_alignment (struct args_size *, int, struct args_size *);
00196 static void pad_below (struct args_size *, enum machine_mode, tree);
00197 static void reorder_blocks_1 (rtx, tree, VEC(tree,heap) **);
00198 static int all_blocks (tree, tree *);
00199 static tree *get_block_vector (tree, int *);
00200 extern tree debug_find_var_in_block_tree (tree, tree);
00201
00202
00203 static void record_insns (rtx, VEC(int,heap) **) ATTRIBUTE_UNUSED;
00204 static int contains (rtx, VEC(int,heap) **);
00205 #ifdef HAVE_return
00206 static void emit_return_into_block (basic_block, rtx);
00207 #endif
00208 #if defined(HAVE_epilogue) && defined(INCOMING_RETURN_ADDR_RTX)
00209 static rtx keep_stack_depressed (rtx);
00210 #endif
00211 static void prepare_function_start (tree);
00212 static void do_clobber_return_reg (rtx, void *);
00213 static void do_use_return_reg (rtx, void *);
00214 static void set_insn_locators (rtx, int) ATTRIBUTE_UNUSED;
00215
00216
00217 struct function *outer_function_chain;
00218
00219
00220
00221
00222 struct function *
00223 find_function_data (tree decl)
00224 {
00225 struct function *p;
00226
00227 for (p = outer_function_chain; p; p = p->outer)
00228 if (p->decl == decl)
00229 return p;
00230
00231 gcc_unreachable ();
00232 }
00233
00234
00235
00236
00237
00238
00239
00240 void
00241 push_function_context_to (tree context ATTRIBUTE_UNUSED)
00242 {
00243 struct function *p;
00244
00245 if (cfun == 0)
00246 init_dummy_function_start ();
00247 p = cfun;
00248
00249 p->outer = outer_function_chain;
00250 outer_function_chain = p;
00251
00252 lang_hooks.function.enter_nested (p);
00253
00254 cfun = 0;
00255 }
00256
00257 void
00258 push_function_context (void)
00259 {
00260 push_function_context_to (current_function_decl);
00261 }
00262
00263
00264
00265
00266 void
00267 pop_function_context_from (tree context ATTRIBUTE_UNUSED)
00268 {
00269 struct function *p = outer_function_chain;
00270
00271 cfun = p;
00272 outer_function_chain = p->outer;
00273
00274 current_function_decl = p->decl;
00275
00276 lang_hooks.function.leave_nested (p);
00277
00278
00279 virtuals_instantiated = 0;
00280 generating_concat_p = 1;
00281 }
00282
00283 void
00284 pop_function_context (void)
00285 {
00286 pop_function_context_from (current_function_decl);
00287 }
00288
00289
00290
00291
00292
00293 void
00294 free_after_parsing (struct function *f)
00295 {
00296
00297
00298
00299
00300
00301 lang_hooks.function.final (f);
00302 }
00303
00304
00305
00306
00307
00308 void
00309 free_after_compilation (struct function *f)
00310 {
00311 VEC_free (int, heap, prologue);
00312 VEC_free (int, heap, epilogue);
00313 VEC_free (int, heap, sibcall_epilogue);
00314
00315 f->eh = NULL;
00316 f->expr = NULL;
00317 f->emit = NULL;
00318 f->varasm = NULL;
00319 f->machine = NULL;
00320 f->cfg = NULL;
00321
00322 f->x_avail_temp_slots = NULL;
00323 f->x_used_temp_slots = NULL;
00324 f->arg_offset_rtx = NULL;
00325 f->return_rtx = NULL;
00326 f->internal_arg_pointer = NULL;
00327 f->x_nonlocal_goto_handler_labels = NULL;
00328 f->x_return_label = NULL;
00329 f->x_naked_return_label = NULL;
00330 f->x_stack_slot_list = NULL;
00331 f->x_stack_check_probe_note = NULL;
00332 f->x_arg_pointer_save_area = NULL;
00333 f->x_parm_birth_insn = NULL;
00334 f->epilogue_delay_list = NULL;
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344 static HOST_WIDE_INT
00345 get_func_frame_size (struct function *f)
00346 {
00347 if (FRAME_GROWS_DOWNWARD)
00348 return -f->x_frame_offset;
00349 else
00350 return f->x_frame_offset;
00351 }
00352
00353
00354
00355
00356
00357 HOST_WIDE_INT
00358 get_frame_size (void)
00359 {
00360 return get_func_frame_size (cfun);
00361 }
00362
00363
00364
00365
00366
00367 bool
00368 frame_offset_overflow (HOST_WIDE_INT offset, tree func)
00369 {
00370 unsigned HOST_WIDE_INT size = FRAME_GROWS_DOWNWARD ? -offset : offset;
00371
00372 if (size > ((unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (Pmode) - 1))
00373
00374 - 64 * UNITS_PER_WORD)
00375 {
00376 error ("%Jtotal size of local objects too large", func);
00377 return TRUE;
00378 }
00379
00380 return FALSE;
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 static rtx
00397 assign_stack_local_1 (enum machine_mode mode, HOST_WIDE_INT size, int align,
00398 struct function *function)
00399 {
00400 rtx x, addr;
00401 int bigend_correction = 0;
00402 unsigned int alignment;
00403 int frame_off, frame_alignment, frame_phase;
00404
00405 if (align == 0)
00406 {
00407 tree type;
00408
00409 if (mode == BLKmode)
00410 alignment = BIGGEST_ALIGNMENT;
00411 else
00412 alignment = GET_MODE_ALIGNMENT (mode);
00413
00414
00415
00416 type = lang_hooks.types.type_for_mode (mode, 0);
00417 if (type)
00418 alignment = LOCAL_ALIGNMENT (type, alignment);
00419
00420 alignment /= BITS_PER_UNIT;
00421 }
00422 else if (align == -1)
00423 {
00424 alignment = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
00425 size = CEIL_ROUND (size, alignment);
00426 }
00427 else if (align == -2)
00428 alignment = 1;
00429 else
00430 alignment = align / BITS_PER_UNIT;
00431
00432 if (FRAME_GROWS_DOWNWARD)
00433 function->x_frame_offset -= size;
00434
00435
00436 if (alignment * BITS_PER_UNIT > PREFERRED_STACK_BOUNDARY)
00437 alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
00438
00439 if (function->stack_alignment_needed < alignment * BITS_PER_UNIT)
00440 function->stack_alignment_needed = alignment * BITS_PER_UNIT;
00441
00442
00443
00444 frame_alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
00445 frame_off = STARTING_FRAME_OFFSET % frame_alignment;
00446 frame_phase = frame_off ? frame_alignment - frame_off : 0;
00447
00448
00449
00450
00451 if (STACK_ALIGNMENT_NEEDED
00452 || mode != BLKmode
00453 || size != 0)
00454 {
00455
00456
00457
00458
00459 if (FRAME_GROWS_DOWNWARD)
00460 function->x_frame_offset
00461 = (FLOOR_ROUND (function->x_frame_offset - frame_phase,
00462 (unsigned HOST_WIDE_INT) alignment)
00463 + frame_phase);
00464 else
00465 function->x_frame_offset
00466 = (CEIL_ROUND (function->x_frame_offset - frame_phase,
00467 (unsigned HOST_WIDE_INT) alignment)
00468 + frame_phase);
00469 }
00470
00471
00472
00473 if (BYTES_BIG_ENDIAN && mode != BLKmode && GET_MODE_SIZE (mode) < size)
00474 bigend_correction = size - GET_MODE_SIZE (mode);
00475
00476
00477
00478 if (function == cfun && virtuals_instantiated)
00479 addr = plus_constant (frame_pointer_rtx,
00480 trunc_int_for_mode
00481 (frame_offset + bigend_correction
00482 + STARTING_FRAME_OFFSET, Pmode));
00483 else
00484 addr = plus_constant (virtual_stack_vars_rtx,
00485 trunc_int_for_mode
00486 (function->x_frame_offset + bigend_correction,
00487 Pmode));
00488
00489 if (!FRAME_GROWS_DOWNWARD)
00490 function->x_frame_offset += size;
00491
00492 x = gen_rtx_MEM (mode, addr);
00493 MEM_NOTRAP_P (x) = 1;
00494
00495 function->x_stack_slot_list
00496 = gen_rtx_EXPR_LIST (VOIDmode, x, function->x_stack_slot_list);
00497
00498 if (frame_offset_overflow (function->x_frame_offset, function->decl))
00499 function->x_frame_offset = 0;
00500
00501 return x;
00502 }
00503
00504
00505
00506
00507 rtx
00508 assign_stack_local (enum machine_mode mode, HOST_WIDE_INT size, int align)
00509 {
00510 return assign_stack_local_1 (mode, size, align, cfun);
00511 }
00512
00513
00514
00515
00516 static void
00517 cut_slot_from_list (struct temp_slot *temp, struct temp_slot **list)
00518 {
00519 if (temp->next)
00520 temp->next->prev = temp->prev;
00521 if (temp->prev)
00522 temp->prev->next = temp->next;
00523 else
00524 *list = temp->next;
00525
00526 temp->prev = temp->next = NULL;
00527 }
00528
00529
00530
00531 static void
00532 insert_slot_to_list (struct temp_slot *temp, struct temp_slot **list)
00533 {
00534 temp->next = *list;
00535 if (*list)
00536 (*list)->prev = temp;
00537 temp->prev = NULL;
00538 *list = temp;
00539 }
00540
00541
00542
00543 static struct temp_slot **
00544 temp_slots_at_level (int level)
00545 {
00546 if (level >= (int) VEC_length (temp_slot_p, used_temp_slots))
00547 {
00548 size_t old_length = VEC_length (temp_slot_p, used_temp_slots);
00549 temp_slot_p *p;
00550
00551 VEC_safe_grow (temp_slot_p, gc, used_temp_slots, level + 1);
00552 p = VEC_address (temp_slot_p, used_temp_slots);
00553 memset (&p[old_length], 0,
00554 sizeof (temp_slot_p) * (level + 1 - old_length));
00555 }
00556
00557 return &(VEC_address (temp_slot_p, used_temp_slots)[level]);
00558 }
00559
00560
00561
00562 static int
00563 max_slot_level (void)
00564 {
00565 if (!used_temp_slots)
00566 return -1;
00567
00568 return VEC_length (temp_slot_p, used_temp_slots) - 1;
00569 }
00570
00571
00572
00573 static void
00574 move_slot_to_level (struct temp_slot *temp, int level)
00575 {
00576 cut_slot_from_list (temp, temp_slots_at_level (temp->level));
00577 insert_slot_to_list (temp, temp_slots_at_level (level));
00578 temp->level = level;
00579 }
00580
00581
00582
00583 static void
00584 make_slot_available (struct temp_slot *temp)
00585 {
00586 cut_slot_from_list (temp, temp_slots_at_level (temp->level));
00587 insert_slot_to_list (temp, &avail_temp_slots);
00588 temp->in_use = 0;
00589 temp->level = -1;
00590 }
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 rtx
00609 assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
00610 int keep, tree type)
00611 {
00612 unsigned int align;
00613 struct temp_slot *p, *best_p = 0, *selected = NULL, **pp;
00614 rtx slot;
00615
00616
00617
00618 gcc_assert (size != -1);
00619
00620
00621 gcc_assert (keep <= 1);
00622
00623 if (mode == BLKmode)
00624 align = BIGGEST_ALIGNMENT;
00625 else
00626 align = GET_MODE_ALIGNMENT (mode);
00627
00628 if (! type)
00629 type = lang_hooks.types.type_for_mode (mode, 0);
00630
00631 if (type)
00632 align = LOCAL_ALIGNMENT (type, align);
00633
00634
00635
00636
00637
00638
00639
00640
00641 if (!virtuals_instantiated)
00642 {
00643 for (p = avail_temp_slots; p; p = p->next)
00644 {
00645 if (p->align >= align && p->size >= size
00646 && GET_MODE (p->slot) == mode
00647 && objects_must_conflict_p (p->type, type)
00648 && (best_p == 0 || best_p->size > p->size
00649 || (best_p->size == p->size && best_p->align > p->align)))
00650 {
00651 if (p->align == align && p->size == size)
00652 {
00653 selected = p;
00654 cut_slot_from_list (selected, &avail_temp_slots);
00655 best_p = 0;
00656 break;
00657 }
00658 best_p = p;
00659 }
00660 }
00661 }
00662
00663
00664 if (best_p)
00665 {
00666 selected = best_p;
00667 cut_slot_from_list (selected, &avail_temp_slots);
00668
00669
00670
00671
00672 if (GET_MODE (best_p->slot) == BLKmode)
00673 {
00674 int alignment = best_p->align / BITS_PER_UNIT;
00675 HOST_WIDE_INT rounded_size = CEIL_ROUND (size, alignment);
00676
00677 if (best_p->size - rounded_size >= alignment)
00678 {
00679 p = ggc_alloc (sizeof (struct temp_slot));
00680 p->in_use = p->addr_taken = 0;
00681 p->size = best_p->size - rounded_size;
00682 p->base_offset = best_p->base_offset + rounded_size;
00683 p->full_size = best_p->full_size - rounded_size;
00684 p->slot = adjust_address_nv (best_p->slot, BLKmode, rounded_size);
00685 p->align = best_p->align;
00686 p->address = 0;
00687 p->type = best_p->type;
00688 insert_slot_to_list (p, &avail_temp_slots);
00689
00690 stack_slot_list = gen_rtx_EXPR_LIST (VOIDmode, p->slot,
00691 stack_slot_list);
00692
00693 best_p->size = rounded_size;
00694 best_p->full_size = rounded_size;
00695 }
00696 }
00697 }
00698
00699
00700 if (selected == 0)
00701 {
00702 HOST_WIDE_INT frame_offset_old = frame_offset;
00703
00704 p = ggc_alloc (sizeof (struct temp_slot));
00705
00706
00707
00708
00709
00710
00711
00712
00713 gcc_assert (mode != BLKmode || align == BIGGEST_ALIGNMENT);
00714 p->slot = assign_stack_local (mode,
00715 (mode == BLKmode
00716 ? CEIL_ROUND (size, (int) align / BITS_PER_UNIT)
00717 : size),
00718 align);
00719
00720 p->align = align;
00721
00722
00723
00724
00725
00726
00727
00728
00729 if (FRAME_GROWS_DOWNWARD)
00730 p->size = frame_offset_old - frame_offset;
00731 else
00732 p->size = size;
00733
00734
00735 if (FRAME_GROWS_DOWNWARD)
00736 {
00737 p->base_offset = frame_offset;
00738 p->full_size = frame_offset_old - frame_offset;
00739 }
00740 else
00741 {
00742 p->base_offset = frame_offset_old;
00743 p->full_size = frame_offset - frame_offset_old;
00744 }
00745 p->address = 0;
00746
00747 selected = p;
00748 }
00749
00750 p = selected;
00751 p->in_use = 1;
00752 p->addr_taken = 0;
00753 p->type = type;
00754 p->level = temp_slot_level;
00755 p->keep = keep;
00756
00757 pp = temp_slots_at_level (p->level);
00758 insert_slot_to_list (p, pp);
00759
00760
00761 slot = gen_rtx_MEM (mode, XEXP (p->slot, 0));
00762 stack_slot_list = gen_rtx_EXPR_LIST (VOIDmode, slot, stack_slot_list);
00763
00764
00765
00766
00767 set_mem_alias_set (slot, type ? get_alias_set (type) : 0);
00768 set_mem_align (slot, align);
00769
00770
00771 if (type != 0)
00772 {
00773 MEM_VOLATILE_P (slot) = TYPE_VOLATILE (type);
00774 MEM_SET_IN_STRUCT_P (slot, AGGREGATE_TYPE_P (type));
00775 }
00776 MEM_NOTRAP_P (slot) = 1;
00777
00778 return slot;
00779 }
00780
00781
00782
00783
00784 rtx
00785 assign_stack_temp (enum machine_mode mode, HOST_WIDE_INT size, int keep)
00786 {
00787 return assign_stack_temp_for_type (mode, size, keep, NULL_TREE);
00788 }
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 rtx
00801 assign_temp (tree type_or_decl, int keep, int memory_required,
00802 int dont_promote ATTRIBUTE_UNUSED)
00803 {
00804 tree type, decl;
00805 enum machine_mode mode;
00806 #ifdef PROMOTE_MODE
00807 int unsignedp;
00808 #endif
00809
00810 if (DECL_P (type_or_decl))
00811 decl = type_or_decl, type = TREE_TYPE (decl);
00812 else
00813 decl = NULL, type = type_or_decl;
00814
00815 mode = TYPE_MODE (type);
00816 #ifdef PROMOTE_MODE
00817 unsignedp = TYPE_UNSIGNED (type);
00818 #endif
00819
00820 if (mode == BLKmode || memory_required)
00821 {
00822 HOST_WIDE_INT size = int_size_in_bytes (type);
00823 rtx tmp;
00824
00825
00826
00827 if (size == 0)
00828 size = 1;
00829
00830
00831
00832
00833 else if (size == -1)
00834 size = max_int_size_in_bytes (type);
00835
00836
00837
00838
00839
00840 if (decl && size == -1
00841 && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST)
00842 {
00843 error ("size of variable %q+D is too large", decl);
00844 size = 1;
00845 }
00846
00847 tmp = assign_stack_temp_for_type (mode, size, keep, type);
00848 return tmp;
00849 }
00850
00851 #ifdef PROMOTE_MODE
00852 if (! dont_promote)
00853 mode = promote_mode (type, mode, &unsignedp, 0);
00854 #endif
00855
00856 return gen_reg_rtx (mode);
00857 }
00858
00859
00860
00861
00862
00863
00864
00865 static void
00866 combine_temp_slots (void)
00867 {
00868 struct temp_slot *p, *q, *next, *next_q;
00869 int num_slots;
00870
00871
00872
00873 if (flag_strict_aliasing)
00874 return;
00875
00876
00877
00878 if (! flag_expensive_optimizations)
00879 for (p = avail_temp_slots, num_slots = 0; p; p = p->next, num_slots++)
00880 if (num_slots > 100 || (num_slots > 10 && optimize == 0))
00881 return;
00882
00883 for (p = avail_temp_slots; p; p = next)
00884 {
00885 int delete_p = 0;
00886
00887 next = p->next;
00888
00889 if (GET_MODE (p->slot) != BLKmode)
00890 continue;
00891
00892 for (q = p->next; q; q = next_q)
00893 {
00894 int delete_q = 0;
00895
00896 next_q = q->next;
00897
00898 if (GET_MODE (q->slot) != BLKmode)
00899 continue;
00900
00901 if (p->base_offset + p->full_size == q->base_offset)
00902 {
00903
00904 p->size += q->size;
00905 p->full_size += q->full_size;
00906 delete_q = 1;
00907 }
00908 else if (q->base_offset + q->full_size == p->base_offset)
00909 {
00910
00911 q->size += p->size;
00912 q->full_size += p->full_size;
00913 delete_p = 1;
00914 break;
00915 }
00916 if (delete_q)
00917 cut_slot_from_list (q, &avail_temp_slots);
00918 }
00919
00920
00921 if (delete_p)
00922 cut_slot_from_list (p, &avail_temp_slots);
00923 }
00924 }
00925
00926
00927
00928 static struct temp_slot *
00929 find_temp_slot_from_address (rtx x)
00930 {
00931 struct temp_slot *p;
00932 rtx next;
00933 int i;
00934
00935 for (i = max_slot_level (); i >= 0; i--)
00936 for (p = *temp_slots_at_level (i); p; p = p->next)
00937 {
00938 if (XEXP (p->slot, 0) == x
00939 || p->address == x
00940 || (GET_CODE (x) == PLUS
00941 && XEXP (x, 0) == virtual_stack_vars_rtx
00942 && GET_CODE (XEXP (x, 1)) == CONST_INT
00943 && INTVAL (XEXP (x, 1)) >= p->base_offset
00944 && INTVAL (XEXP (x, 1)) < p->base_offset + p->full_size))
00945 return p;
00946
00947 else if (p->address != 0 && GET_CODE (p->address) == EXPR_LIST)
00948 for (next = p->address; next; next = XEXP (next, 1))
00949 if (XEXP (next, 0) == x)
00950 return p;
00951 }
00952
00953
00954
00955 if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0))
00956 && (p = find_temp_slot_from_address (XEXP (x, 0))) != 0)
00957 return p;
00958 else if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 1))
00959 && (p = find_temp_slot_from_address (XEXP (x, 1))) != 0)
00960 return p;
00961
00962 return 0;
00963 }
00964
00965
00966
00967
00968 void
00969 update_temp_slot_address (rtx old, rtx new)
00970 {
00971 struct temp_slot *p;
00972
00973 if (rtx_equal_p (old, new))
00974 return;
00975
00976 p = find_temp_slot_from_address (old);
00977
00978
00979
00980
00981
00982
00983 if (p == 0)
00984 {
00985 if (GET_CODE (old) != PLUS)
00986 return;
00987
00988 if (REG_P (new))
00989 {
00990 update_temp_slot_address (XEXP (old, 0), new);
00991 update_temp_slot_address (XEXP (old, 1), new);
00992 return;
00993 }
00994 else if (GET_CODE (new) != PLUS)
00995 return;
00996
00997 if (rtx_equal_p (XEXP (old, 0), XEXP (new, 0)))
00998 update_temp_slot_address (XEXP (old, 1), XEXP (new, 1));
00999 else if (rtx_equal_p (XEXP (old, 1), XEXP (new, 0)))
01000 update_temp_slot_address (XEXP (old, 0), XEXP (new, 1));
01001 else if (rtx_equal_p (XEXP (old, 0), XEXP (new, 1)))
01002 update_temp_slot_address (XEXP (old, 1), XEXP (new, 0));
01003 else if (rtx_equal_p (XEXP (old, 1), XEXP (new, 1)))
01004 update_temp_slot_address (XEXP (old, 0), XEXP (new, 0));
01005
01006 return;
01007 }
01008
01009
01010 else if (p->address == 0)
01011 p->address = new;
01012 else
01013 {
01014 if (GET_CODE (p->address) != EXPR_LIST)
01015 p->address = gen_rtx_EXPR_LIST (VOIDmode, p->address, NULL_RTX);
01016
01017 p->address = gen_rtx_EXPR_LIST (VOIDmode, new, p->address);
01018 }
01019 }
01020
01021
01022
01023
01024 void
01025 mark_temp_addr_taken (rtx x)
01026 {
01027 struct temp_slot *p;
01028
01029 if (x == 0)
01030 return;
01031
01032
01033
01034 if (!MEM_P (x) || CONSTANT_P (XEXP (x, 0)))
01035 return;
01036
01037 p = find_temp_slot_from_address (XEXP (x, 0));
01038 if (p != 0)
01039 p->addr_taken = 1;
01040 }
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051 void
01052 preserve_temp_slots (rtx x)
01053 {
01054 struct temp_slot *p = 0, *next;
01055
01056
01057
01058 if (x == 0)
01059 {
01060 for (p = *temp_slots_at_level (temp_slot_level); p; p = next)
01061 {
01062 next = p->next;
01063
01064 if (p->addr_taken)
01065 move_slot_to_level (p, temp_slot_level - 1);
01066 }
01067
01068 return;
01069 }
01070
01071
01072
01073
01074
01075 if (REG_P (x) && REG_POINTER (x))
01076 p = find_temp_slot_from_address (x);
01077
01078
01079
01080
01081 if (p == 0 && (!MEM_P (x) || CONSTANT_P (XEXP (x, 0))))
01082 {
01083 for (p = *temp_slots_at_level (temp_slot_level); p; p = next)
01084 {
01085 next = p->next;
01086
01087 if (p->addr_taken)
01088 move_slot_to_level (p, temp_slot_level - 1);
01089 }
01090
01091 return;
01092 }
01093
01094
01095 if (p == 0)
01096 p = find_temp_slot_from_address (XEXP (x, 0));
01097
01098 if (p != 0)
01099 {
01100
01101
01102 struct temp_slot *q;
01103
01104 if (p->level == temp_slot_level)
01105 {
01106 for (q = *temp_slots_at_level (temp_slot_level); q; q = next)
01107 {
01108 next = q->next;
01109
01110 if (p != q && q->addr_taken)
01111 move_slot_to_level (q, temp_slot_level - 1);
01112 }
01113
01114 move_slot_to_level (p, temp_slot_level - 1);
01115 p->addr_taken = 0;
01116 }
01117 return;
01118 }
01119
01120
01121 for (p = *temp_slots_at_level (temp_slot_level); p; p = next)
01122 {
01123 next = p->next;
01124
01125 if (!p->keep)
01126 move_slot_to_level (p, temp_slot_level - 1);
01127 }
01128 }
01129
01130
01131
01132
01133 void
01134 free_temp_slots (void)
01135 {
01136 struct temp_slot *p, *next;
01137
01138 for (p = *temp_slots_at_level (temp_slot_level); p; p = next)
01139 {
01140 next = p->next;
01141
01142 if (!p->keep)
01143 make_slot_available (p);
01144 }
01145
01146 combine_temp_slots ();
01147 }
01148
01149
01150
01151 void
01152 push_temp_slots (void)
01153 {
01154 temp_slot_level++;
01155 }
01156
01157
01158
01159
01160 void
01161 pop_temp_slots (void)
01162 {
01163 struct temp_slot *p, *next;
01164
01165 for (p = *temp_slots_at_level (temp_slot_level); p; p = next)
01166 {
01167 next = p->next;
01168 make_slot_available (p);
01169 }
01170
01171 combine_temp_slots ();
01172
01173 temp_slot_level--;
01174 }
01175
01176
01177
01178 void
01179 init_temp_slots (void)
01180 {
01181
01182 avail_temp_slots = 0;
01183 used_temp_slots = 0;
01184 temp_slot_level = 0;
01185 }
01186
01187
01188
01189
01190
01191
01192
01193
01194 static int in_arg_offset;
01195 static int var_offset;
01196 static int dynamic_offset;
01197 static int out_arg_offset;
01198 static int cfa_offset;
01199
01200
01201
01202
01203 #ifndef STACK_POINTER_OFFSET
01204 #define STACK_POINTER_OFFSET 0
01205 #endif
01206
01207
01208
01209
01210
01211 #ifndef STACK_DYNAMIC_OFFSET
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221 #if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)
01222 #define STACK_DYNAMIC_OFFSET(FNDECL) \
01223 ((ACCUMULATE_OUTGOING_ARGS \
01224 ? (current_function_outgoing_args_size + REG_PARM_STACK_SPACE (FNDECL)) : 0)\
01225 + (STACK_POINTER_OFFSET)) \
01226
01227 #else
01228 #define STACK_DYNAMIC_OFFSET(FNDECL) \
01229 ((ACCUMULATE_OUTGOING_ARGS ? current_function_outgoing_args_size : 0) \
01230 + (STACK_POINTER_OFFSET))
01231 #endif
01232 #endif
01233
01234
01235
01236
01237
01238
01239 static rtx
01240 instantiate_new_reg (rtx x, HOST_WIDE_INT *poffset)
01241 {
01242 rtx new;
01243 HOST_WIDE_INT offset;
01244
01245 if (x == virtual_incoming_args_rtx)
01246 new = arg_pointer_rtx, offset = in_arg_offset;
01247 else if (x == virtual_stack_vars_rtx)
01248 new = frame_pointer_rtx, offset = var_offset;
01249 else if (x == virtual_stack_dynamic_rtx)
01250 new = stack_pointer_rtx, offset = dynamic_offset;
01251 else if (x == virtual_outgoing_args_rtx)
01252 new = stack_pointer_rtx, offset = out_arg_offset;
01253 else if (x == virtual_cfa_rtx)
01254 {
01255 #ifdef FRAME_POINTER_CFA_OFFSET
01256 new = frame_pointer_rtx;
01257 #else
01258 new = arg_pointer_rtx;
01259 #endif
01260 offset = cfa_offset;
01261 }
01262 else
01263 return NULL_RTX;
01264
01265 *poffset = offset;
01266 return new;
01267 }
01268
01269
01270
01271
01272
01273
01274
01275 static int
01276 instantiate_virtual_regs_in_rtx (rtx *loc, void *data)
01277 {
01278 HOST_WIDE_INT offset;
01279 bool *changed = (bool *) data;
01280 rtx x, new;
01281
01282 x = *loc;
01283 if (x == 0)
01284 return 0;
01285
01286 switch (GET_CODE (x))
01287 {
01288 case REG:
01289 new = instantiate_new_reg (x, &offset);
01290 if (new)
01291 {
01292 *loc = plus_constant (new, offset);
01293 if (changed)
01294 *changed = true;
01295 }
01296 return -1;
01297
01298 case PLUS:
01299 new = instantiate_new_reg (XEXP (x, 0), &offset);
01300 if (new)
01301 {
01302 new = plus_constant (new, offset);
01303 *loc = simplify_gen_binary (PLUS, GET_MODE (x), new, XEXP (x, 1));
01304 if (changed)
01305 *changed = true;
01306 return -1;
01307 }
01308
01309
01310
01311
01312
01313 break;
01314
01315 default:
01316 break;
01317 }
01318
01319 return 0;
01320 }
01321
01322
01323
01324
01325 static int
01326 safe_insn_predicate (int code, int operand, rtx x)
01327 {
01328 const struct insn_operand_data *op_data;
01329
01330 if (code < 0)
01331 return true;
01332
01333 op_data = &insn_data[code].operand[operand];
01334 if (op_data->predicate == NULL)
01335 return true;
01336
01337 return op_data->predicate (x, op_data->mode);
01338 }
01339
01340
01341
01342
01343 static void
01344 instantiate_virtual_regs_in_insn (rtx insn)
01345 {
01346 HOST_WIDE_INT offset;
01347 int insn_code, i;
01348 bool any_change = false;
01349 rtx set, new, x, seq;
01350
01351
01352 set = single_set (insn);
01353 if (set)
01354 {
01355
01356
01357
01358
01359 new = instantiate_new_reg (SET_DEST (set), &offset);
01360 if (new)
01361 {
01362 start_sequence ();
01363
01364 for_each_rtx (&SET_SRC (set), instantiate_virtual_regs_in_rtx, NULL);
01365 x = simplify_gen_binary (PLUS, GET_MODE (new), SET_SRC (set),
01366 GEN_INT (-offset));
01367 x = force_operand (x, new);
01368 if (x != new)
01369 emit_move_insn (new, x);
01370
01371 seq = get_insns ();
01372 end_sequence ();
01373
01374 emit_insn_before (seq, insn);
01375 delete_insn (insn);
01376 return;
01377 }
01378
01379
01380
01381
01382
01383 new = instantiate_new_reg (SET_SRC (set), &offset);
01384 if (new && offset != 0
01385 && REG_P (SET_DEST (set))
01386 && REGNO (SET_DEST (set)) > LAST_VIRTUAL_REGISTER)
01387 {
01388 start_sequence ();
01389
01390 x = expand_simple_binop (GET_MODE (SET_DEST (set)), PLUS,
01391 new, GEN_INT (offset), SET_DEST (set),
01392 1, OPTAB_LIB_WIDEN);
01393 if (x != SET_DEST (set))
01394 emit_move_insn (SET_DEST (set), x);
01395
01396 seq = get_insns ();
01397 end_sequence ();
01398
01399 emit_insn_before (seq, insn);
01400 delete_insn (insn);
01401 return;
01402 }
01403
01404 extract_insn (insn);
01405 insn_code = INSN_CODE (insn);
01406
01407
01408
01409 if (GET_CODE (SET_SRC (set)) == PLUS
01410 && recog_data.n_operands >= 3
01411 && recog_data.operand_loc[1] == &XEXP (SET_SRC (set), 0)
01412 && recog_data.operand_loc[2] == &XEXP (SET_SRC (set), 1)
01413 && GET_CODE (recog_data.operand[2]) == CONST_INT
01414 && (new = instantiate_new_reg (recog_data.operand[1], &offset)))
01415 {
01416 offset += INTVAL (recog_data.operand[2]);
01417
01418
01419 if (offset == 0
01420 && REG_P (SET_DEST (set))
01421 && REGNO (SET_DEST (set)) > LAST_VIRTUAL_REGISTER)
01422 {
01423 start_sequence ();
01424 emit_move_insn (SET_DEST (set), new);
01425 seq = get_insns ();
01426 end_sequence ();
01427
01428 emit_insn_before (seq, insn);
01429 delete_insn (insn);
01430 return;
01431 }
01432
01433 x = gen_int_mode (offset, recog_data.operand_mode[2]);
01434
01435
01436
01437
01438 if (safe_insn_predicate (insn_code, 1, new)
01439 && safe_insn_predicate (insn_code, 2, x))
01440 {
01441 *recog_data.operand_loc[1] = recog_data.operand[1] = new;
01442 *recog_data.operand_loc[2] = recog_data.operand[2] = x;
01443 any_change = true;
01444
01445
01446
01447 }
01448 }
01449 }
01450 else
01451 {
01452 extract_insn (insn);
01453 insn_code = INSN_CODE (insn);
01454 }
01455
01456
01457
01458 for (i = 0; i < recog_data.n_operands; ++i)
01459 {
01460 x = recog_data.operand[i];
01461 switch (GET_CODE (x))
01462 {
01463 case MEM:
01464 {
01465 rtx addr = XEXP (x, 0);
01466 bool changed = false;
01467
01468 for_each_rtx (&addr, instantiate_virtual_regs_in_rtx, &changed);
01469 if (!changed)
01470 continue;
01471
01472 start_sequence ();
01473 x = replace_equiv_address (x, addr);
01474 seq = get_insns ();
01475 end_sequence ();
01476 if (seq)
01477 emit_insn_before (seq, insn);
01478 }
01479 break;
01480
01481 case REG:
01482 new = instantiate_new_reg (x, &offset);
01483 if (new == NULL)
01484 continue;
01485 if (offset == 0)
01486 x = new;
01487 else
01488 {
01489 start_sequence ();
01490
01491
01492
01493
01494
01495
01496
01497 x = expand_simple_binop (GET_MODE (x), PLUS, new,
01498 GEN_INT (offset), NULL_RTX,
01499 1, OPTAB_LIB_WIDEN);
01500 seq = get_insns ();
01501 end_sequence ();
01502 emit_insn_before (seq, insn);
01503 }
01504 break;
01505
01506 case SUBREG:
01507 new = instantiate_new_reg (SUBREG_REG (x), &offset);
01508 if (new == NULL)
01509 continue;
01510 if (offset != 0)
01511 {
01512 start_sequence ();
01513 new = expand_simple_binop (GET_MODE (new), PLUS, new,
01514 GEN_INT (offset), NULL_RTX,
01515 1, OPTAB_LIB_WIDEN);
01516 seq = get_insns ();
01517 end_sequence ();
01518 emit_insn_before (seq, insn);
01519 }
01520 x = simplify_gen_subreg (recog_data.operand_mode[i], new,
01521 GET_MODE (new), SUBREG_BYTE (x));
01522 break;
01523
01524 default:
01525 continue;
01526 }
01527
01528
01529
01530
01531 if (!safe_insn_predicate (insn_code, i, x))
01532 {
01533 start_sequence ();
01534 x = force_reg (insn_data[insn_code].operand[i].mode, x);
01535 seq = get_insns ();
01536 end_sequence ();
01537 if (seq)
01538 emit_insn_before (seq, insn);
01539 }
01540
01541 *recog_data.operand_loc[i] = recog_data.operand[i] = x;
01542 any_change = true;
01543 }
01544
01545 if (any_change)
01546 {
01547
01548 for (i = 0; i < recog_data.n_dups; ++i)
01549 *recog_data.dup_loc[i]
01550 = recog_data.operand[(unsigned)recog_data.dup_num[i]];
01551
01552
01553 INSN_CODE (insn) = -1;
01554 }
01555
01556 if (asm_noperands (PATTERN (insn)) >= 0)
01557 {
01558 if (!check_asm_operands (PATTERN (insn)))
01559 {
01560 error_for_asm (insn, "impossible constraint in %<asm%>");
01561 delete_insn (insn);
01562 }
01563 }
01564 else
01565 {
01566 if (recog_memoized (insn) < 0)
01567 fatal_insn_not_found (insn);
01568 }
01569 }
01570
01571
01572
01573
01574 static void
01575 instantiate_decl (rtx x)
01576 {
01577 rtx addr;
01578
01579 if (x == 0)
01580 return;
01581
01582
01583 if (GET_CODE (x) == CONCAT)
01584 {
01585 instantiate_decl (XEXP (x, 0));
01586 instantiate_decl (XEXP (x, 1));
01587 return;
01588 }
01589
01590
01591
01592 if (!MEM_P (x))
01593 return;
01594
01595 addr = XEXP (x, 0);
01596 if (CONSTANT_P (addr)
01597 || (REG_P (addr)
01598 && (REGNO (addr) < FIRST_VIRTUAL_REGISTER
01599 || REGNO (addr) > LAST_VIRTUAL_REGISTER)))
01600 return;
01601
01602 for_each_rtx (&XEXP (x, 0), instantiate_virtual_regs_in_rtx, NULL);
01603 }
01604
01605
01606
01607
01608 static tree
01609 instantiate_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
01610 {
01611 tree t = *tp;
01612 if (! EXPR_P (t))
01613 {
01614 *walk_subtrees = 0;
01615 if (DECL_P (t) && DECL_RTL_SET_P (t))
01616 instantiate_decl (DECL_RTL (t));
01617 }
01618 return NULL;
01619 }
01620
01621
01622
01623
01624 static void
01625 instantiate_decls_1 (tree let)
01626 {
01627 tree t;
01628
01629 for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
01630 {
01631 if (DECL_RTL_SET_P (t))
01632 instantiate_decl (DECL_RTL (t));
01633 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
01634 {
01635 tree v = DECL_VALUE_EXPR (t);
01636 walk_tree (&v, instantiate_expr, NULL, NULL);
01637 }
01638 }
01639
01640
01641 for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))
01642 instantiate_decls_1 (t);
01643 }
01644
01645
01646
01647
01648 static void
01649 instantiate_decls (tree fndecl)
01650 {
01651 tree decl;
01652
01653
01654 for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl))
01655 {
01656 instantiate_decl (DECL_RTL (decl));
01657 instantiate_decl (DECL_INCOMING_RTL (decl));
01658 if (DECL_HAS_VALUE_EXPR_P (decl))
01659 {
01660 tree v = DECL_VALUE_EXPR (decl);
01661 walk_tree (&v, instantiate_expr, NULL, NULL);
01662 }
01663 }
01664
01665
01666 instantiate_decls_1 (DECL_INITIAL (fndecl));
01667 }
01668
01669
01670
01671
01672 static unsigned int
01673 instantiate_virtual_regs (void)
01674 {
01675 rtx insn;
01676
01677
01678 in_arg_offset = FIRST_PARM_OFFSET (current_function_decl);
01679 var_offset = STARTING_FRAME_OFFSET;
01680 dynamic_offset = STACK_DYNAMIC_OFFSET (current_function_decl);
01681 out_arg_offset = STACK_POINTER_OFFSET;
01682 #ifdef FRAME_POINTER_CFA_OFFSET
01683 cfa_offset = FRAME_POINTER_CFA_OFFSET (current_function_decl);
01684 #else
01685 cfa_offset = ARG_POINTER_CFA_OFFSET (current_function_decl);
01686 #endif
01687
01688
01689 init_recog ();
01690
01691
01692
01693 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
01694 if (INSN_P (insn))
01695 {
01696
01697
01698 if (GET_CODE (PATTERN (insn)) == USE
01699 || GET_CODE (PATTERN (insn)) == CLOBBER
01700 || GET_CODE (PATTERN (insn)) == ADDR_VEC
01701 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
01702 || GET_CODE (PATTERN (insn)) == ASM_INPUT)
01703 continue;
01704
01705 instantiate_virtual_regs_in_insn (insn);
01706
01707 if (INSN_DELETED_P (insn))
01708 continue;
01709
01710 for_each_rtx (®_NOTES (insn), instantiate_virtual_regs_in_rtx, NULL);
01711
01712
01713 if (GET_CODE (insn) == CALL_INSN)
01714 for_each_rtx (&CALL_INSN_FUNCTION_USAGE (insn),
01715 instantiate_virtual_regs_in_rtx, NULL);
01716 }
01717
01718
01719 instantiate_decls (current_function_decl);
01720
01721
01722
01723 virtuals_instantiated = 1;
01724 return 0;
01725 }
01726
01727 struct tree_opt_pass pass_instantiate_virtual_regs =
01728 {
01729 "vregs",
01730 NULL,
01731 instantiate_virtual_regs,
01732 NULL,
01733 NULL,
01734 0,
01735 0,
01736 0,
01737 0,
01738 0,
01739 0,
01740 TODO_dump_func,
01741 0
01742 };
01743
01744
01745
01746
01747
01748
01749
01750 int
01751 aggregate_value_p (tree exp, tree fntype)
01752 {
01753 int i, regno, nregs;
01754 rtx reg;
01755
01756 tree type = (TYPE_P (exp)) ? exp : TREE_TYPE (exp);
01757
01758
01759
01760
01761 tree fndecl = NULL_TREE;
01762
01763 if (fntype)
01764 switch (TREE_CODE (fntype))
01765 {
01766 case CALL_EXPR:
01767 fndecl = get_callee_fndecl (fntype);
01768 fntype = fndecl ? TREE_TYPE (fndecl) : 0;
01769 break;
01770 case FUNCTION_DECL:
01771 fndecl = fntype;
01772 fntype = TREE_TYPE (fndecl);
01773 break;
01774 case FUNCTION_TYPE:
01775 case METHOD_TYPE:
01776 break;
01777 case IDENTIFIER_NODE:
01778 fntype = 0;
01779 break;
01780 default:
01781
01782 gcc_unreachable ();
01783 }
01784
01785 if (TREE_CODE (type) == VOID_TYPE)
01786 return 0;
01787
01788
01789
01790 if ((TREE_CODE (exp) == PARM_DECL || TREE_CODE (exp) == RESULT_DECL)
01791 && DECL_BY_REFERENCE (exp))
01792 return 1;
01793
01794
01795
01796
01797
01798
01799
01800 if (TREE_CODE (exp) == CALL_EXPR && fndecl && DECL_RESULT (fndecl)
01801 && DECL_BY_REFERENCE (DECL_RESULT (fndecl)))
01802 return 1;
01803
01804 if (targetm.calls.return_in_memory (type, fntype))
01805 return 1;
01806
01807
01808 if (TREE_ADDRESSABLE (type))
01809 return 1;
01810 if (flag_pcc_struct_return && AGGREGATE_TYPE_P (type))
01811 return 1;
01812
01813
01814 reg = hard_function_value (type, 0, fntype, 0);
01815
01816
01817
01818 if (!REG_P (reg))
01819 return 0;
01820
01821 regno = REGNO (reg);
01822 nregs = hard_regno_nregs[regno][TYPE_MODE (type)];
01823 for (i = 0; i < nregs; i++)
01824 if (! call_used_regs[regno + i])
01825 return 1;
01826 return 0;
01827 }
01828
01829
01830
01831
01832 bool
01833 use_register_for_decl (tree decl)
01834 {
01835
01836 if (TREE_SIDE_EFFECTS (decl))
01837 return false;
01838
01839
01840 if (TREE_ADDRESSABLE (decl))
01841 return false;
01842
01843
01844 if (DECL_MODE (decl) == BLKmode)
01845 return false;
01846
01847
01848
01849
01850
01851 if (flag_float_store && FLOAT_TYPE_P (TREE_TYPE (decl)))
01852 return false;
01853
01854
01855
01856 if (DECL_IGNORED_P (decl))
01857 return true;
01858
01859 return (optimize || DECL_REGISTER (decl));
01860 }
01861
01862
01863
01864 bool
01865 pass_by_reference (CUMULATIVE_ARGS *ca, enum machine_mode mode,
01866 tree type, bool named_arg)
01867 {
01868 if (type)
01869 {
01870
01871
01872 if (TREE_ADDRESSABLE (type))
01873 return true;
01874
01875
01876 if (!TYPE_SIZE (type) || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
01877 return true;
01878 }
01879
01880 return targetm.calls.pass_by_reference (ca, mode, type, named_arg);
01881 }
01882
01883
01884
01885
01886 bool
01887 reference_callee_copied (CUMULATIVE_ARGS *ca, enum machine_mode mode,
01888 tree type, bool named_arg)
01889 {
01890 if (type && TREE_ADDRESSABLE (type))
01891 return false;
01892 return targetm.calls.callee_copies (ca, mode, type, named_arg);
01893 }
01894
01895
01896
01897
01898
01899 struct assign_parm_data_all
01900 {
01901 CUMULATIVE_ARGS args_so_far;
01902 struct args_size stack_args_size;
01903 tree function_result_decl;
01904 tree orig_fnargs;
01905 rtx conversion_insns;
01906 HOST_WIDE_INT pretend_args_size;
01907 HOST_WIDE_INT extra_pretend_bytes;
01908 int reg_parm_stack_space;
01909 };
01910
01911 struct assign_parm_data_one
01912 {
01913 tree nominal_type;
01914 tree passed_type;
01915 rtx entry_parm;
01916 rtx stack_parm;
01917 enum machine_mode nominal_mode;
01918 enum machine_mode passed_mode;
01919 enum machine_mode promoted_mode;
01920 struct locate_and_pad_arg_data locate;
01921 int partial;
01922 BOOL_BITFIELD named_arg : 1;
01923 BOOL_BITFIELD passed_pointer : 1;
01924 BOOL_BITFIELD on_stack : 1;
01925 BOOL_BITFIELD loaded_in_reg : 1;
01926 };
01927
01928
01929
01930 static void
01931 assign_parms_initialize_all (struct assign_parm_data_all *all)
01932 {
01933 tree fntype;
01934
01935 memset (all, 0, sizeof (*all));
01936
01937 fntype = TREE_TYPE (current_function_decl);
01938
01939 #ifdef INIT_CUMULATIVE_INCOMING_ARGS
01940 INIT_CUMULATIVE_INCOMING_ARGS (all->args_so_far, fntype, NULL_RTX);
01941 #else
01942 INIT_CUMULATIVE_ARGS (all->args_so_far, fntype, NULL_RTX,
01943 current_function_decl, -1);
01944 #endif
01945
01946 #ifdef REG_PARM_STACK_SPACE
01947 all->reg_parm_stack_space = REG_PARM_STACK_SPACE (current_function_decl);
01948 #endif
01949 }
01950
01951
01952
01953
01954
01955 static tree
01956 split_complex_args (tree args)
01957 {
01958 tree p;
01959
01960
01961 for (p = args; p; p = TREE_CHAIN (p))
01962 {
01963 tree type = TREE_TYPE (p);
01964 if (TREE_CODE (type) == COMPLEX_TYPE
01965 && targetm.calls.split_complex_arg (type))
01966 goto found;
01967 }
01968 return args;
01969
01970 found:
01971 args = copy_list (args);
01972
01973 for (p = args; p; p = TREE_CHAIN (p))
01974 {
01975 tree type = TREE_TYPE (p);
01976 if (TREE_CODE (type) == COMPLEX_TYPE
01977 && targetm.calls.split_complex_arg (type))
01978 {
01979 tree decl;
01980 tree subtype = TREE_TYPE (type);
01981 bool addressable = TREE_ADDRESSABLE (p);
01982
01983
01984 TREE_TYPE (p) = subtype;
01985 DECL_ARG_TYPE (p) = TREE_TYPE (DECL_ARG_TYPE (p));
01986 DECL_MODE (p) = VOIDmode;
01987 DECL_SIZE (p) = NULL;
01988 DECL_SIZE_UNIT (p) = NULL;
01989
01990
01991
01992
01993 DECL_ARTIFICIAL (p) = addressable;
01994 DECL_IGNORED_P (p) = addressable;
01995 TREE_ADDRESSABLE (p) = 0;
01996 layout_decl (p, 0);
01997
01998
01999 decl = build_decl (PARM_DECL, NULL_TREE, subtype);
02000 DECL_ARG_TYPE (decl) = DECL_ARG_TYPE (p);
02001 DECL_ARTIFICIAL (decl) = addressable;
02002 DECL_IGNORED_P (decl) = addressable;
02003 layout_decl (decl, 0);
02004
02005
02006 TREE_CHAIN (decl) = TREE_CHAIN (p);
02007 TREE_CHAIN (p) = decl;
02008 p = decl;
02009 }
02010 }
02011
02012 return args;
02013 }
02014
02015
02016
02017
02018
02019 static tree
02020 assign_parms_augmented_arg_list (struct assign_parm_data_all *all)
02021 {
02022 tree fndecl = current_function_decl;
02023 tree fntype = TREE_TYPE (fndecl);
02024 tree fnargs = DECL_ARGUMENTS (fndecl);
02025
02026
02027 if (aggregate_value_p (DECL_RESULT (fndecl), fndecl)
02028 && ! current_function_returns_pcc_struct
02029 && targetm.calls.struct_value_rtx (TREE_TYPE (fndecl), 1) == 0)
02030 {
02031 tree type = build_pointer_type (TREE_TYPE (fntype));
02032 tree decl;
02033
02034 decl = build_decl (PARM_DECL, NULL_TREE, type);
02035 DECL_ARG_TYPE (decl) = type;
02036 DECL_ARTIFICIAL (decl) = 1;
02037 DECL_IGNORED_P (decl) = 1;
02038
02039 TREE_CHAIN (decl) = fnargs;
02040 fnargs = decl;
02041 all->function_result_decl = decl;
02042 }
02043
02044 all->orig_fnargs = fnargs;
02045
02046
02047 if (targetm.calls.split_complex_arg)
02048 fnargs = split_complex_args (fnargs);
02049
02050 return fnargs;
02051 }
02052
02053
02054
02055
02056
02057 static void
02058 assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm,
02059 struct assign_parm_data_one *data)
02060 {
02061 tree nominal_type, passed_type;
02062 enum machine_mode nominal_mode, passed_mode, promoted_mode;
02063
02064 memset (data, 0, sizeof (*data));
02065
02066
02067 if (!current_function_stdarg)
02068 data->named_arg = 1;
02069 else if (TREE_CHAIN (parm))
02070 data->named_arg = 1;
02071 else if (targetm.calls.strict_argument_naming (&all->args_so_far))
02072 data->named_arg = 1;
02073 else
02074 data->named_arg = 0;
02075
02076 nominal_type = TREE_TYPE (parm);
02077 passed_type = DECL_ARG_TYPE (parm);
02078
02079
02080
02081 if (TREE_TYPE (parm) == error_mark_node
02082
02083
02084 || TREE_CODE (parm) != PARM_DECL
02085 || passed_type == NULL
02086 || VOID_TYPE_P (nominal_type))
02087 {
02088 nominal_type = passed_type = void_type_node;
02089 nominal_mode = passed_mode = promoted_mode = VOIDmode;
02090 goto egress;
02091 }
02092
02093
02094
02095 passed_mode = TYPE_MODE (passed_type);
02096 nominal_mode = TYPE_MODE (nominal_type);
02097
02098
02099
02100
02101 if (TREE_CODE (passed_type) == UNION_TYPE
02102 && TYPE_TRANSPARENT_UNION (passed_type))
02103 passed_type = TREE_TYPE (TYPE_FIELDS (passed_type));
02104
02105
02106 if (pass_by_reference (&all->args_so_far, passed_mode,
02107 passed_type, data->named_arg))
02108 {
02109 passed_type = nominal_type = build_pointer_type (passed_type);
02110 data->passed_pointer = true;
02111 passed_mode = nominal_mode = Pmode;
02112 }
02113
02114
02115 promoted_mode = passed_mode;
02116 if (targetm.calls.promote_function_args (TREE_TYPE (current_function_decl)))
02117 {
02118 int unsignedp = TYPE_UNSIGNED (passed_type);
02119 promoted_mode = promote_mode (passed_type, promoted_mode,
02120 &unsignedp, 1);
02121 }
02122
02123 egress:
02124 data->nominal_type = nominal_type;
02125 data->passed_type = passed_type;
02126 data->nominal_mode = nominal_mode;
02127 data->passed_mode = passed_mode;
02128 data->promoted_mode = promoted_mode;
02129 }
02130
02131
02132
02133 static void
02134 assign_parms_setup_varargs (struct assign_parm_data_all *all,
02135 struct assign_parm_data_one *data, bool no_rtl)
02136 {
02137 int varargs_pretend_bytes = 0;
02138
02139 targetm.calls.setup_incoming_varargs (&all->args_so_far,
02140 data->promoted_mode,
02141 data->passed_type,
02142 &varargs_pretend_bytes, no_rtl);
02143
02144
02145
02146
02147 if (varargs_pretend_bytes > 0)
02148 all->pretend_args_size = varargs_pretend_bytes;
02149 }
02150
02151
02152
02153
02154 static void
02155 assign_parm_find_entry_rtl (struct assign_parm_data_all *all,
02156 struct assign_parm_data_one *data)
02157 {
02158 HOST_WIDE_INT pretend_bytes = 0;
02159 rtx entry_parm;
02160 bool in_regs;
02161
02162 if (data->promoted_mode == VOIDmode)
02163 {
02164 data->entry_parm = data->stack_parm = const0_rtx;
02165 return;
02166 }
02167
02168 #ifdef FUNCTION_INCOMING_ARG
02169 entry_parm = FUNCTION_INCOMING_ARG (all->args_so_far, data->promoted_mode,
02170 data->passed_type, data->named_arg);
02171 #else
02172 entry_parm = FUNCTION_ARG (all->args_so_far, data->promoted_mode,
02173 data->passed_type, data->named_arg);
02174 #endif
02175
02176 if (entry_parm == 0)
02177 data->promoted_mode = data->passed_mode;
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189 in_regs = entry_parm != 0;
02190 #ifdef STACK_PARMS_IN_REG_PARM_AREA
02191 in_regs = true;
02192 #endif
02193 if (!in_regs && !data->named_arg)
02194 {
02195 if (targetm.calls.pretend_outgoing_varargs_named (&all->args_so_far))
02196 {
02197 rtx tem;
02198 #ifdef FUNCTION_INCOMING_ARG
02199 tem = FUNCTION_INCOMING_ARG (all->args_so_far, data->promoted_mode,
02200 data->passed_type, true);
02201 #else
02202 tem = FUNCTION_ARG (all->args_so_far, data->promoted_mode,
02203 data->passed_type, true);
02204 #endif
02205 in_regs = tem != NULL;
02206 }
02207 }
02208
02209
02210
02211 if (targetm.calls.must_pass_in_stack (data->promoted_mode,
02212 data->passed_type))
02213 entry_parm = 0;
02214
02215 if (entry_parm)
02216 {
02217 int partial;
02218
02219 partial = targetm.calls.arg_partial_bytes (&all->args_so_far,
02220 data->promoted_mode,
02221 data->passed_type,
02222 data->named_arg);
02223 data->partial = partial;
02224
02225
02226
02227 if (partial != 0 && all->reg_parm_stack_space == 0)
02228 {
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246 gcc_assert (!all->extra_pretend_bytes && !all->pretend_args_size);
02247
02248 pretend_bytes = partial;
02249 all->pretend_args_size = CEIL_ROUND (pretend_bytes, STACK_BYTES);
02250
02251
02252
02253 all->extra_pretend_bytes = all->pretend_args_size;
02254 }
02255 }
02256
02257 locate_and_pad_parm (data->promoted_mode, data->passed_type, in_regs,
02258 entry_parm ? data->partial : 0, current_function_decl,
02259 &all->stack_args_size, &data->locate);
02260
02261
02262 pretend_bytes = all->extra_pretend_bytes - pretend_bytes;
02263 data->locate.slot_offset.constant += pretend_bytes;
02264 data->locate.offset.constant += pretend_bytes;
02265
02266 data->entry_parm = entry_parm;
02267 }
02268
02269
02270
02271
02272 static bool
02273 assign_parm_is_stack_parm (struct assign_parm_data_all *all,
02274 struct assign_parm_data_one *data)
02275 {
02276
02277 if (data->entry_parm == NULL)
02278 ;
02279
02280
02281 else if (data->partial != 0)
02282 ;
02283
02284
02285 else if (GET_CODE (data->entry_parm) == PARALLEL
02286 && XEXP (XVECEXP (data->entry_parm, 0, 0), 0) == NULL_RTX)
02287 ;
02288
02289
02290 else if (all->reg_parm_stack_space > 0)
02291 ;
02292
02293 else
02294 return false;
02295
02296 all->stack_args_size.constant += data->locate.size.constant;
02297 if (data->locate.size.var)
02298 ADD_PARM_SIZE (all->stack_args_size, data->locate.size.var);
02299
02300 return true;
02301 }
02302
02303
02304
02305
02306 static void
02307 assign_parm_find_stack_rtl (tree parm, struct assign_parm_data_one *data)
02308 {
02309 rtx offset_rtx, stack_parm;
02310 unsigned int align, boundary;
02311
02312
02313
02314 if (data->entry_parm)
02315 offset_rtx = ARGS_SIZE_RTX (data->locate.slot_offset);
02316 else
02317 offset_rtx = ARGS_SIZE_RTX (data->locate.offset);
02318
02319 stack_parm = current_function_internal_arg_pointer;
02320 if (offset_rtx != const0_rtx)
02321 stack_parm = gen_rtx_PLUS (Pmode, stack_parm, offset_rtx);
02322 stack_parm = gen_rtx_MEM (data->promoted_mode, stack_parm);
02323
02324 set_mem_attributes (stack_parm, parm, 1);
02325
02326 boundary = data->locate.boundary;
02327 align = BITS_PER_UNIT;
02328
02329
02330
02331
02332
02333 if (data->locate.where_pad != downward || data->entry_parm)
02334 align = boundary;
02335 else if (GET_CODE (offset_rtx) == CONST_INT)
02336 {
02337 align = INTVAL (offset_rtx) * BITS_PER_UNIT | boundary;
02338 align = align & -align;
02339 }
02340 set_mem_align (stack_parm, align);
02341
02342 if (data->entry_parm)
02343 set_reg_attrs_for_parm (data->entry_parm, stack_parm);
02344
02345 data->stack_parm = stack_parm;
02346 }
02347
02348
02349
02350
02351 static void
02352 assign_parm_adjust_entry_rtl (struct assign_parm_data_one *data)
02353 {
02354 rtx entry_parm = data->entry_parm;
02355 rtx stack_parm = data->stack_parm;
02356
02357
02358
02359
02360
02361
02362 if (data->partial != 0)
02363 {
02364
02365
02366 if (GET_CODE (entry_parm) == PARALLEL)
02367 emit_group_store (validize_mem (stack_parm), entry_parm,
02368 data->passed_type,
02369 int_size_in_bytes (data->passed_type));
02370 else
02371 {
02372 gcc_assert (data->partial % UNITS_PER_WORD == 0);
02373 move_block_from_reg (REGNO (entry_parm), validize_mem (stack_parm),
02374 data->partial / UNITS_PER_WORD);
02375 }
02376
02377 entry_parm = stack_parm;
02378 }
02379
02380
02381
02382 else if (entry_parm == NULL)
02383 entry_parm = stack_parm;
02384
02385
02386
02387
02388 else if (GET_CODE (entry_parm) == PARALLEL
02389 && data->nominal_mode != BLKmode
02390 && data->passed_mode != BLKmode)
02391 {
02392 size_t i, len = XVECLEN (entry_parm, 0);
02393
02394 for (i = 0; i < len; i++)
02395 if (XEXP (XVECEXP (entry_parm, 0, i), 0) != NULL_RTX
02396 && REG_P (XEXP (XVECEXP (entry_parm, 0, i), 0))
02397 && (GET_MODE (XEXP (XVECEXP (entry_parm, 0, i), 0))
02398 == data->passed_mode)
02399 && INTVAL (XEXP (XVECEXP (entry_parm, 0, i), 1)) == 0)
02400 {
02401 entry_parm = XEXP (XVECEXP (entry_parm, 0, i), 0);
02402 break;
02403 }
02404 }
02405
02406 data->entry_parm = entry_parm;
02407 }
02408
02409
02410
02411
02412 static void
02413 assign_parm_adjust_stack_rtl (struct assign_parm_data_one *data)
02414 {
02415 rtx stack_parm = data->stack_parm;
02416
02417
02418
02419
02420 if (stack_parm
02421 && ((STRICT_ALIGNMENT
02422 && GET_MODE_ALIGNMENT (data->nominal_mode) > MEM_ALIGN (stack_parm))
02423 || (data->nominal_type
02424 && TYPE_ALIGN (data->nominal_type) > MEM_ALIGN (stack_parm)
02425 && MEM_ALIGN (stack_parm) < PREFERRED_STACK_BOUNDARY)))
02426 stack_parm = NULL;
02427
02428
02429
02430 else if (data->entry_parm == stack_parm
02431 && data->nominal_mode != BLKmode
02432 && data->nominal_mode != data->passed_mode)
02433 stack_parm = NULL;
02434
02435
02436
02437 else if (cfun->stack_protect_guard
02438 && (flag_stack_protect == 2
02439 || data->passed_pointer
02440 || POINTER_TYPE_P (data->nominal_type)))
02441 stack_parm = NULL;
02442
02443 data->stack_parm = stack_parm;
02444 }
02445
02446
02447
02448
02449 static bool
02450 assign_parm_setup_block_p (struct assign_parm_data_one *data)
02451 {
02452 if (data->nominal_mode == BLKmode)
02453 return true;
02454 if (GET_CODE (data->entry_parm) == PARALLEL)
02455 return true;
02456
02457 #ifdef BLOCK_REG_PADDING
02458
02459
02460 if (REG_P (data->entry_parm)
02461 && GET_MODE_SIZE (data->promoted_mode) < UNITS_PER_WORD
02462 && (BLOCK_REG_PADDING (data->passed_mode, data->passed_type, 1)
02463 == (BYTES_BIG_ENDIAN ? upward : downward)))
02464 return true;
02465 #endif
02466
02467 return false;
02468 }
02469
02470
02471
02472
02473 static void
02474 assign_parm_setup_block (struct assign_parm_data_all *all,
02475 tree parm, struct assign_parm_data_one *data)
02476 {
02477 rtx entry_parm = data->entry_parm;
02478 rtx stack_parm = data->stack_parm;
02479 HOST_WIDE_INT size;
02480 HOST_WIDE_INT size_stored;
02481 rtx orig_entry_parm = entry_parm;
02482
02483 if (GET_CODE (entry_parm) == PARALLEL)
02484 entry_parm = emit_group_move_into_temps (entry_parm);
02485
02486
02487
02488 if (GET_CODE (entry_parm) == PARALLEL
02489 && data->nominal_mode != BLKmode)
02490 {
02491 rtx elt0 = XEXP (XVECEXP (orig_entry_parm, 0, 0), 0);
02492
02493 if ((XVECLEN (entry_parm, 0) > 1
02494 || hard_regno_nregs[REGNO (elt0)][GET_MODE (elt0)] > 1)
02495 && use_register_for_decl (parm))
02496 {
02497 rtx parmreg = gen_reg_rtx (data->nominal_mode);
02498
02499 push_to_sequence (all->conversion_insns);
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513 if (data->nominal_mode != data->passed_mode)
02514 {
02515 rtx t = gen_reg_rtx (GET_MODE (entry_parm));
02516 emit_group_store (t, entry_parm, NULL_TREE,
02517 GET_MODE_SIZE (GET_MODE (entry_parm)));
02518 convert_move (parmreg, t, 0);
02519 }
02520 else
02521 emit_group_store (parmreg, entry_parm, data->nominal_type,
02522 int_size_in_bytes (data->nominal_type));
02523
02524 all->conversion_insns = get_insns ();
02525 end_sequence ();
02526
02527 SET_DECL_RTL (parm, parmreg);
02528 return;
02529 }
02530 }
02531
02532 size = int_size_in_bytes (data->passed_type);
02533 size_stored = CEIL_ROUND (size, UNITS_PER_WORD);
02534 if (stack_parm == 0)
02535 {
02536 DECL_ALIGN (parm) = MAX (DECL_ALIGN (parm), BITS_PER_WORD);
02537 stack_parm = assign_stack_local (BLKmode, size_stored,
02538 DECL_ALIGN (parm));
02539 if (GET_MODE_SIZE (GET_MODE (entry_parm)) == size)
02540 PUT_MODE (stack_parm, GET_MODE (entry_parm));
02541 set_mem_attributes (stack_parm, parm, 1);
02542 }
02543
02544
02545
02546 if (REG_P (entry_parm) || GET_CODE (entry_parm) == PARALLEL)
02547 {
02548 rtx mem;
02549
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559 if (data->stack_parm == 0)
02560 ;
02561 else if (GET_CODE (entry_parm) == PARALLEL)
02562 ;
02563 else
02564 gcc_assert (!size || !(PARM_BOUNDARY % BITS_PER_WORD));
02565
02566 mem = validize_mem (stack_parm);
02567
02568
02569 if (GET_CODE (entry_parm) == PARALLEL)
02570 {
02571 push_to_sequence (all->conversion_insns);
02572 emit_group_store (mem, entry_parm, data->passed_type, size);
02573 all->conversion_insns = get_insns ();
02574 end_sequence ();
02575 }
02576
02577 else if (size == 0)
02578 ;
02579
02580
02581
02582 else if (size <= UNITS_PER_WORD)
02583 {
02584 enum machine_mode mode
02585 = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
02586
02587 if (mode != BLKmode
02588 #ifdef BLOCK_REG_PADDING
02589 && (size == UNITS_PER_WORD
02590 || (BLOCK_REG_PADDING (mode, data->passed_type, 1)
02591 != (BYTES_BIG_ENDIAN ? upward : downward)))
02592 #endif
02593 )
02594 {
02595 rtx reg = gen_rtx_REG (mode, REGNO (entry_parm));
02596 emit_move_insn (change_address (mem, mode, 0), reg);
02597 }
02598
02599
02600
02601
02602
02603 else if (size != UNITS_PER_WORD
02604 #ifdef BLOCK_REG_PADDING
02605 && (BLOCK_REG_PADDING (mode, data->passed_type, 1)
02606 == downward)
02607 #else
02608 && BYTES_BIG_ENDIAN
02609 #endif
02610 )
02611 {
02612 rtx tem, x;
02613 int by = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
02614 rtx reg = gen_rtx_REG (word_mode, REGNO (entry_parm));
02615
02616 x = expand_shift (LSHIFT_EXPR, word_mode, reg,
02617 build_int_cst (NULL_TREE, by),
02618 NULL_RTX, 1);
02619 tem = change_address (mem, word_mode, 0);
02620 emit_move_insn (tem, x);
02621 }
02622 else
02623 move_block_from_reg (REGNO (entry_parm), mem,
02624 size_stored / UNITS_PER_WORD);
02625 }
02626 else
02627 move_block_from_reg (REGNO (entry_parm), mem,
02628 size_stored / UNITS_PER_WORD);
02629 }
02630 else if (data->stack_parm == 0)
02631 {
02632 push_to_sequence (all->conversion_insns);
02633 emit_block_move (stack_parm, data->entry_parm, GEN_INT (size),
02634 BLOCK_OP_NORMAL);
02635 all->conversion_insns = get_insns ();
02636 end_sequence ();
02637 }
02638
02639 data->stack_parm = stack_parm;
02640 SET_DECL_RTL (parm, stack_parm);
02641 }
02642
02643
02644
02645
02646 static void
02647 assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
02648 struct assign_parm_data_one *data)
02649 {
02650 rtx parmreg;
02651 enum machine_mode promoted_nominal_mode;
02652 int unsignedp = TYPE_UNSIGNED (TREE_TYPE (parm));
02653 bool did_conversion = false;
02654
02655
02656
02657
02658
02659
02660 promoted_nominal_mode
02661 = promote_mode (data->nominal_type, data->nominal_mode, &unsignedp, 1);
02662
02663 parmreg = gen_reg_rtx (promoted_nominal_mode);
02664
02665 if (!DECL_ARTIFICIAL (parm))
02666 mark_user_reg (parmreg);
02667
02668
02669
02670 if (data->passed_pointer)
02671 {
02672 rtx x = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (data->passed_type)), parmreg);
02673 set_mem_attributes (x, parm, 1);
02674 SET_DECL_RTL (parm, x);
02675 }
02676 else
02677 SET_DECL_RTL (parm, parmreg);
02678
02679
02680 if (data->nominal_mode != data->passed_mode
02681 || promoted_nominal_mode != data->promoted_mode)
02682 {
02683 int save_tree_used;
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704 rtx tempreg = gen_reg_rtx (GET_MODE (data->entry_parm));
02705
02706 emit_move_insn (tempreg, validize_mem (data->entry_parm));
02707
02708 push_to_sequence (all->conversion_insns);
02709 tempreg = convert_to_mode (data->nominal_mode, tempreg, unsignedp);
02710
02711 if (GET_CODE (tempreg) == SUBREG
02712 && GET_MODE (tempreg) == data->nominal_mode
02713 && REG_P (SUBREG_REG (tempreg))
02714 && data->nominal_mode == data->passed_mode
02715 && GET_MODE (SUBREG_REG (tempreg)) == GET_MODE (data->entry_parm)
02716 && GET_MODE_SIZE (GET_MODE (tempreg))
02717 < GET_MODE_SIZE (GET_MODE (data->entry_parm)))
02718 {
02719
02720
02721 SUBREG_PROMOTED_VAR_P (tempreg) = 1;
02722 SUBREG_PROMOTED_UNSIGNED_SET (tempreg, unsignedp);
02723 }
02724
02725
02726 save_tree_used = TREE_USED (parm);
02727 expand_assignment (parm, make_tree (data->nominal_type, tempreg));
02728 TREE_USED (parm) = save_tree_used;
02729 all->conversion_insns = get_insns ();
02730 end_sequence ();
02731
02732 did_conversion = true;
02733 }
02734 else
02735 emit_move_insn (parmreg, validize_mem (data->entry_parm));
02736
02737
02738
02739 if (data->passed_pointer
02740 && TYPE_MODE (TREE_TYPE (parm)) != BLKmode
02741
02742 && (TYPE_MODE (TREE_TYPE (parm)) != GET_MODE (DECL_RTL (parm))
02743 || use_register_for_decl (parm)))
02744 {
02745
02746
02747 parmreg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (parm)));
02748 mark_user_reg (parmreg);
02749
02750 if (GET_MODE (parmreg) != GET_MODE (DECL_RTL (parm)))
02751 {
02752 rtx tempreg = gen_reg_rtx (GET_MODE (DECL_RTL (parm)));
02753 int unsigned_p = TYPE_UNSIGNED (TREE_TYPE (parm));
02754
02755 push_to_sequence (all->conversion_insns);
02756 emit_move_insn (tempreg, DECL_RTL (parm));
02757 tempreg = convert_to_mode (GET_MODE (parmreg), tempreg, unsigned_p);
02758 emit_move_insn (parmreg, tempreg);
02759 all->conversion_insns = get_insns ();
02760 end_sequence ();
02761
02762 did_conversion = true;
02763 }
02764 else
02765 emit_move_insn (parmreg, DECL_RTL (parm));
02766
02767 SET_DECL_RTL (parm, parmreg);
02768
02769
02770
02771 data->stack_parm = NULL;
02772 }
02773
02774
02775
02776
02777
02778
02779 if (data->nominal_mode == data->passed_mode
02780 && !did_conversion
02781 && data->stack_parm != 0
02782 && MEM_P (data->stack_parm)
02783 && data->locate.offset.var == 0
02784 && reg_mentioned_p (virtual_incoming_args_rtx,
02785 XEXP (data->stack_parm, 0)))
02786 {
02787 rtx linsn = get_last_insn ();
02788 rtx sinsn, set;
02789
02790
02791 if (GET_CODE (parmreg) == CONCAT)
02792 {
02793 enum machine_mode submode
02794 = GET_MODE_INNER (GET_MODE (parmreg));
02795 int regnor = REGNO (XEXP (parmreg, 0));
02796 int regnoi = REGNO (XEXP (parmreg, 1));
02797 rtx stackr = adjust_address_nv (data->stack_parm, submode, 0);
02798 rtx stacki = adjust_address_nv (data->stack_parm, submode,
02799 GET_MODE_SIZE (submode));
02800
02801
02802
02803 for (sinsn = linsn; sinsn != 0;
02804 sinsn = prev_nonnote_insn (sinsn))
02805 {
02806 set = single_set (sinsn);
02807 if (set == 0)
02808 continue;
02809
02810 if (SET_DEST (set) == regno_reg_rtx [regnoi])
02811 REG_NOTES (sinsn)
02812 = gen_rtx_EXPR_LIST (REG_EQUIV, stacki,
02813 REG_NOTES (sinsn));
02814 else if (SET_DEST (set) == regno_reg_rtx [regnor])
02815 REG_NOTES (sinsn)
02816 = gen_rtx_EXPR_LIST (REG_EQUIV, stackr,
02817 REG_NOTES (sinsn));
02818 }
02819 }
02820 else if ((set = single_set (linsn)) != 0
02821 && SET_DEST (set) == parmreg)
02822 REG_NOTES (linsn)
02823 = gen_rtx_EXPR_LIST (REG_EQUIV,
02824 data->stack_parm, REG_NOTES (linsn));
02825 }
02826
02827
02828 if (POINTER_TYPE_P (TREE_TYPE (parm)))
02829 mark_reg_pointer (parmreg,
02830 TYPE_ALIGN (TREE_TYPE (TREE_TYPE (parm))));
02831 }
02832
02833
02834
02835
02836 static void
02837 assign_parm_setup_stack (struct assign_parm_data_all *all, tree parm,
02838 struct assign_parm_data_one *data)
02839 {
02840
02841
02842 bool to_conversion = false;
02843
02844 if (data->promoted_mode != data->nominal_mode)
02845 {
02846
02847 rtx tempreg = gen_reg_rtx (GET_MODE (data->entry_parm));
02848
02849 emit_move_insn (tempreg, validize_mem (data->entry_parm));
02850
02851 push_to_sequence (all->conversion_insns);
02852 to_conversion = true;
02853
02854 data->entry_parm = convert_to_mode (data->nominal_mode, tempreg,
02855 TYPE_UNSIGNED (TREE_TYPE (parm)));
02856
02857 if (data->stack_parm)
02858
02859 data->stack_parm
02860 = adjust_address (data->stack_parm, data->nominal_mode, 0);
02861 }
02862
02863 if (data->entry_parm != data->stack_parm)
02864 {
02865 rtx src, dest;
02866
02867 if (data->stack_parm == 0)
02868 {
02869 data->stack_parm
02870 = assign_stack_local (GET_MODE (data->entry_parm),
02871 GET_MODE_SIZE (GET_MODE (data->entry_parm)),
02872 TYPE_ALIGN (data->passed_type));
02873 set_mem_attributes (data->stack_parm, parm, 1);
02874 }
02875
02876 dest = validize_mem (data->stack_parm);
02877 src = validize_mem (data->entry_parm);
02878
02879 if (MEM_P (src))
02880 {
02881
02882 if (!to_conversion)
02883 push_to_sequence (all->conversion_insns);
02884 to_conversion = true;
02885
02886 emit_block_move (dest, src,
02887 GEN_INT (int_size_in_bytes (data->passed_type)),
02888 BLOCK_OP_NORMAL);
02889 }
02890 else
02891 emit_move_insn (dest, src);
02892 }
02893
02894 if (to_conversion)
02895 {
02896 all->conversion_insns = get_insns ();
02897 end_sequence ();
02898 }
02899
02900 SET_DECL_RTL (parm, data->stack_parm);
02901 }
02902
02903
02904
02905
02906 static void
02907 assign_parms_unsplit_complex (struct assign_parm_data_all *all, tree fnargs)
02908 {
02909 tree parm;
02910 tree orig_fnargs = all->orig_fnargs;
02911
02912 for (parm = orig_fnargs; parm; parm = TREE_CHAIN (parm))
02913 {
02914 if (TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE
02915 && targetm.calls.split_complex_arg (TREE_TYPE (parm)))
02916 {
02917 rtx tmp, real, imag;
02918 enum machine_mode inner = GET_MODE_INNER (DECL_MODE (parm));
02919
02920 real = DECL_RTL (fnargs);
02921 imag = DECL_RTL (TREE_CHAIN (fnargs));
02922 if (inner != GET_MODE (real))
02923 {
02924 real = gen_lowpart_SUBREG (inner, real);
02925 imag = gen_lowpart_SUBREG (inner, imag);
02926 }
02927
02928 if (TREE_ADDRESSABLE (parm))
02929 {
02930 rtx rmem, imem;
02931 HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (parm));
02932
02933
02934
02935 tmp = assign_stack_local (DECL_MODE (parm), size,
02936 TYPE_ALIGN (TREE_TYPE (parm)));
02937 set_mem_attributes (tmp, parm, 1);
02938 rmem = adjust_address_nv (tmp, inner, 0);
02939 imem = adjust_address_nv (tmp, inner, GET_MODE_SIZE (inner));
02940 push_to_sequence (all->conversion_insns);
02941 emit_move_insn (rmem, real);
02942 emit_move_insn (imem, imag);
02943 all->conversion_insns = get_insns ();
02944 end_sequence ();
02945 }
02946 else
02947 tmp = gen_rtx_CONCAT (DECL_MODE (parm), real, imag);
02948 SET_DECL_RTL (parm, tmp);
02949
02950 real = DECL_INCOMING_RTL (fnargs);
02951 imag = DECL_INCOMING_RTL (TREE_CHAIN (fnargs));
02952 if (inner != GET_MODE (real))
02953 {
02954 real = gen_lowpart_SUBREG (inner, real);
02955 imag = gen_lowpart_SUBREG (inner, imag);
02956 }
02957 tmp = gen_rtx_CONCAT (DECL_MODE (parm), real, imag);
02958 set_decl_incoming_rtl (parm, tmp);
02959 fnargs = TREE_CHAIN (fnargs);
02960 }
02961 else
02962 {
02963 SET_DECL_RTL (parm, DECL_RTL (fnargs));
02964 set_decl_incoming_rtl (parm, DECL_INCOMING_RTL (fnargs));
02965
02966
02967
02968 if (DECL_INCOMING_RTL (parm) && MEM_P (DECL_INCOMING_RTL (parm)))
02969 set_mem_expr (DECL_INCOMING_RTL (parm), parm);
02970 }
02971
02972 fnargs = TREE_CHAIN (fnargs);
02973 }
02974 }
02975
02976
02977
02978
02979 static void
02980 assign_parms (tree fndecl)
02981 {
02982 struct assign_parm_data_all all;
02983 tree fnargs, parm;
02984
02985 current_function_internal_arg_pointer
02986 = targetm.calls.internal_arg_pointer ();
02987
02988 assign_parms_initialize_all (&all);
02989 fnargs = assign_parms_augmented_arg_list (&all);
02990
02991 for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
02992 {
02993 struct assign_parm_data_one data;
02994
02995
02996 assign_parm_find_data_types (&all, parm, &data);
02997
02998
02999 if (data.passed_mode == VOIDmode)
03000 {
03001 SET_DECL_RTL (parm, const0_rtx);
03002 DECL_INCOMING_RTL (parm) = DECL_RTL (parm);
03003 continue;
03004 }
03005
03006 if (current_function_stdarg && !TREE_CHAIN (parm))
03007 assign_parms_setup_varargs (&all, &data, false);
03008
03009
03010 assign_parm_find_entry_rtl (&all, &data);
03011
03012
03013 if (assign_parm_is_stack_parm (&all, &data))
03014 {
03015 assign_parm_find_stack_rtl (parm, &data);
03016 assign_parm_adjust_entry_rtl (&data);
03017 }
03018
03019
03020 set_decl_incoming_rtl (parm, data.entry_parm);
03021
03022
03023 FUNCTION_ARG_ADVANCE (all.args_so_far, data.promoted_mode,
03024 data.passed_type, data.named_arg);
03025
03026 assign_parm_adjust_stack_rtl (&data);
03027
03028 if (assign_parm_setup_block_p (&data))
03029 assign_parm_setup_block (&all, parm, &data);
03030 else if (data.passed_pointer || use_register_for_decl (parm))
03031 assign_parm_setup_reg (&all, parm, &data);
03032 else
03033 assign_parm_setup_stack (&all, parm, &data);
03034 }
03035
03036 if (targetm.calls.split_complex_arg && fnargs != all.orig_fnargs)
03037 assign_parms_unsplit_complex (&all, fnargs);
03038
03039
03040
03041 emit_insn (all.conversion_insns);
03042
03043
03044
03045
03046
03047 if (all.function_result_decl)
03048 {
03049 tree result = DECL_RESULT (current_function_decl);
03050 rtx addr = DECL_RTL (all.function_result_decl);
03051 rtx x;
03052
03053 if (DECL_BY_REFERENCE (result))
03054 x = addr;
03055 else
03056 {
03057 addr = convert_memory_address (Pmode, addr);
03058 x = gen_rtx_MEM (DECL_MODE (result), addr);
03059 set_mem_attributes (x, result, 1);
03060 }
03061 SET_DECL_RTL (result, x);
03062 }
03063
03064
03065 current_function_pretend_args_size = all.pretend_args_size;
03066 all.stack_args_size.constant += all.extra_pretend_bytes;
03067 current_function_args_size = all.stack_args_size.constant;
03068
03069
03070
03071
03072 #ifdef REG_PARM_STACK_SPACE
03073 current_function_args_size = MAX (current_function_args_size,
03074 REG_PARM_STACK_SPACE (fndecl));
03075 #endif
03076
03077 current_function_args_size = CEIL_ROUND (current_function_args_size,
03078 PARM_BOUNDARY / BITS_PER_UNIT);
03079
03080 #ifdef ARGS_GROW_DOWNWARD
03081 current_function_arg_offset_rtx
03082 = (all.stack_args_size.var == 0 ? GEN_INT (-all.stack_args_size.constant)
03083 : expand_expr (size_diffop (all.stack_args_size.var,
03084 size_int (-all.stack_args_size.constant)),
03085 NULL_RTX, VOIDmode, 0));
03086 #else
03087 current_function_arg_offset_rtx = ARGS_SIZE_RTX (all.stack_args_size);
03088 #endif
03089
03090
03091
03092
03093 current_function_pops_args = RETURN_POPS_ARGS (fndecl, TREE_TYPE (fndecl),
03094 current_function_args_size);
03095
03096
03097
03098
03099 current_function_args_info = all.args_so_far;
03100
03101
03102
03103
03104
03105
03106 current_function_return_rtx
03107 = (DECL_RTL_SET_P (DECL_RESULT (fndecl))
03108 ? DECL_RTL (DECL_RESULT (fndecl)) : NULL_RTX);
03109
03110
03111
03112
03113 if (DECL_RTL_SET_P (DECL_RESULT (fndecl)))
03114 {
03115 tree decl_result = DECL_RESULT (fndecl);
03116 rtx decl_rtl = DECL_RTL (decl_result);
03117
03118 if (REG_P (decl_rtl)
03119 ? REGNO (decl_rtl) >= FIRST_PSEUDO_REGISTER
03120 : DECL_REGISTER (decl_result))
03121 {
03122 rtx real_decl_rtl;
03123
03124 real_decl_rtl = targetm.calls.function_value (TREE_TYPE (decl_result),
03125 fndecl, true);
03126 REG_FUNCTION_VALUE_P (real_decl_rtl) = 1;
03127
03128
03129
03130 current_function_return_rtx = real_decl_rtl;
03131 }
03132 }
03133 }
03134
03135
03136
03137
03138 static tree
03139 gimplify_parm_type (tree *tp, int *walk_subtrees, void *data)
03140 {
03141 tree t = *tp;
03142
03143 *walk_subtrees = 0;
03144 if (TYPE_P (t))
03145 {
03146 if (POINTER_TYPE_P (t))
03147 *walk_subtrees = 1;
03148 else if (TYPE_SIZE (t) && !TREE_CONSTANT (TYPE_SIZE (t))
03149 && !TYPE_SIZES_GIMPLIFIED (t))
03150 {
03151 gimplify_type_sizes (t, (tree *) data);
03152 *walk_subtrees = 1;
03153 }
03154 }
03155
03156 return NULL;
03157 }
03158
03159
03160
03161
03162
03163
03164
03165 tree
03166 gimplify_parameters (void)
03167 {
03168 struct assign_parm_data_all all;
03169 tree fnargs, parm, stmts = NULL;
03170
03171 assign_parms_initialize_all (&all);
03172 fnargs = assign_parms_augmented_arg_list (&all);
03173
03174 for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
03175 {
03176 struct assign_parm_data_one data;
03177
03178
03179 assign_parm_find_data_types (&all, parm, &data);
03180
03181
03182 if (data.passed_mode == VOIDmode || DECL_SIZE (parm) == NULL)
03183 continue;
03184
03185
03186 FUNCTION_ARG_ADVANCE (all.args_so_far, data.promoted_mode,
03187 data.passed_type, data.named_arg);
03188
03189
03190
03191
03192
03193 walk_tree_without_duplicates (&data.passed_type,
03194 gimplify_parm_type, &stmts);
03195
03196 if (!TREE_CONSTANT (DECL_SIZE (parm)))
03197 {
03198 gimplify_one_sizepos (&DECL_SIZE (parm), &stmts);
03199 gimplify_one_sizepos (&DECL_SIZE_UNIT (parm), &stmts);
03200 }
03201
03202 if (data.passed_pointer)
03203 {
03204 tree type = TREE_TYPE (data.passed_type);
03205 if (reference_callee_copied (&all.args_so_far, TYPE_MODE (type),
03206 type, data.named_arg))
03207 {
03208 tree local, t;
03209
03210
03211
03212 if (TREE_CONSTANT (DECL_SIZE (parm)))
03213 {
03214 local = create_tmp_var (type, get_name (parm));
03215 DECL_IGNORED_P (local) = 0;
03216 }
03217 else
03218 {
03219 tree ptr_type, addr, args;
03220
03221 ptr_type = build_pointer_type (type);
03222 addr = create_tmp_var (ptr_type, get_name (parm));
03223 DECL_IGNORED_P (addr) = 0;
03224 local = build_fold_indirect_ref (addr);
03225
03226 args = tree_cons (NULL, DECL_SIZE_UNIT (parm), NULL);
03227 t = built_in_decls[BUILT_IN_ALLOCA];
03228 t = build_function_call_expr (t, args);
03229 t = fold_convert (ptr_type, t);
03230 t = build2 (MODIFY_EXPR, void_type_node, addr, t);
03231 gimplify_and_add (t, &stmts);
03232 }
03233
03234 t = build2 (MODIFY_EXPR, void_type_node, local, parm);
03235 gimplify_and_add (t, &stmts);
03236
03237 SET_DECL_VALUE_EXPR (parm, local);
03238 DECL_HAS_VALUE_EXPR_P (parm) = 1;
03239 }
03240 }
03241 }
03242
03243 return stmts;
03244 }
03245
03246
03247
03248
03249
03250
03251
03252 rtx
03253 promoted_input_arg (unsigned int regno, enum machine_mode *pmode, int *punsignedp)
03254 {
03255 tree arg;
03256
03257 for (arg = DECL_ARGUMENTS (current_function_decl); arg;
03258 arg = TREE_CHAIN (arg))
03259 if (REG_P (DECL_INCOMING_RTL (arg))
03260 && REGNO (DECL_INCOMING_RTL (arg)) == regno
03261 && TYPE_MODE (DECL_ARG_TYPE (arg)) == TYPE_MODE (TREE_TYPE (arg)))
03262 {
03263 enum machine_mode mode = TYPE_MODE (TREE_TYPE (arg));
03264 int unsignedp = TYPE_UNSIGNED (TREE_TYPE (arg));
03265
03266 mode = promote_mode (TREE_TYPE (arg), mode, &unsignedp, 1);
03267 if (mode == GET_MODE (DECL_INCOMING_RTL (arg))
03268 && mode != DECL_MODE (arg))
03269 {
03270 *pmode = DECL_MODE (arg);
03271 *punsignedp = unsignedp;
03272 return DECL_INCOMING_RTL (arg);
03273 }
03274 }
03275
03276 return 0;
03277 }
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312 void
03313 locate_and_pad_parm (enum machine_mode passed_mode, tree type, int in_regs,
03314 int partial, tree fndecl ATTRIBUTE_UNUSED,
03315 struct args_size *initial_offset_ptr,
03316 struct locate_and_pad_arg_data *locate)
03317 {
03318 tree sizetree;
03319 enum direction where_pad;
03320 unsigned int boundary;
03321 int reg_parm_stack_space = 0;
03322 int part_size_in_regs;
03323
03324 #ifdef REG_PARM_STACK_SPACE
03325 reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
03326
03327
03328
03329 if (! in_regs)
03330 {
03331 if (reg_parm_stack_space > 0)
03332 {
03333 if (initial_offset_ptr->var)
03334 {
03335 initial_offset_ptr->var
03336 = size_binop (MAX_EXPR, ARGS_SIZE_TREE (*initial_offset_ptr),
03337 ssize_int (reg_parm_stack_space));
03338 initial_offset_ptr->constant = 0;
03339 }
03340 else if (initial_offset_ptr->constant < reg_parm_stack_space)
03341 initial_offset_ptr->constant = reg_parm_stack_space;
03342 }
03343 }
03344 #endif
03345
03346 part_size_in_regs = (reg_parm_stack_space == 0 ? partial : 0);
03347
03348 sizetree
03349 = type ? size_in_bytes (type) : size_int (GET_MODE_SIZE (passed_mode));
03350 where_pad = FUNCTION_ARG_PADDING (passed_mode, type);
03351 boundary = FUNCTION_ARG_BOUNDARY (passed_mode, type);
03352 locate->where_pad = where_pad;
03353 locate->boundary = boundary;
03354
03355
03356
03357 if (boundary > PREFERRED_STACK_BOUNDARY)
03358 boundary = PREFERRED_STACK_BOUNDARY;
03359 if (cfun->stack_alignment_needed < boundary)
03360 cfun->stack_alignment_needed = boundary;
03361
03362 #ifdef ARGS_GROW_DOWNWARD
03363 locate->slot_offset.constant = -initial_offset_ptr->constant;
03364 if (initial_offset_ptr->var)
03365 locate->slot_offset.var = size_binop (MINUS_EXPR, ssize_int (0),
03366 initial_offset_ptr->var);
03367
03368 {
03369 tree s2 = sizetree;
03370 if (where_pad != none
03371 && (!host_integerp (sizetree, 1)
03372 || (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % PARM_BOUNDARY))
03373 s2 = round_up (s2, PARM_BOUNDARY / BITS_PER_UNIT);
03374 SUB_PARM_SIZE (locate->slot_offset, s2);
03375 }
03376
03377 locate->slot_offset.constant += part_size_in_regs;
03378
03379 if (!in_regs
03380 #ifdef REG_PARM_STACK_SPACE
03381 || REG_PARM_STACK_SPACE (fndecl) > 0
03382 #endif
03383 )
03384 pad_to_arg_alignment (&locate->slot_offset, boundary,
03385 &locate->alignment_pad);
03386
03387 locate->size.constant = (-initial_offset_ptr->constant
03388 - locate->slot_offset.constant);
03389 if (initial_offset_ptr->var)
03390 locate->size.var = size_binop (MINUS_EXPR,
03391 size_binop (MINUS_EXPR,
03392 ssize_int (0),
03393 initial_offset_ptr->var),
03394 locate->slot_offset.var);
03395
03396
03397
03398 locate->offset = locate->slot_offset;
03399 if (where_pad == downward)
03400 pad_below (&locate->offset, passed_mode, sizetree);
03401
03402 #else
03403 if (!in_regs
03404 #ifdef REG_PARM_STACK_SPACE
03405 || REG_PARM_STACK_SPACE (fndecl) > 0
03406 #endif
03407 )
03408 pad_to_arg_alignment (initial_offset_ptr, boundary,
03409 &locate->alignment_pad);
03410 locate->slot_offset = *initial_offset_ptr;
03411
03412 #ifdef PUSH_ROUNDING
03413 if (passed_mode != BLKmode)
03414 sizetree = size_int (PUSH_ROUNDING (TREE_INT_CST_LOW (sizetree)));
03415 #endif
03416
03417
03418
03419 locate->offset = locate->slot_offset;
03420 if (where_pad == downward)
03421 pad_below (&locate->offset, passed_mode, sizetree);
03422
03423 if (where_pad != none
03424 && (!host_integerp (sizetree, 1)
03425 || (tree_low_cst (sizetree, 1) * BITS_PER_UNIT) % PARM_BOUNDARY))
03426 sizetree = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
03427
03428 ADD_PARM_SIZE (locate->size, sizetree);
03429
03430 locate->size.constant -= part_size_in_regs;
03431 #endif
03432 }
03433
03434
03435
03436
03437 static void
03438 pad_to_arg_alignment (struct args_size *offset_ptr, int boundary,
03439 struct args_size *alignment_pad)
03440 {
03441 tree save_var = NULL_TREE;
03442 HOST_WIDE_INT save_constant = 0;
03443 int boundary_in_bytes = boundary / BITS_PER_UNIT;
03444 HOST_WIDE_INT sp_offset = STACK_POINTER_OFFSET;
03445
03446 #ifdef SPARC_STACK_BOUNDARY_HACK
03447
03448
03449
03450 if (SPARC_STACK_BOUNDARY_HACK)
03451 sp_offset = 0;
03452 #endif
03453
03454 if (boundary > PARM_BOUNDARY && boundary > STACK_BOUNDARY)
03455 {
03456 save_var = offset_ptr->var;
03457 save_constant = offset_ptr->constant;
03458 }
03459
03460 alignment_pad->var = NULL_TREE;
03461 alignment_pad->constant = 0;
03462
03463 if (boundary > BITS_PER_UNIT)
03464 {
03465 if (offset_ptr->var)
03466 {
03467 tree sp_offset_tree = ssize_int (sp_offset);
03468 tree offset = size_binop (PLUS_EXPR,
03469 ARGS_SIZE_TREE (*offset_ptr),
03470 sp_offset_tree);
03471 #ifdef ARGS_GROW_DOWNWARD
03472 tree rounded = round_down (offset, boundary / BITS_PER_UNIT);
03473 #else
03474 tree rounded = round_up (offset, boundary / BITS_PER_UNIT);
03475 #endif
03476
03477 offset_ptr->var = size_binop (MINUS_EXPR, rounded, sp_offset_tree);
03478
03479 offset_ptr->constant = 0;
03480 if (boundary > PARM_BOUNDARY && boundary > STACK_BOUNDARY)
03481 alignment_pad->var = size_binop (MINUS_EXPR, offset_ptr->var,
03482 save_var);
03483 }
03484 else
03485 {
03486 offset_ptr->constant = -sp_offset +
03487 #ifdef ARGS_GROW_DOWNWARD
03488 FLOOR_ROUND (offset_ptr->constant + sp_offset, boundary_in_bytes);
03489 #else
03490 CEIL_ROUND (offset_ptr->constant + sp_offset, boundary_in_bytes);
03491 #endif
03492 if (boundary > PARM_BOUNDARY && boundary > STACK_BOUNDARY)
03493 alignment_pad->constant = offset_ptr->constant - save_constant;
03494 }
03495 }
03496 }
03497
03498 static void
03499 pad_below (struct args_size *offset_ptr, enum machine_mode passed_mode, tree sizetree)
03500 {
03501 if (passed_mode != BLKmode)
03502 {
03503 if (GET_MODE_BITSIZE (passed_mode) % PARM_BOUNDARY)
03504 offset_ptr->constant
03505 += (((GET_MODE_BITSIZE (passed_mode) + PARM_BOUNDARY - 1)
03506 / PARM_BOUNDARY * PARM_BOUNDARY / BITS_PER_UNIT)
03507 - GET_MODE_SIZE (passed_mode));
03508 }
03509 else
03510 {
03511 if (TREE_CODE (sizetree) != INTEGER_CST
03512 || (TREE_INT_CST_LOW (sizetree) * BITS_PER_UNIT) % PARM_BOUNDARY)
03513 {
03514
03515 tree s2 = round_up (sizetree, PARM_BOUNDARY / BITS_PER_UNIT);
03516
03517 ADD_PARM_SIZE (*offset_ptr, s2);
03518 SUB_PARM_SIZE (*offset_ptr, sizetree);
03519 }
03520 }
03521 }
03522
03523
03524
03525
03526
03527
03528 void
03529 setjmp_vars_warning (tree block)
03530 {
03531 tree decl, sub;
03532
03533 for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
03534 {
03535 if (TREE_CODE (decl) == VAR_DECL
03536 && DECL_RTL_SET_P (decl)
03537 && REG_P (DECL_RTL (decl))
03538 && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
03539 warning (0, "variable %q+D might be clobbered by %<longjmp%>"
03540 " or %<vfork%>",
03541 decl);
03542 }
03543
03544 for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub))
03545 setjmp_vars_warning (sub);
03546 }
03547
03548
03549
03550
03551 void
03552 setjmp_args_warning (void)
03553 {
03554 tree decl;
03555 for (decl = DECL_ARGUMENTS (current_function_decl);
03556 decl; decl = TREE_CHAIN (decl))
03557 if (DECL_RTL (decl) != 0
03558 && REG_P (DECL_RTL (decl))
03559 && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
03560 warning (0, "argument %q+D might be clobbered by %<longjmp%> or %<vfork%>",
03561 decl);
03562 }
03563
03564
03565
03566
03567
03568
03569
03570
03571 void
03572 reorder_blocks (void)
03573 {
03574 tree block = DECL_INITIAL (current_function_decl);
03575 VEC(tree,heap) *block_stack;
03576
03577 if (block == NULL_TREE)
03578 return;
03579
03580 block_stack = VEC_alloc (tree, heap, 10);
03581
03582
03583 clear_block_marks (block);
03584
03585
03586 BLOCK_SUBBLOCKS (block) = NULL_TREE;
03587 BLOCK_CHAIN (block) = NULL_TREE;
03588
03589
03590 reorder_blocks_1 (get_insns (), block, &block_stack);
03591 BLOCK_SUBBLOCKS (block) = blocks_nreverse (BLOCK_SUBBLOCKS (block));
03592
03593 VEC_free (tree, heap, block_stack);
03594 }
03595
03596
03597
03598 void
03599 clear_block_marks (tree block)
03600 {
03601 while (block)
03602 {
03603 TREE_ASM_WRITTEN (block) = 0;
03604 clear_block_marks (BLOCK_SUBBLOCKS (block));
03605 block = BLOCK_CHAIN (block);
03606 }
03607 }
03608
03609 static void
03610 reorder_blocks_1 (rtx insns, tree current_block, VEC(tree,heap) **p_block_stack)
03611 {
03612 rtx insn;
03613
03614 for (insn = insns; insn; insn = NEXT_INSN (insn))
03615 {
03616 if (NOTE_P (insn))
03617 {
03618 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
03619 {
03620 tree block = NOTE_BLOCK (insn);
03621 tree origin;
03622
03623 origin = (BLOCK_FRAGMENT_ORIGIN (block)
03624 ? BLOCK_FRAGMENT_ORIGIN (block)
03625 : block);
03626
03627
03628
03629 if (TREE_ASM_WRITTEN (block))
03630 {
03631 tree new_block = copy_node (block);
03632
03633 BLOCK_FRAGMENT_ORIGIN (new_block) = origin;
03634 BLOCK_FRAGMENT_CHAIN (new_block)
03635 = BLOCK_FRAGMENT_CHAIN (origin);
03636 BLOCK_FRAGMENT_CHAIN (origin) = new_block;
03637
03638 NOTE_BLOCK (insn) = new_block;
03639 block = new_block;
03640 }
03641
03642 BLOCK_SUBBLOCKS (block) = 0;
03643 TREE_ASM_WRITTEN (block) = 1;
03644
03645
03646
03647 if (block != current_block)
03648 {
03649 if (block != origin)
03650 gcc_assert (BLOCK_SUPERCONTEXT (origin) == current_block);
03651
03652 BLOCK_SUPERCONTEXT (block) = current_block;
03653 BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block);
03654 BLOCK_SUBBLOCKS (current_block) = block;
03655 current_block = origin;
03656 }
03657 VEC_safe_push (tree, heap, *p_block_stack, block);
03658 }
03659 else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
03660 {
03661 NOTE_BLOCK (insn) = VEC_pop (tree, *p_block_stack);
03662 BLOCK_SUBBLOCKS (current_block)
03663 = blocks_nreverse (BLOCK_SUBBLOCKS (current_block));
03664 current_block = BLOCK_SUPERCONTEXT (current_block);
03665 }
03666 }
03667 }
03668 }
03669
03670
03671
03672
03673 tree
03674 blocks_nreverse (tree t)
03675 {
03676 tree prev = 0, decl, next;
03677 for (decl = t; decl; decl = next)
03678 {
03679 next = BLOCK_CHAIN (decl);
03680 BLOCK_CHAIN (decl) = prev;
03681 prev = decl;
03682 }
03683 return prev;
03684 }
03685
03686
03687
03688
03689
03690
03691 static int
03692 all_blocks (tree block, tree *vector)
03693 {
03694 int n_blocks = 0;
03695
03696 while (block)
03697 {
03698 TREE_ASM_WRITTEN (block) = 0;
03699
03700
03701 if (vector)
03702 vector[n_blocks] = block;
03703
03704 ++n_blocks;
03705
03706
03707 n_blocks += all_blocks (BLOCK_SUBBLOCKS (block),
03708 vector ? vector + n_blocks : 0);
03709 block = BLOCK_CHAIN (block);
03710 }
03711
03712 return n_blocks;
03713 }
03714
03715
03716
03717
03718
03719
03720 static tree *
03721 get_block_vector (tree block, int *n_blocks_p)
03722 {
03723 tree *block_vector;
03724
03725 *n_blocks_p = all_blocks (block, NULL);
03726 block_vector = XNEWVEC (tree, *n_blocks_p);
03727 all_blocks (block, block_vector);
03728
03729 return block_vector;
03730 }
03731
03732 static GTY(()) int next_block_index = 2;
03733
03734
03735
03736 void
03737 number_blocks (tree fn)
03738 {
03739 int i;
03740 int n_blocks;
03741 tree *block_vector;
03742
03743
03744
03745
03746 #if defined (SDB_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
03747 if (write_symbols == SDB_DEBUG || write_symbols == XCOFF_DEBUG)
03748 next_block_index = 1;
03749 #endif
03750
03751 block_vector = get_block_vector (DECL_INITIAL (fn), &n_blocks);
03752
03753
03754 for (i = 1; i < n_blocks; ++i)
03755
03756 BLOCK_NUMBER (block_vector[i]) = next_block_index++;
03757
03758 free (block_vector);
03759
03760 return;
03761 }
03762
03763
03764
03765 tree
03766 debug_find_var_in_block_tree (tree var, tree block)
03767 {
03768 tree t;
03769
03770 for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
03771 if (t == var)
03772 return block;
03773
03774 for (t = BLOCK_SUBBLOCKS (block); t; t = TREE_CHAIN (t))
03775 {
03776 tree ret = debug_find_var_in_block_tree (var, t);
03777 if (ret)
03778 return ret;
03779 }
03780
03781 return NULL_TREE;
03782 }
03783
03784
03785
03786
03787 void
03788 allocate_struct_function (tree fndecl)
03789 {
03790 tree result;
03791 tree fntype = fndecl ? TREE_TYPE (fndecl) : NULL_TREE;
03792
03793 cfun = ggc_alloc_cleared (sizeof (struct function));
03794
03795 cfun->stack_alignment_needed = STACK_BOUNDARY;
03796 cfun->preferred_stack_boundary = STACK_BOUNDARY;
03797
03798 current_function_funcdef_no = funcdef_no++;
03799
03800 cfun->function_frequency = FUNCTION_FREQUENCY_NORMAL;
03801
03802 init_eh_for_function ();
03803
03804 lang_hooks.function.init (cfun);
03805 if (init_machine_status)
03806 cfun->machine = (*init_machine_status) ();
03807
03808 if (fndecl == NULL)
03809 return;
03810
03811 DECL_STRUCT_FUNCTION (fndecl) = cfun;
03812 cfun->decl = fndecl;
03813
03814 result = DECL_RESULT (fndecl);
03815 if (aggregate_value_p (result, fndecl))
03816 {
03817 #ifdef PCC_STATIC_STRUCT_RETURN
03818 current_function_returns_pcc_struct = 1;
03819 #endif
03820 current_function_returns_struct = 1;
03821 }
03822
03823 current_function_returns_pointer = POINTER_TYPE_P (TREE_TYPE (result));
03824
03825 current_function_stdarg
03826 = (fntype
03827 && TYPE_ARG_TYPES (fntype) != 0
03828 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
03829 != void_type_node));
03830
03831
03832 cfun->va_list_gpr_size = VA_LIST_MAX_GPR_SIZE;
03833 cfun->va_list_fpr_size = VA_LIST_MAX_FPR_SIZE;
03834 }
03835
03836
03837
03838
03839 static void
03840 prepare_function_start (tree fndecl)
03841 {
03842 if (fndecl && DECL_STRUCT_FUNCTION (fndecl))
03843 cfun = DECL_STRUCT_FUNCTION (fndecl);
03844 else
03845 allocate_struct_function (fndecl);
03846 init_emit ();
03847 init_varasm_status (cfun);
03848 init_expr ();
03849
03850 cse_not_expected = ! optimize;
03851
03852
03853 caller_save_needed = 0;
03854
03855
03856 reg_renumber = 0;
03857
03858
03859 virtuals_instantiated = 0;
03860
03861
03862 generating_concat_p = 1;
03863
03864
03865 frame_pointer_needed = 0;
03866 }
03867
03868
03869
03870
03871 void
03872 init_dummy_function_start (void)
03873 {
03874 prepare_function_start (NULL);
03875 }
03876
03877
03878
03879
03880
03881 void
03882 init_function_start (tree subr)
03883 {
03884 prepare_function_start (subr);
03885
03886
03887
03888
03889
03890 if (! DECL_IS_BUILTIN (subr))
03891 emit_line_note (DECL_SOURCE_LOCATION (subr));
03892
03893
03894
03895
03896 emit_note (NOTE_INSN_DELETED);
03897
03898
03899
03900 if (AGGREGATE_TYPE_P (TREE_TYPE (DECL_RESULT (subr))))
03901 warning (OPT_Waggregate_return, "function returns an aggregate");
03902 }
03903
03904
03905
03906 unsigned int
03907 init_function_for_compilation (void)
03908 {
03909 reg_renumber = 0;
03910
03911
03912
03913 gcc_assert (VEC_length (int, prologue) == 0);
03914 gcc_assert (VEC_length (int, epilogue) == 0);
03915 gcc_assert (VEC_length (int, sibcall_epilogue) == 0);
03916 return 0;
03917 }
03918
03919 struct tree_opt_pass pass_init_function =
03920 {
03921 NULL,
03922 NULL,
03923 init_function_for_compilation,
03924 NULL,
03925 NULL,
03926 0,
03927 0,
03928 0,
03929 0,
03930 0,
03931 0,
03932 0,
03933 0
03934 };
03935
03936
03937 void
03938 expand_main_function (void)
03939 {
03940 #if (defined(INVOKE__main) \
03941 || (!defined(HAS_INIT_SECTION) \
03942 && !defined(INIT_SECTION_ASM_OP) \
03943 && !defined(INIT_ARRAY_SECTION_ASM_OP)))
03944 emit_library_call (init_one_libfunc (NAME__MAIN), LCT_NORMAL, VOIDmode, 0);
03945 #endif
03946 }
03947
03948
03949
03950
03951 #ifndef HAVE_stack_protect_set
03952 # define HAVE_stack_protect_set 0
03953 # define gen_stack_protect_set(x,y) (gcc_unreachable (), NULL_RTX)
03954 #endif
03955
03956 void
03957 stack_protect_prologue (void)
03958 {
03959 tree guard_decl = targetm.stack_protect_guard ();
03960 rtx x, y;
03961
03962
03963
03964
03965
03966 x = validize_mem (DECL_RTL (cfun->stack_protect_guard));
03967 y = validize_mem (DECL_RTL (guard_decl));
03968
03969
03970
03971 if (HAVE_stack_protect_set)
03972 {
03973 rtx insn = gen_stack_protect_set (x, y);
03974 if (insn)
03975 {
03976 emit_insn (insn);
03977 return;
03978 }
03979 }
03980
03981
03982 emit_move_insn (x, y);
03983 }
03984
03985
03986
03987
03988 #ifndef HAVE_stack_protect_test
03989 # define HAVE_stack_protect_test 0
03990 # define gen_stack_protect_test(x, y, z) (gcc_unreachable (), NULL_RTX)
03991 #endif
03992
03993 void
03994 stack_protect_epilogue (void)
03995 {
03996 tree guard_decl = targetm.stack_protect_guard ();
03997 rtx label = gen_label_rtx ();
03998 rtx x, y, tmp;
03999
04000
04001
04002
04003
04004 x = validize_mem (DECL_RTL (cfun->stack_protect_guard));
04005 y = validize_mem (DECL_RTL (guard_decl));
04006
04007
04008
04009 switch (HAVE_stack_protect_test != 0)
04010 {
04011 case 1:
04012 tmp = gen_stack_protect_test (x, y, label);
04013 if (tmp)
04014 {
04015 emit_insn (tmp);
04016 break;
04017 }
04018
04019
04020 default:
04021 emit_cmp_and_jump_insns (x, y, EQ, NULL_RTX, ptr_mode, 1, label);
04022 break;
04023 }
04024
04025
04026
04027
04028
04029
04030 tmp = get_last_insn ();
04031 if (JUMP_P (tmp))
04032 predict_insn_def (tmp, PRED_NORETURN, TAKEN);
04033
04034 expand_expr_stmt (targetm.stack_protect_fail ());
04035 emit_label (label);
04036 }
04037
04038
04039
04040
04041
04042
04043
04044 void
04045 expand_function_start (tree subr)
04046 {
04047
04048
04049 init_recog_no_volatile ();
04050
04051 current_function_profile
04052 = (profile_flag
04053 && ! DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (subr));
04054
04055 current_function_limit_stack
04056 = (stack_limit_rtx != NULL_RTX && ! DECL_NO_LIMIT_STACK (subr));
04057
04058
04059
04060
04061 return_label = gen_label_rtx ();
04062
04063
04064
04065
04066
04067
04068 if (aggregate_value_p (DECL_RESULT (subr), subr))
04069 {
04070
04071 rtx value_address = 0;
04072
04073 #ifdef PCC_STATIC_STRUCT_RETURN
04074 if (current_function_returns_pcc_struct)
04075 {
04076 int size = int_size_in_bytes (TREE_TYPE (DECL_RESULT (subr)));
04077 value_address = assemble_static_space (size);
04078 }
04079 else
04080 #endif
04081 {
04082 rtx sv = targetm.calls.struct_value_rtx (TREE_TYPE (subr), 2);
04083
04084
04085
04086 if (sv)
04087 {
04088 value_address = gen_reg_rtx (Pmode);
04089 emit_move_insn (value_address, sv);
04090 }
04091 }
04092 if (value_address)
04093 {
04094 rtx x = value_address;
04095 if (!DECL_BY_REFERENCE (DECL_RESULT (subr)))
04096 {
04097 x = gen_rtx_MEM (DECL_MODE (DECL_RESULT (subr)), x);
04098 set_mem_attributes (x, DECL_RESULT (subr), 1);
04099 }
04100 SET_DECL_RTL (DECL_RESULT (subr), x);
04101 }
04102 }
04103 else if (DECL_MODE (DECL_RESULT (subr)) == VOIDmode)
04104
04105 SET_DECL_RTL (DECL_RESULT (subr), NULL_RTX);
04106 else
04107 {
04108
04109
04110 tree return_type = TREE_TYPE (DECL_RESULT (subr));
04111 if (TYPE_MODE (return_type) != BLKmode
04112 && targetm.calls.return_in_msb (return_type))
04113
04114
04115
04116 SET_DECL_RTL (DECL_RESULT (subr),
04117 gen_reg_rtx (TYPE_MODE (return_type)));
04118 else
04119 {
04120
04121
04122
04123 rtx hard_reg = hard_function_value (return_type, subr, 0, 1);
04124
04125
04126
04127 if (REG_P (hard_reg))
04128 SET_DECL_RTL (DECL_RESULT (subr),
04129 gen_reg_rtx (GET_MODE (hard_reg)));
04130 else
04131 {
04132 gcc_assert (GET_CODE (hard_reg) == PARALLEL);
04133 SET_DECL_RTL (DECL_RESULT (subr), gen_group_rtx (hard_reg));
04134 }
04135 }
04136
04137
04138
04139 DECL_REGISTER (DECL_RESULT (subr)) = 1;
04140 }
04141
04142
04143
04144 assign_parms (subr);
04145
04146
04147 if (cfun->static_chain_decl)
04148 {
04149 tree parm = cfun->static_chain_decl;
04150 rtx local = gen_reg_rtx (Pmode);
04151
04152 set_decl_incoming_rtl (parm, static_chain_incoming_rtx);
04153 SET_DECL_RTL (parm, local);
04154 mark_reg_pointer (local, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (parm))));
04155
04156 emit_move_insn (local, static_chain_incoming_rtx);
04157 }
04158
04159
04160
04161 if (cfun->nonlocal_goto_save_area)
04162 {
04163 tree t_save;
04164 rtx r_save;
04165
04166
04167
04168 expand_var (TREE_OPERAND (cfun->nonlocal_goto_save_area, 0));
04169
04170 t_save = build4 (ARRAY_REF, ptr_type_node,
04171 cfun->nonlocal_goto_save_area,
04172 integer_zero_node, NULL_TREE, NULL_TREE);
04173 r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE);
04174 r_save = convert_memory_address (Pmode, r_save);
04175
04176 emit_move_insn (r_save, virtual_stack_vars_rtx);
04177 update_nonlocal_goto_save_area ();
04178 }
04179
04180
04181
04182
04183
04184 emit_note (NOTE_INSN_FUNCTION_BEG);
04185
04186 gcc_assert (NOTE_P (get_last_insn ()));
04187
04188 parm_birth_insn = get_last_insn ();
04189
04190 if (current_function_profile)
04191 {
04192 #ifdef PROFILE_HOOK
04193 PROFILE_HOOK (current_function_funcdef_no);
04194 #endif
04195 }
04196
04197
04198
04199 if(flag_stack_check)
04200 stack_check_probe_note = emit_note (NOTE_INSN_DELETED);
04201
04202
04203 force_next_line_note ();
04204 }
04205
04206
04207 void
04208 expand_dummy_function_end (void)
04209 {
04210
04211 while (in_sequence_p ())
04212 end_sequence ();
04213
04214
04215
04216
04217 free_after_parsing (cfun);
04218 free_after_compilation (cfun);
04219 cfun = 0;
04220 }
04221
04222
04223
04224
04225 void
04226 diddle_return_value (void (*doit) (rtx, void *), void *arg)
04227 {
04228 rtx outgoing = current_function_return_rtx;
04229
04230 if (! outgoing)
04231 return;
04232
04233 if (REG_P (outgoing))
04234 (*doit) (outgoing, arg);
04235 else if (GET_CODE (outgoing) == PARALLEL)
04236 {
04237 int i;
04238
04239 for (i = 0; i < XVECLEN (outgoing, 0); i++)
04240 {
04241 rtx x = XEXP (XVECEXP (outgoing, 0, i), 0);
04242
04243 if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
04244 (*doit) (x, arg);
04245 }
04246 }
04247 }
04248
04249 static void
04250 do_clobber_return_reg (rtx reg, void *arg ATTRIBUTE_UNUSED)
04251 {
04252 emit_insn (gen_rtx_CLOBBER (VOIDmode, reg));
04253 }
04254
04255 void
04256 clobber_return_register (void)
04257 {
04258 diddle_return_value (do_clobber_return_reg, NULL);
04259
04260
04261 if (DECL_RTL_SET_P (DECL_RESULT (current_function_decl)))
04262 {
04263 tree decl_result = DECL_RESULT (current_function_decl);
04264 rtx decl_rtl = DECL_RTL (decl_result);
04265 if (REG_P (decl_rtl) && REGNO (decl_rtl) >= FIRST_PSEUDO_REGISTER)
04266 {
04267 do_clobber_return_reg (decl_rtl, NULL);
04268 }
04269 }
04270 }
04271
04272 static void
04273 do_use_return_reg (rtx reg, void *arg ATTRIBUTE_UNUSED)
04274 {
04275 emit_insn (gen_rtx_USE (VOIDmode, reg));
04276 }
04277
04278 static void
04279 use_return_register (void)
04280 {
04281 diddle_return_value (do_use_return_reg, NULL);
04282 }
04283
04284
04285 void
04286 do_warn_unused_parameter (tree fn)
04287 {
04288 tree decl;
04289
04290 for (decl = DECL_ARGUMENTS (fn);
04291 decl; decl = TREE_CHAIN (decl))
04292 if (!TREE_USED (decl) && TREE_CODE (decl) == PARM_DECL
04293 && DECL_NAME (decl) && !DECL_ARTIFICIAL (decl))
04294 warning (OPT_Wunused_parameter, "unused parameter %q+D", decl);
04295 }
04296
04297 static GTY(()) rtx initial_trampoline;
04298
04299
04300
04301 void
04302 expand_function_end (void)
04303 {
04304 rtx clobber_after;
04305
04306
04307
04308 if (arg_pointer_save_area && ! cfun->arg_pointer_save_area_init)
04309 get_arg_pointer_save_area (cfun);
04310
04311
04312
04313
04314 if (flag_stack_check && ! STACK_CHECK_BUILTIN)
04315 {
04316 rtx insn, seq;
04317
04318 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
04319 if (CALL_P (insn))
04320 {
04321 start_sequence ();
04322 probe_stack_range (STACK_CHECK_PROTECT,
04323 GEN_INT (STACK_CHECK_MAX_FRAME_SIZE));
04324 seq = get_insns ();
04325 end_sequence ();
04326 emit_insn_before (seq, stack_check_probe_note);
04327 break;
04328 }
04329 }
04330
04331
04332
04333
04334 if (warn_unused_parameter
04335 && !lang_hooks.callgraph.expand_function)
04336 do_warn_unused_parameter (current_function_decl);
04337
04338
04339 while (in_sequence_p ())
04340 end_sequence ();
04341
04342 clear_pending_stack_adjust ();
04343 do_pending_stack_adjust ();
04344
04345
04346
04347
04348 emit_note (NOTE_INSN_FUNCTION_END);
04349
04350
04351
04352
04353
04354
04355 if (flag_test_coverage)
04356 emit_note (NOTE_INSN_REPEATED_LINE_NUMBER);
04357
04358
04359
04360 force_next_line_note ();
04361 emit_line_note (input_location);
04362
04363
04364
04365
04366
04367
04368
04369
04370
04371 clobber_after = get_last_insn ();
04372
04373
04374 emit_label (return_label);
04375
04376 if (USING_SJLJ_EXCEPTIONS)
04377 {
04378
04379
04380 if (flag_exceptions)
04381 sjlj_emit_function_exit_after (get_last_insn ());
04382 }
04383 else
04384 {
04385
04386
04387
04388
04389
04390 if (flag_non_call_exceptions)
04391 emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
04392 }
04393
04394
04395
04396 expand_eh_return ();
04397
04398
04399
04400
04401 if (DECL_RTL_SET_P (DECL_RESULT (current_function_decl)))
04402 {
04403 tree decl_result = DECL_RESULT (current_function_decl);
04404 rtx decl_rtl = DECL_RTL (decl_result);
04405
04406 if (REG_P (decl_rtl)
04407 ? REGNO (decl_rtl) >= FIRST_PSEUDO_REGISTER
04408 : DECL_REGISTER (decl_result))
04409 {
04410 rtx real_decl_rtl = current_function_return_rtx;
04411
04412
04413 gcc_assert (REG_FUNCTION_VALUE_P (real_decl_rtl));
04414
04415
04416
04417
04418
04419 if (GET_MODE (real_decl_rtl) == BLKmode)
04420 PUT_MODE (real_decl_rtl, GET_MODE (decl_rtl));
04421
04422
04423
04424
04425
04426 if (TYPE_MODE (TREE_TYPE (decl_result)) != BLKmode
04427 && targetm.calls.return_in_msb (TREE_TYPE (decl_result)))
04428 {
04429 emit_move_insn (gen_rtx_REG (GET_MODE (decl_rtl),
04430 REGNO (real_decl_rtl)),
04431 decl_rtl);
04432 shift_return_value (GET_MODE (decl_rtl), true, real_decl_rtl);
04433 }
04434
04435
04436
04437 else if (GET_MODE (real_decl_rtl) != GET_MODE (decl_rtl))
04438 {
04439 int unsignedp = TYPE_UNSIGNED (TREE_TYPE (decl_result));
04440
04441 if (targetm.calls.promote_function_return (TREE_TYPE (current_function_decl)))
04442 promote_mode (TREE_TYPE (decl_result), GET_MODE (decl_rtl),
04443 &unsignedp, 1);
04444
04445 convert_move (real_decl_rtl, decl_rtl, unsignedp);
04446 }
04447 else if (GET_CODE (real_decl_rtl) == PARALLEL)
04448 {
04449
04450
04451
04452 if (GET_CODE (decl_rtl) == PARALLEL)
04453 emit_group_move (real_decl_rtl, decl_rtl);
04454 else
04455 emit_group_load (real_decl_rtl, decl_rtl,
04456 TREE_TYPE (decl_result),
04457 int_size_in_bytes (TREE_TYPE (decl_result)));
04458 }
04459
04460
04461
04462 else if (GET_CODE (decl_rtl) == CONCAT
04463 && GET_MODE_CLASS (GET_MODE (decl_rtl)) == MODE_COMPLEX_INT
04464 && GET_MODE_BITSIZE (GET_MODE (decl_rtl)) <= BITS_PER_WORD)
04465 {
04466 int old_generating_concat_p;
04467 rtx tmp;
04468
04469 old_generating_concat_p = generating_concat_p;
04470 generating_concat_p = 0;
04471 tmp = gen_reg_rtx (GET_MODE (decl_rtl));
04472 generating_concat_p = old_generating_concat_p;
04473
04474 emit_move_insn (tmp, decl_rtl);
04475 emit_move_insn (real_decl_rtl, tmp);
04476 }
04477 else
04478 emit_move_insn (real_decl_rtl, decl_rtl);
04479 }
04480 }
04481
04482
04483
04484
04485
04486
04487
04488 if (current_function_returns_struct
04489 || current_function_returns_pcc_struct)
04490 {
04491 rtx value_address = DECL_RTL (DECL_RESULT (current_function_decl));
04492 tree type = TREE_TYPE (DECL_RESULT (current_function_decl));
04493 rtx outgoing;
04494
04495 if (DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
04496 type = TREE_TYPE (type);
04497 else
04498 value_address = XEXP (value_address, 0);
04499
04500 outgoing = targetm.calls.function_value (build_pointer_type (type),
04501 current_function_decl, true);
04502
04503
04504
04505 REG_FUNCTION_VALUE_P (outgoing) = 1;
04506
04507
04508 value_address = convert_memory_address (GET_MODE (outgoing),
04509 value_address);
04510
04511 emit_move_insn (outgoing, value_address);
04512
04513
04514
04515 current_function_return_rtx = outgoing;
04516 }
04517
04518
04519 {
04520 rtx seq;
04521
04522 start_sequence ();
04523 clobber_return_register ();
04524 expand_naked_return ();
04525 seq = get_insns ();
04526 end_sequence ();
04527
04528 emit_insn_after (seq, clobber_after);
04529 }
04530
04531
04532 emit_label (naked_return_label);
04533
04534
04535 if (cfun->stack_protect_guard)
04536 stack_protect_epilogue ();
04537
04538
04539
04540
04541 if (! EXIT_IGNORE_STACK
04542 && current_function_calls_alloca)
04543 {
04544 rtx tem = 0;
04545
04546 emit_stack_save (SAVE_FUNCTION, &tem, parm_birth_insn);
04547 emit_stack_restore (SAVE_FUNCTION, tem, NULL_RTX);
04548 }
04549
04550
04551
04552
04553
04554 use_return_register ();
04555 }
04556
04557 rtx
04558 get_arg_pointer_save_area (struct function *f)
04559 {
04560 rtx ret = f->x_arg_pointer_save_area;
04561
04562 if (! ret)
04563 {
04564 ret = assign_stack_local_1 (Pmode, GET_MODE_SIZE (Pmode), 0, f);
04565 f->x_arg_pointer_save_area = ret;
04566 }
04567
04568 if (f == cfun && ! f->arg_pointer_save_area_init)
04569 {
04570 rtx seq;
04571
04572
04573
04574
04575 start_sequence ();
04576 emit_move_insn (validize_mem (ret), virtual_incoming_args_rtx);
04577 seq = get_insns ();
04578 end_sequence ();
04579
04580 push_topmost_sequence ();
04581 emit_insn_after (seq, entry_of_function ());
04582 pop_topmost_sequence ();
04583 }
04584
04585 return ret;
04586 }
04587
04588
04589
04590
04591 static void
04592 record_insns (rtx insns, VEC(int,heap) **vecp)
04593 {
04594 rtx tmp;
04595
04596 for (tmp = insns; tmp != NULL_RTX; tmp = NEXT_INSN (tmp))
04597 VEC_safe_push (int, heap, *vecp, INSN_UID (tmp));
04598 }
04599
04600
04601 static void
04602 set_insn_locators (rtx insn, int loc)
04603 {
04604 while (insn != NULL_RTX)
04605 {
04606 if (INSN_P (insn))
04607 INSN_LOCATOR (insn) = loc;
04608 insn = NEXT_INSN (insn);
04609 }
04610 }
04611
04612
04613
04614
04615 static int
04616 contains (rtx insn, VEC(int,heap) **vec)
04617 {
04618 int i, j;
04619
04620 if (NONJUMP_INSN_P (insn)
04621 && GET_CODE (PATTERN (insn)) == SEQUENCE)
04622 {
04623 int count = 0;
04624 for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
04625 for (j = VEC_length (int, *vec) - 1; j >= 0; --j)
04626 if (INSN_UID (XVECEXP (PATTERN (insn), 0, i))
04627 == VEC_index (int, *vec, j))
04628 count++;
04629 return count;
04630 }
04631 else
04632 {
04633 for (j = VEC_length (int, *vec) - 1; j >= 0; --j)
04634 if (INSN_UID (insn) == VEC_index (int, *vec, j))
04635 return 1;
04636 }
04637 return 0;
04638 }
04639
04640 int
04641 prologue_epilogue_contains (rtx insn)
04642 {
04643 if (contains (insn, &prologue))
04644 return 1;
04645 if (contains (insn, &epilogue))
04646 return 1;
04647 return 0;
04648 }
04649
04650 int
04651 sibcall_epilogue_contains (rtx insn)
04652 {
04653 if (sibcall_epilogue)
04654 return contains (insn, &sibcall_epilogue);
04655 return 0;
04656 }
04657
04658 #ifdef HAVE_return
04659
04660
04661
04662 static void
04663 emit_return_into_block (basic_block bb, rtx line_note)
04664 {
04665 emit_jump_insn_after (gen_return (), BB_END (bb));
04666 if (line_note)
04667 emit_note_copy_after (line_note, PREV_INSN (BB_END (bb)));
04668 }
04669 #endif
04670
04671 #if defined(HAVE_epilogue) && defined(INCOMING_RETURN_ADDR_RTX)
04672
04673
04674
04675
04676
04677
04678
04679
04680
04681
04682
04683
04684
04685
04686
04687
04688
04689
04690
04691
04692
04693
04694
04695
04696
04697
04698
04699
04700
04701
04702
04703 struct epi_info
04704 {
04705 rtx sp_equiv_reg;
04706 HOST_WIDE_INT sp_offset;
04707 rtx new_sp_equiv_reg;
04708 HOST_WIDE_INT new_sp_offset;
04709 rtx equiv_reg_src;
04710
04711
04712 rtx const_equiv[FIRST_PSEUDO_REGISTER];
04713
04714 };
04715
04716 static void handle_epilogue_set (rtx, struct epi_info *);
04717 static void update_epilogue_consts (rtx, rtx, void *);
04718 static void emit_equiv_load (struct epi_info *);
04719
04720
04721
04722
04723 static rtx
04724 keep_stack_depressed (rtx insns)
04725 {
04726 int j;
04727 struct epi_info info;
04728 rtx insn, next;
04729
04730
04731 if (NEXT_INSN (insns) == NULL_RTX)
04732 return insns;
04733
04734
04735
04736 start_sequence ();
04737
04738 info.sp_equiv_reg = stack_pointer_rtx;
04739 info.sp_offset = 0;
04740 info.equiv_reg_src = 0;
04741
04742 for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
04743 info.const_equiv[j] = 0;
04744
04745 insn = insns;
04746 next = NULL_RTX;
04747 while (insn != NULL_RTX)
04748 {
04749 next = NEXT_INSN (insn);
04750
04751 if (!INSN_P (insn))
04752 {
04753 add_insn (insn);
04754 insn = next;
04755 continue;
04756 }
04757
04758
04759
04760
04761 if (info.equiv_reg_src != 0
04762 && reg_referenced_p (info.sp_equiv_reg, PATTERN (insn)))
04763 {
04764 emit_equiv_load (&info);
04765 info.sp_equiv_reg = 0;
04766 }
04767
04768 info.new_sp_equiv_reg = info.sp_equiv_reg;
04769 info.new_sp_offset = info.sp_offset;
04770
04771
04772
04773 if (GET_CODE (PATTERN (insn)) == RETURN
04774 || (GET_CODE (PATTERN (insn)) == PARALLEL
04775 && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == RETURN))
04776 {
04777 rtx retaddr = INCOMING_RETURN_ADDR_RTX;
04778 rtx base = 0;
04779 HOST_WIDE_INT offset = 0;
04780 rtx jump_insn, jump_set;
04781
04782
04783
04784
04785
04786 if (REG_P (retaddr))
04787 {
04788 emit_equiv_load (&info);
04789 add_insn (insn);
04790 insn = next;
04791 continue;
04792 }
04793 else
04794 {
04795 rtx ret_ptr;
04796 gcc_assert (MEM_P (retaddr));
04797
04798 ret_ptr = XEXP (retaddr, 0);
04799
04800 if (REG_P (ret_ptr))
04801 {
04802 base = gen_rtx_REG (Pmode, REGNO (ret_ptr));
04803 offset = 0;
04804 }
04805 else
04806 {
04807 gcc_assert (GET_CODE (ret_ptr) == PLUS
04808 && REG_P (XEXP (ret_ptr, 0))
04809 && GET_CODE (XEXP (ret_ptr, 1)) == CONST_INT);
04810 base = gen_rtx_REG (Pmode, REGNO (XEXP (ret_ptr, 0)));
04811 offset = INTVAL (XEXP (ret_ptr, 1));
04812 }
04813 }
04814
04815
04816
04817
04818 retaddr = plus_constant (base, offset);
04819 if (base == stack_pointer_rtx)
04820 retaddr = simplify_replace_rtx (retaddr, stack_pointer_rtx,
04821 plus_constant (info.sp_equiv_reg,
04822 info.sp_offset));
04823
04824 retaddr = gen_rtx_MEM (Pmode, retaddr);
04825 MEM_NOTRAP_P (retaddr) = 1;
04826
04827
04828
04829
04830 if (info.equiv_reg_src
04831 && reg_overlap_mentioned_p (info.equiv_reg_src, retaddr))
04832 {
04833 unsigned int regno;
04834 rtx reg;
04835
04836 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
04837 if (HARD_REGNO_MODE_OK (regno, Pmode)
04838 && !fixed_regs[regno]
04839 && TEST_HARD_REG_BIT (regs_invalidated_by_call, regno)
04840 && !REGNO_REG_SET_P
04841 (EXIT_BLOCK_PTR->il.rtl->global_live_at_start, regno)
04842 && !refers_to_regno_p (regno,
04843 regno + hard_regno_nregs[regno]
04844 [Pmode],
04845 info.equiv_reg_src, NULL)
04846 && info.const_equiv[regno] == 0)
04847 break;
04848
04849 gcc_assert (regno < FIRST_PSEUDO_REGISTER);
04850
04851 reg = gen_rtx_REG (Pmode, regno);
04852 emit_move_insn (reg, retaddr);
04853 retaddr = reg;
04854 }
04855
04856 emit_equiv_load (&info);
04857 jump_insn = emit_jump_insn (gen_indirect_jump (retaddr));
04858
04859
04860 jump_set = single_set (jump_insn);
04861 gcc_assert (jump_set);
04862 SET_IS_RETURN_P (jump_set) = 1;
04863 }
04864
04865
04866
04867
04868
04869 else if (!reg_mentioned_p (stack_pointer_rtx, PATTERN (insn))
04870 && (info.sp_equiv_reg == stack_pointer_rtx
04871 || !reg_set_p (info.sp_equiv_reg, insn)))
04872 add_insn (insn);
04873 else if (! reg_set_p (stack_pointer_rtx, insn)
04874 && (info.sp_equiv_reg == stack_pointer_rtx
04875 || !reg_set_p (info.sp_equiv_reg, insn)))
04876 {
04877 int changed;
04878
04879 changed = validate_replace_rtx (stack_pointer_rtx,
04880 plus_constant (info.sp_equiv_reg,
04881 info.sp_offset),
04882 insn);
04883 gcc_assert (changed);
04884
04885 add_insn (insn);
04886 }
04887 else if (GET_CODE (PATTERN (insn)) == SET)
04888 handle_epilogue_set (PATTERN (insn), &info);
04889 else if (GET_CODE (PATTERN (insn)) == PARALLEL)
04890 {
04891 for (j = 0; j < XVECLEN (PATTERN (insn), 0); j++)
04892 if (GET_CODE (XVECEXP (PATTERN (insn), 0, j)) == SET)
04893 handle_epilogue_set (XVECEXP (PATTERN (insn), 0, j), &info);
04894 }
04895 else
04896 add_insn (insn);
04897
04898 info.sp_equiv_reg = info.new_sp_equiv_reg;
04899 info.sp_offset = info.new_sp_offset;
04900
04901
04902 note_stores (PATTERN (insn), update_epilogue_consts, &info);
04903 insn = next;
04904 }
04905
04906 insns = get_insns ();
04907 end_sequence ();
04908 return insns;
04909 }
04910
04911
04912
04913
04914
04915
04916 static void
04917 handle_epilogue_set (rtx set, struct epi_info *p)
04918 {
04919
04920
04921 if (reg_set_p (stack_pointer_rtx, set))
04922 {
04923 gcc_assert (SET_DEST (set) == stack_pointer_rtx);
04924
04925 if (GET_CODE (SET_SRC (set)) == PLUS)
04926 {
04927 p->new_sp_equiv_reg = XEXP (SET_SRC (set), 0);
04928 if (GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT)
04929 p->new_sp_offset = INTVAL (XEXP (SET_SRC (set), 1));
04930 else
04931 {
04932 gcc_assert (REG_P (XEXP (SET_SRC (set), 1))
04933 && (REGNO (XEXP (SET_SRC (set), 1))
04934 < FIRST_PSEUDO_REGISTER)
04935 && p->const_equiv[REGNO (XEXP (SET_SRC (set), 1))]);
04936 p->new_sp_offset
04937 = INTVAL (p->const_equiv[REGNO (XEXP (SET_SRC (set), 1))]);
04938 }
04939 }
04940 else
04941 p->new_sp_equiv_reg = SET_SRC (set), p->new_sp_offset = 0;
04942
04943
04944 if (p->new_sp_equiv_reg == stack_pointer_rtx)
04945 {
04946 p->new_sp_equiv_reg = p->sp_equiv_reg;
04947 p->new_sp_offset += p->sp_offset;
04948 }
04949
04950 gcc_assert (p->new_sp_equiv_reg && REG_P (p->new_sp_equiv_reg));
04951
04952 return;
04953 }
04954
04955
04956
04957
04958
04959
04960
04961
04962
04963 else if (p->new_sp_equiv_reg != 0 && reg_set_p (p->new_sp_equiv_reg, set))
04964 {
04965 gcc_assert (!p->equiv_reg_src
04966 && REG_P (p->new_sp_equiv_reg)
04967 && REG_P (SET_DEST (set))
04968 && (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set)))
04969 <= BITS_PER_WORD)
04970 && REGNO (p->new_sp_equiv_reg) == REGNO (SET_DEST (set)));
04971 p->equiv_reg_src
04972 = simplify_replace_rtx (SET_SRC (set), stack_pointer_rtx,
04973 plus_constant (p->sp_equiv_reg,
04974 p->sp_offset));
04975 }
04976
04977
04978
04979 else
04980 {
04981 SET_SRC (set) = simplify_replace_rtx (SET_SRC (set), stack_pointer_rtx,
04982 plus_constant (p->sp_equiv_reg,
04983 p->sp_offset));
04984 SET_DEST (set) = simplify_replace_rtx (SET_DEST (set), stack_pointer_rtx,
04985 plus_constant (p->sp_equiv_reg,
04986 p->sp_offset));
04987 emit_insn (set);
04988 }
04989 }
04990
04991
04992
04993 static void
04994 update_epilogue_consts (rtx dest, rtx x, void *data)
04995 {
04996 struct epi_info *p = (struct epi_info *) data;
04997 rtx new;
04998
04999 if (!REG_P (dest) || REGNO (dest) >= FIRST_PSEUDO_REGISTER)
05000 return;
05001
05002
05003
05004 else if (GET_CODE (x) == CLOBBER || ! rtx_equal_p (dest, SET_DEST (x)))
05005 p->const_equiv[REGNO (dest)] = 0;
05006
05007
05008 else if (GET_CODE (SET_SRC (x)) == CONST_INT)
05009 p->const_equiv[REGNO (dest)] = SET_SRC (x);
05010
05011
05012
05013 else if (ARITHMETIC_P (SET_SRC (x))
05014 && REG_P (XEXP (SET_SRC (x), 0))
05015 && REGNO (XEXP (SET_SRC (x), 0)) < FIRST_PSEUDO_REGISTER
05016 && p->const_equiv[REGNO (XEXP (SET_SRC (x), 0))] != 0
05017 && GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT
05018 && 0 != (new = simplify_binary_operation
05019 (GET_CODE (SET_SRC (x)), GET_MODE (dest),
05020 p->const_equiv[REGNO (XEXP (SET_SRC (x), 0))],
05021 XEXP (SET_SRC (x), 1)))
05022 && GET_CODE (new) == CONST_INT)
05023 p->const_equiv[REGNO (dest)] = new;
05024
05025
05026 else
05027 p->const_equiv[REGNO (dest)] = 0;
05028 }
05029
05030
05031
05032 static void
05033 emit_equiv_load (struct epi_info *p)
05034 {
05035 if (p->equiv_reg_src != 0)
05036 {
05037 rtx dest = p->sp_equiv_reg;
05038
05039 if (GET_MODE (p->equiv_reg_src) != GET_MODE (dest))
05040 dest = gen_rtx_REG (GET_MODE (p->equiv_reg_src),
05041 REGNO (p->sp_equiv_reg));
05042
05043 emit_move_insn (dest, p->equiv_reg_src);
05044 p->equiv_reg_src = 0;
05045 }
05046 }
05047 #endif
05048
05049
05050
05051
05052
05053 void
05054 thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
05055 {
05056 int inserted = 0;
05057 edge e;
05058 #if defined (HAVE_sibcall_epilogue) || defined (HAVE_epilogue) || defined (HAVE_return) || defined (HAVE_prologue)
05059 rtx seq;
05060 #endif
05061 #ifdef HAVE_prologue
05062 rtx prologue_end = NULL_RTX;
05063 #endif
05064 #if defined (HAVE_epilogue) || defined(HAVE_return)
05065 rtx epilogue_end = NULL_RTX;
05066 #endif
05067 edge_iterator ei;
05068
05069 #ifdef HAVE_prologue
05070 if (HAVE_prologue)
05071 {
05072 start_sequence ();
05073 seq = gen_prologue ();
05074 emit_insn (seq);
05075
05076
05077 record_insns (seq, &prologue);
05078 prologue_end = emit_note (NOTE_INSN_PROLOGUE_END);
05079
05080 seq = get_insns ();
05081 end_sequence ();
05082 set_insn_locators (seq, prologue_locator);
05083
05084
05085
05086
05087 gcc_assert (single_succ_p (ENTRY_BLOCK_PTR));
05088
05089 insert_insn_on_edge (seq, single_succ_edge (ENTRY_BLOCK_PTR));
05090 inserted = 1;
05091 }
05092 #endif
05093
05094
05095
05096 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
05097 if ((e->flags & EDGE_FAKE) == 0)
05098 break;
05099 if (e == NULL)
05100 goto epilogue_done;
05101
05102 #ifdef HAVE_return
05103 if (optimize && HAVE_return)
05104 {
05105
05106
05107
05108
05109
05110
05111 basic_block last;
05112 rtx label;
05113
05114 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
05115 if (e->flags & EDGE_FALLTHRU)
05116 break;
05117 if (e == NULL)
05118 goto epilogue_done;
05119 last = e->src;
05120
05121
05122 label = BB_END (last);
05123 while (label && !LABEL_P (label))
05124 {
05125 if (active_insn_p (label))
05126 break;
05127 label = PREV_INSN (label);
05128 }
05129
05130 if (BB_HEAD (last) == label && LABEL_P (label))
05131 {
05132 edge_iterator ei2;
05133 rtx epilogue_line_note = NULL_RTX;
05134
05135
05136
05137 for (seq = get_last_insn ();
05138 seq && ! active_insn_p (seq);
05139 seq = PREV_INSN (seq))
05140 if (NOTE_P (seq) && NOTE_LINE_NUMBER (seq) > 0)
05141 {
05142 epilogue_line_note = seq;
05143 break;
05144 }
05145
05146 for (ei2 = ei_start (last->preds); (e = ei_safe_edge (ei2)); )
05147 {
05148 basic_block bb = e->src;
05149 rtx jump;
05150
05151 if (bb == ENTRY_BLOCK_PTR)
05152 {
05153 ei_next (&ei2);
05154 continue;
05155 }
05156
05157 jump = BB_END (bb);
05158 if (!JUMP_P (jump) || JUMP_LABEL (jump) != label)
05159 {
05160 ei_next (&ei2);
05161 continue;
05162 }
05163
05164
05165
05166 if (simplejump_p (jump))
05167 {
05168 emit_return_into_block (bb, epilogue_line_note);
05169 delete_insn (jump);
05170 }
05171
05172
05173
05174 else if (condjump_p (jump))
05175 {
05176 if (! redirect_jump (jump, 0, 0))
05177 {
05178 ei_next (&ei2);
05179 continue;
05180 }
05181
05182
05183
05184
05185 if (single_succ_p (bb))
05186 {
05187 ei_next (&ei2);
05188 continue;
05189 }
05190 }
05191 else
05192 {
05193 ei_next (&ei2);
05194 continue;
05195 }
05196
05197
05198 redirect_edge_succ (e, EXIT_BLOCK_PTR);
05199 }
05200
05201
05202
05203
05204 emit_barrier_after (BB_END (last));
05205 emit_return_into_block (last, epilogue_line_note);
05206 epilogue_end = BB_END (last);
05207 single_succ_edge (last)->flags &= ~EDGE_FALLTHRU;
05208 goto epilogue_done;
05209 }
05210 }
05211 #endif
05212
05213
05214
05215
05216
05217 FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
05218 if (e->flags & EDGE_FALLTHRU)
05219 break;
05220 if (e == NULL)
05221 goto epilogue_done;
05222
05223 #ifdef HAVE_epilogue
05224 if (HAVE_epilogue)
05225 {
05226 start_sequence ();
05227 epilogue_end = emit_note (NOTE_INSN_EPILOGUE_BEG);
05228
05229 seq = gen_epilogue ();
05230
05231 #ifdef INCOMING_RETURN_ADDR_RTX
05232
05233
05234 if (TREE_CODE (TREE_TYPE (current_function_decl)) == FUNCTION_TYPE
05235 && TYPE_RETURNS_STACK_DEPRESSED (TREE_TYPE (current_function_decl)))
05236 seq = keep_stack_depressed (seq);
05237 #endif
05238
05239 emit_jump_insn (seq);
05240
05241
05242 record_insns (seq, &epilogue);
05243 set_insn_locators (seq, epilogue_locator);
05244
05245 seq = get_insns ();
05246 end_sequence ();
05247
05248 insert_insn_on_edge (seq, e);
05249 inserted = 1;
05250 }
05251 else
05252 #endif
05253 {
05254 basic_block cur_bb;
05255
05256 if (! next_active_insn (BB_END (e->src)))
05257 goto epilogue_done;
05258
05259
05260
05261
05262
05263
05264
05265 cfg_layout_initialize (0);
05266 FOR_EACH_BB (cur_bb)
05267 if (cur_bb->index >= NUM_FIXED_BLOCKS
05268 && cur_bb->next_bb->index >= NUM_FIXED_BLOCKS)
05269 cur_bb->aux = cur_bb->next_bb;
05270 cfg_layout_finalize ();
05271 }
05272 epilogue_done:
05273
05274 if (inserted)
05275 commit_edge_insertions ();
05276
05277 #ifdef HAVE_sibcall_epilogue
05278
05279 for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); )
05280 {
05281 basic_block bb = e->src;
05282 rtx insn = BB_END (bb);
05283
05284 if (!CALL_P (insn)
05285 || ! SIBLING_CALL_P (insn))
05286 {
05287 ei_next (&ei);
05288 continue;
05289 }
05290
05291 start_sequence ();
05292 emit_insn (gen_sibcall_epilogue ());
05293 seq = get_insns ();
05294 end_sequence ();
05295
05296
05297
05298
05299 record_insns (seq, &sibcall_epilogue);
05300 set_insn_locators (seq, epilogue_locator);
05301
05302 emit_insn_before (seq, insn);
05303 ei_next (&ei);
05304 }
05305 #endif
05306
05307 #ifdef HAVE_prologue
05308
05309 if (prologue_end)
05310 {
05311 rtx insn, prev;
05312
05313
05314
05315
05316
05317
05318
05319
05320
05321
05322
05323
05324
05325
05326 for (insn = prologue_end; insn; insn = prev)
05327 {
05328 prev = PREV_INSN (insn);
05329 if (NOTE_P (insn) && NOTE_LINE_NUMBER (insn) > 0)
05330 {
05331
05332
05333
05334 if (prev == NULL)
05335 break;
05336 reorder_insns (insn, insn, prologue_end);
05337 }
05338 }
05339
05340
05341 for (insn = BB_END (ENTRY_BLOCK_PTR->next_bb);
05342 insn != prologue_end && insn;
05343 insn = PREV_INSN (insn))
05344 if (NOTE_P (insn) && NOTE_LINE_NUMBER (insn) > 0)
05345 break;
05346
05347
05348
05349 if (! insn)
05350 {
05351 for (insn = next_active_insn (prologue_end);
05352 insn;
05353 insn = PREV_INSN (insn))
05354 if (NOTE_P (insn) && NOTE_LINE_NUMBER (insn) > 0)
05355 {
05356 emit_note_copy_after (insn, prologue_end);
05357 break;
05358 }
05359 }
05360 }
05361 #endif
05362 #ifdef HAVE_epilogue
05363 if (epilogue_end)
05364 {
05365 rtx insn, next;
05366
05367
05368
05369
05370
05371
05372 for (insn = epilogue_end; insn; insn = next)
05373 {
05374 next = NEXT_INSN (insn);
05375 if (NOTE_P (insn)
05376 && (NOTE_LINE_NUMBER (insn) > 0
05377 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG
05378 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END))
05379 reorder_insns (insn, insn, PREV_INSN (epilogue_end));
05380 }
05381 }
05382 #endif
05383 }
05384
05385
05386
05387
05388 void
05389 reposition_prologue_and_epilogue_notes (rtx f ATTRIBUTE_UNUSED)
05390 {
05391 #if defined (HAVE_prologue) || defined (HAVE_epilogue)
05392 rtx insn, last, note;
05393 int len;
05394
05395 if ((len = VEC_length (int, prologue)) > 0)
05396 {
05397 last = 0, note = 0;
05398
05399
05400
05401
05402 for (insn = f; insn; insn = NEXT_INSN (insn))
05403 {
05404 if (NOTE_P (insn))
05405 {
05406 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
05407 note = insn;
05408 }
05409 else if (contains (insn, &prologue))
05410 {
05411 last = insn;
05412 if (--len == 0)
05413 break;
05414 }
05415 }
05416
05417 if (last)
05418 {
05419
05420
05421 if (note == 0)
05422 {
05423 for (note = last; (note = NEXT_INSN (note));)
05424 if (NOTE_P (note)
05425 && NOTE_LINE_NUMBER (note) == NOTE_INSN_PROLOGUE_END)
05426 break;
05427 }
05428
05429
05430 if (LABEL_P (last))
05431 last = NEXT_INSN (last);
05432 reorder_insns (note, note, last);
05433 }
05434 }
05435
05436 if ((len = VEC_length (int, epilogue)) > 0)
05437 {
05438 last = 0, note = 0;
05439
05440
05441
05442
05443 for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
05444 {
05445 if (NOTE_P (insn))
05446 {
05447 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
05448 note = insn;
05449 }
05450 else if (contains (insn, &epilogue))
05451 {
05452 last = insn;
05453 if (--len == 0)
05454 break;
05455 }
05456 }
05457
05458 if (last)
05459 {
05460
05461
05462 if (note == 0)
05463 {
05464 for (note = insn; (note = PREV_INSN (note));)
05465 if (NOTE_P (note)
05466 && NOTE_LINE_NUMBER (note) == NOTE_INSN_EPILOGUE_BEG)
05467 break;
05468 }
05469
05470 if (PREV_INSN (last) != note)
05471 reorder_insns (note, note, PREV_INSN (last));
05472 }
05473 }
05474 #endif
05475 }
05476
05477
05478
05479 void
05480 reset_block_changes (void)
05481 {
05482 cfun->ib_boundaries_block = VEC_alloc (tree, gc, 100);
05483 VEC_quick_push (tree, cfun->ib_boundaries_block, NULL_TREE);
05484 }
05485
05486
05487 void
05488 record_block_change (tree block)
05489 {
05490 int i, n;
05491 tree last_block;
05492
05493 if (!block)
05494 return;
05495
05496 if(!cfun->ib_boundaries_block)
05497 return;
05498
05499 last_block = VEC_pop (tree, cfun->ib_boundaries_block);
05500 n = get_max_uid ();
05501 for (i = VEC_length (tree, cfun->ib_boundaries_block); i < n; i++)
05502 VEC_safe_push (tree, gc, cfun->ib_boundaries_block, last_block);
05503
05504 VEC_safe_push (tree, gc, cfun->ib_boundaries_block, block);
05505 }
05506
05507
05508 void
05509 finalize_block_changes (void)
05510 {
05511 record_block_change (DECL_INITIAL (current_function_decl));
05512 }
05513
05514
05515 void
05516 check_block_change (rtx insn, tree *block)
05517 {
05518 unsigned uid = INSN_UID (insn);
05519
05520 if (uid >= VEC_length (tree, cfun->ib_boundaries_block))
05521 return;
05522
05523 *block = VEC_index (tree, cfun->ib_boundaries_block, uid);
05524 }
05525
05526
05527 void
05528 free_block_changes (void)
05529 {
05530 VEC_free (tree, gc, cfun->ib_boundaries_block);
05531 }
05532
05533
05534 const char *
05535 current_function_name (void)
05536 {
05537 return lang_hooks.decl_printable_name (cfun->decl, 2);
05538 }
05539
05540
05541 static unsigned int
05542 rest_of_handle_check_leaf_regs (void)
05543 {
05544 #ifdef LEAF_REGISTERS
05545 current_function_uses_only_leaf_regs
05546 = optimize > 0 && only_leaf_regs_used () && leaf_function_p ();
05547 #endif
05548 return 0;
05549 }
05550
05551
05552 static void
05553 used_types_insert_helper (tree type, struct function *func)
05554 {
05555 if (type != NULL && func != NULL)
05556 {
05557 void **slot;
05558
05559 if (func->used_types_hash == NULL)
05560 func->used_types_hash = htab_create_ggc (37, htab_hash_pointer,
05561 htab_eq_pointer, NULL);
05562 slot = htab_find_slot (func->used_types_hash, type, INSERT);
05563 if (*slot == NULL)
05564 *slot = type;
05565 }
05566 }
05567
05568
05569 void
05570 used_types_insert (tree t)
05571 {
05572 while (POINTER_TYPE_P (t) || TREE_CODE (t) == ARRAY_TYPE)
05573 t = TREE_TYPE (t);
05574 t = TYPE_MAIN_VARIANT (t);
05575 if (debug_info_level > DINFO_LEVEL_NONE)
05576 used_types_insert_helper (t, cfun);
05577 }
05578
05579 struct tree_opt_pass pass_leaf_regs =
05580 {
05581 NULL,
05582 NULL,
05583 rest_of_handle_check_leaf_regs,
05584 NULL,
05585 NULL,
05586 0,
05587 0,
05588 0,
05589 0,
05590 0,
05591 0,
05592 0,
05593 0
05594 };
05595
05596
05597 #include "gt-function.h"