annotate gcc/cbc-goto.h @ 3:d43292db8c8c

finished merging
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2009 19:00:23 +0900
parents
children 983001f85155
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2 #define CbC_ARGS_SIZE 256
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 static void
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5 preexpand_argument_expr (struct arg_data *, int);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 static void
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 determine_order(int *, int);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10 static int
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 expand_one_arg_push (struct arg_data *, rtx, int, int, int);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 static void
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 push_overlaps(struct arg_data *, int);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 static int
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 check_frame_offset(rtx);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 static rtx
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 expand_cbc_goto (tree exp, rtx target, tree fndecl, tree funtype, tree fntype,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 tree addr,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 int ignore,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 int flags,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 int num_actuals,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 struct arg_data *args,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 struct args_size *args_size,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
28 CUMULATIVE_ARGS args_so_far,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
29 rtx old_stack_level,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
30 int reg_parm_stack_space,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
31 int old_pending_adj,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
32 unsigned HOST_WIDE_INT preferred_stack_boundary,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
33 unsigned HOST_WIDE_INT preferred_unit_stack_boundary,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 rtx structure_value_addr,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
35 //int structure_value_addr_parm,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
36 int old_inhibit_defer_pop
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
37 )
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
38 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
39
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
40 /* folowing variables is just copied from expand_call. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
41
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
42 int pass = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
43 int i;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
44 #ifdef REG_PARM_STACK_SPACE
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
45 /* Define the boundary of the register parm stack space that needs to be
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
46 saved, if any. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
47 #endif
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
48 rtx funexp;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
49 rtx valreg;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
50 struct args_size adjusted_args_size;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 int unadjusted_args_size;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
52 int reg_parm_seen;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
53 rtx static_chain_value;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
54 int old_stack_allocated;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
55 int old_stack_pointer_delta = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
56 int old_stack_arg_under_construction = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 rtx call_fusage;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
58 char *stack_usage_map_buf = NULL;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 rtx argblock = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 HOST_WIDE_INT struct_value_size = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
61 int pcc_struct_value = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
62 int initial_highest_arg_in_use = highest_outgoing_arg_in_use;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
63 char *initial_stack_usage_map = stack_usage_map;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
64 rtx tail_call_insns = NULL_RTX;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
65
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
66
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
67 int *store_order;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
68
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
69
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
70 int sibcall_failure = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
71 /* We want to emit any pending stack adjustments before the tail
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
72 recursion "call". That way we know any adjustment after the tail
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
73 recursion call can be ignored if we indeed use the tail
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
74 call expansion. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
75 int save_pending_stack_adjust = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 int save_stack_pointer_delta = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
77 rtx insns;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
78 rtx before_call, next_arg_reg;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
79
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
80 /* for environment. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
81 rtx env_rtx;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
82 tree env_tree;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
83
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
84 env_tree = TREE_OPERAND(exp, 2);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
85
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
86
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
87 /* State variables we need to save and restore between
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
88 iterations. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
89 save_pending_stack_adjust = pending_stack_adjust;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
90 save_stack_pointer_delta = stack_pointer_delta;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
91 flags |= ECF_SIBCALL;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
92
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
93 /* Other state variables that we must reinitialize each time
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
94 through the loop (that are not initialized by the loop itself). */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
95 argblock = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
96 call_fusage = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
97
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
98 /* Start a new sequence for the normal call case.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
99
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
100 From this point on, if the sibling call fails, we want to set
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
101 sibcall_failure instead of continuing the loop. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
102 start_sequence ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
103
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
104 /* Don't let pending stack adjusts add up to too much.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
105 Also, do all pending adjustments now if there is any chance
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
106 this might be a call to alloca or if we are expanding a sibling
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 call sequence or if we are calling a function that is to return
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
108 with stack pointer depressed.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
109 Also do the adjustments before a throwing call, otherwise
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
110 exception handling can fail; PR 19225. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
111 if (pending_stack_adjust >= 32
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
112 || (pending_stack_adjust > 0
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
113 && (flags & ECF_MAY_BE_ALLOCA))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
114 || (pending_stack_adjust > 0
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
115 && flag_exceptions && !(flags & ECF_NOTHROW))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
116 || pass == 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
117 do_pending_stack_adjust ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
118
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
119
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
120 if (pass == 0 && crtl->stack_protect_guard)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
121 stack_protect_epilogue ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
122
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
123 adjusted_args_size = *args_size;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
124 /* Compute the actual size of the argument block required. The variable
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
125 and constant sizes must be combined, the size may have to be rounded,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
126 and there may be a minimum required size. When generating a sibcall
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
127 pattern, do not round up, since we'll be re-using whatever space our
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
128 caller provided. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
129 unadjusted_args_size
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
130 = compute_argument_block_size (reg_parm_stack_space,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
131 &adjusted_args_size,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
132 fndecl, fntype,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
133 (pass == 0 ? 0
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
134 : preferred_stack_boundary));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
135
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
136 old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
137
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
138 /* The argument block when performing a sibling call is the
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
139 incoming argument block. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
140 /*
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
141 if ( 0 && !CbC_IS_CODE_SEGMENT(TREE_TYPE(current_function_decl)) )
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
142 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
143 argblock = virtual_outgoing_args_rtx;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
144 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
145 else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
146 */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
147
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
148 if ( env_tree!=NULL_TREE )
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
149 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
150 /*
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
151 * ebp <= TREE_VALUE ( env_tree );
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
152 * argsp <= TREE_PURPOSE ( env_tree );
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
153 *
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
154 */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
155 //rtx tmp;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
156 /* compute environment. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
157 push_temp_slots ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
158 /* expand_expr shouldn't be here... it's moved later. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
159 //env_rtx = expand_expr ( env_tree, NULL_RTX,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
160 //VOIDmode, EXPAND_STACK_PARM);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
161 //argblock = hard_frame_pointer_rtx;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
162 //argblock = env_rtx;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
163 //argblock = plus_constant (argblock, -current_function_arg_offset_rtx);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
164 //tmp = gen_rtx_MINUS (Pmode, hard_frame_pointer_rtx, virtual_incoming_args_rtx);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
165 //argblock = gen_rtx_MINUS (Pmode, env_rtx, tmp);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
166 //argblock = plus_constant (argblock, frame_offset);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
167 argblock = expand_expr ( TREE_VALUE (env_tree), NULL_RTX,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
168 VOIDmode, EXPAND_STACK_PARM);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
169 env_rtx = expand_expr ( TREE_PURPOSE (env_tree), NULL_RTX,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
170 VOIDmode, EXPAND_STACK_PARM);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
171 preserve_temp_slots (argblock);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
172 pop_temp_slots ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
173 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
174 else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
175 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
176 //argblock = virtual_incoming_args_rtx;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
177 argblock = crtl->args.internal_arg_pointer;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
178
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
179 argblock
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
180 #ifdef STACK_GROWS_DOWNWARD
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
181 = plus_constant (argblock, crtl->args.pretend_args_size);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
182 #else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
183 = plus_constant (argblock, -crtl->args.pretend_args_size);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
184 #endif
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
185 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
186
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
187
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
188 stored_args_map = sbitmap_alloc (args_size->constant);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
189 sbitmap_zero (stored_args_map);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
190
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
191
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
192 if (ACCUMULATE_OUTGOING_ARGS)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
193 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
194 /* The save/restore code in store_one_arg handles all
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
195 cases except one: a constructor call (including a C
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
196 function returning a BLKmode struct) to initialize
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
197 an argument. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
198 if (stack_arg_under_construction)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
199 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
200 rtx push_size
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
201 = GEN_INT (adjusted_args_size.constant
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
202 + (OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? fntype
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 : TREE_TYPE (fndecl))) ? 0
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
204 : reg_parm_stack_space));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
205 if (old_stack_level == 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
206 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
207 emit_stack_save (SAVE_BLOCK, &old_stack_level,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
208 NULL_RTX);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
209 old_stack_pointer_delta = stack_pointer_delta;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
210 old_pending_adj = pending_stack_adjust;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
211 pending_stack_adjust = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
212 /* stack_arg_under_construction says whether a stack
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
213 arg is being constructed at the old stack level.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
214 Pushing the stack gets a clean outgoing argument
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
215 block. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
216 old_stack_arg_under_construction
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
217 = stack_arg_under_construction;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
218 stack_arg_under_construction = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
219 /* Make a new map for the new argument list. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
220 if (stack_usage_map_buf)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
221 free (stack_usage_map_buf);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
222 stack_usage_map_buf = XNEWVEC (char, highest_outgoing_arg_in_use);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
223 stack_usage_map = stack_usage_map_buf;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
224 memset (stack_usage_map, 0, highest_outgoing_arg_in_use);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
225 highest_outgoing_arg_in_use = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
226 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
227 allocate_dynamic_stack_space (push_size, NULL_RTX,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
228 BITS_PER_UNIT);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
229 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
230
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
231 /* If argument evaluation might modify the stack pointer,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
232 copy the address of the argument list to a register. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
233 for (i = 0; i < num_actuals; i++)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
234 if (args[i].pass_on_stack)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
235 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
236 argblock = copy_addr_to_reg (argblock);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
237 break;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
238 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
239 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
240
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
241 compute_argument_addresses (args, argblock, num_actuals);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
242
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
243 /* in the case that
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
244 a function goto codesegment.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
245 adjust stack space. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
246 if ( !CbC_IS_CODE_SEGMENT(TREE_TYPE(current_function_decl)) )
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
247 //if ( !(current_function_decl&&CbC_IS_CODE_SEGMENT(current_function_decl)) )
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
248 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
249 HOST_WIDE_INT padding;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
250 padding = CbC_ARGS_SIZE -
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
251 (crtl->args.size - crtl->args.pretend_args_size);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
252 if (0&&padding > 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
253 anti_adjust_stack (GEN_INT (padding));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
254 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
255
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
256 /* Now that the stack is properly aligned, pops can't safely
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
257 be deferred during the evaluation of the arguments. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
258 NO_DEFER_POP;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
259
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
260 funexp = rtx_for_function_call (fndecl, addr);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
261
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
262 /* Figure out the register where the value, if any, will come back. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
263 valreg = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
264
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
265
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
266 /* Precompute all register parameters. It isn't safe to compute anything
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
267 once we have started filling any specific hard regs. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
268 precompute_register_parameters (num_actuals, args, &reg_parm_seen);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
269
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
270 /* operand[2] is environment. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
271 //if (TREE_OPERAND (exp, 2))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
272 //static_chain_value = expand_normal (TREE_OPERAND (exp, 2));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
273 //else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
274 static_chain_value = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
275
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
276
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
277 /* parallel assignment */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
278 store_order = alloca (num_actuals * sizeof (int));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
279 memset (store_order, 0, num_actuals * sizeof (int));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
280
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
281 /* fill the arg[i]->exprs. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
282 for (i = 0; i < num_actuals; i++)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
283 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
284 if (args[i].reg == 0 || args[i].pass_on_stack)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
285 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
286 preexpand_argument_expr (&args[i],
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
287 adjusted_args_size.var != 0);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
288 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
289 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
290
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
291
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
292 /* push overlapped argument to stack. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
293 push_overlaps(args, num_actuals);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
294
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
295 /* determine ordering to store arguments.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
296 and generate RTL that store some variable temporary, if it needed.*/
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
297 /* now... this function do nothing. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
298 determine_order(store_order, num_actuals);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
299
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
300 /* push arguments in the order . */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
301 for (i = 0; i < num_actuals; i++)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
302 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
303 if (args[store_order[i]].reg == 0
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
304 || args[store_order[i]].pass_on_stack
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
305 || args[store_order[i]].partial!=0 )
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
306 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
307 expand_one_arg_push (&args[store_order[i]], argblock, flags,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
308 adjusted_args_size.var != 0,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
309 reg_parm_stack_space);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
310 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
311 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
312
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
313
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
314 /* If register arguments require space on the stack and stack space
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
315 was not preallocated, allocate stack space here for arguments
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
316 passed in registers. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
317 #ifdef OUTGOING_REG_PARM_STACK_SPACE
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
318 //if (!ACCUMULATE_OUTGOING_ARGS
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
319 //&& must_preallocate == 0 && reg_parm_stack_space > 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
320 //anti_adjust_stack (GEN_INT (reg_parm_stack_space));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
321 #endif
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
322
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
323 /* */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
324 funexp = prepare_call_address (funexp, static_chain_value,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
325 &call_fusage, reg_parm_seen, pass == 0);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
326
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
327 /* store args into register. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
328 load_register_parameters (args, num_actuals, &call_fusage, flags,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
329 //pass == 0, &sibcall_failure);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
330 0, NULL);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
331
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
332 /* Save a pointer to the last insn before the call, so that we can
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
333 later safely search backwards to find the CALL_INSN. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
334 before_call = get_last_insn ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
335
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
336 /* Set up next argument register. For sibling calls on machines
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
337 with register windows this should be the incoming register. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
338 #ifdef FUNCTION_INCOMING_ARG
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
339 if (pass == 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
340 next_arg_reg = FUNCTION_INCOMING_ARG (args_so_far, VOIDmode,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
341 void_type_node, 1);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
342 else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
343 #endif
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
344 next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
345 void_type_node, 1);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
346
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
347 /* All arguments and registers used for the call must be set up by
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
348 now! */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
349
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
350 /* Stack must be properly aligned now. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
351 gcc_assert (!pass
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
352 || !(stack_pointer_delta % preferred_unit_stack_boundary));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
353
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
354 /* store environment. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
355 if ( env_tree!=NULL )
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
356 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
357 emit_insn (gen_rtx_CLOBBER (VOIDmode,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
358 gen_rtx_MEM (BLKmode,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
359 hard_frame_pointer_rtx)));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
360 emit_move_insn (hard_frame_pointer_rtx, env_rtx);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
361 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
362 //pop_temp_slots ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
363
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
364 emit_indirect_jump (funexp);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
365 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
366
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
367 /* Generate the actual call instruction. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
368 emit_call_1 (funexp, exp, fndecl, funtype, unadjusted_args_size,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
369 adjusted_args_size.constant, struct_value_size,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
370 //next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
371 next_arg_reg, valreg, 0, call_fusage,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
372 flags, & args_so_far);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
373
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
374 /* If a non-BLKmode value is returned at the most significant end
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
375 of a register, shift the register right by the appropriate amount
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
376 and update VALREG accordingly. BLKmode values are handled by the
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
377 group load/store machinery below. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
378 if (!structure_value_addr
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
379 && !pcc_struct_value
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
380 && TYPE_MODE (TREE_TYPE (exp)) != BLKmode
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
381 && targetm.calls.return_in_msb (TREE_TYPE (exp)))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
382 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
383 if (shift_return_value (TYPE_MODE (TREE_TYPE (exp)), false, valreg))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
384 sibcall_failure = 1;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
385 valreg = gen_rtx_REG (TYPE_MODE (TREE_TYPE (exp)), REGNO (valreg));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
386 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
387
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
388
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
389 /* For calls to `setjmp', etc., inform flow.c it should complain
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
390 if nonvolatile values are live. For functions that cannot return,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
391 inform flow that control does not fall through. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
392
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
393 if ((flags & ECF_NORETURN) || pass == 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
394 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
395 /* The barrier must be emitted
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
396 immediately after the CALL_INSN. Some ports emit more
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
397 than just a CALL_INSN above, so we must search for it here. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
398
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
399 rtx last = get_last_insn ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
400 while (!CALL_P (last))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
401 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
402 last = PREV_INSN (last);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
403 /* There was no CALL_INSN? */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
404 gcc_assert (last != before_call);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
405 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
406
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
407 emit_barrier_after (last);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
408
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
409 /* Stack adjustments after a noreturn call are dead code.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
410 However when NO_DEFER_POP is in effect, we must preserve
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
411 stack_pointer_delta. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
412 if (inhibit_defer_pop == 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
413 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
414 stack_pointer_delta = old_stack_allocated;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
415 pending_stack_adjust = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
416 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
417 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
418
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
419 /* If value type not void, return an rtx for the value. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
420
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
421 if (TYPE_MODE (TREE_TYPE (exp)) == VOIDmode
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
422 || ignore)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
423 target = const0_rtx;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
424
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
425 if (targetm.calls.promote_function_return(funtype))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
426 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
427 /* If we promoted this return value, make the proper SUBREG.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
428 TARGET might be const0_rtx here, so be careful. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
429 if (REG_P (target)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
430 && TYPE_MODE (TREE_TYPE (exp)) != BLKmode
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
431 && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
432 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
433 tree type = TREE_TYPE (exp);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
434 int unsignedp = TYPE_UNSIGNED (type);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
435 int offset = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
436 enum machine_mode pmode;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
437
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
438 pmode = promote_mode (type, TYPE_MODE (type), &unsignedp, 1);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
439 /* If we don't promote as expected, something is wrong. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
440 gcc_assert (GET_MODE (target) == pmode);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
441
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
442 if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
443 && (GET_MODE_SIZE (GET_MODE (target))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
444 > GET_MODE_SIZE (TYPE_MODE (type))))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
445 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
446 offset = GET_MODE_SIZE (GET_MODE (target))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
447 - GET_MODE_SIZE (TYPE_MODE (type));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
448 if (! BYTES_BIG_ENDIAN)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
449 offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
450 else if (! WORDS_BIG_ENDIAN)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
451 offset %= UNITS_PER_WORD;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
452 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
453 target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
454 SUBREG_PROMOTED_VAR_P (target) = 1;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
455 SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
456 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
457 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
458
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
459 /* If size of args is variable or this was a constructor call for a stack
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
460 argument, restore saved stack-pointer value. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
461
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
462 if (old_stack_level)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
463 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
464 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
465 stack_pointer_delta = old_stack_pointer_delta;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
466 pending_stack_adjust = old_pending_adj;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
467 old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
468 stack_arg_under_construction = old_stack_arg_under_construction;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
469 highest_outgoing_arg_in_use = initial_highest_arg_in_use;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
470 stack_usage_map = initial_stack_usage_map;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
471 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
472
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
473 /* If this was alloca, record the new stack level for nonlocal gotos.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
474 Check for the handler slots since we might not have a save area
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
475 for non-local gotos. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
476
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
477 if ((flags & ECF_MAY_BE_ALLOCA) && cfun->nonlocal_goto_save_area != 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
478 update_nonlocal_goto_save_area ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
479
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
480 /* Free up storage we no longer need. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
481 for (i = 0; i < num_actuals; ++i)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
482 if (args[i].aligned_regs)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
483 free (args[i].aligned_regs);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
484
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
485 insns = get_insns ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
486 end_sequence ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
487
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
488 tail_call_insns = insns;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
489
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
490 /* Restore the pending stack adjustment now that we have
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
491 finished generating the sibling call sequence. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
492
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
493 pending_stack_adjust = save_pending_stack_adjust;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
494 stack_pointer_delta = save_stack_pointer_delta;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
495
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
496 /* Prepare arg structure for next iteration. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
497 for (i = 0; i < num_actuals; i++)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
498 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
499 args[i].value = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
500 args[i].aligned_regs = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
501 args[i].stack = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
502 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
503
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
504 sbitmap_free (stored_args_map);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
505
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
506
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
507 emit_insn(tail_call_insns);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
508 crtl->tail_call_emit = true;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
509
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
510 return target;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
511 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
512
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
513
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
514 static void
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
515 preexpand_argument_expr (struct arg_data *arg,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
516 int variable_size ATTRIBUTE_UNUSED)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
517 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
518 tree pval = arg->tree_value;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
519 rtx reg = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
520 int partial = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
521
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
522 if (TREE_CODE (pval) == ERROR_MARK)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
523 return;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
524
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
525 /* Push a new temporary level for any temporaries we make for
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
526 this argument. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
527 push_temp_slots ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
528
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
529
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
530 /* If this isn't going to be placed on both the stack and in registers,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
531 set up the register and number of words. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
532 if (! arg->pass_on_stack)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
533 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
534 //if (flags & ECF_SIBCALL)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
535 reg = arg->tail_call_reg;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
536 //else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
537 //reg = arg->reg;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
538 partial = arg->partial;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
539 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
540
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
541 /* Being passed entirely in a register. We shouldn't be called in
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
542 this case. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
543 gcc_assert (reg == 0 || partial != 0);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
544
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
545 /* If this arg needs special alignment, don't load the registers
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
546 here. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
547 if (arg->n_aligned_regs != 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
548 reg = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
549
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
550 /* Start a new sequence for the arg->exprs. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
551 start_sequence ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
552
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
553
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
554 if (arg->pass_on_stack)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
555 stack_arg_under_construction++;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
556
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
557 arg->value = expand_expr (pval,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
558 (partial
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
559 || TYPE_MODE (TREE_TYPE (pval)) != arg->mode)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
560 ? NULL_RTX : arg->stack,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
561 VOIDmode, EXPAND_STACK_PARM);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
562
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
563 /* If we are promoting object (or for any other reason) the mode
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
564 doesn't agree, convert the mode. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
565
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
566 if (arg->mode != TYPE_MODE (TREE_TYPE (pval)))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
567 arg->value = convert_modes (arg->mode, TYPE_MODE (TREE_TYPE (pval)),
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
568 arg->value, arg->unsignedp);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
569
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
570 if (arg->pass_on_stack)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
571 stack_arg_under_construction--;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
572
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
573 arg->exprs = get_insns ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
574 end_sequence ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
575
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
576 if (arg->exprs) emit_insn(arg->exprs);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
577
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
578 preserve_temp_slots (arg->value);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
579 pop_temp_slots ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
580
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
581 return ;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
582 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
583
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
584 static int
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
585 expand_one_arg_push (struct arg_data *arg, rtx argblock, int flags,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
586 int variable_size ATTRIBUTE_UNUSED, int reg_parm_stack_space)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
587 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
588 tree pval = arg->tree_value;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
589 int used = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
590 int i, lower_bound = 0, upper_bound = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
591 rtx reg = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
592 int partial = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
593
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
594 /* Push a new temporary level for any temporaries we make for
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
595 this argument. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
596 push_temp_slots ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
597
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
598
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
599 /* copy from store_one_arg. modify here after.*/
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
600 /* If this isn't going to be placed on both the stack and in registers,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
601 set up the register and number of words. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
602 if (! arg->pass_on_stack)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
603 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
604 //if (flags & ECF_SIBCALL)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
605 reg = arg->tail_call_reg;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
606 //else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
607 //reg = arg->reg;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
608 partial = arg->partial;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
609 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
610 /* Being passed entirely in a register. We shouldn't be called in
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
611 this case. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
612 gcc_assert (reg == 0 || partial != 0);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
613 /* If this arg needs special alignment, don't load the registers
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
614 here. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
615 if (arg->n_aligned_regs != 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
616 reg = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
617
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
618
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
619
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
620
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
621 if (arg->value == arg->stack)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
622 /* If the value is already in the stack slot, we are done. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
623 ;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
624 else if (arg->mode != BLKmode)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
625 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
626 int size;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
627
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
628 /* Argument is a scalar, not entirely passed in registers.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
629 (If part is passed in registers, arg->partial says how much
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
630 and emit_push_insn will take care of putting it there.)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
631
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
632 Push it, and if its size is less than the
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
633 amount of space allocated to it,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
634 also bump stack pointer by the additional space.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
635 Note that in C the default argument promotions
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
636 will prevent such mismatches. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
637
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
638 size = GET_MODE_SIZE (arg->mode);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
639 /* Compute how much space the push instruction will push.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
640 On many machines, pushing a byte will advance the stack
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
641 pointer by a halfword. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
642 #ifdef PUSH_ROUNDING
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
643 size = PUSH_ROUNDING (size);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
644 #endif
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
645 used = size;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
646
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
647 /* Compute how much space the argument should get:
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
648 round up to a multiple of the alignment for arguments. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
649 if (none != FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
650 used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
651 / (PARM_BOUNDARY / BITS_PER_UNIT))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
652 * (PARM_BOUNDARY / BITS_PER_UNIT));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
653
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
654 /* This isn't already where we want it on the stack, so put it there.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
655 This can either be done with push or copy insns. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
656 emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), NULL_RTX,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
657 PARM_BOUNDARY, partial, reg, used - size, argblock,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
658 ARGS_SIZE_RTX (arg->locate.offset), reg_parm_stack_space,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
659 ARGS_SIZE_RTX (arg->locate.alignment_pad));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
660
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
661 /* Unless this is a partially-in-register argument, the argument is now
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
662 in the stack. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
663 if (partial == 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
664 arg->value = arg->stack;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
665 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
666 else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
667 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
668 /* BLKmode, at least partly to be pushed. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
669
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
670 unsigned int parm_align;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
671 int excess;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
672 rtx size_rtx;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
673
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
674 /* Pushing a nonscalar.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
675 If part is passed in registers, PARTIAL says how much
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
676 and emit_push_insn will take care of putting it there. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
677
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
678 /* Round its size up to a multiple
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
679 of the allocation unit for arguments. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
680
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
681 if (arg->locate.size.var != 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
682 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
683 excess = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
684 size_rtx = ARGS_SIZE_RTX (arg->locate.size);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
685 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
686 else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
687 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
688 /* PUSH_ROUNDING has no effect on us, because emit_push_insn
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
689 for BLKmode is careful to avoid it. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
690 excess = (arg->locate.size.constant
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
691 - int_size_in_bytes (TREE_TYPE (pval))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
692 + partial);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
693 size_rtx = expand_expr (size_in_bytes (TREE_TYPE (pval)),
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
694 NULL_RTX, TYPE_MODE (sizetype), 0);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
695 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
696
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
697 parm_align = arg->locate.boundary;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
698
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
699 /* When an argument is padded down, the block is aligned to
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
700 PARM_BOUNDARY, but the actual argument isn't. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
701 if (FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)) == downward)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
702 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
703 if (arg->locate.size.var)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
704 parm_align = BITS_PER_UNIT;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
705 else if (excess)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
706 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
707 unsigned int excess_align = (excess & -excess) * BITS_PER_UNIT;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
708 parm_align = MIN (parm_align, excess_align);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
709 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
710 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
711
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
712 if ((flags & ECF_SIBCALL) && MEM_P (arg->value))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
713 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
714 /* emit_push_insn might not work properly if arg->value and
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
715 argblock + arg->locate.offset areas overlap. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
716 rtx x = arg->value;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
717 int i = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
718
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
719 if (XEXP (x, 0) == crtl->args.internal_arg_pointer
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
720 || (GET_CODE (XEXP (x, 0)) == PLUS
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
721 && XEXP (XEXP (x, 0), 0) ==
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
722 crtl->args.internal_arg_pointer
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
723 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
724 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
725 if (XEXP (x, 0) != crtl->args.internal_arg_pointer)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
726 i = INTVAL (XEXP (XEXP (x, 0), 1));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
727
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
728 /* expand_call should ensure this. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
729 gcc_assert (!arg->locate.offset.var
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
730 && GET_CODE (size_rtx) == CONST_INT);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
731 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
732 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
733
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
734 emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
735 parm_align, partial, reg, excess, argblock,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
736 ARGS_SIZE_RTX (arg->locate.offset), reg_parm_stack_space,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
737 ARGS_SIZE_RTX (arg->locate.alignment_pad));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
738
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
739 /* Unless this is a partially-in-register argument, the argument is now
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
740 in the stack.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
741
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
742 ??? Unlike the case above, in which we want the actual
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
743 address of the data, so that we can load it directly into a
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
744 register, here we want the address of the stack slot, so that
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
745 it's properly aligned for word-by-word copying or something
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
746 like that. It's not clear that this is always correct. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
747 if (partial == 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
748 arg->value = arg->stack_slot;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
749 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
750
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
751 if (arg->reg && GET_CODE (arg->reg) == PARALLEL)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
752 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
753 tree type = TREE_TYPE (arg->tree_value);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
754 arg->parallel_value
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
755 = emit_group_load_into_temps (arg->reg, arg->value, type,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
756 int_size_in_bytes (type));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
757 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
758
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
759 /* Mark all slots this store used. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
760 if (ACCUMULATE_OUTGOING_ARGS && !(flags & ECF_SIBCALL)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
761 && argblock && ! variable_size && arg->stack)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
762 for (i = lower_bound; i < upper_bound; i++)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
763 stack_usage_map[i] = 1;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
764
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
765 /* Once we have pushed something, pops can't safely
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
766 be deferred during the rest of the arguments. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
767 NO_DEFER_POP;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
768
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
769 /* Free any temporary slots made in processing this argument. Show
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
770 that we might have taken the address of something and pushed that
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
771 as an operand. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
772 preserve_temp_slots (NULL_RTX);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
773 free_temp_slots ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
774 pop_temp_slots ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
775
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
776 return 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
777 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
778
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
779 static void
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
780 determine_order(int *order, int num_actuals)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
781 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
782 int i;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
783 for (i=0; i<num_actuals; i++)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
784 order[i] = num_actuals-i-1;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
785 return;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
786 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
787
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
788 static void
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
789 push_overlaps(struct arg_data *args, int num_actuals)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
790 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
791 int i;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
792
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
793 for (i=0; i<num_actuals; i++)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
794 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
795 int dst_offset; /* */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
796 int src_offset; /* */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
797 rtx temp;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
798 if ( (dst_offset=check_frame_offset(args[i].stack)) < 0 ) continue;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
799 if ( (src_offset=check_frame_offset(args[i].value)) < 0 ) continue;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
800
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
801 /* 退避 */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
802 temp = assign_temp(args[i].tree_value, 1, 0, 0);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
803 if ( args[i].mode==BLKmode )
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
804 emit_block_move ( temp, args[i].value, ARGS_SIZE_RTX(args[i].locate.size), 0 );
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
805 else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
806 emit_move_insn ( temp, args[i].value );
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
807 args[i].value = temp;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
808
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
809 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
810 return;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
811 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
812
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
813 static int
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
814 check_frame_offset(rtx x)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
815 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
816 int i;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
817 rtx addr;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
818 if ( !x || !MEM_P(x))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
819 return -1;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
820
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
821 addr = XEXP(x, 0);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
822 if (addr == crtl->args.internal_arg_pointer)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
823 i = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
824 else if (GET_CODE (addr) == PLUS
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
825 && XEXP (addr, 0) == crtl->args.internal_arg_pointer
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
826 && GET_CODE (XEXP (addr, 1)) == CONST_INT)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
827 i = INTVAL (XEXP (addr, 1));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
828 else if (GET_CODE (addr) == PLUS
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
829 && GET_CODE (XEXP (addr, 0)) == CONST_INT
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
830 && XEXP (addr, 1) == crtl->args.internal_arg_pointer )
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
831 i = INTVAL (XEXP (addr, 0));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
832 else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
833 return -1;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
834
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
835 return i;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
836 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
837