needs to be cleared, the whole stack should be cleared. However,
x87 stack registers that hold the return value should be excluded.
x87 returns in the top (two for complex values) register, so
- num_of_st should be 7/6 when x87 returns, otherwise it will be 8. */
+ num_of_st should be 7/6 when x87 returns, otherwise it will be 8.
+ return the value of num_of_st. */
-static bool
+static int
zero_all_st_registers (HARD_REG_SET need_zeroed_hardregs)
{
/* If the FPU is disabled, no need to zero all st registers. */
if (! (TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387))
- return false;
+ return 0;
unsigned int num_of_st = 0;
for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
}
if (num_of_st == 0)
- return false;
+ return 0;
bool return_with_x87 = false;
return_with_x87 = (crtl->return_rtx
insn = emit_insn (gen_rtx_SET (st_reg, st_reg));
add_reg_note (insn, REG_DEAD, st_reg);
}
- return true;
+ return num_of_st;
}
{
HARD_REG_SET zeroed_hardregs;
bool all_sse_zeroed = false;
- bool all_st_zeroed = false;
+ int all_st_zeroed_num = 0;
bool all_mm_zeroed = false;
CLEAR_HARD_REG_SET (zeroed_hardregs);
if (!exit_with_mmx_mode)
/* x87 exit mode, we should zero all st registers together. */
{
- all_st_zeroed = zero_all_st_registers (need_zeroed_hardregs);
- if (all_st_zeroed)
- SET_HARD_REG_BIT (zeroed_hardregs, FIRST_STACK_REG);
+ all_st_zeroed_num = zero_all_st_registers (need_zeroed_hardregs);
+
+ if (all_st_zeroed_num > 0)
+ for (unsigned int regno = FIRST_STACK_REG; regno <= LAST_STACK_REG; regno++)
+ /* x87 stack registers that hold the return value should be excluded.
+ x87 returns in the top (two for complex values) register. */
+ if (all_st_zeroed_num == 8
+ || !((all_st_zeroed_num >= 6 && regno == REGNO (crtl->return_rtx))
+ || (all_st_zeroed_num == 6
+ && (regno == (REGNO (crtl->return_rtx) + 1)))))
+ SET_HARD_REG_BIT (zeroed_hardregs, regno);
}
else
/* MMX exit mode, check whether we can zero all mm registers. */
that could conceivably contain values that are useful to an attacker.
Return the set of registers that were actually cleared.
+For most targets, the returned set of registers is a subset of
+@var{selected_regs}, however, for some of the targets (for example MIPS),
+clearing some registers that are in the @var{selected_regs} requires
+clearing other call used registers that are not in the @var{selected_regs},
+under such situation, the returned set of registers must be a subset of all
+call used registers.
+
The default implementation uses normal move instructions to zero
all the registers in @var{selected_regs}. Define this hook if the
target has more efficient ways of zeroing certain registers,
df_simulate_one_insn_backwards (bb, ret, live_out);
HARD_REG_SET selected_hardregs;
+ HARD_REG_SET all_call_used_regs;
CLEAR_HARD_REG_SET (selected_hardregs);
+ CLEAR_HARD_REG_SET (all_call_used_regs);
for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
{
if (!crtl->abi->clobbers_full_reg_p (regno))
continue;
if (REGNO_REG_SET_P (live_out, regno))
continue;
+#ifdef LEAF_REG_REMAP
+ if (crtl->uses_only_leaf_regs && LEAF_REG_REMAP (regno) < 0)
+ continue;
+#endif
+ /* This is a call used register that is dead at return. */
+ SET_HARD_REG_BIT (all_call_used_regs, regno);
+
if (only_gpr
&& !TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], regno))
continue;
continue;
if (only_arg && !FUNCTION_ARG_REGNO_P (regno))
continue;
-#ifdef LEAF_REG_REMAP
- if (crtl->uses_only_leaf_regs && LEAF_REG_REMAP (regno) < 0)
- continue;
-#endif
/* Now this is a register that we might want to zero. */
SET_HARD_REG_BIT (selected_hardregs, regno);
HARD_REG_SET zeroed_hardregs;
start_sequence ();
zeroed_hardregs = targetm.calls.zero_call_used_regs (selected_hardregs);
+
+ /* For most targets, the returned set of registers is a subset of
+ selected_hardregs, however, for some of the targets (for example MIPS),
+ clearing some registers that are in selected_hardregs requires clearing
+ other call used registers that are not in the selected_hardregs, under
+ such situation, the returned set of registers must be a subset of
+ all call used registers. */
+ gcc_assert (hard_reg_set_subset_p (zeroed_hardregs, all_call_used_regs));
+
rtx_insn *seq = get_insns ();
end_sequence ();
if (seq)
that could conceivably contain values that are useful to an attacker.\n\
Return the set of registers that were actually cleared.\n\
\n\
+For most targets, the returned set of registers is a subset of\n\
+@var{selected_regs}, however, for some of the targets (for example MIPS),\n\
+clearing some registers that are in the @var{selected_regs} requires\n\
+clearing other call used registers that are not in the @var{selected_regs},\n\
+under such situation, the returned set of registers must be a subset of all\n\
+call used registers.\n\
+\n\
The default implementation uses normal move instructions to zero\n\
all the registers in @var{selected_regs}. Define this hook if the\n\
target has more efficient ways of zeroing certain registers,\n\