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