This is the mail archive of the gcc@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]

Endianess attribute


Hi.

I already have posted about the endianess attribute (http://gcc.gnu.org/ml/gcc/2008-11/threads.html#00146).

For some year, i really need this feature on c projects.

Today i would like to go inside the internals of gcc, and i would like to implement this feature as an exercise.

You already prevent me that it would be a hard task (aliasing, etc.), but i would like to begin with basic specs.


The spec could be :


- add an attribute (this description could change to be compatible with existing ones (diabdata for example))

  __attribute__ ((endian("big")))
  __attribute__ ((endian("lil")))

- this attribute only apply to ints

- this attribute only apply to variables declaration

- a pointer to this variable don't inherit the attribute (this behavior could change later, i don't know...)

- the test case is

  uint32_t x __attribute__ ((endian("big")));
  uint32_t * ptr_x = x;

x = 0xDEADBEEF

  if(plf_is_little)
    {
      assert((*ptr_x == 0xEFBEADDE));
    }
  else if(plf_is_big)
    {
      assert((*ptr_x == 0xDEADBEEF));
    }




My first work is the patch below.


So my questions to the mailing list are :

- is it a good starting point ?

- how can i get the endianess of the target ?


Thank for your help and suggestion.



8<------------------------------------------------------------------------


diff -abBruN gcc-4.4.0.orig/gcc/c-common.c gcc-4.4.0.mod/gcc/c-common.c
--- gcc-4.4.0.orig/gcc/c-common.c	2009-03-30 19:42:27.000000000 +0200
+++ gcc-4.4.0.mod/gcc/c-common.c	2009-07-02 11:10:28.000000000 +0200
@@ -522,6 +522,7 @@
 static bool check_case_bounds (tree, tree, tree *, tree *);

 static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
+static tree handle_endian_attribute (tree *, tree, tree, int, bool *);
 static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
 static tree handle_common_attribute (tree *, tree, tree, int, bool *);
 static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
@@ -761,6 +762,8 @@
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
   { "packed",                 0, 0, false, false, false,
 			      handle_packed_attribute },
+  { "endian",                 1, 1, false, false, false,
+			      handle_endian_attribute },
   { "nocommon",               0, 0, true,  false, false,
 			      handle_nocommon_attribute },
   { "common",                 0, 0, true,  false, false,
@@ -5155,6 +5158,58 @@
   return NULL_TREE;
 }

+/* Handle an "endian" attribute; arguments as in
+   struct attribute_spec.handler.
+   IDENTIFIER_POINTER (name) gives "endian"
+   TREE_CODE (arg) should be a STRING_CST
+*/
+
+static tree
+handle_endian_attribute (tree *node, tree name, tree args,
+			 int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  tree arg = TREE_VALUE (args);
+
+  if (TREE_CODE (arg) != STRING_CST)
+    {
+      error ("argument of %qE attribute should be a string\n", name);
+    }
+  else if (TREE_CODE (*node) != FIELD_DECL &&
+           TREE_CODE (*node) != VAR_DECL  &&
+           TREE_CODE (*node) != TYPE_DECL)
+    {
+      error ("%qE only support FIELD_DECL, VAR_DECL and TYPE_DECL\n", name);
+    }
+  else
+    {
+      if (!strcmp (TREE_STRING_POINTER (arg), "little"))
+        {
+          if(TARGET_BIG_ENDIAN)
+            {
+              DECL_SWAP(*node) = 1;
+              debug_tree(*node);
+            }
+        }
+      else if (!strcmp (TREE_STRING_POINTER (arg), "big"))
+        {
+          if(TARGET_LITTLE_ENDIAN)
+            {
+              DECL_SWAP(*node) = 1;
+              debug_tree(*node);
+            }
+        }
+      else
+        {
+          error ("argument of %qE attribute should be 'little' or 'big'\n", name);
+          *no_add_attrs = true;
+        }
+    }
+
+  *no_add_attrs = true;
+
+  return NULL_TREE;
+}
+
 /* Handle a "nocommon" attribute; arguments as in
    struct attribute_spec.handler.  */

diff -abBruN gcc-4.4.0.orig/gcc/tree.h gcc-4.4.0.mod/gcc/tree.h
--- gcc-4.4.0.orig/gcc/tree.h	2009-03-23 17:29:33.000000000 +0100
+++ gcc-4.4.0.mod/gcc/tree.h	2009-07-02 11:10:28.000000000 +0200
@@ -2721,13 +2721,15 @@
   /* In FIELD_DECL, this is DECL_NONADDRESSABLE_P
      In VAR_DECL and PARM_DECL, this is DECL_HAS_VALUE_EXPR.  */
   unsigned decl_flag_3 : 1;
+  /* In FIELD_DECL, VAR_DECL and TYPE_DECL this is DECL_SWAP.  */
+  unsigned decl_flag_4 : 1;
   /* Logically, these two would go in a theoretical base shared by var and
      parm decl. */
   unsigned gimple_reg_flag : 1;
   /* In a DECL with pointer type, set if no TBAA should be done.  */
   unsigned no_tbaa_flag : 1;
   /* Padding so that 'align' can be on a 32-bit boundary.  */
-  unsigned decl_common_unused : 2;
+  unsigned decl_common_unused : 1;

   unsigned int align : 24;
   /* DECL_OFFSET_ALIGN, used only for FIELD_DECLs.  */
@@ -2854,6 +2856,10 @@
 #define DECL_NONADDRESSABLE_P(NODE) \
   (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_3)

+/* In a FIELD_DECL, indicates this field should be swapped.  */
+#define DECL_SWAP(NODE) \
+  (TREE_CHECK3 (NODE, FIELD_DECL, VAR_DECL, TYPE_DECL)->decl_common.decl_flag_4)
+
 struct tree_field_decl GTY(())
 {
   struct tree_decl_common common;


8<------------------------------------------------------------------------



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