+---------------------------------------+
| Parameter save area (+padding*) (P) | 32
+---------------------------------------+
- | Alloca space (A) | 32+P
+ | Optional ROP hash slot (R) | 32+P
+---------------------------------------+
- | Local variable space (L) | 32+P+A
+ | Alloca space (A) | 32+P+R
+---------------------------------------+
- | Save area for AltiVec registers (W) | 32+P+A+L
+ | Local variable space (L) | 32+P+R+A
+---------------------------------------+
- | AltiVec alignment padding (Y) | 32+P+A+L+W
+ | Save area for AltiVec registers (W) | 32+P+R+A+L
+---------------------------------------+
- | Save area for GP registers (G) | 32+P+A+L+W+Y
+ | AltiVec alignment padding (Y) | 32+P+R+A+L+W
+---------------------------------------+
- | Save area for FP registers (F) | 32+P+A+L+W+Y+G
+ | Save area for GP registers (G) | 32+P+R+A+L+W+Y
+---------------------------------------+
- old SP->| back chain to caller's caller | 32+P+A+L+W+Y+G+F
+ | Save area for FP registers (F) | 32+P+R+A+L+W+Y+G
+ +---------------------------------------+
+ old SP->| back chain to caller's caller | 32+P+R+A+L+W+Y+G+F
+---------------------------------------+
* If the alloca area is present, the parameter save area is
/* Does this function call anything (apart from sibling calls)? */
info->calls_p = (!crtl->is_leaf || cfun->machine->ra_needs_full_frame);
+ info->rop_hash_size = 0;
+
+ if (TARGET_POWER10
+ && info->calls_p
+ && DEFAULT_ABI == ABI_ELFv2
+ && rs6000_rop_protect)
+ info->rop_hash_size = 8;
+ else if (rs6000_rop_protect && DEFAULT_ABI != ABI_ELFv2)
+ {
+ /* We can't check this in rs6000_option_override_internal since
+ DEFAULT_ABI isn't established yet. */
+ error ("%qs requires the ELFv2 ABI", "-mrop-protect");
+ }
/* Determine if we need to save the condition code registers. */
if (save_reg_p (CR2_REGNO)
/* Adjust for AltiVec case. */
info->ehrd_offset = info->altivec_save_offset - ehrd_size;
+
+ /* Adjust for ROP protection. */
+ info->rop_hash_save_offset
+ = info->altivec_save_offset - info->rop_hash_size;
+ info->ehrd_offset -= info->rop_hash_size;
}
else
info->ehrd_offset = info->gp_save_offset - ehrd_size;
+ info->gp_size
+ info->altivec_size
+ info->altivec_padding_size
+ + info->rop_hash_size
+ ehrd_size
+ ehcr_size
+ info->cr_size
fprintf (stderr, "\tvrsave_save_offset = %5d\n",
info->vrsave_save_offset);
+ if (info->rop_hash_size)
+ fprintf (stderr, "\trop_hash_save_offset = %5d\n",
+ info->rop_hash_save_offset);
+
if (info->lr_save_p)
fprintf (stderr, "\tlr_save_offset = %5d\n", info->lr_save_offset);
fprintf (stderr, "\taltivec_padding_size= %5d\n",
info->altivec_padding_size);
+ if (info->rop_hash_size)
+ fprintf (stderr, "\trop_hash_size = %5d\n", info->rop_hash_size);
+
if (info->cr_size)
fprintf (stderr, "\tcr_size = %5d\n", info->cr_size);
}
}
+ /* The ROP hash store must occur before a stack frame is created,
+ since the hash operates on r1. */
+ /* NOTE: The hashst isn't needed if we're going to do a sibcall,
+ but there's no way to know that here. Harmless except for
+ performance, of course. */
+ if (TARGET_POWER10 && rs6000_rop_protect && info->rop_hash_size != 0)
+ {
+ gcc_assert (DEFAULT_ABI == ABI_ELFv2);
+ rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+ rtx addr = gen_rtx_PLUS (Pmode, stack_ptr,
+ GEN_INT (info->rop_hash_save_offset));
+ rtx mem = gen_rtx_MEM (Pmode, addr);
+ rtx reg0 = gen_rtx_REG (Pmode, 0);
+ emit_insn (gen_hashst (mem, reg0));
+ }
+
/* If we need to save CR, put it into r12 or r11. Choose r12 except when
r12 will be needed by out-of-line gpr save. */
cr_save_regno = ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
emit_insn (gen_add3_insn (sp_reg_rtx, sp_reg_rtx, sa));
}
+ /* The ROP hash check must occur after the stack pointer is restored
+ (since the hash involves r1), and is not performed for a sibcall. */
+ if (TARGET_POWER10
+ && rs6000_rop_protect
+ && info->rop_hash_size != 0
+ && epilogue_type != EPILOGUE_TYPE_SIBCALL)
+ {
+ gcc_assert (DEFAULT_ABI == ABI_ELFv2);
+ rtx stack_ptr = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+ rtx addr = gen_rtx_PLUS (Pmode, stack_ptr,
+ GEN_INT (info->rop_hash_save_offset));
+ rtx mem = gen_rtx_MEM (Pmode, addr);
+ rtx reg0 = gen_rtx_REG (Pmode, 0);
+ emit_insn (gen_hashchk (reg0, mem));
+ }
+
if (epilogue_type != EPILOGUE_TYPE_SIBCALL && restoring_FPRs_inline)
{
if (cfa_restores)