annotate gcc/cbc-goto.h @ 50:4e0a8e84ee55

Added tag cbc-4.4.3 for changeset 2e19f845ea37
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Sun, 07 Feb 2010 17:56:48 +0900
parents 2476ed92181e
children 3aaf117db171
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 static void
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3 preexpand_argument_expr (struct arg_data *, int);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5 static void
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 determine_order(int *, int);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 static int
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 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
10
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 static void
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 push_overlaps(struct arg_data *, int);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 static int
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15 check_frame_offset(rtx);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 static rtx
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19 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
20 tree addr,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 int ignore,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 int flags,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 int num_actuals,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 struct arg_data *args,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 struct args_size *args_size,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 CUMULATIVE_ARGS args_so_far,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 rtx old_stack_level,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
28 int reg_parm_stack_space,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
29 int old_pending_adj,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
30 unsigned HOST_WIDE_INT preferred_stack_boundary,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
31 unsigned HOST_WIDE_INT preferred_unit_stack_boundary,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
32 rtx structure_value_addr,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
33 //int structure_value_addr_parm,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 int old_inhibit_defer_pop
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
35 )
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
36 {
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 /* folowing variables is just copied from expand_call. */
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 int pass = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 int i;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
42 #ifdef REG_PARM_STACK_SPACE
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
43 /* 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
44 saved, if any. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
45 #endif
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
46 rtx funexp;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
47 rtx valreg;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
48 struct args_size adjusted_args_size;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
49 int unadjusted_args_size;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
50 int reg_parm_seen;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 rtx static_chain_value;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
52 int old_stack_allocated;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
53 int old_stack_pointer_delta = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
54 int old_stack_arg_under_construction = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
55 rtx call_fusage;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
56 char *stack_usage_map_buf = NULL;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 rtx argblock = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
58 HOST_WIDE_INT struct_value_size = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 int pcc_struct_value = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 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
61 char *initial_stack_usage_map = stack_usage_map;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
62 rtx tail_call_insns = NULL_RTX;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
63
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
64
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
65 int *store_order;
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
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
68 int sibcall_failure = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
69 /* 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
70 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
71 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
72 call expansion. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
73 int save_pending_stack_adjust = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
74 int save_stack_pointer_delta = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
75 rtx insns;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
76 rtx before_call, next_arg_reg;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
77
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
78 /* State variables we need to save and restore between
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
79 iterations. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
80 save_pending_stack_adjust = pending_stack_adjust;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
81 save_stack_pointer_delta = stack_pointer_delta;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
82 flags |= ECF_SIBCALL;
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 /* Other state variables that we must reinitialize each time
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
85 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
86 argblock = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
87 call_fusage = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
88
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
89 /* Start a new sequence for the normal call case.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
90
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
91 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
92 sibcall_failure instead of continuing the loop. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
93 start_sequence ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
94
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
95 /* 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
96 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
97 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
98 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
99 with stack pointer depressed.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
100 Also do the adjustments before a throwing call, otherwise
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
101 exception handling can fail; PR 19225. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
102 if (pending_stack_adjust >= 32
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
103 || (pending_stack_adjust > 0
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
104 && (flags & ECF_MAY_BE_ALLOCA))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
105 || (pending_stack_adjust > 0
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
106 && flag_exceptions && !(flags & ECF_NOTHROW))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
107 || pass == 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
108 do_pending_stack_adjust ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
109
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
110
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
111 if (pass == 0 && crtl->stack_protect_guard)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
112 stack_protect_epilogue ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
113
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
114 adjusted_args_size = *args_size;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
115 /* 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
116 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
117 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
118 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
119 caller provided. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
120 unadjusted_args_size
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
121 = compute_argument_block_size (reg_parm_stack_space,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
122 &adjusted_args_size,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
123 fndecl, fntype,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
124 (pass == 0 ? 0
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
125 : preferred_stack_boundary));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
126
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
127 old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
128
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
129 argblock = crtl->args.internal_arg_pointer;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
130
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
131 argblock
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
132 #ifdef STACK_GROWS_DOWNWARD
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
133 = plus_constant (argblock, crtl->args.pretend_args_size);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
134 #else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
135 = plus_constant (argblock, -crtl->args.pretend_args_size);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
136 #endif
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
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
139 stored_args_map = sbitmap_alloc (args_size->constant);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
140 sbitmap_zero (stored_args_map);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
141
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 if (ACCUMULATE_OUTGOING_ARGS)
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 /* The save/restore code in store_one_arg handles all
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
146 cases except one: a constructor call (including a C
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
147 function returning a BLKmode struct) to initialize
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
148 an argument. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
149 if (stack_arg_under_construction)
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 rtx push_size
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
152 = GEN_INT (adjusted_args_size.constant
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
153 + (OUTGOING_REG_PARM_STACK_SPACE ((!fndecl ? fntype
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
154 : TREE_TYPE (fndecl))) ? 0
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
155 : reg_parm_stack_space));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
156 if (old_stack_level == 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
157 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
158 emit_stack_save (SAVE_BLOCK, &old_stack_level,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
159 NULL_RTX);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
160 old_stack_pointer_delta = stack_pointer_delta;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
161 old_pending_adj = pending_stack_adjust;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
162 pending_stack_adjust = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
163 /* stack_arg_under_construction says whether a stack
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
164 arg is being constructed at the old stack level.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
165 Pushing the stack gets a clean outgoing argument
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
166 block. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
167 old_stack_arg_under_construction
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
168 = stack_arg_under_construction;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
169 stack_arg_under_construction = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
170 /* Make a new map for the new argument list. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
171 if (stack_usage_map_buf)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
172 free (stack_usage_map_buf);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
173 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
174 stack_usage_map = stack_usage_map_buf;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
175 memset (stack_usage_map, 0, highest_outgoing_arg_in_use);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
176 highest_outgoing_arg_in_use = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
177 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
178 allocate_dynamic_stack_space (push_size, NULL_RTX,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
179 BITS_PER_UNIT);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
180 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
181
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
182 /* If argument evaluation might modify the stack pointer,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
183 copy the address of the argument list to a register. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
184 for (i = 0; i < num_actuals; i++)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
185 if (args[i].pass_on_stack)
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 argblock = copy_addr_to_reg (argblock);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
188 break;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
189 }
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 compute_argument_addresses (args, argblock, num_actuals);
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 /* in the case that
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
195 a function goto codesegment.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
196 adjust stack space. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
197 if ( !CbC_IS_CODE_SEGMENT(TREE_TYPE(current_function_decl)) )
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
198 //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
199 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
200 HOST_WIDE_INT padding;
21
959d4c8c8abc add conv.c conv1.c
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 7
diff changeset
201 padding = CbC_PRETENDED_STACK_SIZE -
3
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
202 (crtl->args.size - crtl->args.pretend_args_size);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
203 if (0&&padding > 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
204 anti_adjust_stack (GEN_INT (padding));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
205 }
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 /* 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
208 be deferred during the evaluation of the arguments. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
209 NO_DEFER_POP;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
210
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
211 funexp = rtx_for_function_call (fndecl, addr);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
212
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
213 /* 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
214 valreg = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
215
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
216
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
217 /* 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
218 once we have started filling any specific hard regs. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
219 precompute_register_parameters (num_actuals, args, &reg_parm_seen);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
220
25
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
221 if (CALL_EXPR_STATIC_CHAIN (exp))
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
222 static_chain_value = expand_normal (CALL_EXPR_STATIC_CHAIN (exp));
7
7ff9aed93de8 partially written goto with env...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
223 else
25
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
224 static_chain_value = 0;
3
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
225
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 /* parallel assignment */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
228 store_order = alloca (num_actuals * sizeof (int));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
229 memset (store_order, 0, num_actuals * sizeof (int));
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 /* fill the arg[i]->exprs. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
232 for (i = 0; i < num_actuals; i++)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
233 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
234 if (args[i].reg == 0 || 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 preexpand_argument_expr (&args[i],
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
237 adjusted_args_size.var != 0);
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
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
242 /* push overlapped argument to stack. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
243 push_overlaps(args, num_actuals);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
244
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
245 /* determine ordering to store arguments.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
246 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
247 /* now... this function do nothing. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
248 determine_order(store_order, num_actuals);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
249
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
250 /* push arguments in the order . */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
251 for (i = 0; i < num_actuals; i++)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
252 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
253 if (args[store_order[i]].reg == 0
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
254 || args[store_order[i]].pass_on_stack
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
255 || args[store_order[i]].partial!=0 )
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
256 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
257 expand_one_arg_push (&args[store_order[i]], argblock, flags,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
258 adjusted_args_size.var != 0,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
259 reg_parm_stack_space);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
260 }
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
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
263
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
264 /* 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
265 was not preallocated, allocate stack space here for arguments
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
266 passed in registers. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
267 #ifdef OUTGOING_REG_PARM_STACK_SPACE
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
268 //if (!ACCUMULATE_OUTGOING_ARGS
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
269 //&& must_preallocate == 0 && reg_parm_stack_space > 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
270 //anti_adjust_stack (GEN_INT (reg_parm_stack_space));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
271 #endif
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
272
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
273 /* */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
274 funexp = prepare_call_address (funexp, static_chain_value,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
275 &call_fusage, reg_parm_seen, pass == 0);
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 /* store args into register. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
278 load_register_parameters (args, num_actuals, &call_fusage, flags,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
279 //pass == 0, &sibcall_failure);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
280 0, NULL);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
281
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
282 /* 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
283 later safely search backwards to find the CALL_INSN. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
284 before_call = get_last_insn ();
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 /* Set up next argument register. For sibling calls on machines
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
287 with register windows this should be the incoming register. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
288 #ifdef FUNCTION_INCOMING_ARG
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
289 if (pass == 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
290 next_arg_reg = FUNCTION_INCOMING_ARG (args_so_far, VOIDmode,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
291 void_type_node, 1);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
292 else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
293 #endif
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
294 next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
295 void_type_node, 1);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
296
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
297 /* 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
298 now! */
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 /* Stack must be properly aligned now. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
301 gcc_assert (!pass
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
302 || !(stack_pointer_delta % preferred_unit_stack_boundary));
7
7ff9aed93de8 partially written goto with env...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
303 #if 0
3
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
304 /* store environment. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
305 if ( env_tree!=NULL )
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 emit_insn (gen_rtx_CLOBBER (VOIDmode,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
308 gen_rtx_MEM (BLKmode,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
309 hard_frame_pointer_rtx)));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
310 emit_move_insn (hard_frame_pointer_rtx, env_rtx);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
311 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
312 //pop_temp_slots ();
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 emit_indirect_jump (funexp);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
315 }
7
7ff9aed93de8 partially written goto with env...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 6
diff changeset
316 #endif
25
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
317 if (GET_CODE (funexp) != SYMBOL_REF)
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
318 {
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
319 push_temp_slots();
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
320 preserve_temp_slots(funexp);
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
321 /* Generate the actual call instruction. */
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
322 emit_call_1 (funexp, exp, fndecl, funtype, unadjusted_args_size,
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
323 adjusted_args_size.constant, struct_value_size,
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
324 //next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
325 next_arg_reg, valreg, 0, call_fusage,
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
326 flags, & args_so_far);
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
327 pop_temp_slots();
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
328 }
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
329 else
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
330 {
3
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 /* Generate the actual call instruction. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
333 emit_call_1 (funexp, exp, fndecl, funtype, unadjusted_args_size,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
334 adjusted_args_size.constant, struct_value_size,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
335 //next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
336 next_arg_reg, valreg, 0, call_fusage,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
337 flags, & args_so_far);
25
2476ed92181e modified machine description of i386 for support indirect sibcall attributed fastcall.
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents: 21
diff changeset
338 }
3
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
339
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
340 /* 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
341 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
342 and update VALREG accordingly. BLKmode values are handled by the
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
343 group load/store machinery below. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
344 if (!structure_value_addr
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
345 && !pcc_struct_value
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
346 && TYPE_MODE (TREE_TYPE (exp)) != BLKmode
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
347 && targetm.calls.return_in_msb (TREE_TYPE (exp)))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
348 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
349 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
350 sibcall_failure = 1;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
351 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
352 }
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
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
355 /* 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
356 if nonvolatile values are live. For functions that cannot return,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
357 inform flow that control does not fall through. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
358
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
359 if ((flags & ECF_NORETURN) || pass == 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
360 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
361 /* The barrier must be emitted
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
362 immediately after the CALL_INSN. Some ports emit more
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
363 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
364
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
365 rtx last = get_last_insn ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
366 while (!CALL_P (last))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
367 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
368 last = PREV_INSN (last);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
369 /* There was no CALL_INSN? */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
370 gcc_assert (last != before_call);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
371 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
372
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
373 emit_barrier_after (last);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
374
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
375 /* Stack adjustments after a noreturn call are dead code.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
376 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
377 stack_pointer_delta. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
378 if (inhibit_defer_pop == 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
379 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
380 stack_pointer_delta = old_stack_allocated;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
381 pending_stack_adjust = 0;
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 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
384
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
385 /* 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
386
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
387 if (TYPE_MODE (TREE_TYPE (exp)) == VOIDmode
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
388 || ignore)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
389 target = const0_rtx;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
390
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
391 if (targetm.calls.promote_function_return(funtype))
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 we promoted this return value, make the proper SUBREG.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
394 TARGET might be const0_rtx here, so be careful. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
395 if (REG_P (target)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
396 && TYPE_MODE (TREE_TYPE (exp)) != BLKmode
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
397 && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
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 tree type = TREE_TYPE (exp);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
400 int unsignedp = TYPE_UNSIGNED (type);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
401 int offset = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
402 enum machine_mode pmode;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
403
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
404 pmode = promote_mode (type, TYPE_MODE (type), &unsignedp, 1);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
405 /* If we don't promote as expected, something is wrong. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
406 gcc_assert (GET_MODE (target) == pmode);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
407
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
408 if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
409 && (GET_MODE_SIZE (GET_MODE (target))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
410 > GET_MODE_SIZE (TYPE_MODE (type))))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
411 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
412 offset = GET_MODE_SIZE (GET_MODE (target))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
413 - GET_MODE_SIZE (TYPE_MODE (type));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
414 if (! BYTES_BIG_ENDIAN)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
415 offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
416 else if (! WORDS_BIG_ENDIAN)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
417 offset %= UNITS_PER_WORD;
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 target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
420 SUBREG_PROMOTED_VAR_P (target) = 1;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
421 SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
422 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
423 }
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 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
426 argument, restore saved stack-pointer value. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
427
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
428 if (old_stack_level)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
429 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
430 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
431 stack_pointer_delta = old_stack_pointer_delta;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
432 pending_stack_adjust = old_pending_adj;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
433 old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
434 stack_arg_under_construction = old_stack_arg_under_construction;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
435 highest_outgoing_arg_in_use = initial_highest_arg_in_use;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
436 stack_usage_map = initial_stack_usage_map;
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
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
439 /* 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
440 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
441 for non-local gotos. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
442
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
443 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
444 update_nonlocal_goto_save_area ();
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 /* Free up storage we no longer need. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
447 for (i = 0; i < num_actuals; ++i)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
448 if (args[i].aligned_regs)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
449 free (args[i].aligned_regs);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
450
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
451 insns = get_insns ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
452 end_sequence ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
453
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
454 tail_call_insns = insns;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
455
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
456 /* Restore the pending stack adjustment now that we have
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
457 finished generating the sibling call sequence. */
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 pending_stack_adjust = save_pending_stack_adjust;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
460 stack_pointer_delta = save_stack_pointer_delta;
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 /* Prepare arg structure for next iteration. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
463 for (i = 0; i < num_actuals; i++)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
464 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
465 args[i].value = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
466 args[i].aligned_regs = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
467 args[i].stack = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
468 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
469
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
470 sbitmap_free (stored_args_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 emit_insn(tail_call_insns);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
474 crtl->tail_call_emit = true;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
475
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
476 return target;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
477 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
478
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 static void
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
481 preexpand_argument_expr (struct arg_data *arg,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
482 int variable_size ATTRIBUTE_UNUSED)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
483 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
484 tree pval = arg->tree_value;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
485 rtx reg = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
486 int partial = 0;
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 if (TREE_CODE (pval) == ERROR_MARK)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
489 return;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
490
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
491 /* 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
492 this argument. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
493 push_temp_slots ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
494
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 /* 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
497 set up the register and number of words. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
498 if (! arg->pass_on_stack)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
499 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
500 //if (flags & ECF_SIBCALL)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
501 reg = arg->tail_call_reg;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
502 //else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
503 //reg = arg->reg;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
504 partial = arg->partial;
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 /* 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
508 this case. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
509 gcc_assert (reg == 0 || partial != 0);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
510
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
511 /* 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
512 here. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
513 if (arg->n_aligned_regs != 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
514 reg = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
515
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
516 /* Start a new sequence for the arg->exprs. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
517 start_sequence ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
518
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
519
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
520 if (arg->pass_on_stack)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
521 stack_arg_under_construction++;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
522
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
523 arg->value = expand_expr (pval,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
524 (partial
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
525 || TYPE_MODE (TREE_TYPE (pval)) != arg->mode)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
526 ? NULL_RTX : arg->stack,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
527 VOIDmode, EXPAND_STACK_PARM);
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 /* 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
530 doesn't agree, convert the mode. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
531
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
532 if (arg->mode != TYPE_MODE (TREE_TYPE (pval)))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
533 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
534 arg->value, arg->unsignedp);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
535
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
536 if (arg->pass_on_stack)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
537 stack_arg_under_construction--;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
538
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
539 arg->exprs = get_insns ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
540 end_sequence ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
541
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
542 if (arg->exprs) emit_insn(arg->exprs);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
543
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
544 preserve_temp_slots (arg->value);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
545 pop_temp_slots ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
546
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
547 return ;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
548 }
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 static int
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
551 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
552 int variable_size ATTRIBUTE_UNUSED, int reg_parm_stack_space)
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 tree pval = arg->tree_value;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
555 int used = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
556 int i, lower_bound = 0, upper_bound = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
557 rtx reg = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
558 int partial = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
559
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
560 /* 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
561 this argument. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
562 push_temp_slots ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
563
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
564
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
565 /* copy from store_one_arg. modify here after.*/
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
566 /* 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
567 set up the register and number of words. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
568 if (! arg->pass_on_stack)
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 (flags & ECF_SIBCALL)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
571 reg = arg->tail_call_reg;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
572 //else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
573 //reg = arg->reg;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
574 partial = arg->partial;
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 /* 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
577 this case. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
578 gcc_assert (reg == 0 || partial != 0);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
579 /* 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
580 here. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
581 if (arg->n_aligned_regs != 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
582 reg = 0;
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
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
585
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
586
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
587 if (arg->value == arg->stack)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
588 /* 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
589 ;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
590 else if (arg->mode != BLKmode)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
591 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
592 int size;
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 /* Argument is a scalar, not entirely passed in registers.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
595 (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
596 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
597
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
598 Push it, and if its size is less than the
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
599 amount of space allocated to it,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
600 also bump stack pointer by the additional space.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
601 Note that in C the default argument promotions
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
602 will prevent such mismatches. */
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 size = GET_MODE_SIZE (arg->mode);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
605 /* Compute how much space the push instruction will push.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
606 On many machines, pushing a byte will advance the stack
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
607 pointer by a halfword. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
608 #ifdef PUSH_ROUNDING
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
609 size = PUSH_ROUNDING (size);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
610 #endif
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
611 used = size;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
612
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
613 /* Compute how much space the argument should get:
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
614 round up to a multiple of the alignment for arguments. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
615 if (none != FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
616 used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
617 / (PARM_BOUNDARY / BITS_PER_UNIT))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
618 * (PARM_BOUNDARY / BITS_PER_UNIT));
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 /* 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
621 This can either be done with push or copy insns. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
622 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
623 PARM_BOUNDARY, partial, reg, used - size, argblock,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
624 ARGS_SIZE_RTX (arg->locate.offset), reg_parm_stack_space,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
625 ARGS_SIZE_RTX (arg->locate.alignment_pad));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
626
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
627 /* 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
628 in the stack. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
629 if (partial == 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
630 arg->value = arg->stack;
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 else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
633 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
634 /* BLKmode, at least partly to be pushed. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
635
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
636 unsigned int parm_align;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
637 int excess;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
638 rtx size_rtx;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
639
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
640 /* Pushing a nonscalar.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
641 If part is passed in registers, PARTIAL says how much
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
642 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
643
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
644 /* Round its size up to a multiple
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
645 of the allocation unit for arguments. */
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 if (arg->locate.size.var != 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
648 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
649 excess = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
650 size_rtx = ARGS_SIZE_RTX (arg->locate.size);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
651 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
652 else
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 /* 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
655 for BLKmode is careful to avoid it. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
656 excess = (arg->locate.size.constant
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
657 - int_size_in_bytes (TREE_TYPE (pval))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
658 + partial);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
659 size_rtx = expand_expr (size_in_bytes (TREE_TYPE (pval)),
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
660 NULL_RTX, TYPE_MODE (sizetype), 0);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
661 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
662
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
663 parm_align = arg->locate.boundary;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
664
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
665 /* 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
666 PARM_BOUNDARY, but the actual argument isn't. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
667 if (FUNCTION_ARG_PADDING (arg->mode, TREE_TYPE (pval)) == downward)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
668 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
669 if (arg->locate.size.var)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
670 parm_align = BITS_PER_UNIT;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
671 else if (excess)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
672 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
673 unsigned int excess_align = (excess & -excess) * BITS_PER_UNIT;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
674 parm_align = MIN (parm_align, excess_align);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
675 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
676 }
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 if ((flags & ECF_SIBCALL) && MEM_P (arg->value))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
679 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
680 /* 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
681 argblock + arg->locate.offset areas overlap. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
682 rtx x = arg->value;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
683 int i = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
684
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
685 if (XEXP (x, 0) == crtl->args.internal_arg_pointer
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
686 || (GET_CODE (XEXP (x, 0)) == PLUS
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
687 && XEXP (XEXP (x, 0), 0) ==
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
688 crtl->args.internal_arg_pointer
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
689 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
690 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
691 if (XEXP (x, 0) != crtl->args.internal_arg_pointer)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
692 i = INTVAL (XEXP (XEXP (x, 0), 1));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
693
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
694 /* expand_call should ensure this. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
695 gcc_assert (!arg->locate.offset.var
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
696 && GET_CODE (size_rtx) == CONST_INT);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
697 }
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
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
700 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
701 parm_align, partial, reg, excess, argblock,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
702 ARGS_SIZE_RTX (arg->locate.offset), reg_parm_stack_space,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
703 ARGS_SIZE_RTX (arg->locate.alignment_pad));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
704
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
705 /* 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
706 in the stack.
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
707
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
708 ??? Unlike the case above, in which we want the actual
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
709 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
710 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
711 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
712 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
713 if (partial == 0)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
714 arg->value = arg->stack_slot;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
715 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
716
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
717 if (arg->reg && GET_CODE (arg->reg) == PARALLEL)
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 tree type = TREE_TYPE (arg->tree_value);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
720 arg->parallel_value
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
721 = emit_group_load_into_temps (arg->reg, arg->value, type,
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
722 int_size_in_bytes (type));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
723 }
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 /* Mark all slots this store used. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
726 if (ACCUMULATE_OUTGOING_ARGS && !(flags & ECF_SIBCALL)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
727 && argblock && ! variable_size && arg->stack)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
728 for (i = lower_bound; i < upper_bound; i++)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
729 stack_usage_map[i] = 1;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
730
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
731 /* Once we have pushed something, pops can't safely
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
732 be deferred during the rest of the arguments. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
733 NO_DEFER_POP;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
734
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
735 /* Free any temporary slots made in processing this argument. Show
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
736 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
737 as an operand. */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
738 preserve_temp_slots (NULL_RTX);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
739 free_temp_slots ();
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
740 pop_temp_slots ();
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 return 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
743 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
744
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
745 static void
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
746 determine_order(int *order, int num_actuals)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
747 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
748 int i;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
749 for (i=0; i<num_actuals; i++)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
750 order[i] = num_actuals-i-1;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
751 return;
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
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
754 static void
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
755 push_overlaps(struct arg_data *args, int num_actuals)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
756 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
757 int i;
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 for (i=0; i<num_actuals; i++)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
760 {
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
761 int dst_offset; /* */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
762 int src_offset; /* */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
763 rtx temp;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
764 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
765 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
766
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
767 /* 退避 */
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
768 temp = assign_temp(args[i].tree_value, 1, 0, 0);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
769 if ( args[i].mode==BLKmode )
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
770 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
771 else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
772 emit_move_insn ( temp, args[i].value );
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
773 args[i].value = temp;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
774
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;
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 int
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
780 check_frame_offset(rtx x)
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 rtx addr;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
784 if ( !x || !MEM_P(x))
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
785 return -1;
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 addr = XEXP(x, 0);
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
788 if (addr == crtl->args.internal_arg_pointer)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
789 i = 0;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
790 else if (GET_CODE (addr) == PLUS
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
791 && XEXP (addr, 0) == crtl->args.internal_arg_pointer
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
792 && GET_CODE (XEXP (addr, 1)) == CONST_INT)
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
793 i = INTVAL (XEXP (addr, 1));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
794 else if (GET_CODE (addr) == PLUS
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
795 && GET_CODE (XEXP (addr, 0)) == CONST_INT
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
796 && XEXP (addr, 1) == crtl->args.internal_arg_pointer )
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
797 i = INTVAL (XEXP (addr, 0));
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
798 else
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
799 return -1;
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 return i;
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
802 }
d43292db8c8c finished merging
kent <kent@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
803