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