From f8104bb9dc2365d268ca93e43a24f42e8314fcc1 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Tue, 18 Aug 2020 17:31:49 +0200 Subject: [PATCH] i386: Rewrite restore_stack_nonlocal expander [PR96536]. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit -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 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. --- gcc/config/i386/i386.md | 115 ++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 72 deletions(-) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 09dcaa3..fb677e1 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -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; - - /* 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); + rtx noadj_label = gen_label_rtx (); + emit_cmp_and_jump_insns (reg_ssp, const0_rtx, EQ, NULL_RTX, + word_mode, 1, noadj_label); - /* 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)); + /* 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); - 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; + reg_adj = expand_simple_binop (ptr_mode, LSHIFTRT, reg_adj_neg, + GEN_INT (exact_log2 (UNITS_PER_WORD)), + reg_adj, 1, OPTAB_DIRECT); - rtx reg_255 = gen_reg_rtx (word_mode); - emit_move_insn (reg_255, GEN_INT (255)); + /* Check if number of frames <= 255 so no loop is needed. */ + 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)); - - /* 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; + + reg_adj = expand_simple_binop (ptr_mode, MINUS, + reg_adj, GEN_INT (255), + reg_adj, 1, OPTAB_DIRECT); + + /* 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); -- 2.7.4