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