i386: Rewrite restore_stack_nonlocal expander [PR96536].
-fcf-protection code in restore_stack_nonlocal uses a branch based on a clobber result. The patch adds missing compare and completely rewrites the expander to use high-level functions in RTL construction. 2020-08-18 Uroš Bizjak <ubizjak@gmail.com> gcc/ChangeLog: PR target/96536 * config/i386/i386.md (restore_stack_nonlocal): Add missing compare RTX. Rewrite expander to use high-level functions in RTL construction.
This commit is contained in:
parent
6c1a58b7fb
commit
f8104bb9dc
@ -19112,15 +19112,17 @@
|
||||
""
|
||||
{
|
||||
rtx stack_slot;
|
||||
if ((flag_cf_protection & CF_RETURN))
|
||||
|
||||
if (flag_cf_protection & CF_RETURN)
|
||||
{
|
||||
/* Copy shadow stack pointer to the first slot and stack ppointer
|
||||
to the second slot. */
|
||||
/* Copy shadow stack pointer to the first slot
|
||||
and stack pointer to the second slot. */
|
||||
rtx ssp_slot = adjust_address (operands[0], word_mode, 0);
|
||||
stack_slot = adjust_address (operands[0], Pmode, UNITS_PER_WORD);
|
||||
rtx ssp = force_reg (word_mode, const0_rtx);
|
||||
emit_insn (gen_rdssp (word_mode, ssp, ssp));
|
||||
emit_move_insn (ssp_slot, ssp);
|
||||
|
||||
rtx reg_ssp = force_reg (word_mode, const0_rtx);
|
||||
emit_insn (gen_rdssp (word_mode, reg_ssp, reg_ssp));
|
||||
emit_move_insn (ssp_slot, reg_ssp);
|
||||
}
|
||||
else
|
||||
stack_slot = adjust_address (operands[0], Pmode, 0);
|
||||
@ -19134,95 +19136,64 @@
|
||||
""
|
||||
{
|
||||
rtx stack_slot;
|
||||
if ((flag_cf_protection & CF_RETURN))
|
||||
|
||||
if (flag_cf_protection & CF_RETURN)
|
||||
{
|
||||
/* Restore shadow stack pointer from the first slot and stack
|
||||
pointer from the second slot. */
|
||||
/* Restore shadow stack pointer from the first slot
|
||||
and stack pointer from the second slot. */
|
||||
rtx ssp_slot = adjust_address (operands[1], word_mode, 0);
|
||||
stack_slot = adjust_address (operands[1], Pmode, UNITS_PER_WORD);
|
||||
|
||||
rtx flags, jump, noadj_label, inc_label, loop_label;
|
||||
rtx reg_adj, reg_ssp, tmp, clob;
|
||||
|
||||
/* Get the current shadow stack pointer. The code below will check if
|
||||
SHSTK feature is enabled. If it is not enabled the RDSSP instruction
|
||||
is a NOP. */
|
||||
reg_ssp = force_reg (word_mode, const0_rtx);
|
||||
rtx reg_ssp = force_reg (word_mode, const0_rtx);
|
||||
emit_insn (gen_rdssp (word_mode, reg_ssp, reg_ssp));
|
||||
|
||||
/* Compare through substraction the saved and the current ssp to decide
|
||||
if ssp has to be adjusted. */
|
||||
tmp = gen_rtx_SET (reg_ssp, gen_rtx_MINUS (word_mode, reg_ssp,
|
||||
ssp_slot));
|
||||
clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
|
||||
tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
|
||||
emit_insn (tmp);
|
||||
/* Compare through subtraction the saved and the current ssp
|
||||
to decide if ssp has to be adjusted. */
|
||||
reg_ssp = expand_simple_binop (word_mode, MINUS,
|
||||
reg_ssp, ssp_slot,
|
||||
reg_ssp, 1, OPTAB_DIRECT);
|
||||
|
||||
/* Compare and jump over adjustment code. */
|
||||
noadj_label = gen_label_rtx ();
|
||||
flags = gen_rtx_REG (CCZmode, FLAGS_REG);
|
||||
tmp = gen_rtx_EQ (VOIDmode, flags, const0_rtx);
|
||||
tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
|
||||
gen_rtx_LABEL_REF (VOIDmode, noadj_label),
|
||||
pc_rtx);
|
||||
jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
|
||||
JUMP_LABEL (jump) = noadj_label;
|
||||
rtx noadj_label = gen_label_rtx ();
|
||||
emit_cmp_and_jump_insns (reg_ssp, const0_rtx, EQ, NULL_RTX,
|
||||
word_mode, 1, noadj_label);
|
||||
|
||||
/* Compute the numebr of frames to adjust. */
|
||||
reg_adj = gen_lowpart (ptr_mode, reg_ssp);
|
||||
tmp = gen_rtx_SET (reg_adj,
|
||||
gen_rtx_LSHIFTRT (ptr_mode,
|
||||
negate_rtx (ptr_mode, reg_adj),
|
||||
GEN_INT ((word_mode == SImode)
|
||||
? 2
|
||||
: 3)));
|
||||
clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
|
||||
tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
|
||||
emit_insn (tmp);
|
||||
/* Compute the number of frames to adjust. */
|
||||
rtx reg_adj = gen_lowpart (ptr_mode, reg_ssp);
|
||||
rtx reg_adj_neg = expand_simple_unop (ptr_mode, NEG, reg_adj,
|
||||
NULL_RTX, 1);
|
||||
|
||||
reg_adj = expand_simple_binop (ptr_mode, LSHIFTRT, reg_adj_neg,
|
||||
GEN_INT (exact_log2 (UNITS_PER_WORD)),
|
||||
reg_adj, 1, OPTAB_DIRECT);
|
||||
|
||||
/* Check if number of frames <= 255 so no loop is needed. */
|
||||
tmp = gen_rtx_COMPARE (CCmode, reg_adj, GEN_INT (255));
|
||||
flags = gen_rtx_REG (CCmode, FLAGS_REG);
|
||||
emit_insn (gen_rtx_SET (flags, tmp));
|
||||
|
||||
inc_label = gen_label_rtx ();
|
||||
tmp = gen_rtx_LEU (VOIDmode, flags, const0_rtx);
|
||||
tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
|
||||
gen_rtx_LABEL_REF (VOIDmode, inc_label),
|
||||
pc_rtx);
|
||||
jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
|
||||
JUMP_LABEL (jump) = inc_label;
|
||||
|
||||
rtx reg_255 = gen_reg_rtx (word_mode);
|
||||
emit_move_insn (reg_255, GEN_INT (255));
|
||||
rtx inc_label = gen_label_rtx ();
|
||||
emit_cmp_and_jump_insns (reg_adj, GEN_INT (255), LEU, NULL_RTX,
|
||||
ptr_mode, 1, inc_label);
|
||||
|
||||
/* Adjust the ssp in a loop. */
|
||||
loop_label = gen_label_rtx ();
|
||||
rtx loop_label = gen_label_rtx ();
|
||||
emit_label (loop_label);
|
||||
LABEL_NUSES (loop_label) = 1;
|
||||
|
||||
rtx reg_255 = force_reg (word_mode, GEN_INT (255));
|
||||
emit_insn (gen_incssp (word_mode, reg_255));
|
||||
tmp = gen_rtx_SET (reg_adj, gen_rtx_MINUS (ptr_mode,
|
||||
reg_adj,
|
||||
GEN_INT (255)));
|
||||
clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
|
||||
tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
|
||||
emit_insn (tmp);
|
||||
|
||||
tmp = gen_rtx_COMPARE (CCmode, reg_adj, GEN_INT (255));
|
||||
flags = gen_rtx_REG (CCmode, FLAGS_REG);
|
||||
emit_insn (gen_rtx_SET (flags, tmp));
|
||||
reg_adj = expand_simple_binop (ptr_mode, MINUS,
|
||||
reg_adj, GEN_INT (255),
|
||||
reg_adj, 1, OPTAB_DIRECT);
|
||||
|
||||
/* Jump to the loop label. */
|
||||
tmp = gen_rtx_GTU (VOIDmode, flags, const0_rtx);
|
||||
tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
|
||||
gen_rtx_LABEL_REF (VOIDmode, loop_label),
|
||||
pc_rtx);
|
||||
jump = emit_jump_insn (gen_rtx_SET (pc_rtx, tmp));
|
||||
JUMP_LABEL (jump) = loop_label;
|
||||
/* Compare and jump to the loop label. */
|
||||
emit_cmp_and_jump_insns (reg_adj, GEN_INT (255), GTU, NULL_RTX,
|
||||
ptr_mode, 1, loop_label);
|
||||
|
||||
emit_label (inc_label);
|
||||
LABEL_NUSES (inc_label) = 1;
|
||||
|
||||
emit_insn (gen_incssp (word_mode, reg_ssp));
|
||||
|
||||
emit_label (noadj_label);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user