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]

[arm] EABI array cookies


The patch implements ARM C++ EABI compliant array cookies.
These have a fixed size of 8 bytes, and contain both the element size and 
number of elements.

Bootstrapped on i686-linux and tested with cross to arm-none-elf.
Ok?

Paul

2004-06-29  Paul Brook  <paul@codesourcery.com>

gcc/
	* target-def.h (TARGET_CXX_GET_COOKIE_SIZE,
	TARGET_CXX_COOKIE_HAS_SIZE): Define.
	(TARGET_CXX): Use them.
	* target.h (struct gcc_target): Add cxx.get_cookie_size and
	cxx.cookie_has_size.
	* targhooks.c (default_cxx_get_cookie_size): New fucntion.
	* targhooks.h (default_cxx_get_cookie_size): Add prototype.
	* config/arm/arm.c (TARGET_CXX_GET_COOKIE_SIZE,
	TARGET_CXX_COOKIE_HAS_SIZE): Define.
	(arm_get_cookie_size, arm_cookie_has_size): New functions.
	* Make-lang.in (cp/init.o): Add dependency on $(TARGET_H).
	* init.c: Include target.h.
	(get_cookie_size): Remove and replace with target hook.
	Update callers.
	(build_new_1): Store the element size in the cookie.
libstdc++-v3/
	* libsupc++/vec.cc (__cxa_vec_new2, __cxa_vec_new3): Store the
	element size in the cookie.
testsuite/
	* g++.old-deja/g++.abi/arraynew.C: Handle ARM EABI cookies.
	* g++.old-deja/g++.abi/cxa_vec.C: Allocate larger cookies for AEABI.

Index: gcc/target-def.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/target-def.h,v
retrieving revision 1.81
diff -u -p -r1.81 target-def.h
--- gcc/target-def.h	25 Jun 2004 17:15:35 -0000	1.81
+++ gcc/target-def.h	27 Jun 2004 00:01:05 -0000
@@ -400,10 +400,20 @@ Foundation, 59 Temple Place - Suite 330,
 #define TARGET_CXX_GUARD_MASK_BIT hook_bool_void_false
 #endif
 
+#ifndef TARGET_CXX_GET_COOKIE_SIZE
+#define TARGET_CXX_GET_COOKIE_SIZE default_cxx_get_cookie_size
+#endif
+
+#ifndef TARGET_CXX_COOKIE_HAS_SIZE
+#define TARGET_CXX_COOKIE_HAS_SIZE hook_bool_void_false
+#endif
+
 #define TARGET_CXX		\
   {				\
     TARGET_CXX_GUARD_TYPE,	\
-    TARGET_CXX_GUARD_MASK_BIT	\
+    TARGET_CXX_GUARD_MASK_BIT,	\
+    TARGET_CXX_GET_COOKIE_SIZE,	\
+    TARGET_CXX_COOKIE_HAS_SIZE	\
   }
 
 /* The whole shebang.  */
Index: gcc/target.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/target.h,v
retrieving revision 1.93
diff -u -p -r1.93 target.h
--- gcc/target.h	25 Jun 2004 17:15:37 -0000	1.93
+++ gcc/target.h	27 Jun 2004 00:02:58 -0000
@@ -482,6 +482,11 @@ struct gcc_target
     tree (*guard_type) (void);
     /* Return true if only the low bit of the guard should be tested.  */
     bool (*guard_mask_bit) (void);
+    /* Returns the size of the array cookie for and array of type.  */
+    tree (*get_cookie_size) (tree);
+    /* Returns true if the element size should be stored in the
+       array cookie.  */
+    bool (*cookie_has_size) (void);
   } cxx;
 
   /* Leave the boolean fields at the end.  */
Index: gcc/targhooks.c
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/targhooks.c,v
retrieving revision 2.22
diff -u -p -r2.22 targhooks.c
--- gcc/targhooks.c	25 Jun 2004 17:15:38 -0000	2.22
+++ gcc/targhooks.c	29 Jun 2004 11:42:39 -0000
@@ -143,3 +143,28 @@ default_cxx_guard_type (void)
 {
   return long_long_integer_type_node;
 }
+
+
+/* Returns the size of the cookie to use when allocating an array
+   whose elements have the indicated TYPE.  Assumes that it is already
+   known that a cookie is needed.  */
+
+tree
+default_cxx_get_cookie_size (tree type)
+{
+  tree cookie_size;
+
+  /* We need to allocate an additional max (sizeof (size_t), alignof
+     (true_type)) bytes.  */
+  tree sizetype_size;
+  tree type_align;
+  
+  sizetype_size = size_in_bytes (sizetype);
+  type_align = size_int (TYPE_ALIGN_UNIT (type));
+  if (INT_CST_LT_UNSIGNED (type_align, sizetype_size))
+    cookie_size = sizetype_size;
+  else
+    cookie_size = type_align;
+
+  return cookie_size;
+}
Index: gcc/targhooks.h
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/targhooks.h,v
retrieving revision 2.13
diff -u -p -r2.13 targhooks.h
--- gcc/targhooks.h	25 Jun 2004 17:15:38 -0000	2.13
+++ gcc/targhooks.h	27 Jun 2004 00:31:44 -0000
@@ -33,3 +33,4 @@ extern bool default_pretend_outgoing_var
 
 extern bool hook_bool_CUMULATIVE_ARGS_true (CUMULATIVE_ARGS *);
 extern tree default_cxx_guard_type (void);
+extern tree default_cxx_get_cookie_size (tree);
Index: gcc/config/arm/arm.c
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.368
diff -u -p -r1.368 arm.c
--- gcc/config/arm/arm.c	25 Jun 2004 17:15:38 -0000	1.368
+++ gcc/config/arm/arm.c	29 Jun 2004 11:32:41 -0000
@@ -164,6 +164,8 @@ static bool arm_align_anon_bitfield (voi
 
 static tree arm_cxx_guard_type (void);
 static bool arm_cxx_guard_mask_bit (void);
+static tree arm_get_cookie_size (tree);
+static bool arm_cookie_has_size (void);
 
 
 /* Initialize the GCC target structure.  */
@@ -273,6 +275,12 @@ static bool arm_cxx_guard_mask_bit (void
 #undef TARGET_CXX_GUARD_MASK_BIT
 #define TARGET_CXX_GUARD_MASK_BIT arm_cxx_guard_mask_bit
 
+#undef TARGET_CXX_GET_COOKIE_SIZE
+#define TARGET_CXX_GET_COOKIE_SIZE arm_get_cookie_size
+
+#undef TARGET_CXX_COOKIE_HAS_SIZE
+#define TARGET_CXX_COOKIE_HAS_SIZE arm_cookie_has_size
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Obstack for minipool constant handling.  */
@@ -14564,3 +14572,28 @@ arm_cxx_guard_mask_bit (void)
 {
   return TARGET_AAPCS_BASED;
 }
+
+
+/* The EABI specifies that all array cookies and 8 bytes long.  */
+
+static tree
+arm_get_cookie_size (tree type)
+{
+  tree size;
+
+  if (!TARGET_AAPCS_BASED)
+    return default_cxx_get_cookie_size (type);
+
+  size = build_int_2 (8, 0);
+  TREE_TYPE (size) = sizetype;
+  return size;
+}
+
+
+/* The EABI says that array cookies should also contain the element size.  */
+
+static bool
+arm_cookie_has_size (void)
+{
+  return TARGET_AAPCS_BASED;
+}
Index: gcc/cp/Make-lang.in
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/cp/Make-lang.in,v
retrieving revision 1.184
diff -u -p -r1.184 Make-lang.in
--- gcc/cp/Make-lang.in	24 Jun 2004 06:48:41 -0000	1.184
+++ gcc/cp/Make-lang.in	24 Jun 2004 22:08:27 -0000
@@ -235,7 +235,7 @@ cp/call.o: cp/call.c $(CXX_TREE_H) $(TM_
      diagnostic.h intl.h gt-cp-call.h convert.h target.h
 cp/friend.o: cp/friend.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) toplev.h 
$(EXPR_H)
 cp/init.o: cp/init.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) 
toplev.h \
-  except.h
+  except.h $(TARGET_H)
 cp/method.o: cp/method.c $(CXX_TREE_H) $(TM_H) toplev.h $(RTL_H) $(EXPR_H) \
   $(TM_P_H) $(TARGET_H) gt-cp-method.h
 cp/cvt.o: cp/cvt.c $(CXX_TREE_H) $(TM_H) cp/decl.h flags.h toplev.h convert.h
Index: gcc/cp/init.c
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/cp/init.c,v
retrieving revision 1.377
diff -u -p -r1.377 init.c
--- gcc/cp/init.c	24 Jun 2004 15:05:34 -0000	1.377
+++ gcc/cp/init.c	29 Jun 2004 11:42:54 -0000
@@ -34,6 +34,7 @@ Boston, MA 02111-1307, USA.  */
 #include "output.h"
 #include "except.h"
 #include "toplev.h"
+#include "target.h"
 
 static bool begin_init_stmts (tree *, tree *);
 static tree finish_init_stmts (bool, tree, tree);
@@ -52,7 +53,6 @@ static tree get_temp_regvar (tree, tree)
 static tree dfs_initialize_vtbl_ptrs (tree, void *);
 static tree build_default_init (tree, tree);
 static tree build_new_1	(tree);
-static tree get_cookie_size (tree);
 static tree build_dtor_call (tree, special_function_kind, int);
 static tree build_field_list (tree, tree, int *);
 static tree build_vtbl_address (tree);
@@ -1759,29 +1759,6 @@ build_java_class_ref (tree type)
   return class_decl;
 }
 
-/* Returns the size of the cookie to use when allocating an array
-   whose elements have the indicated TYPE.  Assumes that it is already
-   known that a cookie is needed.  */
-
-static tree
-get_cookie_size (tree type)
-{
-  tree cookie_size;
-
-  /* We need to allocate an additional max (sizeof (size_t), alignof
-     (true_type)) bytes.  */
-  tree sizetype_size;
-  tree type_align;
-  
-  sizetype_size = size_in_bytes (sizetype);
-  type_align = size_int (TYPE_ALIGN_UNIT (type));
-  if (INT_CST_LT_UNSIGNED (type_align, sizetype_size))
-    cookie_size = sizetype_size;
-  else
-    cookie_size = type_align;
-
-  return cookie_size;
-}
 
 /* Called from cplus_expand_expr when expanding a NEW_EXPR.  The return
    value is immediately handed to expand_expr.  */
@@ -1928,7 +1905,7 @@ build_new_1 (tree exp)
 	  /* If a cookie is required, add some extra space.  */
 	  if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type))
 	    {
-	      cookie_size = get_cookie_size (true_type);
+	      cookie_size = targetm.cxx.get_cookie_size (true_type);
 	      size = size_binop (PLUS_EXPR, size, cookie_size);
 	    }
 	  /* Create the argument list.  */
@@ -1951,7 +1928,7 @@ build_new_1 (tree exp)
 	  /* Use a global operator new.  */
 	  /* See if a cookie might be required.  */
 	  if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type))
-	    cookie_size = get_cookie_size (true_type);
+	    cookie_size = targetm.cxx.get_cookie_size (true_type);
 	  else
 	    cookie_size = NULL_TREE;
 
@@ -2022,6 +1999,7 @@ build_new_1 (tree exp)
   if (cookie_size)
     {
       tree cookie;
+      tree cookie_ptr;
 
       /* Adjust so we're pointing to the start of the object.  */
       data_addr = get_target_expr (build (PLUS_EXPR, full_pointer_type,
@@ -2030,11 +2008,23 @@ build_new_1 (tree exp)
       /* Store the number of bytes allocated so that we can know how
 	 many elements to destroy later.  We use the last sizeof
 	 (size_t) bytes to store the number of elements.  */
-      cookie = build (MINUS_EXPR, build_pointer_type (sizetype),
+      cookie_ptr = build (MINUS_EXPR, build_pointer_type (sizetype),
 		      data_addr, size_in_bytes (sizetype));
-      cookie = build_indirect_ref (cookie, NULL);
+      cookie = build_indirect_ref (cookie_ptr, NULL);
 
       cookie_expr = build (MODIFY_EXPR, sizetype, cookie, nelts);
+
+      if (targetm.cxx.cookie_has_size ())
+	{
+	  /* Also store the element size.  */
+	  cookie_ptr = build (MINUS_EXPR, build_pointer_type (sizetype),
+			      cookie_ptr, size_in_bytes (sizetype));
+	  cookie = build_indirect_ref (cookie_ptr, NULL);
+	  cookie = build (MODIFY_EXPR, sizetype, cookie,
+			  size_in_bytes(true_type));
+	  cookie_expr = build (COMPOUND_EXPR, TREE_TYPE (cookie_expr),
+			       cookie, cookie_expr);
+	}
       data_addr = TARGET_EXPR_SLOT (data_addr);
     }
   else
@@ -2281,7 +2271,7 @@ build_vec_delete_1 (tree base, tree maxi
 	{
 	  tree cookie_size;
 
-	  cookie_size = get_cookie_size (type);
+	  cookie_size = targetm.cxx.get_cookie_size (type);
 	  base_tbd 
 	    = cp_convert (ptype,
 			  cp_build_binary_op (MINUS_EXPR,
Index: gcc/testsuite/g++.old-deja/g++.abi/arraynew.C
===================================================================
RCS 
file: /var/cvsroot/gcc-cvs/gcc/gcc/testsuite/g++.old-deja/g++.abi/arraynew.C,v
retrieving revision 1.5
diff -u -p -r1.5 arraynew.C
--- gcc/testsuite/g++.old-deja/g++.abi/arraynew.C	1 May 2003 02:02:33 -0000	
1.5
+++ gcc/testsuite/g++.old-deja/g++.abi/arraynew.C	28 Jun 2004 19:25:23 -0000
@@ -36,11 +36,16 @@ template <typename T>
 void check_cookie (int i)
 {
   void* a = new T[11];
+  size_t x;
   
   // Compute the cookie location manually.
-  size_t x = __alignof__ (T);
+#ifdef __ARM_EABI__
+  x = 8;
+#else
+  x = __alignof__ (T);
   if (x < sizeof (size_t))
     x = sizeof (size_t);
+#endif
   if ((char *) a - x != (char *) p)
     exit (i);
 
@@ -48,6 +53,12 @@ void check_cookie (int i)
   size_t *sp = ((size_t *) a) - 1;
   if (*sp != 11)
     exit (i);
+
+#ifdef __ARM_EABI__
+  size_t *sp = ((size_t *) a) - 2;
+  if (*sp != sizeof (T))
+    exit (i);
+#endif
 }
 
 template <typename T>
@@ -55,11 +66,16 @@ void check_placement_cookie (int i)
 {
   p = malloc (sizeof (T) * 11 + 100);
   void* a = new (p) T[11];
+  size_t x;
   
   // Compute the cookie location manually.
-  size_t x = __alignof__ (T);
+#ifdef __ARM_EABI__
+  x = 8;
+#else
+  x = __alignof__ (T);
   if (x < sizeof (size_t))
     x = sizeof (size_t);
+#endif
   if ((char *) a - x != (char *) p)
     exit (i);
 
@@ -67,6 +83,12 @@ void check_placement_cookie (int i)
   size_t *sp = ((size_t *) a) - 1;
   if (*sp != 11)
     exit (i);
+
+#ifdef __ARM_EABI__
+  size_t *sp = ((size_t *) a) - 2;
+  if (*sp != sizeof (T))
+    exit (i);
+#endif
 }
 
 struct X {};
Index: gcc/testsuite/g++.old-deja/g++.abi/cxa_vec.C
===================================================================
RCS 
file: /var/cvsroot/gcc-cvs/gcc/gcc/testsuite/g++.old-deja/g++.abi/cxa_vec.C,v
retrieving revision 1.5
diff -u -p -r1.5 cxa_vec.C
--- gcc/testsuite/g++.old-deja/g++.abi/cxa_vec.C	7 Jun 2004 20:36:55 -0000	1.5
+++ gcc/testsuite/g++.old-deja/g++.abi/cxa_vec.C	29 Jun 2004 12:03:09 -0000
@@ -14,6 +14,13 @@ static int ctor_count = 0;
 static int dtor_count = 0;
 static bool dtor_repeat = false;
 
+// Allocate enough padding to hold an array cookie.
+#ifdef __ARM_EABI__
+#define padding 8
+#else
+#define padding (sizeof (std::size_t))
+#endif
+
 // our pseudo ctors and dtors
 static void ctor (void *)
 {
@@ -71,8 +78,8 @@ void test0 ()
       
       try
         {
-          void *ary = abi::__cxa_vec_new (5, 1, sizeof (std::size_t), ctor, 
dtor);
-          abi::__cxa_vec_delete (ary, 1, sizeof (std::size_t), dtor);
+          void *ary = abi::__cxa_vec_new (5, 1, padding, ctor, dtor);
+          abi::__cxa_vec_delete (ary, 1, padding, dtor);
           if (ctor_count || dtor_count || blocks)
             longjmp (jump, 1);
         }
@@ -105,7 +112,7 @@ void test1 ()
       ctor_count = 4;
       try
         {
-          void *ary = abi::__cxa_vec_new (5, 1, sizeof (std::size_t), ctor, 
dtor);
+          void *ary = abi::__cxa_vec_new (5, 1, padding, ctor, dtor);
           longjmp (jump, 1);
         }
       catch (...)
@@ -138,8 +145,8 @@ void test2 ()
       dtor_count = 3;
       try
         {
-          void *ary = abi::__cxa_vec_new (5, 1, sizeof (std::size_t), ctor, 
dtor);
-          abi::__cxa_vec_delete (ary, 1, sizeof (std::size_t), dtor);
+          void *ary = abi::__cxa_vec_new (5, 1, padding, ctor, dtor);
+          abi::__cxa_vec_delete (ary, 1, padding, dtor);
           longjmp (jump, 1);
         }
       catch (...)
@@ -174,8 +181,8 @@ void test3 ()
       dtor_repeat = true;
       try
         {
-          void *ary = abi::__cxa_vec_new (5, 1, sizeof (std::size_t), ctor, 
dtor);
-          abi::__cxa_vec_delete (ary, 1, sizeof (std::size_t), dtor);
+          void *ary = abi::__cxa_vec_new (5, 1, padding, ctor, dtor);
+          abi::__cxa_vec_delete (ary, 1, padding, dtor);
           longjmp (jump, 1);
         }
       catch (...)
@@ -212,7 +219,7 @@ void test4 ()
       dtor_count = 2;
       try
         {
-          void *ary = abi::__cxa_vec_new (5, 1, sizeof (std::size_t), ctor, 
dtor);
+          void *ary = abi::__cxa_vec_new (5, 1, padding, ctor, dtor);
           longjmp (jump, 1);
         }
       catch (...)
Index: libstdc++-v3/libsupc++/vec.cc
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/libstdc++-v3/libsupc++/vec.cc,v
retrieving revision 1.14
diff -u -p -r1.14 vec.cc
--- libstdc++-v3/libsupc++/vec.cc	22 May 2004 21:07:28 -0000	1.14
+++ libstdc++-v3/libsupc++/vec.cc	26 Jun 2004 22:30:46 -0000
@@ -96,6 +96,10 @@ namespace __cxxabiv1
       {
 	base += padding_size;
 	reinterpret_cast <std::size_t *> (base)[-1] = element_count;
+#ifdef __ARM_EABI__
+	// ARM EABI array cookies also contain the element size.
+	reinterpret_cast <std::size_t *> (base)[-2] = element_size;
+#endif
       }
     try
       {
@@ -131,6 +135,10 @@ namespace __cxxabiv1
       {
 	base += padding_size;
 	reinterpret_cast<std::size_t *>(base)[-1] = element_count;
+#ifdef __ARM_EABI__
+	// ARM EABI array cookies also contain the element size.
+	reinterpret_cast <std::size_t *> (base)[-2] = element_size;
+#endif
       }
     try
       {


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