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<------------------------------------------------------------------------