1 From fa44ef9d6bb7dc67efaa6f04cd0b242f10d3975c Mon Sep 17 00:00:00 2001
2 From: Richard Lowe <richlowe@richlowe.net>
3 Date: Sat, 23 Jan 2016 22:14:56 -0500
4 Subject: i386: Save integer-passed arguments to the stack, to
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
10 Merged from 5.3 to 7.2 by: Aurélien Larcher
12 Originally implemented in:
13 commit 023cc9a4c9c698bed1f51d38eac850d327fc1146
14 Author: jsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
15 Date: Wed Jun 29 23:51:34 2005 +0000
17 * gcc/dwarf2.h (DW_AT_SUN_amd64_parmdump): New.
18 * gcc/dwarf2out.c (gen_subprogram_die): Add this attribute.
19 * gcc/doc/invoke.texi (-msave-args): New x86-64 option.
20 * gcc/config/i386/i386.h (MASK_SAVE_ARGS, TARGET_SAVE_ARGS): New.
21 (TARGET_SWITCHES): Add -msave-args.
22 * gcc/config/i386/i386.c (struct ix86_frame): Add nmsave_args and
24 (pro_epilogue_adjust_stack): Declare.
25 (ix86_nsaved_args): New.
26 (override_options, ix86_can_use_return_insn_p,
27 ix86_frame_pointer_required, ix86_compute_frame_layout,
28 ix86_emit_save_regs, ix86_emit_save_regs_using_mov,
29 ix86_expand_prologue, ix86_expand_epilogue): Handle -msave-args.
31 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/csl-sol210-3_4-branch@101443 138bc75d-0d04-0410-961f-82ee72b054a4
33 gcc/config/i386/i386-options.cc | 3 +
34 gcc/config/i386/i386.cc | 130 +++++++++++++++++-
35 gcc/config/i386/i386.h | 7 +
36 gcc/config/i386/i386.opt | 10 ++
37 gcc/doc/invoke.texi | 4 +
38 gcc/dwarf2out.cc | 5 +
39 .../gcc.target/i386/msave-args-mov.c | 26 ++++
40 .../gcc.target/i386/msave-args-push.c | 26 ++++
41 include/dwarf2.def | 2 +
42 9 files changed, 206 insertions(+), 7 deletions(-)
43 create mode 100644 gcc/testsuite/gcc.target/i386/msave-args-mov.c
44 create mode 100644 gcc/testsuite/gcc.target/i386/msave-args-push.c
46 diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
47 index 099cec4b610..a26cb878b68 100644
48 --- a/gcc/config/i386/i386-options.cc
49 +++ b/gcc/config/i386/i386-options.cc
50 @@ -2460,6 +2460,9 @@ ix86_option_override_internal (bool main_args_p,
51 &= ~((OPTION_MASK_ISA_BMI | OPTION_MASK_ISA_BMI2 | OPTION_MASK_ISA_TBM)
52 & ~opts->x_ix86_isa_flags_explicit);
54 + if (!TARGET_64BIT_P (opts->x_ix86_isa_flags) && TARGET_SAVE_ARGS)
55 + error ("-msave-args makes no sense in the 32-bit mode");
57 /* Validate -mpreferred-stack-boundary= value or default it to
58 PREFERRED_STACK_BOUNDARY_DEFAULT. */
59 ix86_preferred_stack_boundary = PREFERRED_STACK_BOUNDARY_DEFAULT;
60 diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
61 index ce156c3be3a..a3e4787dfb8 100644
62 --- a/gcc/config/i386/i386.cc
63 +++ b/gcc/config/i386/i386.cc
64 @@ -421,6 +421,9 @@ static bool i386_asm_output_addr_const_extra (FILE *, rtx);
65 static bool ix86_can_inline_p (tree, tree);
66 static unsigned int ix86_minimum_incoming_stack_boundary (bool);
68 +static int ix86_nsaved_args (void);
69 +static rtx_def* pro_epilogue_adjust_stack (rtx, rtx, rtx, int, bool);
72 /* Whether -mtune= or -march= were specified */
73 int ix86_tune_defaulted;
74 @@ -5701,7 +5704,7 @@ ix86_can_use_return_insn_p (void)
76 struct ix86_frame &frame = cfun->machine->frame;
77 return (frame.stack_pointer_offset == UNITS_PER_WORD
78 - && (frame.nregs + frame.nsseregs) == 0);
79 + && (frame.nmsave_args + frame.nregs + frame.nsseregs) == 0);
82 /* Return stack frame size. get_frame_size () returns used stack slots
83 @@ -5738,6 +5741,9 @@ ix86_frame_pointer_required (void)
84 if (TARGET_32BIT_MS_ABI && cfun->calls_setjmp)
87 + if (TARGET_SAVE_ARGS)
90 /* Win64 SEH, very large frames need a frame-pointer as maximum stack
92 if (TARGET_64BIT_MS_ABI && ix86_get_frame_size () > SEH_MAX_FRAME_SIZE)
93 @@ -6578,6 +6584,7 @@ ix86_compute_frame_layout (void)
95 frame->nregs = ix86_nsaved_regs ();
96 frame->nsseregs = ix86_nsaved_sseregs ();
97 + frame->nmsave_args = ix86_nsaved_args ();
99 /* 64-bit MS ABI seem to require stack alignment to be always 16,
100 except for function prologues, leaf functions and when the defult
101 @@ -6659,7 +6666,8 @@ ix86_compute_frame_layout (void)
104 frame->save_regs_using_mov
105 - = TARGET_PROLOGUE_USING_MOVE && m->use_fast_prologue_epilogue;
106 + = TARGET_FORCE_SAVE_REGS_USING_MOV ||
107 + (TARGET_PROLOGUE_USING_MOVE && m->use_fast_prologue_epilogue);
109 /* Skip return address and error code in exception handler. */
110 offset = INCOMING_FRAME_SP_OFFSET;
111 @@ -6676,6 +6684,13 @@ ix86_compute_frame_layout (void)
112 /* The traditional frame pointer location is at the top of the frame. */
113 frame->hard_frame_pointer_offset = offset;
115 + if (TARGET_SAVE_ARGS)
117 + offset += frame->nmsave_args * UNITS_PER_WORD;
118 + offset += (frame->nmsave_args % 2) * UNITS_PER_WORD;
120 + frame->arg_save_offset = offset;
122 /* Register save area */
123 offset += frame->nregs * UNITS_PER_WORD;
124 frame->reg_save_offset = offset;
125 @@ -6809,7 +6824,7 @@ ix86_compute_frame_layout (void)
126 /* Size prologue needs to allocate. */
127 to_allocate = offset - frame->sse_reg_save_offset;
129 - if ((!to_allocate && frame->nregs <= 1)
130 + if ((!TARGET_SAVE_ARGS && !to_allocate && frame->nregs <= 1)
131 || (TARGET_64BIT && to_allocate >= HOST_WIDE_INT_C (0x80000000))
132 /* If static stack checking is enabled and done with probes,
133 the registers need to be saved before allocating the frame. */
134 @@ -6833,7 +6848,11 @@ ix86_compute_frame_layout (void)
136 frame->red_zone_size = to_allocate;
137 if (frame->save_regs_using_mov)
139 frame->red_zone_size += frame->nregs * UNITS_PER_WORD;
140 + frame->red_zone_size += frame->nmsave_args * UNITS_PER_WORD;
141 + frame->red_zone_size += (frame->nmsave_args % 2) * UNITS_PER_WORD;
143 if (frame->red_zone_size > RED_ZONE_SIZE - RED_ZONE_RESERVE)
144 frame->red_zone_size = RED_ZONE_SIZE - RED_ZONE_RESERVE;
146 @@ -6891,6 +6910,22 @@ ix86_compute_frame_layout (void)
148 frame->hard_frame_pointer_offset = frame->hfp_save_offset;
151 + if (getenv("DEBUG_FRAME_STUFF") != NULL)
153 + printf("nmsave_args: %d\n", frame->nmsave_args);
154 + printf("nsseregs: %d\n", frame->nsseregs);
155 + printf("nregs: %d\n", frame->nregs);
157 + printf("frame_pointer_offset: %llx\n", frame->frame_pointer_offset);
158 + printf("hard_frame_pointer_offset: %llx\n", frame->hard_frame_pointer_offset);
159 + printf("stack_pointer_offset: %llx\n", frame->stack_pointer_offset);
160 + printf("hfp_save_offset: %llx\n", frame->hfp_save_offset);
161 + printf("arg_save_offset: %llx\n", frame->arg_save_offset);
162 + printf("reg_save_offset: %llx\n", frame->reg_save_offset);
163 + printf("sse_reg_save_offset: %llx\n", frame->sse_reg_save_offset);
168 /* This is semi-inlined memory_address_length, but simplified
169 @@ -7106,6 +7141,23 @@ ix86_emit_save_regs (void)
173 + if (TARGET_SAVE_ARGS)
176 + int nsaved = ix86_nsaved_args ();
177 + int start = cfun->returns_struct;
179 + for (i = start; i < start + nsaved; i++)
181 + regno = x86_64_int_parameter_registers[i];
182 + insn = emit_insn (gen_push (gen_rtx_REG (word_mode, regno)));
183 + RTX_FRAME_RELATED_P (insn) = 1;
185 + if (nsaved % 2 != 0)
186 + pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
187 + GEN_INT (-UNITS_PER_WORD), -1, false);
190 for (regno = FIRST_PSEUDO_REGISTER - 1; regno-- > 0; )
191 if (GENERAL_REGNO_P (regno) && ix86_save_reg (regno, true, true))
193 @@ -7192,9 +7244,30 @@ ix86_emit_save_reg_using_mov (machine_mode mode, unsigned int regno,
194 /* Emit code to save registers using MOV insns.
195 First register is stored at CFA - CFA_OFFSET. */
197 -ix86_emit_save_regs_using_mov (HOST_WIDE_INT cfa_offset)
198 +ix86_emit_save_regs_using_mov (const struct ix86_frame *frame)
201 + HOST_WIDE_INT cfa_offset = frame->arg_save_offset;
203 + if (TARGET_SAVE_ARGS)
206 + int nsaved = ix86_nsaved_args ();
207 + int start = cfun->returns_struct;
209 + /* We deal with this twice? */
210 + if (nsaved % 2 != 0)
211 + cfa_offset -= UNITS_PER_WORD;
213 + for (i = start + nsaved - 1; i >= start; i--)
215 + regno = x86_64_int_parameter_registers[i];
216 + ix86_emit_save_reg_using_mov(word_mode, regno, cfa_offset);
217 + cfa_offset -= UNITS_PER_WORD;
221 + cfa_offset = frame->reg_save_offset;
223 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
224 if (GENERAL_REGNO_P (regno) && ix86_save_reg (regno, true, true))
225 @@ -8549,7 +8622,7 @@ ix86_expand_prologue (void)
229 - int_registers_saved = (frame.nregs == 0);
230 + int_registers_saved = (frame.nregs == 0 && frame.nmsave_args == 0);
231 sse_registers_saved = (frame.nsseregs == 0);
232 save_stub_call_needed = (m->call_ms2sysv);
233 gcc_assert (sse_registers_saved || !save_stub_call_needed);
234 @@ -8591,7 +8664,7 @@ ix86_expand_prologue (void)
235 && (! TARGET_STACK_PROBE
236 || frame.stack_pointer_offset < CHECK_STACK_LIMIT))
238 - ix86_emit_save_regs_using_mov (frame.reg_save_offset);
239 + ix86_emit_save_regs_using_mov (&frame);
240 cfun->machine->red_zone_used = true;
241 int_registers_saved = true;
243 @@ -8891,7 +8964,7 @@ ix86_expand_prologue (void)
246 if (!int_registers_saved)
247 - ix86_emit_save_regs_using_mov (frame.reg_save_offset);
248 + ix86_emit_save_regs_using_mov (&frame);
249 if (!sse_registers_saved)
250 ix86_emit_save_sse_regs_using_mov (frame.sse_reg_save_offset);
251 else if (save_stub_call_needed)
252 @@ -8926,6 +8999,7 @@ ix86_expand_prologue (void)
253 relative to the value of the stack pointer at the end of the function
254 prologue, and moving instructions that access redzone area via frame
255 pointer inside push sequence violates this assumption. */
256 + /* XXX: We may wish to do this when SAVE_ARGS in general */
257 if (frame_pointer_needed && frame.red_zone_size)
258 emit_insn (gen_memory_blockage ());
260 @@ -9310,6 +9384,7 @@ ix86_expand_epilogue (int style)
262 /* See the comment about red zone and frame
263 pointer usage in ix86_expand_prologue. */
264 + /* XXX: We may wish to do this when SAVE_ARGS in general */
265 if (frame_pointer_needed && frame.red_zone_size)
266 emit_insn (gen_memory_blockage ());
268 @@ -9549,6 +9624,35 @@ ix86_expand_epilogue (int style)
269 ix86_emit_restore_regs_using_pop ();
272 + if (TARGET_SAVE_ARGS) {
274 + * For each saved argument, emit a restore note, to make sure it happens
275 + * correctly within the shrink wrapping (I think).
277 + * Note that 'restore' in this case merely means the rule is the same as
278 + * it was on function entry, not that we have actually done a register
279 + * restore (which of course, we haven't).
281 + * If we do not do this, the DWARF code will emit sufficient restores to
282 + * provide balance on its own initiative, which in the presence of
283 + * -fshrink-wrap may actually _introduce_ unbalance (whereby we only
284 + * .cfi_offset a register sometimes, but will always .cfi_restore it.
285 + * This will trip an assert.)
287 + int start = cfun->returns_struct;
288 + int nsaved = ix86_nsaved_args();
291 + for (i = start + nsaved - 1; i >= start; i--)
292 + queued_cfa_restores
293 + = alloc_reg_note (REG_CFA_RESTORE,
295 + x86_64_int_parameter_registers[i]),
296 + queued_cfa_restores);
298 + gcc_assert(m->fs.fp_valid);
301 /* If we used a stack pointer and haven't already got rid of it,
304 @@ -10674,6 +10778,18 @@ ix86_cannot_force_const_mem (machine_mode mode, rtx x)
305 return !ix86_legitimate_constant_p (mode, x);
308 +/* Return number of arguments to be saved on the stack with
312 +ix86_nsaved_args (void)
314 + if (TARGET_SAVE_ARGS)
315 + return crtl->args.info.regno - cfun->returns_struct;
320 /* Nonzero if the symbol is marked as dllimport, or as stub-variable,
323 diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
324 index fce0b3564a8..f92a00f4a3d 100644
325 --- a/gcc/config/i386/i386.h
326 +++ b/gcc/config/i386/i386.h
327 @@ -2511,6 +2511,11 @@ enum avx_u128_state
329 saved frame pointer if frame_pointer_needed
330 <- HARD_FRAME_POINTER
332 + [-msave-args] <- arg_save_offset
339 @@ -2544,6 +2549,7 @@ enum avx_u128_state
341 struct GTY(()) ix86_frame
347 @@ -2555,6 +2561,7 @@ struct GTY(()) ix86_frame
348 HOST_WIDE_INT hard_frame_pointer_offset;
349 HOST_WIDE_INT stack_pointer_offset;
350 HOST_WIDE_INT hfp_save_offset;
351 + HOST_WIDE_INT arg_save_offset;
352 HOST_WIDE_INT reg_save_offset;
353 HOST_WIDE_INT stack_realign_allocate;
354 HOST_WIDE_INT stack_realign_offset;
355 diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
356 index a3675e515bc..62944030337 100644
357 --- a/gcc/config/i386/i386.opt
358 +++ b/gcc/config/i386/i386.opt
359 @@ -518,6 +518,16 @@ mtls-direct-seg-refs
360 Target Mask(TLS_DIRECT_SEG_REFS)
361 Use direct references against %gs when accessing tls data.
364 +Target Mask(SAVE_ARGS) Var(ix86_target_flags)
365 +Save integer arguments on the stack at function entry.
367 +mforce-save-regs-using-mov
368 +Target Mask(FORCE_SAVE_REGS_USING_MOV) Var(ix86_target_flags)
369 +Save registers using push in function prologues. This is intentionally
370 +undocumented and used for msave-args testing.
374 Target RejectNegative Negative(mtune=) Joined Var(ix86_tune_string)
375 Schedule code for given CPU.
376 diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
377 index f003f8ce480..6529ed54965 100644
378 --- a/gcc/doc/invoke.texi
379 +++ b/gcc/doc/invoke.texi
380 @@ -19050,6 +19050,10 @@ addresses and sizes of sections. Programs can be statically linked only. The
381 @option{-mcmodel=large} option is incompatible with @option{-mabi=ilp32},
382 @option{-fpic} and @option{-fPIC}.
386 +Save integer-sized arguments on the stack on function entry.
389 @itemx -mno-strict-align
390 @opindex mstrict-align
391 diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
392 index 0a5c081d85e..6c1d8c57939 100644
393 --- a/gcc/dwarf2out.cc
394 +++ b/gcc/dwarf2out.cc
395 @@ -24036,6 +24036,11 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
396 /* Add the calling convention attribute if requested. */
397 add_calling_convention_attribute (subr_die, decl);
399 +#ifdef TARGET_SAVE_ARGS
400 + if (declaration && TARGET_SAVE_ARGS)
401 + add_AT_flag (subr_die, DW_AT_SUN_amd64_parmdump, 1);
404 /* Output Dwarf info for all of the stuff within the body of the function
405 (if it has one - it may be just a declaration).
407 diff --git a/gcc/testsuite/gcc.target/i386/msave-args-mov.c b/gcc/testsuite/gcc.target/i386/msave-args-mov.c
409 index 00000000000..a2ca76752a9
411 +++ b/gcc/testsuite/gcc.target/i386/msave-args-mov.c
413 +/* { dg-do run { target { { i?86-*-solaris2.* } && lp64 } } } */
414 +/* { dg-options "-msave-args -mforce-save-regs-using-mov -save-temps" } */
418 +void t(int, int, int, int, int) __attribute__ ((noinline));
421 +main(int argc, char **argv)
428 +t(int a, int b, int c, int d, int e)
430 + printf("%d %d %d %d %d", a, b, c, d, e);
433 +/* { dg-final { scan-assembler "movq\t%rdi, -8\\(%rbp\\)" } } */
434 +/* { dg-final { scan-assembler "movq\t%rsi, -16\\(%rbp\\)" } } */
435 +/* { dg-final { scan-assembler "movq\t%rdx, -24\\(%rbp\\)" } } */
436 +/* { dg-final { scan-assembler "movq\t%rcx, -32\\(%rbp\\)" } } */
437 +/* { dg-final { scan-assembler "movq\t%r8, -40\\(%rbp\\)" } } */
438 +/* { dg-final { cleanup-saved-temps } } */
439 diff --git a/gcc/testsuite/gcc.target/i386/msave-args-push.c b/gcc/testsuite/gcc.target/i386/msave-args-push.c
441 index 00000000000..fbe053dadc8
443 +++ b/gcc/testsuite/gcc.target/i386/msave-args-push.c
445 +/* { dg-do run { target { { i?86-*-solaris2.* } && lp64 } } } */
446 +/* { dg-options "-msave-args -save-temps " } */
450 +void t(int, int, int, int, int) __attribute__ ((noinline));
453 +main(int argc, char **argv)
460 +t(int a, int b, int c, int d, int e)
462 + printf("%d %d %d %d %d", a, b, c, d, e);
465 +/* { dg-final { scan-assembler "pushq\t%rdi" } } */
466 +/* { dg-final { scan-assembler "pushq\t%rsi" } } */
467 +/* { dg-final { scan-assembler "pushq\t%rdx" } } */
468 +/* { dg-final { scan-assembler "pushq\t%rcx" } } */
469 +/* { dg-final { scan-assembler "pushq\t%r8" } } */
470 +/* { dg-final { cleanup-saved-temps } } */
471 diff --git a/include/dwarf2.def b/include/dwarf2.def
472 index 4214c80907a..c2f36db4aa4 100644
473 --- a/include/dwarf2.def
474 +++ b/include/dwarf2.def
475 @@ -467,6 +467,8 @@ DW_TAG (DW_AT_GNU_denominator, 0x2304)
476 /* Biased integer extension.
477 See https://gcc.gnu.org/wiki/DW_AT_GNU_bias . */
478 DW_TAG (DW_AT_GNU_bias, 0x2305)
479 +/* Sun extension. */
480 +DW_AT (DW_AT_SUN_amd64_parmdump, 0x2224)
482 DW_AT (DW_AT_upc_threads_scaled, 0x3210)
483 /* PGI (STMicroelectronics) extensions. */