i386: Rewrite restore_stack_nonlocal expander [PR96536].
authorUros Bizjak <ubizjak@gmail.com>
Tue, 18 Aug 2020 15:31:49 +0000 (17:31 +0200)
committerUros Bizjak <ubizjak@gmail.com>
Tue, 18 Aug 2020 15:31:49 +0000 (17:31 +0200)
-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.

gcc/config/i386/i386.md

index 09dcaa3..fb677e1 100644 (file)
   ""
 {
   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);
   ""
 {
   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);