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