Changeset 1394 for trunk/src/gcc/gcc/calls.c
- Timestamp:
- Apr 28, 2004, 6:58:06 AM (21 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/gcc/gcc/calls.c
-
Property cvs2svn:cvs-rev
changed from
1.2
to1.3
r1393 r1394 1 1 /* Convert function calls to rtl insns, for GNU C compiler. 2 2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998 3 1999, 2000, 2001 Free Software Foundation, Inc.3 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. 4 4 5 5 This file is part of GCC. … … 34 34 #include "timevar.h" 35 35 #include "sbitmap.h" 36 #include "langhooks.h" 37 #include "target.h" 38 #include "except.h" 36 39 37 40 #if !defined FUNCTION_OK_FOR_SIBCALL … … 92 95 Also 0 if not passed in registers. */ 93 96 int partial; 94 /* Non -zero if argument must be passed on stack.97 /* Nonzero if argument must be passed on stack. 95 98 Note that some arguments may be passed on the stack 96 99 even though pass_on_stack is zero, just because FUNCTION_ARG says so. … … 127 130 }; 128 131 129 /* A vector of one char per byte of stack space. A byte if non -zero if132 /* A vector of one char per byte of stack space. A byte if nonzero if 130 133 the corresponding stack location has been used. 131 134 This vector is used to prevent a function call within an argument from … … 226 229 static int combine_pending_stack_adjustment_and_call 227 230 PARAMS ((int, struct args_size *, int)); 231 static tree fix_unsafe_tree PARAMS ((tree)); 228 232 229 233 #ifdef REG_PARM_STACK_SPACE … … 617 621 REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, const0_rtx, 618 622 REG_NOTES (call_insn)); 623 else 624 note_eh_region_may_contain_throw (); 619 625 620 626 if (ecf_flags & ECF_NORETURN) … … 637 643 if the context of the call as a whole permits. */ 638 644 inhibit_defer_pop = old_inhibit_defer_pop; 645 646 /* Don't bother cleaning up after a noreturn function. */ 647 if (ecf_flags & (ECF_NORETURN | ECF_LONGJMP)) 648 return; 639 649 640 650 if (n_popped > 0) … … 802 812 } 803 813 814 /* Return true when exp contains alloca call. */ 815 bool 816 alloca_call_p (exp) 817 tree exp; 818 { 819 if (TREE_CODE (exp) == CALL_EXPR 820 && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR 821 && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) 822 == FUNCTION_DECL) 823 && (special_function_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0), 824 0) & ECF_MAY_BE_ALLOCA)) 825 return true; 826 return false; 827 } 828 804 829 /* Detect flags (function attributes) from the function decl or type node. */ 805 830 … … 825 850 if (TREE_NOTHROW (exp)) 826 851 flags |= ECF_NOTHROW; 852 853 if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp)) 854 flags |= ECF_LIBCALL_BLOCK; 827 855 } 828 856 829 857 if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp)) 830 flags |= ECF_CONST | ECF_LIBCALL_BLOCK;858 flags |= ECF_CONST; 831 859 832 860 if (TREE_THIS_VOLATILE (exp)) … … 878 906 emit_queue (); 879 907 } 908 909 /* If the value is a non-legitimate constant, force it into a 910 pseudo now. TLS symbols sometimes need a call to resolve. */ 911 if (CONSTANT_P (args[i].value) 912 && !LEGITIMATE_CONSTANT_P (args[i].value)) 913 args[i].value = force_reg (args[i].mode, args[i].value); 880 914 881 915 /* If we are to promote the function arg to a wider mode, … … 970 1004 { 971 1005 save_area = assign_stack_temp (BLKmode, num_to_save, 0); 972 /* Cannot use emit_block_move here because it can be done by a 973 library call which in turn gets into this place again and deadly 974 infinite recursion happens. */ 975 move_by_pieces (validize_mem (save_area), stack_area, num_to_save, 976 PARM_BOUNDARY); 1006 emit_block_move (validize_mem (save_area), stack_area, 1007 GEN_INT (num_to_save), BLOCK_OP_CALL_PARM); 977 1008 } 978 1009 else … … 1011 1042 emit_move_insn (stack_area, save_area); 1012 1043 else 1013 /* Cannot use emit_block_move here because it can be done by a library 1014 call which in turn gets into this place again and deadly infinite 1015 recursion happens. */ 1016 move_by_pieces (stack_area, validize_mem (save_area), 1017 high_to_save - low_to_save + 1, PARM_BOUNDARY); 1044 emit_block_move (stack_area, validize_mem (save_area), 1045 GEN_INT (high_to_save - low_to_save + 1), 1046 BLOCK_OP_CALL_PARM); 1018 1047 } 1019 1048 #endif /* REG_PARM_STACK_SPACE */ … … 1056 1085 calculating the bit offset. */ 1057 1086 if (BYTES_BIG_ENDIAN 1058 && !FUNCTION_ARG_REG_LITTLE_ENDIAN1059 1087 && bytes < UNITS_PER_WORD) 1060 1088 big_endian_correction = (BITS_PER_WORD - (bytes * BITS_PER_UNIT)); … … 1542 1570 = gen_lowpart_SUBREG (mode, args[i].value); 1543 1571 SUBREG_PROMOTED_VAR_P (args[i].initial_value) = 1; 1544 SUBREG_PROMOTED_UNSIGNED_ P (args[i].initial_value)1545 = args[i].unsignedp;1572 SUBREG_PROMOTED_UNSIGNED_SET (args[i].initial_value, 1573 args[i].unsignedp); 1546 1574 } 1547 1575 #endif … … 1648 1676 addr = plus_constant (addr, arg_offset); 1649 1677 args[i].stack = gen_rtx_MEM (args[i].mode, addr); 1678 set_mem_align (args[i].stack, PARM_BOUNDARY); 1650 1679 set_mem_attributes (args[i].stack, 1651 1680 TREE_TYPE (args[i].tree_value), 1); … … 1658 1687 addr = plus_constant (addr, arg_offset); 1659 1688 args[i].stack_slot = gen_rtx_MEM (args[i].mode, addr); 1689 set_mem_align (args[i].stack_slot, PARM_BOUNDARY); 1660 1690 set_mem_attributes (args[i].stack_slot, 1661 1691 TREE_TYPE (args[i].tree_value), 1); … … 1677 1707 FNDECL will be NULL_TREE. 1678 1708 1679 EXP is theCALL_EXPR for this call. */1709 ADDR is the operand 0 of CALL_EXPR for this call. */ 1680 1710 1681 1711 static rtx 1682 rtx_for_function_call (fndecl, exp)1712 rtx_for_function_call (fndecl, addr) 1683 1713 tree fndecl; 1684 tree exp;1714 tree addr; 1685 1715 { 1686 1716 rtx funexp; … … 1706 1736 push_temp_slots (); 1707 1737 funaddr = funexp 1708 = expand_expr ( TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);1738 = expand_expr (addr, NULL_RTX, VOIDmode, 0); 1709 1739 pop_temp_slots (); /* FUNEXP can't be BLKmode. */ 1710 1740 emit_queue (); … … 1884 1914 seq = get_insns (); 1885 1915 end_sequence (); 1886 emit_insn s_before (seq, first_insn);1916 emit_insn_before (seq, first_insn); 1887 1917 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX); 1888 1918 } … … 1907 1937 warning ("called from here"); 1908 1938 } 1909 mark_addressable(fndecl);1939 (*lang_hooks.mark_addressable) (fndecl); 1910 1940 return (rtx) (size_t) - 1; 1911 1941 } … … 1973 2003 we already clobbered by tail call arguments (as noted in stored_args_map 1974 2004 bitmap). 1975 Return non -zero if X expression dereferences such argument slots,2005 Return nonzero if X expression dereferences such argument slots, 1976 2006 zero otherwise. */ 1977 2007 … … 2036 2066 we already clobbered by tail call arguments (as noted in stored_args_map 2037 2067 bitmap). Add stack slots for ARG to stored_args_map bitmap afterwards. 2038 Return non -zero if sequence after INSN dereferences such argument slots,2068 Return nonzero if sequence after INSN dereferences such argument slots, 2039 2069 zero otherwise. */ 2040 2070 … … 2207 2237 rtx call_fusage; 2208 2238 tree p = TREE_OPERAND (exp, 0); 2239 tree addr = TREE_OPERAND (exp, 0); 2209 2240 int i; 2210 2241 /* The alignment of the stack, in bits. */ … … 2242 2273 warning ("called from here"); 2243 2274 } 2244 mark_addressable(fndecl);2275 (*lang_hooks.mark_addressable) (fndecl); 2245 2276 } 2246 2277 … … 2288 2319 used. */ 2289 2320 if (! TREE_ADDRESSABLE (fndecl)) 2290 mark_addressable(fndecl);2321 (*lang_hooks.mark_addressable) (fndecl); 2291 2322 is_integrable = 0; 2292 2323 } … … 2328 2359 2329 2360 /* Operand 0 is a pointer-to-function; get the type of the function. */ 2330 funtype = TREE_TYPE ( TREE_OPERAND (exp, 0));2361 funtype = TREE_TYPE (addr); 2331 2362 if (! POINTER_TYPE_P (funtype)) 2332 2363 abort (); … … 2465 2496 /* Tail recursion fails, when we are not dealing with recursive calls. */ 2466 2497 if (!try_tail_recursion 2467 || TREE_CODE ( TREE_OPERAND (exp, 0)) != ADDR_EXPR2468 || TREE_OPERAND ( TREE_OPERAND (exp, 0), 0) != current_function_decl)2498 || TREE_CODE (addr) != ADDR_EXPR 2499 || TREE_OPERAND (addr, 0) != current_function_decl) 2469 2500 try_tail_recursion = 0; 2470 2501 … … 2490 2521 before the sibcall_epilogue. */ 2491 2522 || fndecl == NULL_TREE 2492 || (flags & (ECF_RETURNS_TWICE | ECF_LONGJMP)) 2493 || TREE_THIS_VOLATILE (fndecl) 2523 || (flags & (ECF_RETURNS_TWICE | ECF_LONGJMP | ECF_NORETURN)) 2494 2524 || !FUNCTION_OK_FOR_SIBCALL (fndecl) 2495 2525 /* If this function requires more stack slots than the current … … 2498 2528 /* If the callee pops its own arguments, then it must pop exactly 2499 2529 the same number of arguments as the current function. */ 2500 || RETURN_POPS_ARGS (fndecl, funtype, args_size.constant) 2501 != RETURN_POPS_ARGS (current_function_decl, 2502 TREE_TYPE (current_function_decl), 2503 current_function_args_size)) 2504 try_tail_call = 0; 2530 || (RETURN_POPS_ARGS (fndecl, funtype, args_size.constant) 2531 != RETURN_POPS_ARGS (current_function_decl, 2532 TREE_TYPE (current_function_decl), 2533 current_function_args_size)) 2534 || !(*lang_hooks.decls.ok_for_sibcall) (fndecl)) 2535 try_tail_call = 0; 2505 2536 2506 2537 if (try_tail_call || try_tail_recursion) … … 2547 2578 /* Do the same for the function address if it is an expression. */ 2548 2579 if (!fndecl) 2549 TREE_OPERAND (exp, 0) = fix_unsafe_tree (TREE_OPERAND (exp, 0));2580 addr = fix_unsafe_tree (addr); 2550 2581 /* Expanding one of those dangerous arguments could have added 2551 2582 cleanups, but otherwise give it a whirl. */ … … 2941 2972 NO_DEFER_POP; 2942 2973 2943 funexp = rtx_for_function_call (fndecl, exp);2974 funexp = rtx_for_function_call (fndecl, addr); 2944 2975 2945 2976 /* Figure out the register where the value, if any, will come back. */ … … 3077 3108 /* Verify that we've deallocated all the stack we used. */ 3078 3109 if (pass 3110 && ! (flags & (ECF_NORETURN | ECF_LONGJMP)) 3079 3111 && old_stack_allocated != stack_pointer_delta - pending_stack_adjust) 3080 3112 abort (); … … 3092 3124 insns = get_insns (); 3093 3125 end_sequence (); 3094 emit_insn s(insns);3126 emit_insn (insns); 3095 3127 } 3096 3128 else … … 3146 3178 insns = get_insns (); 3147 3179 end_sequence (); 3148 emit_insn s(insns);3180 emit_insn (insns); 3149 3181 valreg = temp; 3150 3182 } … … 3170 3202 3171 3203 emit_barrier_after (last); 3204 3205 /* Stack adjustments after a noreturn call are dead code. */ 3206 stack_pointer_delta = old_stack_allocated; 3207 pending_stack_adjust = 0; 3172 3208 } 3173 3209 … … 3291 3327 target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset); 3292 3328 SUBREG_PROMOTED_VAR_P (target) = 1; 3293 SUBREG_PROMOTED_UNSIGNED_ P (target) = unsignedp;3329 SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp); 3294 3330 } 3295 3331 #endif … … 3330 3366 emit_move_insn (stack_area, args[i].save_area); 3331 3367 else 3332 emit_block_move (stack_area, 3333 validize_mem (args[i].save_area),3334 GEN_INT (args[i].size.constant));3368 emit_block_move (stack_area, args[i].save_area, 3369 GEN_INT (args[i].size.constant), 3370 BLOCK_OP_CALL_PARM); 3335 3371 } 3336 3372 … … 3433 3469 } 3434 3470 else 3435 emit_insn s(normal_call_insns);3471 emit_insn (normal_call_insns); 3436 3472 3437 3473 currently_expanding_call--; … … 3498 3534 int needed; 3499 3535 rtx before_call; 3536 tree tfom; /* type_for_mode (outmode, 0) */ 3500 3537 3501 3538 #ifdef REG_PARM_STACK_SPACE … … 3559 3596 /* If this kind of value comes back in memory, 3560 3597 decide where in memory it should come back. */ 3561 if (outmode != VOIDmode && aggregate_value_p (type_for_mode (outmode, 0))) 3562 { 3598 if (outmode != VOIDmode) 3599 { 3600 tfom = (*lang_hooks.types.type_for_mode) (outmode, 0); 3601 if (aggregate_value_p (tfom)) 3602 { 3563 3603 #ifdef PCC_STATIC_STRUCT_RETURN 3564 rtx pointer_reg 3565 = hard_function_value (build_pointer_type (type_for_mode (outmode, 0)), 3566 0, 0); 3567 mem_value = gen_rtx_MEM (outmode, pointer_reg); 3568 pcc_struct_value = 1; 3569 if (value == 0) 3570 value = gen_reg_rtx (outmode); 3604 rtx pointer_reg 3605 = hard_function_value (build_pointer_type (tfom), 0, 0); 3606 mem_value = gen_rtx_MEM (outmode, pointer_reg); 3607 pcc_struct_value = 1; 3608 if (value == 0) 3609 value = gen_reg_rtx (outmode); 3571 3610 #else /* not PCC_STATIC_STRUCT_RETURN */ 3572 struct_value_size = GET_MODE_SIZE (outmode); 3573 if (value != 0 && GET_CODE (value) == MEM) 3574 mem_value = value; 3575 else 3576 mem_value = assign_temp (type_for_mode (outmode, 0), 0, 1, 1); 3577 #endif 3578 3579 /* This call returns a big structure. */ 3580 flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK); 3581 } 3611 struct_value_size = GET_MODE_SIZE (outmode); 3612 if (value != 0 && GET_CODE (value) == MEM) 3613 mem_value = value; 3614 else 3615 mem_value = assign_temp (tfom, 0, 1, 1); 3616 #endif 3617 /* This call returns a big structure. */ 3618 flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK); 3619 } 3620 } 3621 else 3622 tfom = void_type_node; 3582 3623 3583 3624 /* ??? Unfinished: must pass the memory address as an argument. */ … … 3687 3728 #endif 3688 3729 ; 3730 3731 /* loop.c won't look at CALL_INSN_FUNCTION_USAGE of const/pure 3732 functions, so we have to pretend this isn't such a function. */ 3733 if (flags & ECF_LIBCALL_BLOCK) 3734 { 3735 rtx insns = get_insns (); 3736 end_sequence (); 3737 emit_insn (insns); 3738 } 3739 flags &= ~(ECF_CONST | ECF_PURE | ECF_LIBCALL_BLOCK); 3689 3740 3690 3741 /* If this was a CONST function, it is now PURE since … … 3700 3751 else if (must_copy) 3701 3752 { 3702 slot = assign_temp (type_for_mode (mode, 0), 0, 1, 1); 3753 slot = assign_temp ((*lang_hooks.types.type_for_mode) (mode, 0), 3754 0, 1, 1); 3703 3755 emit_move_insn (slot, val); 3704 3756 } 3705 3757 else 3706 3758 { 3707 tree type = type_for_mode(mode, 0);3759 tree type = (*lang_hooks.types.type_for_mode) (mode, 0); 3708 3760 3709 3761 slot = gen_rtx_MEM (mode, … … 3915 3967 save_area = assign_stack_temp (BLKmode, num_to_save, 0); 3916 3968 set_mem_align (save_area, PARM_BOUNDARY); 3917 emit_block_move ( validize_mem (save_area), stack_area,3918 GEN_INT (num_to_save));3969 emit_block_move (save_area, stack_area, GEN_INT (num_to_save), 3970 BLOCK_OP_CALL_PARM); 3919 3971 } 3920 3972 else … … 3978 4030 plus_constant (argblock, 3979 4031 argvec[argnum].offset.constant))); 3980 argvec[argnum].save_area = gen_reg_rtx (save_mode); 3981 3982 emit_move_insn (argvec[argnum].save_area, stack_area); 4032 if (save_mode == BLKmode) 4033 { 4034 argvec[argnum].save_area 4035 = assign_stack_temp (BLKmode, 4036 argvec[argnum].size.constant, 0); 4037 4038 emit_block_move (validize_mem (argvec[argnum].save_area), 4039 stack_area, 4040 GEN_INT (argvec[argnum].size.constant), 4041 BLOCK_OP_CALL_PARM); 4042 } 4043 else 4044 { 4045 argvec[argnum].save_area = gen_reg_rtx (save_mode); 4046 4047 emit_move_insn (argvec[argnum].save_area, stack_area); 4048 } 3983 4049 } 3984 4050 } 3985 4051 3986 emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0, 3987 argblock, GEN_INT (argvec[argnum].offset.constant), 4052 emit_push_insn (val, mode, NULL_TREE, NULL_RTX, PARM_BOUNDARY, 4053 partial, reg, 0, argblock, 4054 GEN_INT (argvec[argnum].offset.constant), 3988 4055 reg_parm_stack_space, ARGS_SIZE_RTX (alignment_pad)); 3989 4056 … … 4072 4139 emit_call_1 (fun, 4073 4140 get_identifier (XSTR (orgfun, 0)), 4074 build_function_type (outmode == VOIDmode ? void_type_node 4075 : type_for_mode (outmode, 0), NULL_TREE), 4141 build_function_type (tfom, NULL_TREE), 4076 4142 original_args_size.constant, args_size.constant, 4077 4143 struct_value_size, … … 4113 4179 rtx insns; 4114 4180 4115 if (valreg == 0 || GET_CODE (valreg) == PARALLEL)4181 if (valreg == 0) 4116 4182 { 4117 4183 insns = get_insns (); 4118 4184 end_sequence (); 4119 emit_insn s(insns);4185 emit_insn (insns); 4120 4186 } 4121 4187 else 4122 4188 { 4123 4189 rtx note = 0; 4124 rtx temp = gen_reg_rtx (GET_MODE (valreg));4190 rtx temp; 4125 4191 int i; 4192 4193 if (GET_CODE (valreg) == PARALLEL) 4194 { 4195 temp = gen_reg_rtx (outmode); 4196 emit_group_store (temp, valreg, outmode); 4197 valreg = temp; 4198 } 4199 4200 temp = gen_reg_rtx (GET_MODE (valreg)); 4126 4201 4127 4202 /* Construct an "equal form" for the value which mentions all the … … 4158 4233 emit_move_insn (value, mem_value); 4159 4234 } 4235 else if (GET_CODE (valreg) == PARALLEL) 4236 { 4237 if (value == 0) 4238 value = gen_reg_rtx (outmode); 4239 emit_group_store (value, valreg, outmode); 4240 } 4160 4241 else if (value != 0) 4161 emit_move_insn (value, hard_libcall_value (outmode));4242 emit_move_insn (value, valreg); 4162 4243 else 4163 value = hard_libcall_value (outmode);4244 value = valreg; 4164 4245 } 4165 4246 … … 4187 4268 emit_move_insn (stack_area, save_area); 4188 4269 else 4189 emit_block_move (stack_area, validize_mem (save_area), 4190 GEN_INT (high_to_save - low_to_save + 1)); 4270 emit_block_move (stack_area, save_area, 4271 GEN_INT (high_to_save - low_to_save + 1), 4272 BLOCK_OP_CALL_PARM); 4191 4273 } 4192 4274 #endif … … 4204 4286 argvec[count].offset.constant))); 4205 4287 4206 emit_move_insn (stack_area, argvec[count].save_area); 4288 if (save_mode == BLKmode) 4289 emit_block_move (stack_area, 4290 validize_mem (argvec[count].save_area), 4291 GEN_INT (argvec[count].size.constant), 4292 BLOCK_OP_CALL_PARM); 4293 else 4294 emit_move_insn (stack_area, argvec[count].save_area); 4207 4295 } 4208 4296 … … 4293 4381 FNDECL is the declaration of the function we are calling. 4294 4382 4295 Return non -zero if this arg should cause sibcall failure,4383 Return nonzero if this arg should cause sibcall failure, 4296 4384 zero otherwise. */ 4297 4385 … … 4301 4389 rtx argblock; 4302 4390 int flags; 4303 int variable_size ;4391 int variable_size ATTRIBUTE_UNUSED; 4304 4392 int reg_parm_stack_space; 4305 4393 { … … 4368 4456 preserve_temp_slots (arg->save_area); 4369 4457 emit_block_move (validize_mem (arg->save_area), stack_area, 4370 expr_size (arg->tree_value)); 4458 expr_size (arg->tree_value), 4459 BLOCK_OP_CALL_PARM); 4371 4460 } 4372 4461 else … … 4376 4465 } 4377 4466 } 4378 4379 /* Now that we have saved any slots that will be overwritten4380 by this store, mark all slots this store will use. We4381 must do this before we actually expand the argument since4382 the expansion itself may trigger library calls which might4383 need to use the same stack slot. We only do it if we can't4384 pass all arguments to a library call in registers. */4385 if (arg->partial)4386 {4387 for (i = lower_bound; i < upper_bound; i++)4388 stack_usage_map[i] = 1;4389 4390 /* Set it so that we don't do it again. */4391 variable_size = 1;4392 }4393 4467 } 4394 4468 } … … 4444 4518 || TYPE_MODE (TREE_TYPE (pval)) != arg->mode) 4445 4519 ? NULL_RTX : arg->stack, 4446 VOIDmode, 0);4520 VOIDmode, EXPAND_STACK_PARM); 4447 4521 4448 4522 /* If we are promoting object (or for any other reason) the mode … … 4497 4571 /* This isn't already where we want it on the stack, so put it there. 4498 4572 This can either be done with push or copy insns. */ 4499 emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX, 0,4500 partial, reg, used - size, argblock,4573 emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX, 4574 PARM_BOUNDARY, partial, reg, used - size, argblock, 4501 4575 ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space, 4502 4576 ARGS_SIZE_RTX (arg->alignment_pad)); … … 4511 4585 /* BLKmode, at least partly to be pushed. */ 4512 4586 4587 unsigned int parm_align; 4513 4588 int excess; 4514 4589 rtx size_rtx; … … 4534 4609 size_rtx = expand_expr (size_in_bytes (TREE_TYPE (pval)), 4535 4610 NULL_RTX, TYPE_MODE (sizetype), 0); 4611 } 4612 4613 /* Some types will require stricter alignment, which will be 4614 provided for elsewhere in argument layout. */ 4615 parm_align = MAX (PARM_BOUNDARY, TYPE_ALIGN (TREE_TYPE (pval))); 4616 4617 /* When an argument is padded down, the block is aligned to 4618 PARM_BOUNDARY, but the actual argument isn't. */ 4619 if (FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)) == downward) 4620 { 4621 if (arg->size.var) 4622 parm_align = BITS_PER_UNIT; 4623 else if (excess) 4624 { 4625 unsigned int excess_align = (excess & -excess) * BITS_PER_UNIT; 4626 parm_align = MIN (parm_align, excess_align); 4627 } 4536 4628 } 4537 4629 … … 4569 4661 } 4570 4662 4571 /* Special handling is required if part of the parameter lies in the4572 register parameter area. The argument may be copied into the stack4573 slot using memcpy(), but the original contents of the register4574 parameter area will be restored after the memcpy() call.4575 4576 To ensure that the part that lies in the register parameter area4577 is copied correctly, we emit a separate push for that part. This4578 push should be small enough to avoid a call to memcpy(). */4579 #ifndef STACK_PARMS_IN_REG_PARM_AREA4580 if (arg->reg && arg->pass_on_stack)4581 #else4582 if (1)4583 #endif4584 {4585 if (arg->offset.constant < reg_parm_stack_space && arg->offset.var)4586 error ("variable offset is passed partially in stack and in reg");4587 else if (arg->offset.constant < reg_parm_stack_space && arg->size.var)4588 error ("variable size is passed partially in stack and in reg");4589 else if (arg->offset.constant < reg_parm_stack_space4590 && ((arg->offset.constant + arg->size.constant)4591 > reg_parm_stack_space))4592 {4593 rtx size_rtx1 = GEN_INT (reg_parm_stack_space - arg->offset.constant);4594 emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx1,4595 TYPE_ALIGN (TREE_TYPE (pval)), partial, reg,4596 excess, argblock, ARGS_SIZE_RTX (arg->offset),4597 reg_parm_stack_space,4598 ARGS_SIZE_RTX (arg->alignment_pad));4599 }4600 }4601 4602 4603 4663 emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx, 4604 TYPE_ALIGN (TREE_TYPE (pval)), partial, reg, excess, 4605 argblock, ARGS_SIZE_RTX (arg->offset), 4606 reg_parm_stack_space, 4664 parm_align, partial, reg, excess, argblock, 4665 ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space, 4607 4666 ARGS_SIZE_RTX (arg->alignment_pad)); 4608 4667 … … 4619 4678 } 4620 4679 4680 /* Mark all slots this store used. */ 4621 4681 if (ACCUMULATE_OUTGOING_ARGS && !(flags & ECF_SIBCALL) 4622 4682 && argblock && ! variable_size && arg->stack) -
Property cvs2svn:cvs-rev
changed from
Note:
See TracChangeset
for help on using the changeset viewer.