00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "coretypes.h"
00026 #include "tm.h"
00027 #include "rtl.h"
00028 #include "tree.h"
00029 #include "flags.h"
00030 #include "expr.h"
00031 #include "optabs.h"
00032 #include "libfuncs.h"
00033 #include "function.h"
00034 #include "regs.h"
00035 #include "toplev.h"
00036 #include "output.h"
00037 #include "tm_p.h"
00038 #include "timevar.h"
00039 #include "sbitmap.h"
00040 #include "langhooks.h"
00041 #include "target.h"
00042 #include "cgraph.h"
00043 #include "except.h"
00044
00045
00046 #define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
00047
00048
00049
00050 struct arg_data
00051 {
00052
00053 tree tree_value;
00054
00055 enum machine_mode mode;
00056
00057 rtx value;
00058
00059 rtx initial_value;
00060
00061
00062
00063 rtx reg;
00064
00065
00066
00067 rtx tail_call_reg;
00068
00069
00070 rtx parallel_value;
00071
00072
00073 int unsignedp;
00074
00075
00076 int partial;
00077
00078
00079
00080
00081 int pass_on_stack;
00082
00083 struct locate_and_pad_arg_data locate;
00084
00085
00086 rtx stack;
00087
00088
00089
00090 rtx stack_slot;
00091
00092 rtx save_area;
00093
00094
00095
00096
00097 rtx *aligned_regs;
00098 int n_aligned_regs;
00099 };
00100
00101
00102
00103
00104
00105 static char *stack_usage_map;
00106
00107
00108 static int highest_outgoing_arg_in_use;
00109
00110
00111
00112
00113
00114
00115 static sbitmap stored_args_map;
00116
00117
00118
00119
00120
00121
00122 int stack_arg_under_construction;
00123
00124 static void emit_call_1 (rtx, tree, tree, tree, HOST_WIDE_INT, HOST_WIDE_INT,
00125 HOST_WIDE_INT, rtx, rtx, int, rtx, int,
00126 CUMULATIVE_ARGS *);
00127 static void precompute_register_parameters (int, struct arg_data *, int *);
00128 static int store_one_arg (struct arg_data *, rtx, int, int, int);
00129 static void store_unaligned_arguments_into_pseudos (struct arg_data *, int);
00130 static int finalize_must_preallocate (int, int, struct arg_data *,
00131 struct args_size *);
00132 static void precompute_arguments (int, int, struct arg_data *);
00133 static int compute_argument_block_size (int, struct args_size *, int);
00134 static void initialize_argument_information (int, struct arg_data *,
00135 struct args_size *, int, tree,
00136 tree, CUMULATIVE_ARGS *, int,
00137 rtx *, int *, int *, int *,
00138 bool *, bool);
00139 static void compute_argument_addresses (struct arg_data *, rtx, int);
00140 static rtx rtx_for_function_call (tree, tree);
00141 static void load_register_parameters (struct arg_data *, int, rtx *, int,
00142 int, int *);
00143 static rtx emit_library_call_value_1 (int, rtx, rtx, enum libcall_type,
00144 enum machine_mode, int, va_list);
00145 static int special_function_p (tree, int);
00146 static int check_sibcall_argument_overlap_1 (rtx);
00147 static int check_sibcall_argument_overlap (rtx, struct arg_data *, int);
00148
00149 static int combine_pending_stack_adjustment_and_call (int, struct args_size *,
00150 unsigned int);
00151 static tree split_complex_values (tree);
00152 static tree split_complex_types (tree);
00153
00154 #ifdef REG_PARM_STACK_SPACE
00155 static rtx save_fixed_argument_area (int, rtx, int *, int *);
00156 static void restore_fixed_argument_area (rtx, rtx, int, int);
00157 #endif
00158
00159
00160
00161
00162
00163
00164
00165
00166 rtx
00167 prepare_call_address (rtx funexp, rtx static_chain_value,
00168 rtx *call_fusage, int reg_parm_seen, int sibcallp)
00169 {
00170
00171
00172 if (GET_CODE (funexp) != SYMBOL_REF)
00173
00174
00175 funexp = ((SMALL_REGISTER_CLASSES && reg_parm_seen)
00176 ? force_not_mem (memory_address (FUNCTION_MODE, funexp))
00177 : memory_address (FUNCTION_MODE, funexp));
00178 else if (! sibcallp)
00179 {
00180 #ifndef NO_FUNCTION_CSE
00181 if (optimize && ! flag_no_function_cse)
00182 funexp = force_reg (Pmode, funexp);
00183 #endif
00184 }
00185
00186 if (static_chain_value != 0)
00187 {
00188 static_chain_value = convert_memory_address (Pmode, static_chain_value);
00189 emit_move_insn (static_chain_rtx, static_chain_value);
00190
00191 if (REG_P (static_chain_rtx))
00192 use_reg (call_fusage, static_chain_rtx);
00193 }
00194
00195 return funexp;
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 static void
00239 emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED,
00240 tree funtype ATTRIBUTE_UNUSED,
00241 HOST_WIDE_INT stack_size ATTRIBUTE_UNUSED,
00242 HOST_WIDE_INT rounded_stack_size,
00243 HOST_WIDE_INT struct_value_size ATTRIBUTE_UNUSED,
00244 rtx next_arg_reg ATTRIBUTE_UNUSED, rtx valreg,
00245 int old_inhibit_defer_pop, rtx call_fusage, int ecf_flags,
00246 CUMULATIVE_ARGS *args_so_far ATTRIBUTE_UNUSED)
00247 {
00248 rtx rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
00249 rtx call_insn;
00250 int already_popped = 0;
00251 HOST_WIDE_INT n_popped = RETURN_POPS_ARGS (fndecl, funtype, stack_size);
00252 #if defined (HAVE_call) && defined (HAVE_call_value)
00253 rtx struct_value_size_rtx;
00254 struct_value_size_rtx = GEN_INT (struct_value_size);
00255 #endif
00256
00257 #ifdef CALL_POPS_ARGS
00258 n_popped += CALL_POPS_ARGS (* args_so_far);
00259 #endif
00260
00261
00262
00263
00264 if (GET_CODE (funexp) != SYMBOL_REF)
00265 funexp = memory_address (FUNCTION_MODE, funexp);
00266
00267 #if defined (HAVE_sibcall_pop) && defined (HAVE_sibcall_value_pop)
00268 if ((ecf_flags & ECF_SIBCALL)
00269 && HAVE_sibcall_pop && HAVE_sibcall_value_pop
00270 && (n_popped > 0 || stack_size == 0))
00271 {
00272 rtx n_pop = GEN_INT (n_popped);
00273 rtx pat;
00274
00275
00276
00277
00278 if (valreg)
00279 pat = GEN_SIBCALL_VALUE_POP (valreg,
00280 gen_rtx_MEM (FUNCTION_MODE, funexp),
00281 rounded_stack_size_rtx, next_arg_reg,
00282 n_pop);
00283 else
00284 pat = GEN_SIBCALL_POP (gen_rtx_MEM (FUNCTION_MODE, funexp),
00285 rounded_stack_size_rtx, next_arg_reg, n_pop);
00286
00287 emit_call_insn (pat);
00288 already_popped = 1;
00289 }
00290 else
00291 #endif
00292
00293 #if defined (HAVE_call_pop) && defined (HAVE_call_value_pop)
00294
00295
00296
00297
00298 #if defined (HAVE_call) && defined (HAVE_call_value)
00299 if (HAVE_call && HAVE_call_value && HAVE_call_pop && HAVE_call_value_pop
00300 && n_popped > 0 && ! (ecf_flags & ECF_SP_DEPRESSED))
00301 #else
00302 if (HAVE_call_pop && HAVE_call_value_pop)
00303 #endif
00304 {
00305 rtx n_pop = GEN_INT (n_popped);
00306 rtx pat;
00307
00308
00309
00310
00311 if (valreg)
00312 pat = GEN_CALL_VALUE_POP (valreg,
00313 gen_rtx_MEM (FUNCTION_MODE, funexp),
00314 rounded_stack_size_rtx, next_arg_reg, n_pop);
00315 else
00316 pat = GEN_CALL_POP (gen_rtx_MEM (FUNCTION_MODE, funexp),
00317 rounded_stack_size_rtx, next_arg_reg, n_pop);
00318
00319 emit_call_insn (pat);
00320 already_popped = 1;
00321 }
00322 else
00323 #endif
00324
00325 #if defined (HAVE_sibcall) && defined (HAVE_sibcall_value)
00326 if ((ecf_flags & ECF_SIBCALL)
00327 && HAVE_sibcall && HAVE_sibcall_value)
00328 {
00329 if (valreg)
00330 emit_call_insn (GEN_SIBCALL_VALUE (valreg,
00331 gen_rtx_MEM (FUNCTION_MODE, funexp),
00332 rounded_stack_size_rtx,
00333 next_arg_reg, NULL_RTX));
00334 else
00335 emit_call_insn (GEN_SIBCALL (gen_rtx_MEM (FUNCTION_MODE, funexp),
00336 rounded_stack_size_rtx, next_arg_reg,
00337 struct_value_size_rtx));
00338 }
00339 else
00340 #endif
00341
00342 #if defined (HAVE_call) && defined (HAVE_call_value)
00343 if (HAVE_call && HAVE_call_value)
00344 {
00345 if (valreg)
00346 emit_call_insn (GEN_CALL_VALUE (valreg,
00347 gen_rtx_MEM (FUNCTION_MODE, funexp),
00348 rounded_stack_size_rtx, next_arg_reg,
00349 NULL_RTX));
00350 else
00351 emit_call_insn (GEN_CALL (gen_rtx_MEM (FUNCTION_MODE, funexp),
00352 rounded_stack_size_rtx, next_arg_reg,
00353 struct_value_size_rtx));
00354 }
00355 else
00356 #endif
00357 gcc_unreachable ();
00358
00359
00360 call_insn = last_call_insn ();
00361
00362
00363 if (ecf_flags & ECF_PURE)
00364 call_fusage
00365 = gen_rtx_EXPR_LIST
00366 (VOIDmode,
00367 gen_rtx_USE (VOIDmode,
00368 gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode))),
00369 call_fusage);
00370
00371
00372 add_function_usage_to (call_insn, call_fusage);
00373
00374
00375 if (ecf_flags & (ECF_CONST | ECF_PURE))
00376 CONST_OR_PURE_CALL_P (call_insn) = 1;
00377
00378
00379
00380 if (ecf_flags & ECF_NOTHROW)
00381 REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, const0_rtx,
00382 REG_NOTES (call_insn));
00383 else
00384 {
00385 int rn = lookup_stmt_eh_region (fntree);
00386
00387
00388
00389 if (rn > 0)
00390 REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, GEN_INT (rn),
00391 REG_NOTES (call_insn));
00392 note_current_region_may_contain_throw ();
00393 }
00394
00395 if (ecf_flags & ECF_NORETURN)
00396 REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_NORETURN, const0_rtx,
00397 REG_NOTES (call_insn));
00398 if (ecf_flags & ECF_ALWAYS_RETURN)
00399 REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_ALWAYS_RETURN, const0_rtx,
00400 REG_NOTES (call_insn));
00401
00402 if (ecf_flags & ECF_RETURNS_TWICE)
00403 {
00404 REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_SETJMP, const0_rtx,
00405 REG_NOTES (call_insn));
00406 current_function_calls_setjmp = 1;
00407 }
00408
00409 SIBLING_CALL_P (call_insn) = ((ecf_flags & ECF_SIBCALL) != 0);
00410
00411
00412
00413 inhibit_defer_pop = old_inhibit_defer_pop;
00414
00415 if (n_popped > 0)
00416 {
00417 if (!already_popped)
00418 CALL_INSN_FUNCTION_USAGE (call_insn)
00419 = gen_rtx_EXPR_LIST (VOIDmode,
00420 gen_rtx_CLOBBER (VOIDmode, stack_pointer_rtx),
00421 CALL_INSN_FUNCTION_USAGE (call_insn));
00422 rounded_stack_size -= n_popped;
00423 rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
00424 stack_pointer_delta -= n_popped;
00425 }
00426
00427 if (!ACCUMULATE_OUTGOING_ARGS)
00428 {
00429
00430
00431
00432
00433
00434
00435
00436 if (rounded_stack_size != 0)
00437 {
00438 if (ecf_flags & (ECF_SP_DEPRESSED | ECF_NORETURN))
00439
00440 stack_pointer_delta -= rounded_stack_size;
00441 else if (flag_defer_pop && inhibit_defer_pop == 0
00442 && ! (ecf_flags & (ECF_CONST | ECF_PURE)))
00443 pending_stack_adjust += rounded_stack_size;
00444 else
00445 adjust_stack (rounded_stack_size_rtx);
00446 }
00447 }
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459 else if (n_popped)
00460 anti_adjust_stack (GEN_INT (n_popped));
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 static int
00475 special_function_p (tree fndecl, int flags)
00476 {
00477 if (fndecl && DECL_NAME (fndecl)
00478 && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) <= 17
00479
00480
00481
00482
00483
00484
00485
00486 && (DECL_CONTEXT (fndecl) == NULL_TREE
00487 || TREE_CODE (DECL_CONTEXT (fndecl)) == TRANSLATION_UNIT_DECL)
00488 && TREE_PUBLIC (fndecl))
00489 {
00490 const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
00491 const char *tname = name;
00492
00493
00494
00495
00496 if (((IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 6
00497 && name[0] == 'a'
00498 && ! strcmp (name, "alloca"))
00499 || (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 16
00500 && name[0] == '_'
00501 && ! strcmp (name, "__builtin_alloca"))))
00502 flags |= ECF_MAY_BE_ALLOCA;
00503
00504
00505 if (name[0] == '_')
00506 {
00507 if (name[1] == '_' && name[2] == 'x')
00508 tname += 3;
00509 else if (name[1] == '_')
00510 tname += 2;
00511 else
00512 tname += 1;
00513 }
00514
00515 if (tname[0] == 's')
00516 {
00517 if ((tname[1] == 'e'
00518 && (! strcmp (tname, "setjmp")
00519 || ! strcmp (tname, "setjmp_syscall")))
00520 || (tname[1] == 'i'
00521 && ! strcmp (tname, "sigsetjmp"))
00522 || (tname[1] == 'a'
00523 && ! strcmp (tname, "savectx")))
00524 flags |= ECF_RETURNS_TWICE;
00525
00526 if (tname[1] == 'i'
00527 && ! strcmp (tname, "siglongjmp"))
00528 flags |= ECF_NORETURN;
00529 }
00530 else if ((tname[0] == 'q' && tname[1] == 's'
00531 && ! strcmp (tname, "qsetjmp"))
00532 || (tname[0] == 'v' && tname[1] == 'f'
00533 && ! strcmp (tname, "vfork")))
00534 flags |= ECF_RETURNS_TWICE;
00535
00536 else if (tname[0] == 'l' && tname[1] == 'o'
00537 && ! strcmp (tname, "longjmp"))
00538 flags |= ECF_NORETURN;
00539 }
00540
00541 return flags;
00542 }
00543
00544
00545
00546 int
00547 setjmp_call_p (tree fndecl)
00548 {
00549 return special_function_p (fndecl, 0) & ECF_RETURNS_TWICE;
00550 }
00551
00552
00553 bool
00554 alloca_call_p (tree exp)
00555 {
00556 if (TREE_CODE (exp) == CALL_EXPR
00557 && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
00558 && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
00559 == FUNCTION_DECL)
00560 && (special_function_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
00561 0) & ECF_MAY_BE_ALLOCA))
00562 return true;
00563 return false;
00564 }
00565
00566
00567
00568 int
00569 flags_from_decl_or_type (tree exp)
00570 {
00571 int flags = 0;
00572 tree type = exp;
00573
00574 if (DECL_P (exp))
00575 {
00576 struct cgraph_rtl_info *i = cgraph_rtl_info (exp);
00577 type = TREE_TYPE (exp);
00578
00579 if (i)
00580 {
00581 if (i->pure_function)
00582 flags |= ECF_PURE | ECF_LIBCALL_BLOCK;
00583 if (i->const_function)
00584 flags |= ECF_CONST | ECF_LIBCALL_BLOCK;
00585 }
00586
00587
00588 if (DECL_IS_MALLOC (exp))
00589 flags |= ECF_MALLOC;
00590
00591
00592 if (DECL_IS_PURE (exp))
00593 flags |= ECF_PURE | ECF_LIBCALL_BLOCK;
00594
00595 if (TREE_NOTHROW (exp))
00596 flags |= ECF_NOTHROW;
00597
00598 if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
00599 flags |= ECF_LIBCALL_BLOCK | ECF_CONST;
00600
00601 flags = special_function_p (exp, flags);
00602 }
00603 else if (TYPE_P (exp) && TYPE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
00604 flags |= ECF_CONST;
00605
00606 if (TREE_THIS_VOLATILE (exp))
00607 flags |= ECF_NORETURN;
00608
00609
00610
00611 if (TREE_CODE (type) == FUNCTION_TYPE && TYPE_RETURNS_STACK_DEPRESSED (type))
00612 {
00613 flags |= ECF_SP_DEPRESSED;
00614 flags &= ~(ECF_PURE | ECF_CONST | ECF_LIBCALL_BLOCK);
00615 }
00616
00617 return flags;
00618 }
00619
00620
00621
00622 int
00623 call_expr_flags (tree t)
00624 {
00625 int flags;
00626 tree decl = get_callee_fndecl (t);
00627
00628 if (decl)
00629 flags = flags_from_decl_or_type (decl);
00630 else
00631 {
00632 t = TREE_TYPE (TREE_OPERAND (t, 0));
00633 if (t && TREE_CODE (t) == POINTER_TYPE)
00634 flags = flags_from_decl_or_type (TREE_TYPE (t));
00635 else
00636 flags = 0;
00637 }
00638
00639 return flags;
00640 }
00641
00642
00643
00644
00645
00646
00647
00648
00649 static void
00650 precompute_register_parameters (int num_actuals, struct arg_data *args,
00651 int *reg_parm_seen)
00652 {
00653 int i;
00654
00655 *reg_parm_seen = 0;
00656
00657 for (i = 0; i < num_actuals; i++)
00658 if (args[i].reg != 0 && ! args[i].pass_on_stack)
00659 {
00660 *reg_parm_seen = 1;
00661
00662 if (args[i].value == 0)
00663 {
00664 push_temp_slots ();
00665 args[i].value = expand_expr (args[i].tree_value, NULL_RTX,
00666 VOIDmode, 0);
00667 preserve_temp_slots (args[i].value);
00668 pop_temp_slots ();
00669 }
00670
00671
00672
00673 if (CONSTANT_P (args[i].value)
00674 && !LEGITIMATE_CONSTANT_P (args[i].value))
00675 args[i].value = force_reg (args[i].mode, args[i].value);
00676
00677
00678
00679
00680 if (args[i].mode != TYPE_MODE (TREE_TYPE (args[i].tree_value)))
00681 args[i].value
00682 = convert_modes (args[i].mode,
00683 TYPE_MODE (TREE_TYPE (args[i].tree_value)),
00684 args[i].value, args[i].unsignedp);
00685
00686
00687
00688
00689 if (GET_CODE (args[i].reg) == PARALLEL)
00690 {
00691 tree type = TREE_TYPE (args[i].tree_value);
00692 args[i].parallel_value
00693 = emit_group_load_into_temps (args[i].reg, args[i].value,
00694 type, int_size_in_bytes (type));
00695 }
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 else if ((! (REG_P (args[i].value)
00706 || (GET_CODE (args[i].value) == SUBREG
00707 && REG_P (SUBREG_REG (args[i].value)))))
00708 && args[i].mode != BLKmode
00709 && rtx_cost (args[i].value, SET) > COSTS_N_INSNS (1)
00710 && ((SMALL_REGISTER_CLASSES && *reg_parm_seen)
00711 || optimize))
00712 args[i].value = copy_to_mode_reg (args[i].mode, args[i].value);
00713 }
00714 }
00715
00716 #ifdef REG_PARM_STACK_SPACE
00717
00718
00719
00720
00721
00722 static rtx
00723 save_fixed_argument_area (int reg_parm_stack_space, rtx argblock, int *low_to_save, int *high_to_save)
00724 {
00725 int low;
00726 int high;
00727
00728
00729 high = reg_parm_stack_space;
00730 #ifdef ARGS_GROW_DOWNWARD
00731 high += 1;
00732 #endif
00733 if (high > highest_outgoing_arg_in_use)
00734 high = highest_outgoing_arg_in_use;
00735
00736 for (low = 0; low < high; low++)
00737 if (stack_usage_map[low] != 0)
00738 {
00739 int num_to_save;
00740 enum machine_mode save_mode;
00741 int delta;
00742 rtx stack_area;
00743 rtx save_area;
00744
00745 while (stack_usage_map[--high] == 0)
00746 ;
00747
00748 *low_to_save = low;
00749 *high_to_save = high;
00750
00751 num_to_save = high - low + 1;
00752 save_mode = mode_for_size (num_to_save * BITS_PER_UNIT, MODE_INT, 1);
00753
00754
00755
00756 if ((low & (MIN (GET_MODE_SIZE (save_mode),
00757 BIGGEST_ALIGNMENT / UNITS_PER_WORD) - 1)))
00758 save_mode = BLKmode;
00759
00760 #ifdef ARGS_GROW_DOWNWARD
00761 delta = -high;
00762 #else
00763 delta = low;
00764 #endif
00765 stack_area = gen_rtx_MEM (save_mode,
00766 memory_address (save_mode,
00767 plus_constant (argblock,
00768 delta)));
00769
00770 set_mem_align (stack_area, PARM_BOUNDARY);
00771 if (save_mode == BLKmode)
00772 {
00773 save_area = assign_stack_temp (BLKmode, num_to_save, 0);
00774 emit_block_move (validize_mem (save_area), stack_area,
00775 GEN_INT (num_to_save), BLOCK_OP_CALL_PARM);
00776 }
00777 else
00778 {
00779 save_area = gen_reg_rtx (save_mode);
00780 emit_move_insn (save_area, stack_area);
00781 }
00782
00783 return save_area;
00784 }
00785
00786 return NULL_RTX;
00787 }
00788
00789 static void
00790 restore_fixed_argument_area (rtx save_area, rtx argblock, int high_to_save, int low_to_save)
00791 {
00792 enum machine_mode save_mode = GET_MODE (save_area);
00793 int delta;
00794 rtx stack_area;
00795
00796 #ifdef ARGS_GROW_DOWNWARD
00797 delta = -high_to_save;
00798 #else
00799 delta = low_to_save;
00800 #endif
00801 stack_area = gen_rtx_MEM (save_mode,
00802 memory_address (save_mode,
00803 plus_constant (argblock, delta)));
00804 set_mem_align (stack_area, PARM_BOUNDARY);
00805
00806 if (save_mode != BLKmode)
00807 emit_move_insn (stack_area, save_area);
00808 else
00809 emit_block_move (stack_area, validize_mem (save_area),
00810 GEN_INT (high_to_save - low_to_save + 1),
00811 BLOCK_OP_CALL_PARM);
00812 }
00813 #endif
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824 static void
00825 store_unaligned_arguments_into_pseudos (struct arg_data *args, int num_actuals)
00826 {
00827 int i, j;
00828
00829 for (i = 0; i < num_actuals; i++)
00830 if (args[i].reg != 0 && ! args[i].pass_on_stack
00831 && args[i].mode == BLKmode
00832 && (TYPE_ALIGN (TREE_TYPE (args[i].tree_value))
00833 < (unsigned int) MIN (BIGGEST_ALIGNMENT, BITS_PER_WORD)))
00834 {
00835 int bytes = int_size_in_bytes (TREE_TYPE (args[i].tree_value));
00836 int endian_correction = 0;
00837
00838 if (args[i].partial)
00839 {
00840 gcc_assert (args[i].partial % UNITS_PER_WORD == 0);
00841 args[i].n_aligned_regs = args[i].partial / UNITS_PER_WORD;
00842 }
00843 else
00844 {
00845 args[i].n_aligned_regs
00846 = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
00847 }
00848
00849 args[i].aligned_regs = xmalloc (sizeof (rtx) * args[i].n_aligned_regs);
00850
00851
00852
00853
00854
00855 if (bytes < UNITS_PER_WORD
00856 #ifdef BLOCK_REG_PADDING
00857 && (BLOCK_REG_PADDING (args[i].mode,
00858 TREE_TYPE (args[i].tree_value), 1)
00859 == downward)
00860 #else
00861 && BYTES_BIG_ENDIAN
00862 #endif
00863 )
00864 endian_correction = BITS_PER_WORD - bytes * BITS_PER_UNIT;
00865
00866 for (j = 0; j < args[i].n_aligned_regs; j++)
00867 {
00868 rtx reg = gen_reg_rtx (word_mode);
00869 rtx word = operand_subword_force (args[i].value, j, BLKmode);
00870 int bitsize = MIN (bytes * BITS_PER_UNIT, BITS_PER_WORD);
00871
00872 args[i].aligned_regs[j] = reg;
00873 word = extract_bit_field (word, bitsize, 0, 1, NULL_RTX,
00874 word_mode, word_mode);
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887 emit_move_insn (reg, const0_rtx);
00888
00889 bytes -= bitsize / BITS_PER_UNIT;
00890 store_bit_field (reg, bitsize, endian_correction, word_mode,
00891 word);
00892 }
00893 }
00894 }
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923 static void
00924 initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
00925 struct arg_data *args,
00926 struct args_size *args_size,
00927 int n_named_args ATTRIBUTE_UNUSED,
00928 tree actparms, tree fndecl,
00929 CUMULATIVE_ARGS *args_so_far,
00930 int reg_parm_stack_space,
00931 rtx *old_stack_level, int *old_pending_adj,
00932 int *must_preallocate, int *ecf_flags,
00933 bool *may_tailcall, bool call_from_thunk_p)
00934 {
00935
00936 int inc;
00937
00938
00939 int argpos;
00940
00941 int i;
00942 tree p;
00943
00944 args_size->constant = 0;
00945 args_size->var = 0;
00946
00947
00948
00949
00950
00951 if (PUSH_ARGS_REVERSED)
00952 {
00953 i = num_actuals - 1, inc = -1;
00954
00955
00956 }
00957 else
00958 {
00959 i = 0, inc = 1;
00960 }
00961
00962
00963 for (p = actparms, argpos = 0; p; p = TREE_CHAIN (p), i += inc, argpos++)
00964 {
00965 tree type = TREE_TYPE (TREE_VALUE (p));
00966 int unsignedp;
00967 enum machine_mode mode;
00968
00969 args[i].tree_value = TREE_VALUE (p);
00970
00971
00972 if (type == error_mark_node || !COMPLETE_TYPE_P (type))
00973 args[i].tree_value = integer_zero_node, type = integer_type_node;
00974
00975
00976
00977
00978 if (TREE_CODE (type) == UNION_TYPE && TYPE_TRANSPARENT_UNION (type))
00979 type = TREE_TYPE (TYPE_FIELDS (type));
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996 if (pass_by_reference (args_so_far, TYPE_MODE (type),
00997 type, argpos < n_named_args))
00998 {
00999 bool callee_copies;
01000 tree base;
01001
01002 callee_copies
01003 = reference_callee_copied (args_so_far, TYPE_MODE (type),
01004 type, argpos < n_named_args);
01005
01006
01007
01008 if (call_from_thunk_p
01009 || (callee_copies
01010 && !TREE_ADDRESSABLE (type)
01011 && (base = get_base_address (args[i].tree_value))
01012 && (!DECL_P (base) || MEM_P (DECL_RTL (base)))))
01013 {
01014
01015
01016 if (!call_from_thunk_p && DECL_P (base) && !TREE_STATIC (base))
01017 *may_tailcall = false;
01018
01019 args[i].tree_value = build_fold_addr_expr (args[i].tree_value);
01020 type = TREE_TYPE (args[i].tree_value);
01021
01022 *ecf_flags &= ~(ECF_CONST | ECF_LIBCALL_BLOCK);
01023 }
01024 else
01025 {
01026
01027
01028 rtx copy;
01029
01030 if (!COMPLETE_TYPE_P (type)
01031 || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
01032 || (flag_stack_check && ! STACK_CHECK_BUILTIN
01033 && (0 < compare_tree_int (TYPE_SIZE_UNIT (type),
01034 STACK_CHECK_MAX_VAR_SIZE))))
01035 {
01036
01037
01038 rtx size_rtx = expr_size (TREE_VALUE (p));
01039
01040 if (*old_stack_level == 0)
01041 {
01042 emit_stack_save (SAVE_BLOCK, old_stack_level, NULL_RTX);
01043 *old_pending_adj = pending_stack_adjust;
01044 pending_stack_adjust = 0;
01045 }
01046
01047 copy = gen_rtx_MEM (BLKmode,
01048 allocate_dynamic_stack_space
01049 (size_rtx, NULL_RTX, TYPE_ALIGN (type)));
01050 set_mem_attributes (copy, type, 1);
01051 }
01052 else
01053 copy = assign_temp (type, 0, 1, 0);
01054
01055 store_expr (args[i].tree_value, copy, 0);
01056
01057 if (callee_copies)
01058 *ecf_flags &= ~(ECF_CONST | ECF_LIBCALL_BLOCK);
01059 else
01060 *ecf_flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
01061
01062 args[i].tree_value
01063 = build_fold_addr_expr (make_tree (type, copy));
01064 type = TREE_TYPE (args[i].tree_value);
01065 *may_tailcall = false;
01066 }
01067 }
01068
01069 mode = TYPE_MODE (type);
01070 unsignedp = TYPE_UNSIGNED (type);
01071
01072 if (targetm.calls.promote_function_args (fndecl ? TREE_TYPE (fndecl) : 0))
01073 mode = promote_mode (type, mode, &unsignedp, 1);
01074
01075 args[i].unsignedp = unsignedp;
01076 args[i].mode = mode;
01077
01078 args[i].reg = FUNCTION_ARG (*args_so_far, mode, type,
01079 argpos < n_named_args);
01080 #ifdef FUNCTION_INCOMING_ARG
01081
01082
01083
01084 args[i].tail_call_reg = FUNCTION_INCOMING_ARG (*args_so_far, mode, type,
01085 argpos < n_named_args);
01086 #else
01087 args[i].tail_call_reg = args[i].reg;
01088 #endif
01089
01090 if (args[i].reg)
01091 args[i].partial
01092 = targetm.calls.arg_partial_bytes (args_so_far, mode, type,
01093 argpos < n_named_args);
01094
01095 args[i].pass_on_stack = targetm.calls.must_pass_in_stack (mode, type);
01096
01097
01098
01099
01100 if (args[i].reg && GET_CODE (args[i].reg) == PARALLEL
01101 && XEXP (XVECEXP (args[i].reg, 0, 0), 0) == 0)
01102 args[i].pass_on_stack = 1;
01103
01104
01105
01106
01107
01108
01109 if (TREE_ADDRESSABLE (type)
01110 || (args[i].pass_on_stack && args[i].reg != 0))
01111 *must_preallocate = 1;
01112
01113
01114
01115 if (TREE_ADDRESSABLE (type))
01116 *ecf_flags &= ~ECF_LIBCALL_BLOCK;
01117
01118
01119 if (args[i].reg == 0 || args[i].partial != 0
01120 || reg_parm_stack_space > 0
01121 || args[i].pass_on_stack)
01122 locate_and_pad_parm (mode, type,
01123 #ifdef STACK_PARMS_IN_REG_PARM_AREA
01124 1,
01125 #else
01126 args[i].reg != 0,
01127 #endif
01128 args[i].pass_on_stack ? 0 : args[i].partial,
01129 fndecl, args_size, &args[i].locate);
01130 #ifdef BLOCK_REG_PADDING
01131 else
01132
01133
01134 args[i].locate.where_pad =
01135 BLOCK_REG_PADDING (mode, type,
01136 int_size_in_bytes (type) <= UNITS_PER_WORD);
01137 #endif
01138
01139
01140
01141 args_size->constant += args[i].locate.size.constant;
01142 if (args[i].locate.size.var)
01143 ADD_PARM_SIZE (*args_size, args[i].locate.size.var);
01144
01145
01146
01147
01148 FUNCTION_ARG_ADVANCE (*args_so_far, TYPE_MODE (type), type,
01149 argpos < n_named_args);
01150 }
01151 }
01152
01153
01154
01155
01156
01157
01158
01159 static int
01160 compute_argument_block_size (int reg_parm_stack_space,
01161 struct args_size *args_size,
01162 int preferred_stack_boundary ATTRIBUTE_UNUSED)
01163 {
01164 int unadjusted_args_size = args_size->constant;
01165
01166
01167
01168
01169 if (ACCUMULATE_OUTGOING_ARGS && preferred_stack_boundary > STACK_BOUNDARY)
01170 preferred_stack_boundary = STACK_BOUNDARY;
01171
01172
01173
01174
01175
01176 if (args_size->var)
01177 {
01178 args_size->var = ARGS_SIZE_TREE (*args_size);
01179 args_size->constant = 0;
01180
01181 preferred_stack_boundary /= BITS_PER_UNIT;
01182 if (preferred_stack_boundary > 1)
01183 {
01184
01185
01186
01187 gcc_assert (!(stack_pointer_delta & (preferred_stack_boundary - 1)));
01188 args_size->var = round_up (args_size->var, preferred_stack_boundary);
01189 }
01190
01191 if (reg_parm_stack_space > 0)
01192 {
01193 args_size->var
01194 = size_binop (MAX_EXPR, args_size->var,
01195 ssize_int (reg_parm_stack_space));
01196
01197 #ifndef OUTGOING_REG_PARM_STACK_SPACE
01198
01199
01200 args_size->var
01201 = size_binop (MINUS_EXPR, args_size->var,
01202 ssize_int (reg_parm_stack_space));
01203 #endif
01204 }
01205 }
01206 else
01207 {
01208 preferred_stack_boundary /= BITS_PER_UNIT;
01209 if (preferred_stack_boundary < 1)
01210 preferred_stack_boundary = 1;
01211 args_size->constant = (((args_size->constant
01212 + stack_pointer_delta
01213 + preferred_stack_boundary - 1)
01214 / preferred_stack_boundary
01215 * preferred_stack_boundary)
01216 - stack_pointer_delta);
01217
01218 args_size->constant = MAX (args_size->constant,
01219 reg_parm_stack_space);
01220
01221 #ifndef OUTGOING_REG_PARM_STACK_SPACE
01222 args_size->constant -= reg_parm_stack_space;
01223 #endif
01224 }
01225 return unadjusted_args_size;
01226 }
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238 static void
01239 precompute_arguments (int flags, int num_actuals, struct arg_data *args)
01240 {
01241 int i;
01242
01243
01244
01245 if ((flags & ECF_LIBCALL_BLOCK) == 0)
01246 return;
01247
01248 for (i = 0; i < num_actuals; i++)
01249 {
01250 enum machine_mode mode;
01251
01252
01253 gcc_assert (!TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value)));
01254
01255 args[i].initial_value = args[i].value
01256 = expand_expr (args[i].tree_value, NULL_RTX, VOIDmode, 0);
01257
01258 mode = TYPE_MODE (TREE_TYPE (args[i].tree_value));
01259 if (mode != args[i].mode)
01260 {
01261 args[i].value
01262 = convert_modes (args[i].mode, mode,
01263 args[i].value, args[i].unsignedp);
01264 #if defined(PROMOTE_FUNCTION_MODE) && !defined(PROMOTE_MODE)
01265
01266
01267
01268 if (REG_P (args[i].value)
01269 && GET_MODE_CLASS (args[i].mode) == MODE_INT)
01270 {
01271 args[i].initial_value
01272 = gen_lowpart_SUBREG (mode, args[i].value);
01273 SUBREG_PROMOTED_VAR_P (args[i].initial_value) = 1;
01274 SUBREG_PROMOTED_UNSIGNED_SET (args[i].initial_value,
01275 args[i].unsignedp);
01276 }
01277 #endif
01278 }
01279 }
01280 }
01281
01282
01283
01284
01285
01286 static int
01287 finalize_must_preallocate (int must_preallocate, int num_actuals, struct arg_data *args, struct args_size *args_size)
01288 {
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308 if (! must_preallocate)
01309 {
01310 int partial_seen = 0;
01311 int copy_to_evaluate_size = 0;
01312 int i;
01313
01314 for (i = 0; i < num_actuals && ! must_preallocate; i++)
01315 {
01316 if (args[i].partial > 0 && ! args[i].pass_on_stack)
01317 partial_seen = 1;
01318 else if (partial_seen && args[i].reg == 0)
01319 must_preallocate = 1;
01320
01321 if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) == BLKmode
01322 && (TREE_CODE (args[i].tree_value) == CALL_EXPR
01323 || TREE_CODE (args[i].tree_value) == TARGET_EXPR
01324 || TREE_CODE (args[i].tree_value) == COND_EXPR
01325 || TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value))))
01326 copy_to_evaluate_size
01327 += int_size_in_bytes (TREE_TYPE (args[i].tree_value));
01328 }
01329
01330 if (copy_to_evaluate_size * 2 >= args_size->constant
01331 && args_size->constant > 0)
01332 must_preallocate = 1;
01333 }
01334 return must_preallocate;
01335 }
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345 static void
01346 compute_argument_addresses (struct arg_data *args, rtx argblock, int num_actuals)
01347 {
01348 if (argblock)
01349 {
01350 rtx arg_reg = argblock;
01351 int i, arg_offset = 0;
01352
01353 if (GET_CODE (argblock) == PLUS)
01354 arg_reg = XEXP (argblock, 0), arg_offset = INTVAL (XEXP (argblock, 1));
01355
01356 for (i = 0; i < num_actuals; i++)
01357 {
01358 rtx offset = ARGS_SIZE_RTX (args[i].locate.offset);
01359 rtx slot_offset = ARGS_SIZE_RTX (args[i].locate.slot_offset);
01360 rtx addr;
01361 unsigned int align, boundary;
01362
01363
01364 if (! args[i].pass_on_stack && args[i].reg != 0)
01365 continue;
01366
01367 if (GET_CODE (offset) == CONST_INT)
01368 addr = plus_constant (arg_reg, INTVAL (offset));
01369 else
01370 addr = gen_rtx_PLUS (Pmode, arg_reg, offset);
01371
01372 addr = plus_constant (addr, arg_offset);
01373 args[i].stack = gen_rtx_MEM (args[i].mode, addr);
01374 set_mem_attributes (args[i].stack,
01375 TREE_TYPE (args[i].tree_value), 1);
01376 align = BITS_PER_UNIT;
01377 boundary = args[i].locate.boundary;
01378 if (args[i].locate.where_pad != downward)
01379 align = boundary;
01380 else if (GET_CODE (offset) == CONST_INT)
01381 {
01382 align = INTVAL (offset) * BITS_PER_UNIT | boundary;
01383 align = align & -align;
01384 }
01385 set_mem_align (args[i].stack, align);
01386
01387 if (GET_CODE (slot_offset) == CONST_INT)
01388 addr = plus_constant (arg_reg, INTVAL (slot_offset));
01389 else
01390 addr = gen_rtx_PLUS (Pmode, arg_reg, slot_offset);
01391
01392 addr = plus_constant (addr, arg_offset);
01393 args[i].stack_slot = gen_rtx_MEM (args[i].mode, addr);
01394 set_mem_attributes (args[i].stack_slot,
01395 TREE_TYPE (args[i].tree_value), 1);
01396 set_mem_align (args[i].stack_slot, args[i].locate.boundary);
01397
01398
01399
01400
01401
01402 set_mem_alias_set (args[i].stack, 0);
01403 set_mem_alias_set (args[i].stack_slot, 0);
01404 }
01405 }
01406 }
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416 static rtx
01417 rtx_for_function_call (tree fndecl, tree addr)
01418 {
01419 rtx funexp;
01420
01421
01422 if (fndecl)
01423 {
01424
01425
01426 if (! TREE_USED (fndecl))
01427 {
01428 assemble_external (fndecl);
01429 TREE_USED (fndecl) = 1;
01430 }
01431
01432
01433 funexp = XEXP (DECL_RTL (fndecl), 0);
01434 }
01435 else
01436
01437 {
01438 push_temp_slots ();
01439 funexp = expand_expr (addr, NULL_RTX, VOIDmode, 0);
01440 pop_temp_slots ();
01441 }
01442 return funexp;
01443 }
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455 static void
01456 load_register_parameters (struct arg_data *args, int num_actuals,
01457 rtx *call_fusage, int flags, int is_sibcall,
01458 int *sibcall_failure)
01459 {
01460 int i, j;
01461
01462 for (i = 0; i < num_actuals; i++)
01463 {
01464 rtx reg = ((flags & ECF_SIBCALL)
01465 ? args[i].tail_call_reg : args[i].reg);
01466 if (reg)
01467 {
01468 int partial = args[i].partial;
01469 int nregs;
01470 int size = 0;
01471 rtx before_arg = get_last_insn ();
01472
01473
01474
01475
01476 nregs = -1;
01477 if (GET_CODE (reg) == PARALLEL)
01478 ;
01479 else if (partial)
01480 {
01481 gcc_assert (partial % UNITS_PER_WORD == 0);
01482 nregs = partial / UNITS_PER_WORD;
01483 }
01484 else if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) == BLKmode)
01485 {
01486 size = int_size_in_bytes (TREE_TYPE (args[i].tree_value));
01487 nregs = (size + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
01488 }
01489 else
01490 size = GET_MODE_SIZE (args[i].mode);
01491
01492
01493
01494
01495 if (GET_CODE (reg) == PARALLEL)
01496 emit_group_move (reg, args[i].parallel_value);
01497
01498
01499
01500
01501
01502 else if (nregs == -1)
01503 {
01504 emit_move_insn (reg, args[i].value);
01505 #ifdef BLOCK_REG_PADDING
01506
01507
01508
01509 if (size < UNITS_PER_WORD
01510 && (args[i].locate.where_pad
01511 == (BYTES_BIG_ENDIAN ? upward : downward)))
01512 {
01513 rtx x;
01514 int shift = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
01515
01516
01517
01518
01519
01520 reg = gen_rtx_REG (word_mode, REGNO (reg));
01521 x = expand_shift (LSHIFT_EXPR, word_mode, reg,
01522 build_int_cst (NULL_TREE, shift),
01523 reg, 1);
01524 if (x != reg)
01525 emit_move_insn (reg, x);
01526 }
01527 #endif
01528 }
01529
01530
01531
01532
01533 else if (args[i].n_aligned_regs != 0)
01534 for (j = 0; j < args[i].n_aligned_regs; j++)
01535 emit_move_insn (gen_rtx_REG (word_mode, REGNO (reg) + j),
01536 args[i].aligned_regs[j]);
01537
01538 else if (partial == 0 || args[i].pass_on_stack)
01539 {
01540 rtx mem = validize_mem (args[i].value);
01541
01542
01543 if (nregs == 1 && size < UNITS_PER_WORD
01544 #ifdef BLOCK_REG_PADDING
01545 && args[i].locate.where_pad == downward
01546 #else
01547 && BYTES_BIG_ENDIAN
01548 #endif
01549 )
01550 {
01551 rtx tem = operand_subword_force (mem, 0, args[i].mode);
01552 rtx ri = gen_rtx_REG (word_mode, REGNO (reg));
01553 rtx x = gen_reg_rtx (word_mode);
01554 int shift = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
01555 enum tree_code dir = BYTES_BIG_ENDIAN ? RSHIFT_EXPR
01556 : LSHIFT_EXPR;
01557
01558 emit_move_insn (x, tem);
01559 x = expand_shift (dir, word_mode, x,
01560 build_int_cst (NULL_TREE, shift),
01561 ri, 1);
01562 if (x != ri)
01563 emit_move_insn (ri, x);
01564 }
01565 else
01566 move_block_to_reg (REGNO (reg), mem, nregs, args[i].mode);
01567 }
01568
01569
01570
01571
01572 if (is_sibcall
01573 && check_sibcall_argument_overlap (before_arg, &args[i], 0))
01574 *sibcall_failure = 1;
01575
01576
01577
01578 if (GET_CODE (reg) == PARALLEL)
01579 use_group_regs (call_fusage, reg);
01580 else if (nregs == -1)
01581 use_reg (call_fusage, reg);
01582 else if (nregs > 0)
01583 use_regs (call_fusage, REGNO (reg), nregs);
01584 }
01585 }
01586 }
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597 static int
01598 combine_pending_stack_adjustment_and_call (int unadjusted_args_size,
01599 struct args_size *args_size,
01600 unsigned int preferred_unit_stack_boundary)
01601 {
01602
01603
01604 HOST_WIDE_INT adjustment;
01605
01606
01607 unsigned HOST_WIDE_INT unadjusted_alignment;
01608
01609 unadjusted_alignment
01610 = ((stack_pointer_delta + unadjusted_args_size)
01611 % preferred_unit_stack_boundary);
01612
01613
01614
01615
01616
01617
01618
01619
01620 unadjusted_alignment
01621 = (unadjusted_alignment
01622 - (pending_stack_adjust % preferred_unit_stack_boundary));
01623 adjustment = pending_stack_adjust;
01624
01625
01626 if (preferred_unit_stack_boundary > 1)
01627 {
01628 if (unadjusted_alignment > 0)
01629 adjustment -= preferred_unit_stack_boundary - unadjusted_alignment;
01630 else
01631 adjustment += unadjusted_alignment;
01632 }
01633
01634
01635
01636
01637
01638 args_size->constant
01639 = pending_stack_adjust - adjustment + unadjusted_args_size;
01640
01641 return adjustment;
01642 }
01643
01644
01645
01646
01647
01648
01649
01650 static int
01651 check_sibcall_argument_overlap_1 (rtx x)
01652 {
01653 RTX_CODE code;
01654 int i, j;
01655 unsigned int k;
01656 const char *fmt;
01657
01658 if (x == NULL_RTX)
01659 return 0;
01660
01661 code = GET_CODE (x);
01662
01663 if (code == MEM)
01664 {
01665 if (XEXP (x, 0) == current_function_internal_arg_pointer)
01666 i = 0;
01667 else if (GET_CODE (XEXP (x, 0)) == PLUS
01668 && XEXP (XEXP (x, 0), 0) ==
01669 current_function_internal_arg_pointer
01670 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
01671 i = INTVAL (XEXP (XEXP (x, 0), 1));
01672 else
01673 return 0;
01674
01675 #ifdef ARGS_GROW_DOWNWARD
01676 i = -i - GET_MODE_SIZE (GET_MODE (x));
01677 #endif
01678
01679 for (k = 0; k < GET_MODE_SIZE (GET_MODE (x)); k++)
01680 if (i + k < stored_args_map->n_bits
01681 && TEST_BIT (stored_args_map, i + k))
01682 return 1;
01683
01684 return 0;
01685 }
01686
01687
01688 fmt = GET_RTX_FORMAT (code);
01689 for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
01690 {
01691 if (*fmt == 'e')
01692 {
01693 if (check_sibcall_argument_overlap_1 (XEXP (x, i)))
01694 return 1;
01695 }
01696 else if (*fmt == 'E')
01697 {
01698 for (j = 0; j < XVECLEN (x, i); j++)
01699 if (check_sibcall_argument_overlap_1 (XVECEXP (x, i, j)))
01700 return 1;
01701 }
01702 }
01703 return 0;
01704 }
01705
01706
01707
01708
01709
01710
01711
01712
01713 static int
01714 check_sibcall_argument_overlap (rtx insn, struct arg_data *arg, int mark_stored_args_map)
01715 {
01716 int low, high;
01717
01718 if (insn == NULL_RTX)
01719 insn = get_insns ();
01720 else
01721 insn = NEXT_INSN (insn);
01722
01723 for (; insn; insn = NEXT_INSN (insn))
01724 if (INSN_P (insn)
01725 && check_sibcall_argument_overlap_1 (PATTERN (insn)))
01726 break;
01727
01728 if (mark_stored_args_map)
01729 {
01730 #ifdef ARGS_GROW_DOWNWARD
01731 low = -arg->locate.slot_offset.constant - arg->locate.size.constant;
01732 #else
01733 low = arg->locate.slot_offset.constant;
01734 #endif
01735
01736 for (high = low + arg->locate.size.constant; low < high; low++)
01737 SET_BIT (stored_args_map, low);
01738 }
01739 return insn != NULL_RTX;
01740 }
01741
01742
01743
01744
01745
01746 bool
01747 shift_return_value (enum machine_mode mode, bool left_p, rtx value)
01748 {
01749 HOST_WIDE_INT shift;
01750
01751 gcc_assert (REG_P (value) && HARD_REGISTER_P (value));
01752 shift = GET_MODE_BITSIZE (GET_MODE (value)) - GET_MODE_BITSIZE (mode);
01753 if (shift == 0)
01754 return false;
01755
01756
01757
01758
01759 if (!force_expand_binop (GET_MODE (value), left_p ? ashl_optab : ashr_optab,
01760 value, GEN_INT (shift), value, 1, OPTAB_WIDEN))
01761 gcc_unreachable ();
01762 return true;
01763 }
01764
01765
01766
01767 static void
01768 purge_reg_equiv_notes (void)
01769 {
01770 rtx insn;
01771
01772 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
01773 {
01774 while (1)
01775 {
01776 rtx note = find_reg_note (insn, REG_EQUIV, 0);
01777 if (note)
01778 {
01779
01780
01781 remove_note (insn, note);
01782 continue;
01783 }
01784 break;
01785 }
01786 }
01787 }
01788
01789
01790
01791
01792
01793
01794
01795 rtx
01796 expand_call (tree exp, rtx target, int ignore)
01797 {
01798
01799 static int currently_expanding_call = 0;
01800
01801
01802 tree actparms = TREE_OPERAND (exp, 1);
01803
01804 rtx funexp;
01805
01806 rtx normal_call_insns = NULL_RTX;
01807
01808 rtx tail_call_insns = NULL_RTX;
01809
01810 tree funtype;
01811 tree type_arg_types;
01812
01813
01814 tree fndecl = 0;
01815
01816 tree fntype;
01817 bool try_tail_call = CALL_EXPR_TAILCALL (exp);
01818 int pass;
01819
01820
01821
01822 rtx valreg;
01823
01824
01825 rtx structure_value_addr = 0;
01826
01827
01828
01829 int structure_value_addr_parm = 0;
01830
01831
01832
01833 HOST_WIDE_INT struct_value_size = 0;
01834
01835
01836 int pcc_struct_value = 0;
01837 rtx struct_value = 0;
01838
01839
01840 int num_actuals;
01841
01842
01843 int n_named_args;
01844
01845
01846
01847
01848 struct arg_data *args;
01849
01850
01851 struct args_size args_size;
01852 struct args_size adjusted_args_size;
01853
01854 int unadjusted_args_size;
01855
01856 CUMULATIVE_ARGS args_so_far;
01857
01858 int reg_parm_seen;
01859
01860
01861
01862
01863
01864
01865
01866
01867 int must_preallocate = !PUSH_ARGS;
01868
01869
01870 int reg_parm_stack_space = 0;
01871
01872
01873
01874 rtx argblock = 0;
01875
01876
01877 int flags = 0;
01878 #ifdef REG_PARM_STACK_SPACE
01879
01880
01881 int low_to_save, high_to_save;
01882 rtx save_area = 0;
01883 #endif
01884
01885 int initial_highest_arg_in_use = highest_outgoing_arg_in_use;
01886 char *initial_stack_usage_map = stack_usage_map;
01887
01888 int old_stack_allocated;
01889
01890
01891 rtx old_stack_level = 0;
01892 int old_stack_arg_under_construction = 0;
01893 int old_pending_adj = 0;
01894 int old_inhibit_defer_pop = inhibit_defer_pop;
01895
01896
01897
01898
01899 int old_stack_pointer_delta = 0;
01900
01901 rtx call_fusage;
01902 tree p = TREE_OPERAND (exp, 0);
01903 tree addr = TREE_OPERAND (exp, 0);
01904 int i;
01905
01906 unsigned HOST_WIDE_INT preferred_stack_boundary;
01907
01908 unsigned HOST_WIDE_INT preferred_unit_stack_boundary;
01909
01910 rtx static_chain_value;
01911
01912 if (TREE_NOTHROW (exp))
01913 flags |= ECF_NOTHROW;
01914
01915
01916
01917 fndecl = get_callee_fndecl (exp);
01918 if (fndecl)
01919 {
01920 fntype = TREE_TYPE (fndecl);
01921 flags |= flags_from_decl_or_type (fndecl);
01922 }
01923 else
01924 {
01925 fntype = TREE_TYPE (TREE_TYPE (p));
01926 flags |= flags_from_decl_or_type (fntype);
01927 }
01928
01929 struct_value = targetm.calls.struct_value_rtx (fntype, 0);
01930
01931
01932
01933 if (warn_aggregate_return && AGGREGATE_TYPE_P (TREE_TYPE (exp)))
01934 warning ("function call has aggregate value");
01935
01936
01937
01938
01939 if ((flags & (ECF_CONST | ECF_PURE))
01940 && (ignore || target == const0_rtx
01941 || TYPE_MODE (TREE_TYPE (exp)) == VOIDmode))
01942 {
01943 bool volatilep = false;
01944 tree arg;
01945
01946 for (arg = actparms; arg; arg = TREE_CHAIN (arg))
01947 if (TREE_THIS_VOLATILE (TREE_VALUE (arg)))
01948 {
01949 volatilep = true;
01950 break;
01951 }
01952
01953 if (! volatilep)
01954 {
01955 for (arg = actparms; arg; arg = TREE_CHAIN (arg))
01956 expand_expr (TREE_VALUE (arg), const0_rtx,
01957 VOIDmode, EXPAND_NORMAL);
01958 return const0_rtx;
01959 }
01960 }
01961
01962 #ifdef REG_PARM_STACK_SPACE
01963 reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
01964 #endif
01965
01966 #ifndef OUTGOING_REG_PARM_STACK_SPACE
01967 if (reg_parm_stack_space > 0 && PUSH_ARGS)
01968 must_preallocate = 1;
01969 #endif
01970
01971
01972
01973
01974 if (aggregate_value_p (exp, fndecl))
01975 {
01976
01977 flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
01978
01979 #ifdef PCC_STATIC_STRUCT_RETURN
01980 {
01981 pcc_struct_value = 1;
01982 }
01983 #else
01984 {
01985 struct_value_size = int_size_in_bytes (TREE_TYPE (exp));
01986
01987 if (CALL_EXPR_HAS_RETURN_SLOT_ADDR (exp))
01988 {
01989
01990
01991
01992 tree return_arg = TREE_VALUE (actparms);
01993 actparms = TREE_CHAIN (actparms);
01994 structure_value_addr = expand_expr (return_arg, NULL_RTX,
01995 VOIDmode, EXPAND_NORMAL);
01996 }
01997 #if 0
01998 else if (target && MEM_P (target))
01999 structure_value_addr = XEXP (target, 0);
02000 #endif
02001 else
02002 {
02003
02004
02005
02006 rtx d = assign_temp (TREE_TYPE (exp), 1, 1, 1);
02007
02008 mark_temp_addr_taken (d);
02009 structure_value_addr = XEXP (d, 0);
02010 target = 0;
02011 }
02012 }
02013 #endif
02014 }
02015
02016
02017 preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
02018 if (fndecl)
02019 {
02020 struct cgraph_rtl_info *i = cgraph_rtl_info (fndecl);
02021 if (i && i->preferred_incoming_stack_boundary)
02022 preferred_stack_boundary = i->preferred_incoming_stack_boundary;
02023 }
02024
02025
02026 funtype = TREE_TYPE (addr);
02027 gcc_assert (POINTER_TYPE_P (funtype));
02028 funtype = TREE_TYPE (funtype);
02029
02030
02031
02032 if (targetm.calls.split_complex_arg)
02033 {
02034 type_arg_types = split_complex_types (TYPE_ARG_TYPES (funtype));
02035 actparms = split_complex_values (actparms);
02036 }
02037 else
02038 type_arg_types = TYPE_ARG_TYPES (funtype);
02039
02040 if (flags & ECF_MAY_BE_ALLOCA)
02041 current_function_calls_alloca = 1;
02042
02043
02044
02045 if (structure_value_addr && struct_value == 0)
02046 {
02047
02048
02049
02050
02051
02052 rtx temp = (!REG_P (structure_value_addr)
02053 || (ACCUMULATE_OUTGOING_ARGS
02054 && stack_arg_under_construction
02055 && structure_value_addr == virtual_outgoing_args_rtx)
02056 ? copy_addr_to_reg (convert_memory_address
02057 (Pmode, structure_value_addr))
02058 : structure_value_addr);
02059
02060 actparms
02061 = tree_cons (error_mark_node,
02062 make_tree (build_pointer_type (TREE_TYPE (funtype)),
02063 temp),
02064 actparms);
02065 structure_value_addr_parm = 1;
02066 }
02067
02068
02069 for (p = actparms, num_actuals = 0; p; p = TREE_CHAIN (p))
02070 num_actuals++;
02071
02072
02073
02074
02075 if (type_arg_types != 0)
02076 n_named_args
02077 = (list_length (type_arg_types)
02078
02079 + structure_value_addr_parm);
02080 else
02081
02082 n_named_args = num_actuals;
02083
02084
02085
02086
02087
02088
02089
02090 INIT_CUMULATIVE_ARGS (args_so_far, funtype, NULL_RTX, fndecl, n_named_args);
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110 if (type_arg_types != 0
02111 && targetm.calls.strict_argument_naming (&args_so_far))
02112 ;
02113 else if (type_arg_types != 0
02114 && ! targetm.calls.pretend_outgoing_varargs_named (&args_so_far))
02115
02116 --n_named_args;
02117 else
02118
02119 n_named_args = num_actuals;
02120
02121
02122 args = alloca (num_actuals * sizeof (struct arg_data));
02123 memset (args, 0, num_actuals * sizeof (struct arg_data));
02124
02125
02126
02127 initialize_argument_information (num_actuals, args, &args_size,
02128 n_named_args, actparms, fndecl,
02129 &args_so_far, reg_parm_stack_space,
02130 &old_stack_level, &old_pending_adj,
02131 &must_preallocate, &flags,
02132 &try_tail_call, CALL_FROM_THUNK_P (exp));
02133
02134 if (args_size.var)
02135 {
02136
02137
02138
02139
02140
02141 flags &= ~ECF_LIBCALL_BLOCK;
02142 must_preallocate = 1;
02143 }
02144
02145
02146 must_preallocate = finalize_must_preallocate (must_preallocate,
02147 num_actuals, args,
02148 &args_size);
02149
02150
02151
02152
02153
02154 if (structure_value_addr
02155 && (reg_mentioned_p (virtual_stack_dynamic_rtx, structure_value_addr)
02156 || reg_mentioned_p (virtual_outgoing_args_rtx,
02157 structure_value_addr))
02158 && (args_size.var
02159 || (!ACCUMULATE_OUTGOING_ARGS && args_size.constant)))
02160 structure_value_addr = copy_to_reg (structure_value_addr);
02161
02162
02163
02164
02165
02166
02167 if (currently_expanding_call++ != 0
02168 || !flag_optimize_sibling_calls
02169 || args_size.var
02170 || lookup_stmt_eh_region (exp) >= 0)
02171 try_tail_call = 0;
02172
02173
02174 if (
02175 #ifdef HAVE_sibcall_epilogue
02176 !HAVE_sibcall_epilogue
02177 #else
02178 1
02179 #endif
02180 || !try_tail_call
02181
02182
02183
02184
02185 || structure_value_addr != NULL_RTX
02186
02187
02188 || !targetm.function_ok_for_sibcall (fndecl, exp)
02189
02190
02191 || (flags & (ECF_RETURNS_TWICE | ECF_NORETURN))
02192 || TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (addr)))
02193
02194
02195
02196 || (fndecl && decl_function_context (fndecl) == current_function_decl)
02197
02198
02199 || args_size.constant > current_function_args_size
02200
02201
02202 || (RETURN_POPS_ARGS (fndecl, funtype, args_size.constant)
02203 != RETURN_POPS_ARGS (current_function_decl,
02204 TREE_TYPE (current_function_decl),
02205 current_function_args_size))
02206 || !lang_hooks.decls.ok_for_sibcall (fndecl))
02207 try_tail_call = 0;
02208
02209
02210
02211
02212 if (cfun->preferred_stack_boundary < preferred_stack_boundary
02213 && fndecl != current_function_decl)
02214 cfun->preferred_stack_boundary = preferred_stack_boundary;
02215 if (fndecl == current_function_decl)
02216 cfun->recursive_call_emit = true;
02217
02218 preferred_unit_stack_boundary = preferred_stack_boundary / BITS_PER_UNIT;
02219
02220
02221
02222
02223 for (pass = try_tail_call ? 0 : 1; pass < 2; pass++)
02224 {
02225 int sibcall_failure = 0;
02226
02227
02228
02229
02230 int save_pending_stack_adjust = 0;
02231 int save_stack_pointer_delta = 0;
02232 rtx insns;
02233 rtx before_call, next_arg_reg;
02234
02235 if (pass == 0)
02236 {
02237
02238
02239 save_pending_stack_adjust = pending_stack_adjust;
02240 save_stack_pointer_delta = stack_pointer_delta;
02241 }
02242 if (pass)
02243 flags &= ~ECF_SIBCALL;
02244 else
02245 flags |= ECF_SIBCALL;
02246
02247
02248
02249 argblock = 0;
02250 call_fusage = 0;
02251
02252
02253
02254
02255
02256 start_sequence ();
02257
02258
02259
02260
02261
02262
02263
02264
02265 if (pending_stack_adjust >= 32
02266 || (pending_stack_adjust > 0
02267 && (flags & (ECF_MAY_BE_ALLOCA | ECF_SP_DEPRESSED)))
02268 || (pending_stack_adjust > 0
02269 && flag_exceptions && !(flags & ECF_NOTHROW))
02270 || pass == 0)
02271 do_pending_stack_adjust ();
02272
02273
02274
02275 if (pass && (flags & ECF_LIBCALL_BLOCK))
02276 NO_DEFER_POP;
02277
02278
02279 if (pass)
02280 precompute_arguments (flags, num_actuals, args);
02281
02282
02283
02284 if (pass && (flags & (ECF_LIBCALL_BLOCK | ECF_MALLOC)))
02285 start_sequence ();
02286
02287 adjusted_args_size = args_size;
02288
02289
02290
02291
02292
02293 unadjusted_args_size
02294 = compute_argument_block_size (reg_parm_stack_space,
02295 &adjusted_args_size,
02296 (pass == 0 ? 0
02297 : preferred_stack_boundary));
02298
02299 old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
02300
02301
02302
02303 if (pass == 0)
02304 {
02305 argblock = virtual_incoming_args_rtx;
02306 argblock
02307 #ifdef STACK_GROWS_DOWNWARD
02308 = plus_constant (argblock, current_function_pretend_args_size);
02309 #else
02310 = plus_constant (argblock, -current_function_pretend_args_size);
02311 #endif
02312 stored_args_map = sbitmap_alloc (args_size.constant);
02313 sbitmap_zero (stored_args_map);
02314 }
02315
02316
02317
02318 else if (adjusted_args_size.var != 0)
02319 {
02320 if (old_stack_level == 0)
02321 {
02322 emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX);
02323 old_stack_pointer_delta = stack_pointer_delta;
02324 old_pending_adj = pending_stack_adjust;
02325 pending_stack_adjust = 0;
02326
02327
02328
02329 old_stack_arg_under_construction = stack_arg_under_construction;
02330 stack_arg_under_construction = 0;
02331 }
02332 argblock = push_block (ARGS_SIZE_RTX (adjusted_args_size), 0, 0);
02333 }
02334 else
02335 {
02336
02337
02338
02339
02340
02341 int needed = adjusted_args_size.constant;
02342
02343
02344
02345
02346
02347 if (needed > current_function_outgoing_args_size)
02348 current_function_outgoing_args_size = needed;
02349
02350 if (must_preallocate)
02351 {
02352 if (ACCUMULATE_OUTGOING_ARGS)
02353 {
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368 #ifndef OUTGOING_REG_PARM_STACK_SPACE
02369
02370
02371
02372 needed += reg_parm_stack_space;
02373 #endif
02374
02375 #ifdef ARGS_GROW_DOWNWARD
02376 highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
02377 needed + 1);
02378 #else
02379 highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
02380 needed);
02381 #endif
02382 stack_usage_map = alloca (highest_outgoing_arg_in_use);
02383
02384 if (initial_highest_arg_in_use)
02385 memcpy (stack_usage_map, initial_stack_usage_map,
02386 initial_highest_arg_in_use);
02387
02388 if (initial_highest_arg_in_use != highest_outgoing_arg_in_use)
02389 memset (&stack_usage_map[initial_highest_arg_in_use], 0,
02390 (highest_outgoing_arg_in_use
02391 - initial_highest_arg_in_use));
02392 needed = 0;
02393
02394
02395
02396
02397
02398
02399 argblock = virtual_outgoing_args_rtx;
02400 }
02401 else
02402 {
02403 if (inhibit_defer_pop == 0)
02404 {
02405
02406
02407 needed
02408 = (combine_pending_stack_adjustment_and_call
02409 (unadjusted_args_size,
02410 &adjusted_args_size,
02411 preferred_unit_stack_boundary));
02412
02413
02414
02415
02416
02417 needed = unadjusted_args_size - needed;
02418
02419 if (needed < 0)
02420 {
02421
02422
02423
02424 pending_stack_adjust = -needed;
02425 do_pending_stack_adjust ();
02426 needed = 0;
02427 }
02428 else
02429
02430
02431 pending_stack_adjust = 0;
02432 }
02433
02434
02435
02436 if (needed == 0)
02437 argblock = virtual_outgoing_args_rtx;
02438 else
02439 {
02440 argblock = push_block (GEN_INT (needed), 0, 0);
02441 #ifdef ARGS_GROW_DOWNWARD
02442 argblock = plus_constant (argblock, needed);
02443 #endif
02444 }
02445
02446
02447
02448
02449
02450
02451
02452
02453 argblock = copy_to_reg (argblock);
02454 }
02455 }
02456 }
02457
02458 if (ACCUMULATE_OUTGOING_ARGS)
02459 {
02460
02461
02462
02463
02464 if (stack_arg_under_construction)
02465 {
02466 #ifndef OUTGOING_REG_PARM_STACK_SPACE
02467 rtx push_size = GEN_INT (reg_parm_stack_space
02468 + adjusted_args_size.constant);
02469 #else
02470 rtx push_size = GEN_INT (adjusted_args_size.constant);
02471 #endif
02472 if (old_stack_level == 0)
02473 {
02474 emit_stack_save (SAVE_BLOCK, &old_stack_level,
02475 NULL_RTX);
02476 old_stack_pointer_delta = stack_pointer_delta;
02477 old_pending_adj = pending_stack_adjust;
02478 pending_stack_adjust = 0;
02479
02480
02481
02482
02483 old_stack_arg_under_construction
02484 = stack_arg_under_construction;
02485 stack_arg_under_construction = 0;
02486
02487 stack_usage_map = alloca (highest_outgoing_arg_in_use);
02488 memset (stack_usage_map, 0, highest_outgoing_arg_in_use);
02489 highest_outgoing_arg_in_use = 0;
02490 }
02491 allocate_dynamic_stack_space (push_size, NULL_RTX,
02492 BITS_PER_UNIT);
02493 }
02494
02495
02496
02497 for (i = 0; i < num_actuals; i++)
02498 if (args[i].pass_on_stack)
02499 {
02500 argblock = copy_addr_to_reg (argblock);
02501 break;
02502 }
02503 }
02504
02505 compute_argument_addresses (args, argblock, num_actuals);
02506
02507
02508
02509 if (PUSH_ARGS_REVERSED && argblock == 0
02510 && adjusted_args_size.constant != unadjusted_args_size)
02511 {
02512
02513
02514 if (pending_stack_adjust
02515 && ! (flags & ECF_LIBCALL_BLOCK)
02516 && ! inhibit_defer_pop)
02517 {
02518 pending_stack_adjust
02519 = (combine_pending_stack_adjustment_and_call
02520 (unadjusted_args_size,
02521 &adjusted_args_size,
02522 preferred_unit_stack_boundary));
02523 do_pending_stack_adjust ();
02524 }
02525 else if (argblock == 0)
02526 anti_adjust_stack (GEN_INT (adjusted_args_size.constant
02527 - unadjusted_args_size));
02528 }
02529
02530
02531 NO_DEFER_POP;
02532
02533 funexp = rtx_for_function_call (fndecl, addr);
02534
02535
02536 valreg = 0;
02537 if (TYPE_MODE (TREE_TYPE (exp)) != VOIDmode
02538 && ! structure_value_addr)
02539 {
02540 if (pcc_struct_value)
02541 valreg = hard_function_value (build_pointer_type (TREE_TYPE (exp)),
02542 fndecl, (pass == 0));
02543 else
02544 valreg = hard_function_value (TREE_TYPE (exp), fndecl, (pass == 0));
02545 }
02546
02547
02548
02549 precompute_register_parameters (num_actuals, args, ®_parm_seen);
02550
02551 if (TREE_OPERAND (exp, 2))
02552 static_chain_value = expand_expr (TREE_OPERAND (exp, 2),
02553 NULL_RTX, VOIDmode, 0);
02554 else
02555 static_chain_value = 0;
02556
02557 #ifdef REG_PARM_STACK_SPACE
02558
02559
02560 if (ACCUMULATE_OUTGOING_ARGS && pass)
02561 save_area = save_fixed_argument_area (reg_parm_stack_space, argblock,
02562 &low_to_save, &high_to_save);
02563 #endif
02564
02565
02566
02567
02568
02569
02570
02571 for (i = 0; i < num_actuals; i++)
02572 if (args[i].reg == 0 || args[i].pass_on_stack)
02573 {
02574 rtx before_arg = get_last_insn ();
02575
02576 if (store_one_arg (&args[i], argblock, flags,
02577 adjusted_args_size.var != 0,
02578 reg_parm_stack_space)
02579 || (pass == 0
02580 && check_sibcall_argument_overlap (before_arg,
02581 &args[i], 1)))
02582 sibcall_failure = 1;
02583
02584 if (flags & ECF_CONST
02585 && args[i].stack
02586 && args[i].value == args[i].stack)
02587 call_fusage = gen_rtx_EXPR_LIST (VOIDmode,
02588 gen_rtx_USE (VOIDmode,
02589 args[i].value),
02590 call_fusage);
02591 }
02592
02593
02594
02595
02596
02597 if (STRICT_ALIGNMENT)
02598 store_unaligned_arguments_into_pseudos (args, num_actuals);
02599
02600
02601
02602 if (reg_parm_seen)
02603 for (i = 0; i < num_actuals; i++)
02604 if (args[i].partial != 0 && ! args[i].pass_on_stack)
02605 {
02606 rtx before_arg = get_last_insn ();
02607
02608 if (store_one_arg (&args[i], argblock, flags,
02609 adjusted_args_size.var != 0,
02610 reg_parm_stack_space)
02611 || (pass == 0
02612 && check_sibcall_argument_overlap (before_arg,
02613 &args[i], 1)))
02614 sibcall_failure = 1;
02615 }
02616
02617
02618
02619 if (!PUSH_ARGS_REVERSED && argblock == 0)
02620 anti_adjust_stack (GEN_INT (adjusted_args_size.constant
02621 - unadjusted_args_size));
02622
02623
02624
02625
02626 #ifdef OUTGOING_REG_PARM_STACK_SPACE
02627 if (!ACCUMULATE_OUTGOING_ARGS
02628 && must_preallocate == 0 && reg_parm_stack_space > 0)
02629 anti_adjust_stack (GEN_INT (reg_parm_stack_space));
02630 #endif
02631
02632
02633
02634 if (pass != 0 && structure_value_addr && ! structure_value_addr_parm)
02635 {
02636 structure_value_addr
02637 = convert_memory_address (Pmode, structure_value_addr);
02638 emit_move_insn (struct_value,
02639 force_reg (Pmode,
02640 force_operand (structure_value_addr,
02641 NULL_RTX)));
02642
02643 if (REG_P (struct_value))
02644 use_reg (&call_fusage, struct_value);
02645 }
02646
02647 funexp = prepare_call_address (funexp, static_chain_value,
02648 &call_fusage, reg_parm_seen, pass == 0);
02649
02650 load_register_parameters (args, num_actuals, &call_fusage, flags,
02651 pass == 0, &sibcall_failure);
02652
02653
02654
02655 before_call = get_last_insn ();
02656
02657
02658
02659 #ifdef FUNCTION_INCOMING_ARG
02660 if (pass == 0)
02661 next_arg_reg = FUNCTION_INCOMING_ARG (args_so_far, VOIDmode,
02662 void_type_node, 1);
02663 else
02664 #endif
02665 next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode,
02666 void_type_node, 1);
02667
02668
02669
02670
02671
02672 gcc_assert (!pass
02673 || !(stack_pointer_delta % preferred_unit_stack_boundary));
02674
02675
02676 emit_call_1 (funexp, exp, fndecl, funtype, unadjusted_args_size,
02677 adjusted_args_size.constant, struct_value_size,
02678 next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
02679 flags, & args_so_far);
02680
02681
02682
02683
02684
02685 if (!structure_value_addr
02686 && !pcc_struct_value
02687 && TYPE_MODE (TREE_TYPE (exp)) != BLKmode
02688 && targetm.calls.return_in_msb (TREE_TYPE (exp)))
02689 {
02690 if (shift_return_value (TYPE_MODE (TREE_TYPE (exp)), false, valreg))
02691 sibcall_failure = 1;
02692 valreg = gen_rtx_REG (TYPE_MODE (TREE_TYPE (exp)), REGNO (valreg));
02693 }
02694
02695
02696
02697
02698
02699 if (pass && (flags & ECF_LIBCALL_BLOCK))
02700 {
02701 rtx insns;
02702 rtx insn;
02703 bool failed = valreg == 0 || GET_CODE (valreg) == PARALLEL;
02704
02705 insns = get_insns ();
02706
02707
02708
02709 for (insn = insns; insn; insn = NEXT_INSN (insn))
02710 if (JUMP_P (insn))
02711 failed = true;
02712
02713 if (failed)
02714 {
02715 end_sequence ();
02716 emit_insn (insns);
02717 }
02718 else
02719 {
02720 rtx note = 0;
02721 rtx temp = gen_reg_rtx (GET_MODE (valreg));
02722
02723
02724 if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
02725 mark_reg_pointer (temp,
02726 TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp))));
02727
02728 end_sequence ();
02729 if (flag_unsafe_math_optimizations
02730 && fndecl
02731 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
02732 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SQRT
02733 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SQRTF
02734 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SQRTL))
02735 note = gen_rtx_fmt_e (SQRT,
02736 GET_MODE (temp),
02737 args[0].initial_value);
02738 else
02739 {
02740
02741
02742
02743 for (i = 0; i < num_actuals; i++)
02744 note = gen_rtx_EXPR_LIST (VOIDmode,
02745 args[i].initial_value, note);
02746 note = gen_rtx_EXPR_LIST (VOIDmode, funexp, note);
02747
02748 if (flags & ECF_PURE)
02749 note = gen_rtx_EXPR_LIST (VOIDmode,
02750 gen_rtx_USE (VOIDmode,
02751 gen_rtx_MEM (BLKmode,
02752 gen_rtx_SCRATCH (VOIDmode))),
02753 note);
02754 }
02755 emit_libcall_block (insns, temp, valreg, note);
02756
02757 valreg = temp;
02758 }
02759 }
02760 else if (pass && (flags & ECF_MALLOC))
02761 {
02762 rtx temp = gen_reg_rtx (GET_MODE (valreg));
02763 rtx last, insns;
02764
02765
02766 if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
02767 mark_reg_pointer (temp, BIGGEST_ALIGNMENT);
02768
02769 emit_move_insn (temp, valreg);
02770
02771
02772
02773 last = get_last_insn ();
02774 REG_NOTES (last) =
02775 gen_rtx_EXPR_LIST (REG_NOALIAS, temp, REG_NOTES (last));
02776
02777
02778 insns = get_insns ();
02779 end_sequence ();
02780 emit_insn (insns);
02781 valreg = temp;
02782 }
02783
02784
02785
02786
02787
02788 if ((flags & ECF_NORETURN) || pass == 0)
02789 {
02790
02791
02792
02793
02794 rtx last = get_last_insn ();
02795 while (!CALL_P (last))
02796 {
02797 last = PREV_INSN (last);
02798
02799 gcc_assert (last != before_call);
02800 }
02801
02802 emit_barrier_after (last);
02803
02804
02805
02806
02807 if (inhibit_defer_pop == 0)
02808 {
02809 stack_pointer_delta = old_stack_allocated;
02810 pending_stack_adjust = 0;
02811 }
02812 }
02813
02814
02815
02816 if (TYPE_MODE (TREE_TYPE (exp)) == VOIDmode
02817 || ignore)
02818 target = const0_rtx;
02819 else if (structure_value_addr)
02820 {
02821 if (target == 0 || !MEM_P (target))
02822 {
02823 target
02824 = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)),
02825 memory_address (TYPE_MODE (TREE_TYPE (exp)),
02826 structure_value_addr));
02827 set_mem_attributes (target, exp, 1);
02828 }
02829 }
02830 else if (pcc_struct_value)
02831 {
02832
02833
02834
02835 target = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)),
02836 copy_to_reg (valreg));
02837 set_mem_attributes (target, exp, 1);
02838 }
02839
02840
02841 else if (GET_CODE (valreg) == PARALLEL)
02842 {
02843 if (target == 0)
02844 {
02845
02846 tree nt = build_qualified_type (TREE_TYPE (exp),
02847 (TYPE_QUALS (TREE_TYPE (exp))
02848 | TYPE_QUAL_CONST));
02849
02850 target = assign_temp (nt, 0, 1, 1);
02851 }
02852
02853 if (! rtx_equal_p (target, valreg))
02854 emit_group_store (target, valreg, TREE_TYPE (exp),
02855 int_size_in_bytes (TREE_TYPE (exp)));
02856
02857
02858 sibcall_failure = 1;
02859 }
02860 else if (target
02861 && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp))
02862 && GET_MODE (target) == GET_MODE (valreg))
02863 {
02864
02865
02866
02867
02868
02869
02870 emit_move_insn (target, valreg);
02871
02872
02873
02874
02875 if (MEM_P (target))
02876 sibcall_failure = 1;
02877 }
02878 else if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
02879 {
02880 target = copy_blkmode_from_reg (target, valreg, TREE_TYPE (exp));
02881
02882
02883 sibcall_failure = 1;
02884 }
02885 else
02886 target = copy_to_reg (valreg);
02887
02888 if (targetm.calls.promote_function_return(funtype))
02889 {
02890
02891
02892 if (REG_P (target)
02893 && TYPE_MODE (TREE_TYPE (exp)) != BLKmode
02894 && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
02895 {
02896 tree type = TREE_TYPE (exp);
02897 int unsignedp = TYPE_UNSIGNED (type);
02898 int offset = 0;
02899 enum machine_mode pmode;
02900
02901 pmode = promote_mode (type, TYPE_MODE (type), &unsignedp, 1);
02902
02903 gcc_assert (GET_MODE (target) == pmode);
02904
02905 if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
02906 && (GET_MODE_SIZE (GET_MODE (target))
02907 > GET_MODE_SIZE (TYPE_MODE (type))))
02908 {
02909 offset = GET_MODE_SIZE (GET_MODE (target))
02910 - GET_MODE_SIZE (TYPE_MODE (type));
02911 if (! BYTES_BIG_ENDIAN)
02912 offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
02913 else if (! WORDS_BIG_ENDIAN)
02914 offset %= UNITS_PER_WORD;
02915 }
02916 target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
02917 SUBREG_PROMOTED_VAR_P (target) = 1;
02918 SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp);
02919 }
02920 }
02921
02922
02923
02924
02925 if (old_stack_level && ! (flags & ECF_SP_DEPRESSED))
02926 {
02927 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
02928 stack_pointer_delta = old_stack_pointer_delta;
02929 pending_stack_adjust = old_pending_adj;
02930 old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
02931 stack_arg_under_construction = old_stack_arg_under_construction;
02932 highest_outgoing_arg_in_use = initial_highest_arg_in_use;
02933 stack_usage_map = initial_stack_usage_map;
02934 sibcall_failure = 1;
02935 }
02936 else if (ACCUMULATE_OUTGOING_ARGS && pass)
02937 {
02938 #ifdef REG_PARM_STACK_SPACE
02939 if (save_area)
02940 restore_fixed_argument_area (save_area, argblock,
02941 high_to_save, low_to_save);
02942 #endif
02943
02944
02945 for (i = 0; i < num_actuals; i++)
02946 if (args[i].save_area)
02947 {
02948 enum machine_mode save_mode = GET_MODE (args[i].save_area);
02949 rtx stack_area
02950 = gen_rtx_MEM (save_mode,
02951 memory_address (save_mode,
02952 XEXP (args[i].stack_slot, 0)));
02953
02954 if (save_mode != BLKmode)
02955 emit_move_insn (stack_area, args[i].save_area);
02956 else
02957 emit_block_move (stack_area, args[i].save_area,
02958 GEN_INT (args[i].locate.size.constant),
02959 BLOCK_OP_CALL_PARM);
02960 }
02961
02962 highest_outgoing_arg_in_use = initial_highest_arg_in_use;
02963 stack_usage_map = initial_stack_usage_map;
02964 }
02965
02966
02967
02968
02969
02970 if ((flags & ECF_MAY_BE_ALLOCA) && cfun->nonlocal_goto_save_area != 0)
02971 update_nonlocal_goto_save_area ();
02972
02973
02974 for (i = 0; i < num_actuals; ++i)
02975 if (args[i].aligned_regs)
02976 free (args[i].aligned_regs);
02977
02978 insns = get_insns ();
02979 end_sequence ();
02980
02981 if (pass == 0)
02982 {
02983 tail_call_insns = insns;
02984
02985
02986
02987
02988 pending_stack_adjust = save_pending_stack_adjust;
02989 stack_pointer_delta = save_stack_pointer_delta;
02990
02991
02992 for (i = 0; i < num_actuals; i++)
02993 {
02994 args[i].value = 0;
02995 args[i].aligned_regs = 0;
02996 args[i].stack = 0;
02997 }
02998
02999 sbitmap_free (stored_args_map);
03000 }
03001 else
03002 {
03003 normal_call_insns = insns;
03004
03005
03006 gcc_assert ((flags & ECF_NORETURN)
03007 || (old_stack_allocated
03008 == stack_pointer_delta - pending_stack_adjust));
03009 }
03010
03011
03012
03013 if (sibcall_failure)
03014 tail_call_insns = NULL_RTX;
03015 else
03016 break;
03017 }
03018
03019
03020
03021 if (tail_call_insns)
03022 {
03023 emit_insn (tail_call_insns);
03024 cfun->tail_call_emit = true;
03025 }
03026 else
03027 emit_insn (normal_call_insns);
03028
03029 currently_expanding_call--;
03030
03031
03032
03033
03034 if (flags & ECF_SP_DEPRESSED)
03035 {
03036 clear_pending_stack_adjust ();
03037 emit_insn (gen_rtx_CLOBBER (VOIDmode, stack_pointer_rtx));
03038 emit_move_insn (virtual_stack_dynamic_rtx, stack_pointer_rtx);
03039 }
03040
03041 return target;
03042 }
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054 void
03055 fixup_tail_calls (void)
03056 {
03057 purge_reg_equiv_notes ();
03058 }
03059
03060
03061
03062 static tree
03063 split_complex_values (tree values)
03064 {
03065 tree p;
03066
03067
03068 for (p = values; p; p = TREE_CHAIN (p))
03069 {
03070 tree type = TREE_TYPE (TREE_VALUE (p));
03071 if (type && TREE_CODE (type) == COMPLEX_TYPE
03072 && targetm.calls.split_complex_arg (type))
03073 goto found;
03074 }
03075 return values;
03076
03077 found:
03078 values = copy_list (values);
03079
03080 for (p = values; p; p = TREE_CHAIN (p))
03081 {
03082 tree complex_value = TREE_VALUE (p);
03083 tree complex_type;
03084
03085 complex_type = TREE_TYPE (complex_value);
03086 if (!complex_type)
03087 continue;
03088
03089 if (TREE_CODE (complex_type) == COMPLEX_TYPE
03090 && targetm.calls.split_complex_arg (complex_type))
03091 {
03092 tree subtype;
03093 tree real, imag, next;
03094
03095 subtype = TREE_TYPE (complex_type);
03096 complex_value = save_expr (complex_value);
03097 real = build1 (REALPART_EXPR, subtype, complex_value);
03098 imag = build1 (IMAGPART_EXPR, subtype, complex_value);
03099
03100 TREE_VALUE (p) = real;
03101 next = TREE_CHAIN (p);
03102 imag = build_tree_list (NULL_TREE, imag);
03103 TREE_CHAIN (p) = imag;
03104 TREE_CHAIN (imag) = next;
03105
03106
03107 p = TREE_CHAIN (p);
03108 }
03109 }
03110
03111 return values;
03112 }
03113
03114
03115
03116 static tree
03117 split_complex_types (tree types)
03118 {
03119 tree p;
03120
03121
03122 for (p = types; p; p = TREE_CHAIN (p))
03123 {
03124 tree type = TREE_VALUE (p);
03125 if (TREE_CODE (type) == COMPLEX_TYPE
03126 && targetm.calls.split_complex_arg (type))
03127 goto found;
03128 }
03129 return types;
03130
03131 found:
03132 types = copy_list (types);
03133
03134 for (p = types; p; p = TREE_CHAIN (p))
03135 {
03136 tree complex_type = TREE_VALUE (p);
03137
03138 if (TREE_CODE (complex_type) == COMPLEX_TYPE
03139 && targetm.calls.split_complex_arg (complex_type))
03140 {
03141 tree next, imag;
03142
03143
03144 TREE_VALUE (p) = TREE_TYPE (complex_type);
03145 next = TREE_CHAIN (p);
03146
03147
03148 imag = build_tree_list (NULL_TREE, TREE_VALUE (p));
03149 TREE_CHAIN (p) = imag;
03150 TREE_CHAIN (imag) = next;
03151
03152
03153 p = TREE_CHAIN (p);
03154 }
03155 }
03156
03157 return types;
03158 }
03159
03160
03161
03162
03163
03164 static rtx
03165 emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
03166 enum libcall_type fn_type,
03167 enum machine_mode outmode, int nargs, va_list p)
03168 {
03169
03170 struct args_size args_size;
03171
03172 struct args_size original_args_size;
03173 int argnum;
03174 rtx fun;
03175 int inc;
03176 int count;
03177 rtx argblock = 0;
03178 CUMULATIVE_ARGS args_so_far;
03179 struct arg
03180 {
03181 rtx value;
03182 enum machine_mode mode;
03183 rtx reg;
03184 int partial;
03185 struct locate_and_pad_arg_data locate;
03186 rtx save_area;
03187 };
03188 struct arg *argvec;
03189 int old_inhibit_defer_pop = inhibit_defer_pop;
03190 rtx call_fusage = 0;
03191 rtx mem_value = 0;
03192 rtx valreg;
03193 int pcc_struct_value = 0;
03194 int struct_value_size = 0;
03195 int flags;
03196 int reg_parm_stack_space = 0;
03197 int needed;
03198 rtx before_call;
03199 tree tfom;
03200
03201 #ifdef REG_PARM_STACK_SPACE
03202
03203
03204 int low_to_save, high_to_save;
03205 rtx save_area = 0;
03206 #endif
03207
03208
03209 int initial_highest_arg_in_use = highest_outgoing_arg_in_use;
03210 char *initial_stack_usage_map = stack_usage_map;
03211
03212 rtx struct_value = targetm.calls.struct_value_rtx (0, 0);
03213
03214 #ifdef REG_PARM_STACK_SPACE
03215 reg_parm_stack_space = REG_PARM_STACK_SPACE ((tree) 0);
03216 #endif
03217
03218
03219 flags = ECF_NOTHROW;
03220
03221 switch (fn_type)
03222 {
03223 case LCT_NORMAL:
03224 break;
03225 case LCT_CONST:
03226 flags |= ECF_CONST;
03227 break;
03228 case LCT_PURE:
03229 flags |= ECF_PURE;
03230 break;
03231 case LCT_CONST_MAKE_BLOCK:
03232 flags |= ECF_CONST | ECF_LIBCALL_BLOCK;
03233 break;
03234 case LCT_PURE_MAKE_BLOCK:
03235 flags |= ECF_PURE | ECF_LIBCALL_BLOCK;
03236 break;
03237 case LCT_NORETURN:
03238 flags |= ECF_NORETURN;
03239 break;
03240 case LCT_THROW:
03241 flags = ECF_NORETURN;
03242 break;
03243 case LCT_ALWAYS_RETURN:
03244 flags = ECF_ALWAYS_RETURN;
03245 break;
03246 case LCT_RETURNS_TWICE:
03247 flags = ECF_RETURNS_TWICE;
03248 break;
03249 }
03250 fun = orgfun;
03251
03252
03253
03254 if (cfun->preferred_stack_boundary < PREFERRED_STACK_BOUNDARY)
03255 cfun->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
03256
03257
03258
03259 if (outmode != VOIDmode)
03260 {
03261 tfom = lang_hooks.types.type_for_mode (outmode, 0);
03262 if (aggregate_value_p (tfom, 0))
03263 {
03264 #ifdef PCC_STATIC_STRUCT_RETURN
03265 rtx pointer_reg
03266 = hard_function_value (build_pointer_type (tfom), 0, 0);
03267 mem_value = gen_rtx_MEM (outmode, pointer_reg);
03268 pcc_struct_value = 1;
03269 if (value == 0)
03270 value = gen_reg_rtx (outmode);
03271 #else
03272 struct_value_size = GET_MODE_SIZE (outmode);
03273 if (value != 0 && MEM_P (value))
03274 mem_value = value;
03275 else
03276 mem_value = assign_temp (tfom, 0, 1, 1);
03277 #endif
03278
03279 flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
03280 }
03281 }
03282 else
03283 tfom = void_type_node;
03284
03285
03286
03287
03288
03289
03290
03291
03292
03293
03294 argvec = alloca ((nargs + 1) * sizeof (struct arg));
03295 memset (argvec, 0, (nargs + 1) * sizeof (struct arg));
03296
03297 #ifdef INIT_CUMULATIVE_LIBCALL_ARGS
03298 INIT_CUMULATIVE_LIBCALL_ARGS (args_so_far, outmode, fun);
03299 #else
03300 INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE, fun, 0, nargs);
03301 #endif
03302
03303 args_size.constant = 0;
03304 args_size.var = 0;
03305
03306 count = 0;
03307
03308
03309
03310 if (flags & ECF_LIBCALL_BLOCK)
03311 start_sequence ();
03312
03313 push_temp_slots ();
03314
03315
03316
03317 if (mem_value && struct_value == 0 && ! pcc_struct_value)
03318 {
03319 rtx addr = XEXP (mem_value, 0);
03320
03321 nargs++;
03322
03323
03324 if (!REG_P (addr) && !MEM_P (addr)
03325 && ! (CONSTANT_P (addr) && LEGITIMATE_CONSTANT_P (addr)))
03326 addr = force_operand (addr, NULL_RTX);
03327
03328 argvec[count].value = addr;
03329 argvec[count].mode = Pmode;
03330 argvec[count].partial = 0;
03331
03332 argvec[count].reg = FUNCTION_ARG (args_so_far, Pmode, NULL_TREE, 1);
03333 gcc_assert (targetm.calls.arg_partial_bytes (&args_so_far, Pmode,
03334 NULL_TREE, 1) == 0);
03335
03336 locate_and_pad_parm (Pmode, NULL_TREE,
03337 #ifdef STACK_PARMS_IN_REG_PARM_AREA
03338 1,
03339 #else
03340 argvec[count].reg != 0,
03341 #endif
03342 0, NULL_TREE, &args_size, &argvec[count].locate);
03343
03344 if (argvec[count].reg == 0 || argvec[count].partial != 0
03345 || reg_parm_stack_space > 0)
03346 args_size.constant += argvec[count].locate.size.constant;
03347
03348 FUNCTION_ARG_ADVANCE (args_so_far, Pmode, (tree) 0, 1);
03349
03350 count++;
03351 }
03352
03353 for (; count < nargs; count++)
03354 {
03355 rtx val = va_arg (p, rtx);
03356 enum machine_mode mode = va_arg (p, enum machine_mode);
03357
03358
03359
03360 gcc_assert (mode != BLKmode
03361 && (GET_MODE (val) == mode || GET_MODE (val) == VOIDmode));
03362
03363
03364 if (!REG_P (val) && !MEM_P (val)
03365 && ! (CONSTANT_P (val) && LEGITIMATE_CONSTANT_P (val)))
03366 val = force_operand (val, NULL_RTX);
03367
03368 if (pass_by_reference (&args_so_far, mode, NULL_TREE, 1))
03369 {
03370 rtx slot;
03371 int must_copy
03372 = !reference_callee_copied (&args_so_far, mode, NULL_TREE, 1);
03373
03374
03375
03376 if (flags & ECF_LIBCALL_BLOCK)
03377 {
03378 rtx insns = get_insns ();
03379 end_sequence ();
03380 emit_insn (insns);
03381 }
03382 flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK);
03383
03384
03385
03386 if (flags & ECF_CONST)
03387 {
03388 flags &= ~ECF_CONST;
03389 flags |= ECF_PURE;
03390 }
03391
03392 if (GET_MODE (val) == MEM && !must_copy)
03393 slot = val;
03394 else
03395 {
03396 slot = assign_temp (lang_hooks.types.type_for_mode (mode, 0),
03397 0, 1, 1);
03398 emit_move_insn (slot, val);
03399 }
03400
03401 call_fusage = gen_rtx_EXPR_LIST (VOIDmode,
03402 gen_rtx_USE (VOIDmode, slot),
03403 call_fusage);
03404 if (must_copy)
03405 call_fusage = gen_rtx_EXPR_LIST (VOIDmode,
03406 gen_rtx_CLOBBER (VOIDmode,
03407 slot),
03408 call_fusage);
03409
03410 mode = Pmode;
03411 val = force_operand (XEXP (slot, 0), NULL_RTX);
03412 }
03413
03414 argvec[count].value = val;
03415 argvec[count].mode = mode;
03416
03417 argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1);
03418
03419 argvec[count].partial
03420 = targetm.calls.arg_partial_bytes (&args_so_far, mode, NULL_TREE, 1);
03421
03422 locate_and_pad_parm (mode, NULL_TREE,
03423 #ifdef STACK_PARMS_IN_REG_PARM_AREA
03424 1,
03425 #else
03426 argvec[count].reg != 0,
03427 #endif
03428 argvec[count].partial,
03429 NULL_TREE, &args_size, &argvec[count].locate);
03430
03431 gcc_assert (!argvec[count].locate.size.var);
03432
03433 if (argvec[count].reg == 0 || argvec[count].partial != 0
03434 || reg_parm_stack_space > 0)
03435 args_size.constant += argvec[count].locate.size.constant;
03436
03437 FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree) 0, 1);
03438 }
03439
03440
03441
03442 assemble_external_libcall (fun);
03443
03444 original_args_size = args_size;
03445 args_size.constant = (((args_size.constant
03446 + stack_pointer_delta
03447 + STACK_BYTES - 1)
03448 / STACK_BYTES
03449 * STACK_BYTES)
03450 - stack_pointer_delta);
03451
03452 args_size.constant = MAX (args_size.constant,
03453 reg_parm_stack_space);
03454
03455 #ifndef OUTGOING_REG_PARM_STACK_SPACE
03456 args_size.constant -= reg_parm_stack_space;
03457 #endif
03458
03459 if (args_size.constant > current_function_outgoing_args_size)
03460 current_function_outgoing_args_size = args_size.constant;
03461
03462 if (ACCUMULATE_OUTGOING_ARGS)
03463 {
03464
03465
03466
03467
03468
03469
03470
03471
03472
03473
03474
03475
03476 needed = args_size.constant;
03477
03478 #ifndef OUTGOING_REG_PARM_STACK_SPACE
03479
03480
03481
03482 needed += reg_parm_stack_space;
03483 #endif
03484
03485 #ifdef ARGS_GROW_DOWNWARD
03486 highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
03487 needed + 1);
03488 #else
03489 highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
03490 needed);
03491 #endif
03492 stack_usage_map = alloca (highest_outgoing_arg_in_use);
03493
03494 if (initial_highest_arg_in_use)
03495 memcpy (stack_usage_map, initial_stack_usage_map,
03496 initial_highest_arg_in_use);
03497
03498 if (initial_highest_arg_in_use != highest_outgoing_arg_in_use)
03499 memset (&stack_usage_map[initial_highest_arg_in_use], 0,
03500 highest_outgoing_arg_in_use - initial_highest_arg_in_use);
03501 needed = 0;
03502
03503
03504
03505
03506
03507
03508 if (virtuals_instantiated)
03509 argblock = plus_constant (stack_pointer_rtx, STACK_POINTER_OFFSET);
03510 else
03511 argblock = virtual_outgoing_args_rtx;
03512 }
03513 else
03514 {
03515 if (!PUSH_ARGS)
03516 argblock = push_block (GEN_INT (args_size.constant), 0, 0);
03517 }
03518
03519
03520
03521 if (argblock == 0 && PUSH_ARGS_REVERSED)
03522 anti_adjust_stack (GEN_INT (args_size.constant
03523 - original_args_size.constant));
03524
03525 if (PUSH_ARGS_REVERSED)
03526 {
03527 inc = -1;
03528 argnum = nargs - 1;
03529 }
03530 else
03531 {
03532 inc = 1;
03533 argnum = 0;
03534 }
03535
03536 #ifdef REG_PARM_STACK_SPACE
03537 if (ACCUMULATE_OUTGOING_ARGS)
03538 {
03539
03540
03541
03542 save_area = save_fixed_argument_area (reg_parm_stack_space, argblock,
03543 &low_to_save, &high_to_save);
03544 }
03545 #endif
03546
03547
03548
03549
03550
03551 for (count = 0; count < nargs; count++, argnum += inc)
03552 {
03553 enum machine_mode mode = argvec[argnum].mode;
03554 rtx val = argvec[argnum].value;
03555 rtx reg = argvec[argnum].reg;
03556 int partial = argvec[argnum].partial;
03557 int lower_bound = 0, upper_bound = 0, i;
03558
03559 if (! (reg != 0 && partial == 0))
03560 {
03561 if (ACCUMULATE_OUTGOING_ARGS)
03562 {
03563
03564
03565
03566 #ifdef ARGS_GROW_DOWNWARD
03567
03568
03569 upper_bound = -argvec[argnum].locate.offset.constant + 1;
03570 lower_bound = upper_bound - argvec[argnum].locate.size.constant;
03571 #else
03572 lower_bound = argvec[argnum].locate.offset.constant;
03573 upper_bound = lower_bound + argvec[argnum].locate.size.constant;
03574 #endif
03575
03576 i = lower_bound;
03577
03578
03579 if (i < reg_parm_stack_space)
03580 i = reg_parm_stack_space;
03581 while (i < upper_bound && stack_usage_map[i] == 0)
03582 i++;
03583
03584 if (i < upper_bound)
03585 {
03586
03587 unsigned int size
03588 = argvec[argnum].locate.size.constant * BITS_PER_UNIT;
03589 enum machine_mode save_mode
03590 = mode_for_size (size, MODE_INT, 1);
03591 rtx adr
03592 = plus_constant (argblock,
03593 argvec[argnum].locate.offset.constant);
03594 rtx stack_area
03595 = gen_rtx_MEM (save_mode, memory_address (save_mode, adr));
03596
03597 if (save_mode == BLKmode)
03598 {
03599 argvec[argnum].save_area
03600 = assign_stack_temp (BLKmode,
03601 argvec[argnum].locate.size.constant,
03602 0);
03603
03604 emit_block_move (validize_mem (argvec[argnum].save_area),
03605 stack_area,
03606 GEN_INT (argvec[argnum].locate.size.constant),
03607 BLOCK_OP_CALL_PARM);
03608 }
03609 else
03610 {
03611 argvec[argnum].save_area = gen_reg_rtx (save_mode);
03612
03613 emit_move_insn (argvec[argnum].save_area, stack_area);
03614 }
03615 }
03616 }
03617
03618 emit_push_insn (val, mode, NULL_TREE, NULL_RTX, PARM_BOUNDARY,
03619 partial, reg, 0, argblock,
03620 GEN_INT (argvec[argnum].locate.offset.constant),
03621 reg_parm_stack_space,
03622 ARGS_SIZE_RTX (argvec[argnum].locate.alignment_pad));
03623
03624
03625 if (ACCUMULATE_OUTGOING_ARGS)
03626 for (i = lower_bound; i < upper_bound; i++)
03627 stack_usage_map[i] = 1;
03628
03629 NO_DEFER_POP;
03630 }
03631 }
03632
03633
03634
03635 if (argblock == 0 && !PUSH_ARGS_REVERSED)
03636 anti_adjust_stack (GEN_INT (args_size.constant
03637 - original_args_size.constant));
03638
03639 if (PUSH_ARGS_REVERSED)
03640 argnum = nargs - 1;
03641 else
03642 argnum = 0;
03643
03644 fun = prepare_call_address (fun, NULL, &call_fusage, 0, 0);
03645
03646
03647
03648
03649
03650 for (count = 0; count < nargs; count++, argnum += inc)
03651 {
03652 enum machine_mode mode = argvec[argnum].mode;
03653 rtx val = argvec[argnum].value;
03654 rtx reg = argvec[argnum].reg;
03655 int partial = argvec[argnum].partial;
03656
03657
03658
03659 if (reg != 0 && GET_CODE (reg) == PARALLEL)
03660 emit_group_load (reg, val, NULL_TREE, GET_MODE_SIZE (mode));
03661 else if (reg != 0 && partial == 0)
03662 emit_move_insn (reg, val);
03663
03664 NO_DEFER_POP;
03665 }
03666
03667
03668 for (count = 0; count < nargs; count++)
03669 {
03670 rtx reg = argvec[count].reg;
03671 if (reg != 0 && GET_CODE (reg) == PARALLEL)
03672 use_group_regs (&call_fusage, reg);
03673 else if (reg != 0)
03674 use_reg (&call_fusage, reg);
03675 }
03676
03677
03678 if (mem_value != 0 && struct_value != 0 && ! pcc_struct_value)
03679 {
03680 emit_move_insn (struct_value,
03681 force_reg (Pmode,
03682 force_operand (XEXP (mem_value, 0),
03683 NULL_RTX)));
03684 if (REG_P (struct_value))
03685 use_reg (&call_fusage, struct_value);
03686 }
03687
03688
03689
03690 NO_DEFER_POP;
03691 valreg = (mem_value == 0 && outmode != VOIDmode
03692 ? hard_libcall_value (outmode) : NULL_RTX);
03693
03694
03695 gcc_assert (!(stack_pointer_delta
03696 & (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT - 1)));
03697
03698 before_call = get_last_insn ();
03699
03700
03701
03702
03703
03704
03705
03706
03707 emit_call_1 (fun, NULL,
03708 get_identifier (XSTR (orgfun, 0)),
03709 build_function_type (tfom, NULL_TREE),
03710 original_args_size.constant, args_size.constant,
03711 struct_value_size,
03712 FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
03713 valreg,
03714 old_inhibit_defer_pop + 1, call_fusage, flags, & args_so_far);
03715
03716
03717
03718
03719
03720 if (flags & ECF_NORETURN)
03721 {
03722
03723
03724
03725
03726 rtx last = get_last_insn ();
03727 while (!CALL_P (last))
03728 {
03729 last = PREV_INSN (last);
03730
03731 gcc_assert (last != before_call);
03732 }
03733
03734 emit_barrier_after (last);
03735 }
03736
03737
03738 OK_DEFER_POP;
03739
03740
03741
03742
03743
03744 if (flags & ECF_LIBCALL_BLOCK)
03745 {
03746 rtx insns;
03747
03748 if (valreg == 0)
03749 {
03750 insns = get_insns ();
03751 end_sequence ();
03752 emit_insn (insns);
03753 }
03754 else
03755 {
03756 rtx note = 0;
03757 rtx temp;
03758 int i;
03759
03760 if (GET_CODE (valreg) == PARALLEL)
03761 {
03762 temp = gen_reg_rtx (outmode);
03763 emit_group_store (temp, valreg, NULL_TREE,
03764 GET_MODE_SIZE (outmode));
03765 valreg = temp;
03766 }
03767
03768 temp = gen_reg_rtx (GET_MODE (valreg));
03769
03770
03771
03772 for (i = 0; i < nargs; i++)
03773 note = gen_rtx_EXPR_LIST (VOIDmode, argvec[i].value, note);
03774 note = gen_rtx_EXPR_LIST (VOIDmode, fun, note);
03775
03776 insns = get_insns ();
03777 end_sequence ();
03778
03779 if (flags & ECF_PURE)
03780 note = gen_rtx_EXPR_LIST (VOIDmode,
03781 gen_rtx_USE (VOIDmode,
03782 gen_rtx_MEM (BLKmode,
03783 gen_rtx_SCRATCH (VOIDmode))),
03784 note);
03785
03786 emit_libcall_block (insns, temp, valreg, note);
03787
03788 valreg = temp;
03789 }
03790 }
03791 pop_temp_slots ();
03792
03793
03794 if (outmode != VOIDmode && retval)
03795 {
03796 if (mem_value)
03797 {
03798 if (value == 0)
03799 value = mem_value;
03800 if (value != mem_value)
03801 emit_move_insn (value, mem_value);
03802 }
03803 else if (GET_CODE (valreg) == PARALLEL)
03804 {
03805 if (value == 0)
03806 value = gen_reg_rtx (outmode);
03807 emit_group_store (value, valreg, NULL_TREE, GET_MODE_SIZE (outmode));
03808 }
03809 else if (value != 0)
03810 emit_move_insn (value, valreg);
03811 else
03812 value = valreg;
03813 }
03814
03815 if (ACCUMULATE_OUTGOING_ARGS)
03816 {
03817 #ifdef REG_PARM_STACK_SPACE
03818 if (save_area)
03819 restore_fixed_argument_area (save_area, argblock,
03820 high_to_save, low_to_save);
03821 #endif
03822
03823
03824 for (count = 0; count < nargs; count++)
03825 if (argvec[count].save_area)
03826 {
03827 enum machine_mode save_mode = GET_MODE (argvec[count].save_area);
03828 rtx adr = plus_constant (argblock,
03829 argvec[count].locate.offset.constant);
03830 rtx stack_area = gen_rtx_MEM (save_mode,
03831 memory_address (save_mode, adr));
03832
03833 if (save_mode == BLKmode)
03834 emit_block_move (stack_area,
03835 validize_mem (argvec[count].save_area),
03836 GEN_INT (argvec[count].locate.size.constant),
03837 BLOCK_OP_CALL_PARM);
03838 else
03839 emit_move_insn (stack_area, argvec[count].save_area);
03840 }
03841
03842 highest_outgoing_arg_in_use = initial_highest_arg_in_use;
03843 stack_usage_map = initial_stack_usage_map;
03844 }
03845
03846 return value;
03847
03848 }
03849
03850
03851
03852
03853
03854
03855
03856
03857
03858
03859
03860
03861
03862
03863 void
03864 emit_library_call (rtx orgfun, enum libcall_type fn_type,
03865 enum machine_mode outmode, int nargs, ...)
03866 {
03867 va_list p;
03868
03869 va_start (p, nargs);
03870 emit_library_call_value_1 (0, orgfun, NULL_RTX, fn_type, outmode, nargs, p);
03871 va_end (p);
03872 }
03873
03874
03875
03876
03877
03878
03879
03880
03881
03882 rtx
03883 emit_library_call_value (rtx orgfun, rtx value,
03884 enum libcall_type fn_type,
03885 enum machine_mode outmode, int nargs, ...)
03886 {
03887 rtx result;
03888 va_list p;
03889
03890 va_start (p, nargs);
03891 result = emit_library_call_value_1 (1, orgfun, value, fn_type, outmode,
03892 nargs, p);
03893 va_end (p);
03894
03895 return result;
03896 }
03897
03898
03899
03900
03901
03902
03903
03904
03905
03906
03907
03908
03909
03910
03911
03912
03913
03914
03915
03916
03917 static int
03918 store_one_arg (struct arg_data *arg, rtx argblock, int flags,
03919 int variable_size ATTRIBUTE_UNUSED, int reg_parm_stack_space)
03920 {
03921 tree pval = arg->tree_value;
03922 rtx reg = 0;
03923 int partial = 0;
03924 int used = 0;
03925 int i, lower_bound = 0, upper_bound = 0;
03926 int sibcall_failure = 0;
03927
03928 if (TREE_CODE (pval) == ERROR_MARK)
03929 return 1;
03930
03931
03932
03933 push_temp_slots ();
03934
03935 if (ACCUMULATE_OUTGOING_ARGS && !(flags & ECF_SIBCALL))
03936 {
03937
03938
03939 if (argblock && ! variable_size && arg->stack)
03940 {
03941 #ifdef ARGS_GROW_DOWNWARD
03942
03943
03944 if (GET_CODE (XEXP (arg->stack_slot, 0)) == PLUS)
03945 upper_bound = -INTVAL (XEXP (XEXP (arg->stack_slot, 0), 1)) + 1;
03946 else
03947 upper_bound = 0;
03948
03949 lower_bound = upper_bound - arg->locate.size.constant;
03950 #else
03951 if (GET_CODE (XEXP (arg->stack_slot, 0)) == PLUS)
03952 lower_bound = INTVAL (XEXP (XEXP (arg->stack_slot, 0), 1));
03953 else
03954 lower_bound = 0;
03955
03956 upper_bound = lower_bound + arg->locate.size.constant;
03957 #endif
03958
03959 i = lower_bound;
03960
03961
03962 if (i < reg_parm_stack_space)
03963 i = reg_parm_stack_space;
03964 while (i < upper_bound && stack_usage_map[i] == 0)
03965 i++;
03966
03967 if (i < upper_bound)
03968 {
03969
03970 unsigned int size = arg->locate.size.constant * BITS_PER_UNIT;
03971 enum machine_mode save_mode = mode_for_size (size, MODE_INT, 1);
03972 rtx adr = memory_address (save_mode, XEXP (arg->stack_slot, 0));
03973 rtx stack_area = gen_rtx_MEM (save_mode, adr);
03974
03975 if (save_mode == BLKmode)
03976 {
03977 tree ot = TREE_TYPE (arg->tree_value);
03978 tree nt = build_qualified_type (ot, (TYPE_QUALS (ot)
03979 | TYPE_QUAL_CONST));
03980
03981 arg->save_area = assign_temp (nt, 0, 1, 1);
03982 preserve_temp_slots (arg->save_area);
03983 emit_block_move (validize_mem (arg->save_area), stack_area,
03984 expr_size (arg->tree_value),
03985 BLOCK_OP_CALL_PARM);
03986 }
03987 else
03988 {
03989 arg->save_area = gen_reg_rtx (save_mode);
03990 emit_move_insn (arg->save_area, stack_area);
03991 }
03992 }
03993 }
03994 }
03995
03996
03997
03998 if (! arg->pass_on_stack)
03999 {
04000 if (flags & ECF_SIBCALL)
04001 reg = arg->tail_call_reg;
04002 else
04003 reg = arg->reg;
04004 partial = arg->partial;
04005 }
04006
04007
04008
04009 gcc_assert (reg == 0 || partial != 0);
04010
04011
04012
04013 if (arg->n_aligned_regs != 0)
04014 reg = 0;
04015
04016
04017
04018 if (arg->value == 0)
04019 {
04020
04021
04022
04023
04024
04025
04026
04027
04028
04029
04030
04031
04032
04033
04034
04035
04036
04037
04038 if (arg->pass_on_stack)
04039 stack_arg_under_construction++;
04040
04041 arg->value = expand_expr (pval,
04042 (partial
04043 || TYPE_MODE (TREE_TYPE (pval)) != arg->mode)
04044 ? NULL_RTX : arg->stack,
04045 VOIDmode, EXPAND_STACK_PARM);
04046
04047
04048
04049
04050 if (arg->mode != TYPE_MODE (TREE_TYPE (pval)))
04051 arg->value = convert_modes (arg->mode, TYPE_MODE (TREE_TYPE (pval)),
04052 arg->value, arg->unsignedp);
04053
04054 if (arg->pass_on_stack)
04055 stack_arg_under_construction--;
04056 }
04057
04058
04059 if ((flags & ECF_SIBCALL) && MEM_P (arg->value))
04060 {
04061 int i = -1;
04062 unsigned HOST_WIDE_INT k;
04063 rtx x = arg->value;
04064
04065 if (XEXP (x, 0) == current_function_internal_arg_pointer)
04066 i = 0;
04067 else if (GET_CODE (XEXP (x, 0)) == PLUS
04068 && XEXP (XEXP (x, 0), 0) ==
04069 current_function_internal_arg_pointer
04070 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
04071 i = INTVAL (XEXP (XEXP (x, 0), 1));
04072 else
04073 i = -1;
04074
04075 if (i >= 0)
04076 {
04077 #ifdef ARGS_GROW_DOWNWARD
04078 i = -i - arg->locate.size.constant;
04079 #endif
04080 if (arg->locate.size.constant > 0)
04081 {
04082 unsigned HOST_WIDE_INT sc = arg->locate.size.constant;
04083
04084 for (k = 0; k < sc; k++)
04085 if (i + k < stored_args_map->n_bits
04086 && TEST_BIT (stored_args_map, i + k))
04087 {
04088 sibcall_failure = 1;
04089 break;
04090 }
04091 }
04092 }
04093 }
04094
04095
04096
04097 if (flags & ECF_MAY_BE_ALLOCA)
04098 do_pending_stack_adjust ();
04099
04100 if (arg->value == arg->stack)
04101
04102 ;
04103 else if (arg->mode != BLKmode)
04104 {
04105 int size;
04106
04107
04108
04109
04110
04111
04112
04113
04114
04115
04116
04117 size = GET_MODE_SIZE (arg->mode);
04118
04119
04120
04121 #ifdef PUSH_ROUNDING
04122 size = PUSH_ROUNDING (size);
04123 #endif
04124 used = size;
04125
04126
04127
04128 if (none != FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)))
04129 used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
04130 / (PARM_BOUNDARY / BITS_PER_UNIT))
04131 * (PARM_BOUNDARY / BITS_PER_UNIT));
04132
04133
04134
04135 emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX,
04136 PARM_BOUNDARY, partial, reg, used - size, argblock,
04137 ARGS_SIZE_RTX (arg->locate.offset), reg_parm_stack_space,
04138 ARGS_SIZE_RTX (arg->locate.alignment_pad));
04139
04140
04141
04142 if (partial == 0)
04143 arg->value = arg->stack;
04144 }
04145 else
04146 {
04147
04148
04149 unsigned int parm_align;
04150 int excess;
04151 rtx size_rtx;
04152
04153
04154
04155
04156
04157
04158
04159
04160 if (arg->locate.size.var != 0)
04161 {
04162 excess = 0;
04163 size_rtx = ARGS_SIZE_RTX (arg->locate.size);
04164 }
04165 else
04166 {
04167
04168
04169 excess = (arg->locate.size.constant
04170 - int_size_in_bytes (TREE_TYPE (pval))
04171 + partial);
04172 size_rtx = expand_expr (size_in_bytes (TREE_TYPE (pval)),
04173 NULL_RTX, TYPE_MODE (sizetype), 0);
04174 }
04175
04176 parm_align = arg->locate.boundary;
04177
04178
04179
04180 if (FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)) == downward)
04181 {
04182 if (arg->locate.size.var)
04183 parm_align = BITS_PER_UNIT;
04184 else if (excess)
04185 {
04186 unsigned int excess_align = (excess & -excess) * BITS_PER_UNIT;
04187 parm_align = MIN (parm_align, excess_align);
04188 }
04189 }
04190
04191 if ((flags & ECF_SIBCALL) && MEM_P (arg->value))
04192 {
04193
04194
04195 rtx x = arg->value;
04196 int i = 0;
04197
04198 if (XEXP (x, 0) == current_function_internal_arg_pointer
04199 || (GET_CODE (XEXP (x, 0)) == PLUS
04200 && XEXP (XEXP (x, 0), 0) ==
04201 current_function_internal_arg_pointer
04202 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
04203 {
04204 if (XEXP (x, 0) != current_function_internal_arg_pointer)
04205 i = INTVAL (XEXP (XEXP (x, 0), 1));
04206
04207
04208 gcc_assert (!arg->locate.offset.var
04209 && GET_CODE (size_rtx) == CONST_INT);
04210
04211 if (arg->locate.offset.constant > i)
04212 {
04213 if (arg->locate.offset.constant < i + INTVAL (size_rtx))
04214 sibcall_failure = 1;
04215 }
04216 else if (arg->locate.offset.constant < i)
04217 {
04218 if (i < arg->locate.offset.constant + INTVAL (size_rtx))
04219 sibcall_failure = 1;
04220 }
04221 }
04222 }
04223
04224 emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
04225 parm_align, partial, reg, excess, argblock,
04226 ARGS_SIZE_RTX (arg->locate.offset), reg_parm_stack_space,
04227 ARGS_SIZE_RTX (arg->locate.alignment_pad));
04228
04229
04230
04231
04232
04233
04234
04235
04236
04237 if (partial == 0)
04238 arg->value = arg->stack_slot;
04239 }
04240
04241 if (arg->reg && GET_CODE (arg->reg) == PARALLEL)
04242 {
04243 tree type = TREE_TYPE (arg->tree_value);
04244 arg->parallel_value
04245 = emit_group_load_into_temps (arg->reg, arg->value, type,
04246 int_size_in_bytes (type));
04247 }
04248
04249
04250 if (ACCUMULATE_OUTGOING_ARGS && !(flags & ECF_SIBCALL)
04251 && argblock && ! variable_size && arg->stack)
04252 for (i = lower_bound; i < upper_bound; i++)
04253 stack_usage_map[i] = 1;
04254
04255
04256
04257 NO_DEFER_POP;
04258
04259
04260
04261
04262 preserve_temp_slots (NULL_RTX);
04263 free_temp_slots ();
04264 pop_temp_slots ();
04265
04266 return sibcall_failure;
04267 }
04268
04269
04270
04271 bool
04272 must_pass_in_stack_var_size (enum machine_mode mode ATTRIBUTE_UNUSED,
04273 tree type)
04274 {
04275 if (!type)
04276 return false;
04277
04278
04279 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
04280 return true;
04281
04282
04283
04284 if (TREE_ADDRESSABLE (type))
04285 return true;
04286
04287 return false;
04288 }
04289
04290
04291
04292
04293
04294 bool
04295 must_pass_in_stack_var_size_or_pad (enum machine_mode mode, tree type)
04296 {
04297 if (!type)
04298 return false;
04299
04300
04301 if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
04302 return true;
04303
04304
04305
04306 if (TREE_ADDRESSABLE (type))
04307 return true;
04308
04309
04310
04311 if (mode == BLKmode
04312 && int_size_in_bytes (type) % (PARM_BOUNDARY / BITS_PER_UNIT)
04313 && (FUNCTION_ARG_PADDING (mode, type)
04314 == (BYTES_BIG_ENDIAN ? upward : downward)))
04315 return true;
04316
04317 return false;
04318 }