e835ae2
2012-12-19  Jakub Jelinek  <jakub@redhat.com>
e835ae2
e835ae2
	PR fortran/55341
e835ae2
	* asan.c (asan_clear_shadow): New function.
e835ae2
	(asan_emit_stack_protection): Use it.
e835ae2
e835ae2
--- gcc/asan.c.jj	2012-12-13 00:05:04.000000000 +0100
e835ae2
+++ gcc/asan.c	2012-12-19 12:25:57.676365851 +0100
e835ae2
@@ -270,6 +270,45 @@ asan_shadow_cst (unsigned char shadow_by
e835ae2
   return GEN_INT (trunc_int_for_mode (val, SImode));
e835ae2
 }
e835ae2
 
e835ae2
+/* Clear shadow memory at SHADOW_MEM, LEN bytes.  Can't call a library call here
e835ae2
+   though.  */
e835ae2
+
e835ae2
+static void
e835ae2
+asan_clear_shadow (rtx shadow_mem, HOST_WIDE_INT len)
e835ae2
+{
e835ae2
+  rtx insn, insns, top_label, end, addr, tmp, jump;
e835ae2
+
e835ae2
+  start_sequence ();
e835ae2
+  clear_storage (shadow_mem, GEN_INT (len), BLOCK_OP_NORMAL);
e835ae2
+  insns = get_insns ();
e835ae2
+  end_sequence ();
e835ae2
+  for (insn = insns; insn; insn = NEXT_INSN (insn))
e835ae2
+    if (CALL_P (insn))
e835ae2
+      break;
e835ae2
+  if (insn == NULL_RTX)
e835ae2
+    {
e835ae2
+      emit_insn (insns);
e835ae2
+      return;
e835ae2
+    }
e835ae2
+
e835ae2
+  gcc_assert ((len & 3) == 0);
e835ae2
+  top_label = gen_label_rtx ();
e835ae2
+  addr = force_reg (Pmode, XEXP (shadow_mem, 0));
e835ae2
+  shadow_mem = adjust_automodify_address (shadow_mem, SImode, addr, 0);
e835ae2
+  end = force_reg (Pmode, plus_constant (Pmode, addr, len));
e835ae2
+  emit_label (top_label);
e835ae2
+
e835ae2
+  emit_move_insn (shadow_mem, const0_rtx);
e835ae2
+  tmp = expand_simple_binop (Pmode, PLUS, addr, GEN_INT (4), addr,
e835ae2
+                             true, OPTAB_LIB_WIDEN);
e835ae2
+  if (tmp != addr)
e835ae2
+    emit_move_insn (addr, tmp);
e835ae2
+  emit_cmp_and_jump_insns (addr, end, LT, NULL_RTX, Pmode, true, top_label);
e835ae2
+  jump = get_last_insn ();
e835ae2
+  gcc_assert (JUMP_P (jump));
e835ae2
+  add_reg_note (jump, REG_BR_PROB, GEN_INT (REG_BR_PROB_BASE * 80 / 100));
e835ae2
+}
e835ae2
+
e835ae2
 /* Insert code to protect stack vars.  The prologue sequence should be emitted
e835ae2
    directly, epilogue sequence returned.  BASE is the register holding the
e835ae2
    stack base, against which OFFSETS array offsets are relative to, OFFSETS
e835ae2
@@ -404,8 +443,7 @@ asan_emit_stack_protection (rtx base, HO
e835ae2
 				       (last_offset - prev_offset)
e835ae2
 				       >> ASAN_SHADOW_SHIFT);
e835ae2
 	  prev_offset = last_offset;
e835ae2
-	  clear_storage (shadow_mem, GEN_INT (last_size >> ASAN_SHADOW_SHIFT),
e835ae2
-			 BLOCK_OP_NORMAL);
e835ae2
+	  asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
e835ae2
 	  last_offset = offset;
e835ae2
 	  last_size = 0;
e835ae2
 	}
e835ae2
@@ -418,8 +456,7 @@ asan_emit_stack_protection (rtx base, HO
e835ae2
       shadow_mem = adjust_address (shadow_mem, VOIDmode,
e835ae2
 				   (last_offset - prev_offset)
e835ae2
 				   >> ASAN_SHADOW_SHIFT);
e835ae2
-      clear_storage (shadow_mem, GEN_INT (last_size >> ASAN_SHADOW_SHIFT),
e835ae2
-		     BLOCK_OP_NORMAL);
e835ae2
+      asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
e835ae2
     }
e835ae2
 
e835ae2
   do_pending_stack_adjust ();