This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Detect frame size overflow (2)


Hi,

In November of last year I submitted a generic patch to detect frame size 
overflow:

	* function.c (assign_stack_local_1): Issue an error message if
	the frame size overflows in the signed target arithmetics.

It turned out to be incomplete, as demonstrated by the attached testcase which 
should cause the compiler to issue 2 error messages on x86, not only 1 as it 
currently does:

/home/eric/gnat/bugs/EA28-003/bm.adb: In function 'BM.NEGATE':
/home/eric/gnat/bugs/EA28-003/bm.adb:20: error: total size of local objects 
too large

Moreover, I've also changed the check to use signed target pointer arithmetics 
as suggested by Ian in http://gcc.gnu.org/ml/gcc/2005-11/msg00540.html.

Bootstrapped/regtested on x86_64-suse-linux.  OK for mainline?


2006-03-09  Eric Botcazou  <ebotcazou@adacore.com>

	* function.h (frame_offset_overflow): Declare.
	* function.c (frame_offset_overflow): New function.
	(assign_stack_local_1): Call it to detect that the offset overflows.
	* cfgexpand.c (alloc_stack_frame_space): Likewise.


-- 
Eric Botcazou
procedure BM is

   type Bitpos_Range_T is new Positive;
   type Bitmap_Array_T is array (Bitpos_Range_T) of Boolean;

   type Bitmap_T is record
      Bits : Bitmap_Array_T := (others => False);
   end record;
   
   function 
     Set_In (Bitmap : Bitmap_T; Bitpos : Bitpos_Range_T)  return Bitmap_T
   is
      Result: Bitmap_T := Bitmap;
   begin
      Result.Bits (Bitpos) := True;
      return Result;
   end;

   function Negate (Bitmap : Bitmap_T) return Bitmap_T is
      Result: Bitmap_T;
   begin
      for E in Bitpos_Range_T loop
	 Result.Bits (E) := not Bitmap.Bits (E);
      end loop;
      return Result;
  end;

begin
   null;
END;
Index: function.h
===================================================================
--- function.h	(revision 111804)
+++ function.h	(working copy)
@@ -534,6 +534,11 @@ extern void free_block_changes (void);
    the caller may have to do that.  */
 extern HOST_WIDE_INT get_frame_size (void);
 
+/* Issue an error message and return TRUE if frame OFFSET overflows in
+   the signed target pointer arithmetics for function FUNC.  Otherwise
+   return FALSE.  */
+extern bool frame_offset_overflow (HOST_WIDE_INT, tree);
+
 /* A pointer to a function to create target specific, per-function
    data structures.  */
 extern struct machine_function * (*init_machine_status) (void);
Index: function.c
===================================================================
--- function.c	(revision 111804)
+++ function.c	(working copy)
@@ -358,12 +358,33 @@ get_func_frame_size (struct function *f)
 /* Return size needed for stack frame based on slots so far allocated.
    This size counts from zero.  It is not rounded to PREFERRED_STACK_BOUNDARY;
    the caller may have to do that.  */
+
 HOST_WIDE_INT
 get_frame_size (void)
 {
   return get_func_frame_size (cfun);
 }
 
+/* Issue an error message and return TRUE if frame OFFSET overflows in
+   the signed target pointer arithmetics for function FUNC.  Otherwise
+   return FALSE.  */
+
+bool
+frame_offset_overflow (HOST_WIDE_INT offset, tree func)
+{  
+  unsigned HOST_WIDE_INT size = FRAME_GROWS_DOWNWARD ? -offset : offset;
+
+  if (size > ((unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (Pmode) - 1))
+	       /* Leave room for the fixed part of the frame.  */
+	       - 64 * UNITS_PER_WORD)
+    {
+      error ("%Jtotal size of local objects too large", func);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
 /* Allocate a stack slot of SIZE bytes and return a MEM rtx for it
    with machine mode MODE.
 
@@ -479,20 +500,8 @@ assign_stack_local_1 (enum machine_mode 
   function->x_stack_slot_list
     = gen_rtx_EXPR_LIST (VOIDmode, x, function->x_stack_slot_list);
 
-  /* Try to detect frame size overflows on native platforms.  */
-#if BITS_PER_WORD >= 32
-  if ((FRAME_GROWS_DOWNWARD
-       ? (unsigned HOST_WIDE_INT) -function->x_frame_offset
-       : (unsigned HOST_WIDE_INT) function->x_frame_offset)
-	> ((unsigned HOST_WIDE_INT) 1 << (BITS_PER_WORD - 1))
-	    /* Leave room for the fixed part of the frame.  */
-	    - 64 * UNITS_PER_WORD)
-    {
-      error ("%Jtotal size of local objects too large", function->decl);
-      /* Avoid duplicate error messages as much as possible.  */
-      function->x_frame_offset = 0;
-    }
-#endif
+  if (frame_offset_overflow (function->x_frame_offset, function->decl))
+    function->x_frame_offset = 0;
 
   return x;
 }
Index: cfgexpand.c
===================================================================
--- cfgexpand.c	(revision 111804)
+++ cfgexpand.c	(working copy)
@@ -192,6 +192,9 @@ alloc_stack_frame_space (HOST_WIDE_INT s
     }
   frame_offset = new_frame_offset;
 
+  if (frame_offset_overflow (frame_offset, cfun->decl))
+    frame_offset = offset = 0;
+
   return offset;
 }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]