This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Detect frame size overflow (2)
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 9 Mar 2006 18:36:34 +0100
- Subject: [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;
}