I have redone the implementation of the eeprom attribute in my prototype.
It is now a cleaner solution, but requires larger changes in the core,
but the changes in the core should not affect any backend/frontend, if
it does not uses them (except a missing case in tree_copy_mem_area, which
will cause an assertion to fail).

The patches are against the CVS of 20050412.

The changes in the core are:
1) MEM_REF_FLAGS introduced 
(http://www.auto.tuwien.ac.at/~mkoegler/gcc/memref.patch)
The flags are stored in u.fld[2].rt_int of MEM.
A new target hook is introduced, which takes an expression, decl or type
and calculates the target specific MEM_REF_FLAGS.

In set_mem_attributes_minus_bitops (as well es set_mem_attr_from reg),
MEM_REF_FLAGS is initialized from the provided expression.

The most relevant diffs are:
Index: rtl.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.def,v
retrieving revision 1.100
diff -u -r1.100 rtl.def
--- rtl.def     22 Jan 2005 22:48:57 -0000      1.100
+++ rtl.def     27 Apr 2005 17:46:53 -0000
@@ -385,8 +385,9 @@

 /* A memory location; operand is the address.  The second operand is the
    alias set to which this MEM belongs.  We use `0' instead of `w' for this
-   field so that the field need not be specified in machine descriptions.  */
-DEF_RTL_EXPR(MEM, "mem", "e0", RTX_OBJ)
+   field so that the field need not be specified in machine descriptions.
+   the third the memory flags */
+DEF_RTL_EXPR(MEM, "mem", "e00", RTX_OBJ)

 /* Reference to an assembler label in the code for this function.
    The operand is a CODE_LABEL found in the insn chain.
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.543
diff -u -r1.543 rtl.h
--- rtl.h       25 Mar 2005 02:23:57 -0000      1.543
+++ rtl.h       27 Apr 2005 17:46:53 -0000
@@ -1080,6 +1080,9 @@
    in the block and provide defaults if none specified.  */
 #define MEM_ATTRS(RTX) X0MEMATTR (RTX, 1)

+/* A set of flags on a mem */
+#define MEM_REF_FLAGS(RTX)     X0INT ((RTX), 2)
+
 /* The register attribute block.  We provide access macros for each value
    in the block and provide defaults if none specified.  */
 #define REG_ATTRS(RTX) X0REGATTR (RTX, 2)
Index: target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.131
diff -u -r1.131 target.h
--- target.h    12 Apr 2005 06:33:23 -0000      1.131
+++ target.h    27 Apr 2005 17:46:53 -0000
@@ -514,6 +514,9 @@
      to be checked for va_list references.  */
   bool (*stdarg_optimize_hook) (struct stdarg_info *ai, tree lhs, tree rhs);

+  /* extracts MEM_REF_FLAGS out of a tree expression */
+  int (*extract_mem_ref_flags) (tree t);
+
   /* Functions relating to calls - argument passing, returns, etc.  */
   struct calls {
     bool (*promote_function_args) (tree fntype);
Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.436
diff -u -r1.436 emit-rtl.c
--- emit-rtl.c  25 Mar 2005 02:23:57 -0000      1.436
+++ emit-rtl.c  27 Apr 2005 17:46:50 -0000
@@ -1449,6 +1453,8 @@
   if (t == NULL_TREE)
     return;

+  MEM_REF_FLAGS(ref) = targetm.extract_mem_ref_flags (t);
+
   type = TYPE_P (t) ? t : TREE_TYPE (t);
   if (type == error_mark_node)
     return;
@@ -1685,6 +1691,10 @@
     = get_mem_attrs (MEM_ALIAS_SET (mem), REG_EXPR (reg),
                     GEN_INT (REG_OFFSET (reg)),
                     MEM_SIZE (mem), MEM_ALIGN (mem), GET_MODE (mem));
+
+  if(REG_EXPR (reg))
+    MEM_REF_FLAGS(mem) = targetm.extract_mem_ref_flags (REG_EXPR (reg));
+
 }

 /* Set the alias set of MEM to SET.  */

2) Handling of the eeprom attribute 
(http://www.auto.tuwien.ac.at/~mkoegler/gcc/addr.patch)
As my old solution had too much problem, I tried a clean implementation, which 
provided
something, like in DTR18037.

First a new type for storing memory address spaces was introduced. At the 
moment, it is implemented
as an integer. The value 0 is used as NO_MEM_AREA, which means, that no memory 
has been
assiged. This value is useful for finding missing initialization of a memory 
address space variable.
Value 1 is DEFAULT_MEM_AREA, which is the usually adress space, including stack 
and data segement.
As the memory area is only used in the backend code, the EEPROM address space 
is not defined here.
As I have not changed the parser, the address space is initialized using an 
attribute.

The address space attribute has been adden to the following tree constructs:
*TYPE_MEM_AREA: memory area of the pointer target, for other types unused
*DECL_MEM_AREA: memory area, where a variable is located (used for var_decls)
*EXPR_MEM_AREA: current memory area. Basically it is only needed for 
component_ref, indirect_ref
or an array_ref. As eg. a compound_expr may appear in place of a of a decl, 
such expression
inherit the MEM_AREA from their "return" expression

For copying the MEM_AREA from a DECL or EXPR to a EXPR, tree_copy_mem_area was 
written.
It takes care of all possiblities, I have noticed.

As each creation of a INDIRECT_REF, ARRAY_REF or COMPONENT_REF in an optimizer 
need also
to copy the MEM_AREA, special build function (build*_REF) were written, which 
set MEM_AREA.
So most changes in the patch consists only of a change of the function call.

To build1_INDIRECT_REF, as first argument, not the element type, but the 
complete pointer type
or the evaluation expression is passed. In few cases, the memory area of the 
pointer is not available.
For these, another solution to get the memory area, is needed.

So far, I have tested it with a part of C frontend. It need more testing (as 
well as correction of
missing MEM_AREAs in expressions). Other frontends will propably also need some 
modifications,
if they should provide the correct value for MEM_AREA.

Important part of the patch:
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.714
diff -u -r1.714 tree.h
--- tree.h      9 Apr 2005 17:19:03 -0000       1.714
+++ tree.h      27 Apr 2005 17:46:55 -0000
@@ -27,6 +27,10 @@
 #include "statistics.h"
 #include "vec.h"

+#define NO_MEM_AREA 0
+#define DEFAULT_MEM_AREA 1
+typedef int memory_area_t;
+
 /* Codes of tree nodes */

 #define DEFTREECODE(SYM, STRING, TYPE, NARGS)   SYM,
@@ -1173,6 +1177,8 @@
 /* In a LOOP_EXPR node.  */
 #define LOOP_EXPR_BODY(NODE) TREE_OPERAND_CHECK_CODE (NODE, LOOP_EXPR, 0)

+#define EXPR_MEM_AREA(NODE) (EXPR_CHECK (NODE)->exp.area)
+
 #ifdef USE_MAPPED_LOCATION
 /* The source location of this expression.  Non-tree_exp nodes such as
    decls and constants can be shared among multiple locations, so
@@ -1292,6 +1298,7 @@
   struct tree_common common;
   source_locus locus;
   int complexity;
+  memory_area_t area;
   tree block;
   tree GTY ((special ("tree_exp"),
             desc ("TREE_CODE ((tree) &%0)")))
@@ -1543,6 +1550,7 @@
 #define TYPE_MAIN_VARIANT(NODE) (TYPE_CHECK (NODE)->type.main_variant)
 #define TYPE_CONTEXT(NODE) (TYPE_CHECK (NODE)->type.context)
 #define TYPE_LANG_SPECIFIC(NODE) (TYPE_CHECK (NODE)->type.lang_specific)
+#define TYPE_MEM_AREA(NODE) (TYPE_CHECK (NODE)->type.area)

 /* For a VECTOR_TYPE node, this describes a different type which is emitted
    in the debugging output.  We use this to describe a vector as a
@@ -1740,6 +1748,7 @@
   HOST_WIDE_INT alias_set;
   /* Points to a structure whose details depend on the language in use.  */
   struct lang_type *lang_specific;
+  memory_area_t area;
 };
 ^L
 /* Define accessor macros for information about type inheritance
@@ -1921,6 +1930,8 @@
     NULL_TREE or a TRANSLATION_UNIT_DECL if the given decl has "file
     scope".  */
 #define DECL_CONTEXT(NODE) (DECL_CHECK (NODE)->decl.context)
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.472
diff -u -r1.472 tree.c
--- tree.c      30 Mar 2005 21:34:29 -0000      1.472
+++ tree.c      27 Apr 2005 17:46:55 -0000
@@ -6664,4 +6676,47 @@
   return result;
 }

+void
+tree_copy_mem_area (tree to, tree from)
+{
+  if(!from)
+    EXPR_MEM_AREA(to)=NO_MEM_AREA;
+  else if(TREE_CODE(from)==INTEGER_CST)
+    EXPR_MEM_AREA(to)=DEFAULT_MEM_AREA;
+  else if(TREE_CODE(from)==STRING_CST)
+    EXPR_MEM_AREA(to)=DEFAULT_MEM_AREA;
+  else if(DECL_P(from))
+    EXPR_MEM_AREA(to)=DECL_MEM_AREA(from);
+  else
+    EXPR_MEM_AREA(to)=EXPR_MEM_AREA(from);
+}
+
+tree
+build1_INDIRECT_REF (tree type, tree pointer)
+{
+  tree t = build1 (INDIRECT_REF, TREE_TYPE (type), pointer);
+  
if(TREE_CODE(type)==ARRAY_REF||TREE_CODE(type)==ARRAY_RANGE_REF||TREE_CODE(type)==INDIRECT_REF||TREE_CODE(type)==COMPONENT_REF)
+    EXPR_MEM_AREA(t) = EXPR_MEM_AREA(type);
+  else
+    EXPR_MEM_AREA(t) = TYPE_MEM_AREA(type);
+  return t;
+}
+
+tree
+build3_COMPONENT_REF (tree a, tree b, tree c, tree d)
+{
+  tree t;
+  t = build3 (COMPONENT_REF, a, b, c, d);
+  tree_copy_mem_area (t, b);
+  return t;
+}
+tree build4_ARRAY_REF (tree a, tree b, tree c, tree d, tree e)
+{
+  tree t;
+  t = build4 (ARRAY_REF, a, b, c, d, e);
+  tree_copy_mem_area (t, b);
+  return t;
+}
+
+
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.431
diff -u -r1.431 c-typeck.c
--- c-typeck.c  9 Apr 2005 03:18:07 -0000       1.431
+++ c-typeck.c  27 Apr 2005 17:46:50 -0000
@@ -1595,6 +1597,8 @@
          if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum))
            TREE_THIS_VOLATILE (ref) = 1;

+         tree_copy_mem_area(ref,datum);
+
          if (TREE_DEPRECATED (subdatum))
            warn_deprecated_use (subdatum);

@@ -1658,6 +1662,7 @@
          TREE_SIDE_EFFECTS (ref)
            = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
          TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
+         EXPR_MEM_AREA (ref) = TYPE_MEM_AREA(type);
          return ref;
        }
     }
@@ -1784,6 +1789,9 @@
               in an inline function.
               Hope it doesn't break something else.  */
            | TREE_THIS_VOLATILE (array));
+
+      tree_copy_mem_area(rval,array);
+
       return require_complete_type (fold (rval));
     }
   else
@@ -2070,6 +2078,7 @@

   result = build3 (CALL_EXPR, TREE_TYPE (fntype),
                   function, coerced_params, NULL_TREE);
+  EXPR_MEM_AREA (result) = DEFAULT_MEM_AREA;
   TREE_SIDE_EFFECTS (result) = 1;

   if (require_constant_value)

3) Use of this function in the port:
As I have not change the frontend, I created two attributes:
1) A decl attribute eeprom
2) A type attribute eepromt for marking pointers:

Usage example:
struct x y __attribute__ ((eeprom));
typedef struct x* ax __attribute__ ((eepromt));

important code:
/* Handle a "eeprom" attribute; arguments as in
   struct attribute_spec.handler.  */
static tree
m68hc05_handle_eeprom_attribute (tree * node, tree name,
                                 tree args ATTRIBUTE_UNUSED,
                                 int flags ATTRIBUTE_UNUSED,
                                 bool * no_add_attrs)
{
  if(POINTER_TYPE_P(*node))
    {
      *node = copy_node (*node);
      TYPE_MEM_AREA(*node)=2;
    }
  else if(DECL_P(*node)&&TREE_CODE(*node)!=TYPE_DECL)
    {
      *node = copy_node (*node);
      DECL_MEM_AREA(*node)=2;
    }
  else
    warning ("%qs attribute does not apply",
             IDENTIFIER_POINTER (name));

  return NULL_TREE;
}
const struct attribute_spec m68hc05_attribute_table[] = {
  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
  {"eepromt", 0, 0, false, true, false, m68hc05_handle_eeprom_attribute},
  {"eeprom", 0, 0, true, false, false, m68hc05_handle_eeprom_attribute},
};

/* HOOK for TARGET_EXTRACT_MEM_REF_FLAGS, does the following:
   *check the memory area for eeprom, and return 1, if it is set.
   *stop at unset memory areas
*/

static int
m68hc05_extract_mem_ref_flags (tree expr)
{
  tree t;
  int ref=0;
  if(TREE_CODE(expr)==IMAGPART_EXPR||TREE_CODE(expr)==REALPART_EXPR)
    expr=TREE_OPERAND (expr, 0);
  if(TYPE_P(expr)||TREE_CODE(expr)==STRING_CST||TREE_CODE(expr)==COMPLEX_CST)
    {
      ref=DEFAULT_MEM_AREA;
    }
  else if(DECL_P(expr))
    {
      ref=DECL_MEM_AREA(expr);
    }
  else if(EXPR_P(expr))
    {
      ref=EXPR_MEM_AREA(expr);
    }
  gcc_assert(ref);
  if(ref==2)
    return 1;
  else
    return 0;
}

// my predicate to check for eeprom address space

int
eeprom_operand (op, mode)
     rtx op;
     enum machine_mode mode;
{
  tree t = 0;
  int deref = 0;
  if (mode == VOIDmode)
    mode = GET_MODE (op);
  if (GET_MODE (op) != mode)
    return 0;
  if (!MEM_P (op))
    return 0;

  if (MEM_P (op) && (MEM_REF_FLAGS (op) & 1))
    return 1;
  else
    return 0;
}

The rest is the same, as I described it before.

I hope, that it is understandable, what I am doing.

Adding a syntax for in the C frontend for the address space modifiers
is not an priority for me, as the two attribute solution should
work. An important part, that is still missing, is the type
compatibility checking between pointers to different memory areas.
At the moment, even no warning is issued. I itend to introduce a new
target hook for this, which checks, if two memory areas are compatible.

Comments?

mfg Martin Kögler
PS: Please CC me on replies.


Reply via email to