]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rtl.h (mem_attrs): Rename decl to expr; adjust all users.
authorRichard Henderson <rth@redhat.com>
Sun, 2 Dec 2001 19:04:23 +0000 (11:04 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Sun, 2 Dec 2001 19:04:23 +0000 (11:04 -0800)
        * rtl.h (mem_attrs): Rename decl to expr; adjust all users.
        (MEM_EXPR): Rename from MEM_DECL; adjust all users.
        * emit-rtl.c (set_mem_expr): Rename from set_mem_decl.
        * expr.h, final.c, reload1.c: Adjust users.

        * alias.c (nonoverlapping_component_refs_p): New.
        (decl_for_component_ref, adjust_offset_for_component_ref): New.
        (nonoverlapping_memrefs_p): Use them.
        * emit-rtl.c (component_ref_for_mem_expr): New.
        (set_mem_attributes): Use it.
        (set_mem_offset): New.
        * expr.c (expand_assignment): Call set_mem_attributes for
        inner references; adjust the memory offset as needed.
        * print-rtl.c (print_mem_expr): New.
        (print_rtx): Use it.

From-SVN: r47534

gcc/ChangeLog
gcc/alias.c
gcc/emit-rtl.c
gcc/expr.c
gcc/expr.h
gcc/final.c
gcc/print-rtl.c
gcc/reload1.c
gcc/rtl.h

index 2e3bd957de5c85a7942f8acf13f6da760421f43d..f7c1b463d74cba80153be2725c1c3ccf29d51ad9 100644 (file)
@@ -1,3 +1,21 @@
+2001-12-02  Richard Henderson  <rth@redhat.com>
+
+       * rtl.h (mem_attrs): Rename decl to expr; adjust all users.
+       (MEM_EXPR): Rename from MEM_DECL; adjust all users.
+       * emit-rtl.c (set_mem_expr): Rename from set_mem_decl.
+       * expr.h, final.c, reload1.c: Adjust users.
+
+       * alias.c (nonoverlapping_component_refs_p): New.
+       (decl_for_component_ref, adjust_offset_for_component_ref): New.
+       (nonoverlapping_memrefs_p): Use them.
+       * emit-rtl.c (component_ref_for_mem_expr): New.
+       (set_mem_attributes): Use it.
+       (set_mem_offset): New.
+       * expr.c (expand_assignment): Call set_mem_attributes for 
+       inner references; adjust the memory offset as needed.
+       * print-rtl.c (print_mem_expr): New.
+       (print_rtx): Use it.
+
 Sun Dec  2 09:22:25 2001  Douglas B. Rupp  <rupp@gnat.com>
 
        * config/x-interix3 (SYSTEM_HEADER_DIR): Put back default.
index da9ca04bd86672a5b0c938bccb1eefdae9e7ec5c..21563ec565e669c8e033174a5d4fc3f79e61388b 100644 (file)
@@ -103,6 +103,9 @@ static alias_set_entry get_alias_set_entry PARAMS ((HOST_WIDE_INT));
 static rtx fixed_scalar_and_varying_struct_p PARAMS ((rtx, rtx, rtx, rtx,
                                                      int (*) (rtx, int)));
 static int aliases_everything_p         PARAMS ((rtx));
+static bool nonoverlapping_component_refs_p PARAMS ((tree, tree));
+static tree decl_for_component_ref     PARAMS ((tree));
+static rtx adjust_offset_for_component_ref PARAMS ((tree, rtx));
 static int nonoverlapping_memrefs_p    PARAMS ((rtx, rtx));
 static int write_dependence_p           PARAMS ((rtx, rtx, int));
 static int nonlocal_mentioned_p         PARAMS ((rtx));
@@ -1736,23 +1739,158 @@ aliases_everything_p (mem)
   return 0;
 }
 
-/* Return nonzero if we can deterimine the decls corresponding to memrefs
+/* Return true if we can determine that the fields referenced cannot
+   overlap for any pair of objects.  */
+
+static bool
+nonoverlapping_component_refs_p (x, y)
+     tree x, y;
+{
+  tree fieldx, fieldy, typex, typey, orig_y;
+
+  do
+    {
+      /* The comparison has to be done at a common type, since we don't
+        know how the inheritance heirarchy works.  */
+      orig_y = y;
+      do
+       {
+         fieldx = TREE_OPERAND (x, 1);
+         typex = DECL_FIELD_CONTEXT (fieldx);
+
+         y = orig_y;
+         do
+           {
+             fieldy = TREE_OPERAND (y, 1);
+             typey = DECL_FIELD_CONTEXT (fieldy);
+
+             if (typex == typey)
+               goto found;
+
+             y = TREE_OPERAND (y, 0);
+           }
+         while (y && TREE_CODE (y) == COMPONENT_REF);
+
+         x = TREE_OPERAND (x, 0);
+       }
+      while (x && TREE_CODE (x) == COMPONENT_REF);
+
+      /* Never found a common type.  */
+      return false;
+
+    found:
+      /* If we're left with accessing different fields of a structure,
+        then no overlap.  */
+      if (TREE_CODE (typex) == RECORD_TYPE
+         && fieldx != fieldy)
+       return true;
+
+      /* The comparison on the current field failed.  If we're accessing
+        a very nested structure, look at the next outer level.  */
+      x = TREE_OPERAND (x, 0);
+      y = TREE_OPERAND (y, 0);
+    }
+  while (x && y
+        && TREE_CODE (x) == COMPONENT_REF
+        && TREE_CODE (y) == COMPONENT_REF);
+  
+  return false;
+}
+
+/* Look at the bottom of the COMPONENT_REF list for a DECL, and return it.  */
+
+static tree
+decl_for_component_ref (x)
+     tree x;
+{
+  do
+    {
+      x = TREE_OPERAND (x, 0);
+    }
+  while (x && TREE_CODE (x) == COMPONENT_REF);
+
+  return x && DECL_P (x) ? x : NULL_TREE;
+}
+
+/* Walk up the COMPONENT_REF list and adjust OFFSET to compensate for the
+   offset of the field reference.  */
+
+static rtx
+adjust_offset_for_component_ref (x, offset)
+     tree x;
+     rtx offset;
+{
+  HOST_WIDE_INT ioffset;
+
+  if (! offset)
+    return NULL_RTX;
+
+  ioffset = INTVAL (offset);
+  do 
+    {
+      tree field = TREE_OPERAND (x, 1);
+
+      if (! host_integerp (DECL_FIELD_OFFSET (field), 1))
+       return NULL_RTX;
+      ioffset += (tree_low_cst (DECL_FIELD_OFFSET (field), 1)
+                 + (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
+                    / BITS_PER_UNIT));
+
+      x = TREE_OPERAND (x, 0);
+    }
+  while (x && TREE_CODE (x) == COMPONENT_REF);
+
+  return GEN_INT (ioffset);
+}
+
+/* Return nonzero if we can deterimine the exprs corresponding to memrefs
    X and Y and they do not overlap.  */
 
 static int
 nonoverlapping_memrefs_p (x, y)
      rtx x, y;
 {
+  tree exprx = MEM_EXPR (x), expry = MEM_EXPR (y);
   rtx rtlx, rtly;
   rtx basex, basey;
+  rtx moffsetx, moffsety;
   HOST_WIDE_INT offsetx = 0, offsety = 0, sizex, sizey, tem;
 
-  /* Unless both have decls, we can't tell anything.  */
-  if (MEM_DECL (x) == 0 || MEM_DECL (y) == 0)
+  /* Unless both have exprs, we can't tell anything.  */
+  if (exprx == 0 || expry == 0)
+    return 0;
+
+  /* If both are field references, we may be able to determine something.  */
+  if (TREE_CODE (exprx) == COMPONENT_REF
+      && TREE_CODE (expry) == COMPONENT_REF
+      && nonoverlapping_component_refs_p (exprx, expry))
+    return 1;
+
+  /* If the field reference test failed, look at the DECLs involved.  */
+  moffsetx = MEM_OFFSET (x);
+  if (TREE_CODE (exprx) == COMPONENT_REF)
+    {
+      tree t = decl_for_component_ref (exprx);
+      if (! t)
+       return 0;
+      moffsetx = adjust_offset_for_component_ref (exprx, moffsetx);
+      exprx = t;
+    }
+  moffsety = MEM_OFFSET (y);
+  if (TREE_CODE (expry) == COMPONENT_REF)
+    {
+      tree t = decl_for_component_ref (expry);
+      if (! t)
+       return 0;
+      moffsety = adjust_offset_for_component_ref (expry, moffsety);
+      expry = t;
+    }
+
+  if (! DECL_P (exprx) || ! DECL_P (expry))
     return 0;
 
-  rtlx = DECL_RTL (MEM_DECL (x));
-  rtly = DECL_RTL (MEM_DECL (y));
+  rtlx = DECL_RTL (exprx);
+  rtly = DECL_RTL (expry);
 
   /* If either RTL is not a MEM, it must be a REG or CONCAT, meaning they
      can't overlap unless they are the same because we never reuse that part
@@ -1784,26 +1922,26 @@ nonoverlapping_memrefs_p (x, y)
              || (CONSTANT_P (basey) && REG_P (basex)
                  && REGNO_PTR_FRAME_P (REGNO (basex))));
 
-  sizex = (GET_CODE (rtlx) != MEM ? GET_MODE_SIZE (GET_MODE (rtlx))
+  sizex = (GET_CODE (rtlx) != MEM ? (int) GET_MODE_SIZE (GET_MODE (rtlx))
           : MEM_SIZE (rtlx) ? INTVAL (MEM_SIZE (rtlx))
           : -1);
-  sizey = (GET_CODE (rtly) != MEM ? GET_MODE_SIZE (GET_MODE (rtly))
+  sizey = (GET_CODE (rtly) != MEM ? (int) GET_MODE_SIZE (GET_MODE (rtly))
           : MEM_SIZE (rtly) ? INTVAL (MEM_SIZE (rtly)) :
           -1);
 
   /* If we have an offset for either memref, it can update the values computed
      above.  */
-  if (MEM_OFFSET (x))
-    offsetx += INTVAL (MEM_OFFSET (x)), sizex -= INTVAL (MEM_OFFSET (x));
-  if (MEM_OFFSET (y))
-    offsety += INTVAL (MEM_OFFSET (y)), sizey -= INTVAL (MEM_OFFSET (y));
+  if (moffsetx)
+    offsetx += INTVAL (moffsetx), sizex -= INTVAL (moffsetx);
+  if (moffsety)
+    offsety += INTVAL (moffsety), sizey -= INTVAL (moffsety);
 
   /* If a memref has both a size and an offset, we can use the smaller size.
      We can't do this if the offset isn't known because we must view this
      memref as being anywhere inside the DECL's MEM.  */
-  if (MEM_SIZE (x) && MEM_OFFSET (x))
+  if (MEM_SIZE (x) && moffsetx)
     sizex = INTVAL (MEM_SIZE (x));
-  if (MEM_SIZE (y) && MEM_OFFSET (y))
+  if (MEM_SIZE (y) && moffsety)
     sizey = INTVAL (MEM_SIZE (y));
 
   /* Put the values of the memref with the lower offset in X's values.  */
index e7afacd8a4eaf25ff0f6da70dbd6fc9a72f7812c..d25e5496c88089ff4f63d77d6f07463fa33ad09b 100644 (file)
@@ -195,6 +195,7 @@ static void mem_attrs_mark          PARAMS ((const void *));
 static mem_attrs *get_mem_attrs                PARAMS ((HOST_WIDE_INT, tree, rtx,
                                                 rtx, unsigned int,
                                                 enum machine_mode));
+static tree component_ref_for_mem_expr PARAMS ((tree));
 
 /* Probability of the conditional branch currently proceeded by try_split.
    Set to -1 otherwise.  */
@@ -232,7 +233,7 @@ mem_attrs_htab_hash (x)
   return (p->alias ^ (p->align * 1000)
          ^ ((p->offset ? INTVAL (p->offset) : 0) * 50000)
          ^ ((p->size ? INTVAL (p->size) : 0) * 2500000)
-         ^ (long) p->decl);
+         ^ (size_t) p->expr);
 }
 
 /* Returns non-zero if the value represented by X (which is really a
@@ -247,7 +248,7 @@ mem_attrs_htab_eq (x, y)
   mem_attrs *p = (mem_attrs *) x;
   mem_attrs *q = (mem_attrs *) y;
 
-  return (p->alias == q->alias && p->decl == q->decl && p->offset == q->offset
+  return (p->alias == q->alias && p->expr == q->expr && p->offset == q->offset
          && p->size == q->size && p->align == q->align);
 }
 
@@ -260,8 +261,8 @@ mem_attrs_mark (x)
 {
   mem_attrs *p = (mem_attrs *) x;
 
-  if (p->decl)
-    ggc_mark_tree (p->decl);
+  if (p->expr)
+    ggc_mark_tree (p->expr);
 
   if (p->offset)
     ggc_mark_rtx (p->offset);
@@ -275,9 +276,9 @@ mem_attrs_mark (x)
    MEM of mode MODE.  */
 
 static mem_attrs *
-get_mem_attrs (alias, decl, offset, size, align, mode)
+get_mem_attrs (alias, expr, offset, size, align, mode)
      HOST_WIDE_INT alias;
-     tree decl;
+     tree expr;
      rtx offset;
      rtx size;
      unsigned int align;
@@ -287,7 +288,7 @@ get_mem_attrs (alias, decl, offset, size, align, mode)
   void **slot;
 
   /* If everything is the default, we can just return zero.  */
-  if (alias == 0 && decl == 0 && offset == 0
+  if (alias == 0 && expr == 0 && offset == 0
       && (size == 0
          || (mode != BLKmode && GET_MODE_SIZE (mode) == INTVAL (size)))
       && (align == BITS_PER_UNIT
@@ -295,7 +296,7 @@ get_mem_attrs (alias, decl, offset, size, align, mode)
     return 0;
 
   attrs.alias = alias;
-  attrs.decl = decl;
+  attrs.expr = expr;
   attrs.offset = offset;
   attrs.size = size;
   attrs.align = align;
@@ -1636,6 +1637,26 @@ reverse_comparison (insn)
     }
 }
 \f
+/* Within a MEM_EXPR, we care about either (1) a component ref of a decl,
+   or (2) a component ref of something variable.  Represent the later with
+   a NULL expression.  */
+
+static tree
+component_ref_for_mem_expr (ref)
+     tree ref;
+{
+  tree inner = TREE_OPERAND (ref, 0);
+
+  if (TREE_CODE (inner) == COMPONENT_REF)
+    inner = component_ref_for_mem_expr (inner);
+  else if (! DECL_P (inner))
+    inner = NULL_TREE;
+
+  if (inner == TREE_OPERAND (ref, 0))
+    return ref;
+  else
+    return build (COMPONENT_REF, TREE_TYPE (ref), inner, TREE_OPERAND (ref, 1));
+}
 
 /* Given REF, a MEM, and T, either the type of X or the expression
    corresponding to REF, set the memory attributes.  OBJECTP is nonzero
@@ -1648,7 +1669,7 @@ set_mem_attributes (ref, t, objectp)
      int objectp;
 {
   HOST_WIDE_INT alias = MEM_ALIAS_SET (ref);
-  tree decl = MEM_DECL (ref);
+  tree expr = MEM_EXPR (ref);
   rtx offset = MEM_OFFSET (ref);
   rtx size = MEM_SIZE (ref);
   unsigned int align = MEM_ALIGN (ref);
@@ -1716,8 +1737,8 @@ set_mem_attributes (ref, t, objectp)
       /* If this is a decl, set the attributes of the MEM from it.  */
       if (DECL_P (t))
        {
-         decl = t;
-         offset = GEN_INT (0);
+         expr = t;
+         offset = const0_rtx;
          size = (DECL_SIZE_UNIT (t)
                  && host_integerp (DECL_SIZE_UNIT (t), 1)
                  ? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0);
@@ -1732,11 +1753,51 @@ set_mem_attributes (ref, t, objectp)
          align = CONSTANT_ALIGNMENT (t, align);
 #endif
        }
+
+      /* If this is a field reference and not a bit-field, record it.  */
+      /* ??? There is some information that can be gleened from bit-fields,
+        such as the word offset in the structure that might be modified.
+        But skip it for now.  */
+      else if (TREE_CODE (t) == COMPONENT_REF
+              && ! DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
+       {
+         expr = component_ref_for_mem_expr (t);
+         offset = const0_rtx;
+         /* ??? Any reason the field size would be different than
+            the size we got from the type?  */
+       }
+
+      /* If this is an array reference, look for an outer field reference.  */
+      else if (TREE_CODE (t) == ARRAY_REF)
+       {
+         tree off_tree = size_zero_node;
+
+         do
+           {
+             off_tree
+               = fold (build (PLUS_EXPR, sizetype,
+                              fold (build (MULT_EXPR, sizetype,
+                                           TREE_OPERAND (t, 1),
+                                           TYPE_SIZE_UNIT (TREE_TYPE (t)))),
+                              off_tree));
+             t = TREE_OPERAND (t, 0);
+           }
+         while (TREE_CODE (t) == ARRAY_REF);
+
+         if (TREE_CODE (t) == COMPONENT_REF)
+           {
+             expr = component_ref_for_mem_expr (t);
+             if (host_integerp (off_tree, 1))
+               offset = GEN_INT (tree_low_cst (off_tree, 1));
+             /* ??? Any reason the field size would be different than
+                the size we got from the type?  */
+           }
+       }
     }
 
   /* Now set the attributes we computed above.  */
   MEM_ATTRS (ref)
-    = get_mem_attrs (alias, decl, offset, size, align, GET_MODE (ref));
+    = get_mem_attrs (alias, expr, offset, size, align, GET_MODE (ref));
 
   /* If this is already known to be a scalar or aggregate, we are done.  */
   if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref))
@@ -1763,7 +1824,7 @@ set_mem_alias_set (mem, set)
     abort ();
 #endif
 
-  MEM_ATTRS (mem) = get_mem_attrs (set, MEM_DECL (mem), MEM_OFFSET (mem),
+  MEM_ATTRS (mem) = get_mem_attrs (set, MEM_EXPR (mem), MEM_OFFSET (mem),
                                   MEM_SIZE (mem), MEM_ALIGN (mem),
                                   GET_MODE (mem));
 }
@@ -1775,22 +1836,33 @@ set_mem_align (mem, align)
      rtx mem;
      unsigned int align;
 {
-  MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_DECL (mem),
+  MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
                                   MEM_OFFSET (mem), MEM_SIZE (mem), align,
                                   GET_MODE (mem));
 }
 
-/* Set the decl for MEM to DECL.  */
+/* Set the expr for MEM to EXPR.  */
 
 void
-set_mem_decl (mem, decl)
+set_mem_expr (mem, expr)
      rtx mem;
-     tree decl;
+     tree expr;
 {
   MEM_ATTRS (mem)
-    = get_mem_attrs (MEM_ALIAS_SET (mem), decl, MEM_OFFSET (mem),
+    = get_mem_attrs (MEM_ALIAS_SET (mem), expr, MEM_OFFSET (mem),
                     MEM_SIZE (mem), MEM_ALIGN (mem), GET_MODE (mem));
 }
+
+/* Set the offset of MEM to OFFSET.  */
+
+void
+set_mem_offset (mem, offset)
+     rtx mem, offset;
+{
+  MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
+                                  offset, MEM_SIZE (mem), MEM_ALIGN (mem),
+                                  GET_MODE (mem));
+}
 \f
 /* Return a memory reference like MEMREF, but with its mode changed to MODE
    and its address changed to ADDR.  (VOIDmode means don't change the mode.
@@ -1907,7 +1979,7 @@ adjust_address_1 (memref, mode, offset, validate, adjust)
   else if (MEM_SIZE (memref))
     size = plus_constant (MEM_SIZE (memref), -offset);
 
-  MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_DECL (memref),
+  MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref),
                                   memoffset, size, memalign, GET_MODE (new));
 
   /* At some point, we should validate that this offset is within the object,
@@ -1948,7 +2020,7 @@ offset_address (memref, offset, pow2)
 
   /* Update the alignment to reflect the offset.  Reset the offset, which
      we don't know.  */
-  MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_DECL (memref),
+  MEM_ATTRS (new) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref),
                                   0, 0, MIN (MEM_ALIGN (memref),
                                              pow2 * BITS_PER_UNIT),
                                   GET_MODE (new));
index eb7f2d317eafdeb4efcb676146b4a3b9c84ee160..659ff032db4f2f48ed3b8194fd22f32ca7a9fdc5 100644 (file)
@@ -3603,7 +3603,6 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
            }
 
          emit_move_insn (dest, x);
-
        }
 
       if (current_function_check_memory_usage && ! in_check_memory_usage)
@@ -3768,6 +3767,26 @@ expand_assignment (to, from, want_value, suggest_reg)
                                   highest_pow2_factor (offset));
        }
 
+      if (GET_CODE (to_rtx) == MEM)
+       {
+         tree old_expr = MEM_EXPR (to_rtx);
+
+         /* If the field is at offset zero, we could have been given the
+            DECL_RTX of the parent struct.  Don't munge it.  */
+         to_rtx = shallow_copy_rtx (to_rtx);
+
+         set_mem_attributes (to_rtx, to, 0);
+
+         /* If we changed MEM_EXPR, that means we're now referencing
+            the COMPONENT_REF, which means that MEM_OFFSET must be
+            relative to that field.  But we've not yet reflected BITPOS
+            in TO_RTX.  This will be done in store_field.  Adjust for
+            that by biasing MEM_OFFSET by -bitpos.  */
+         if (MEM_EXPR (to_rtx) != old_expr && MEM_OFFSET (to_rtx)
+             && (bitpos / BITS_PER_UNIT) != 0)
+           set_mem_offset (to_rtx, GEN_INT (INTVAL (MEM_OFFSET (to_rtx))
+                                            - (bitpos / BITS_PER_UNIT)));
+       }
 
       /* Deal with volatile and readonly fields.  The former is only done
         for MEM.  Also set MEM_KEEP_ALIAS_SET_P if needed.  */
index 4275b8129533591445c34c48d3c082a4a9b5bdd0..aa4bde69fdb14fc77a3a9507f7c93516f7d196c7 100644 (file)
@@ -614,8 +614,11 @@ extern void set_mem_alias_set PARAMS ((rtx, HOST_WIDE_INT));
 /* Set the alignment of MEM to ALIGN bits.  */
 extern void set_mem_align PARAMS ((rtx, unsigned int));
 
-/* Set the DECL for MEM to DECL.  */
-extern void set_mem_decl PARAMS ((rtx, tree));
+/* Set the expr for MEM to EXPR.  */
+extern void set_mem_expr PARAMS ((rtx, tree));
+
+/* Set the offset for MEM to OFFSET.  */
+extern void set_mem_offset PARAMS ((rtx, rtx));
 
 /* Return a memory reference like MEMREF, but with its mode changed
    to MODE and its address changed to ADDR.
index 7af2c1f66a56f555e05afba777a87bb32d13b5ba..158da0b858bd6c527230e9d1507d14a09201e227 100644 (file)
@@ -245,7 +245,7 @@ static int add_bb_string    PARAMS ((const char *, int));
 static void notice_source_line PARAMS ((rtx));
 static rtx walk_alter_subreg   PARAMS ((rtx *));
 static void output_asm_name    PARAMS ((void));
-static tree get_decl_from_op   PARAMS ((rtx, int *));
+static tree get_mem_expr_from_op       PARAMS ((rtx, int *));
 static void output_asm_operand_names PARAMS ((rtx *, int *, int));
 static void output_operand     PARAMS ((rtx, int));
 #ifdef LEAF_REGISTERS
@@ -3302,16 +3302,16 @@ output_asm_name ()
     }
 }
 
-/* If OP is a REG or MEM and we can find a decl corresponding to it or
-   its address, return that decl.  Set *PADDRESSP to 1 if the decl
+/* If OP is a REG or MEM and we can find a MEM_EXPR corresponding to it
+   or its address, return that expr .  Set *PADDRESSP to 1 if the expr
    corresponds to the address of the object and 0 if to the object.  */
 
 static tree
-get_decl_from_op (op, paddressp)
+get_mem_expr_from_op (op, paddressp)
      rtx op;
      int *paddressp;
 {
-  tree decl;
+  tree expr;
   int inner_addressp;
 
   *paddressp = 0;
@@ -3321,8 +3321,8 @@ get_decl_from_op (op, paddressp)
   else if (GET_CODE (op) != MEM)
     return 0;
 
-  if (MEM_DECL (op) != 0)
-    return MEM_DECL (op);
+  if (MEM_EXPR (op) != 0)
+    return MEM_EXPR (op);
 
   /* Otherwise we have an address, so indicate it and look at the address.  */
   *paddressp = 1;
@@ -3331,18 +3331,18 @@ get_decl_from_op (op, paddressp)
   /* First check if we have a decl for the address, then look at the right side
      if it is a PLUS.  Otherwise, strip off arithmetic and keep looking.
      But don't allow the address to itself be indirect.  */
-  if ((decl = get_decl_from_op (op, &inner_addressp)) && ! inner_addressp)
-    return decl;
+  if ((expr = get_mem_expr_from_op (op, &inner_addressp)) && ! inner_addressp)
+    return expr;
   else if (GET_CODE (op) == PLUS
-          && (decl = get_decl_from_op (XEXP (op, 1), &inner_addressp)))
-    return decl;
+          && (expr = get_mem_expr_from_op (XEXP (op, 1), &inner_addressp)))
+    return expr;
 
   while (GET_RTX_CLASS (GET_CODE (op)) == '1'
         || GET_RTX_CLASS (GET_CODE (op)) == '2')
     op = XEXP (op, 0);
 
-  decl = get_decl_from_op (op, &inner_addressp);
-  return inner_addressp ? 0 : decl;
+  expr = get_mem_expr_from_op (op, &inner_addressp);
+  return inner_addressp ? 0 : expr;
 }
   
 /* Output operand names for assembler instructions.  OPERANDS is the
@@ -3361,13 +3361,14 @@ output_asm_operand_names (operands, oporder, nops)
   for (i = 0; i < nops; i++)
     {
       int addressp;
-      tree decl = get_decl_from_op (operands[oporder[i]], &addressp);
+      tree expr = get_mem_expr_from_op (operands[oporder[i]], &addressp);
 
-      if (decl && DECL_NAME (decl))
+      if (expr)
        {
-         fprintf (asm_out_file, "%c%s %s%s",
+         fprintf (asm_out_file, "%c%s %s",
                   wrote ? ',' : '\t', wrote ? "" : ASM_COMMENT_START,
-                  addressp ? "*" : "", IDENTIFIER_POINTER (DECL_NAME (decl)));
+                  addressp ? "*" : "");
+         print_mem_expr (asm_out_file, expr);
          wrote = 1;
        }
     }
index 3213a511926b11304db2a70f30aadb462e494f30..b819d143a340c88d89b7d916bfa97ec239d29369 100644 (file)
@@ -77,6 +77,28 @@ int dump_for_graph;
 /* Nonzero to dump all call_placeholder alternatives.  */
 static int debug_call_placeholder_verbose;
 
+void
+print_mem_expr (outfile, expr)
+     FILE *outfile;
+     tree expr;
+{
+  if (TREE_CODE (expr) == COMPONENT_REF)
+    {
+      if (TREE_OPERAND (expr, 0))
+        print_mem_expr (outfile, TREE_OPERAND (expr, 0));
+      else
+       fputs (" <variable>", outfile);
+      fprintf (outfile, ".%s",
+              IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (expr, 1))));
+    }
+  else if (DECL_NAME (expr))
+    fprintf (outfile, " %s", IDENTIFIER_POINTER (DECL_NAME (expr)));
+  else if (TREE_CODE (expr) == RESULT_DECL)
+    fputs (" <result>", outfile);
+  else
+    fputs (" <anonymous>", outfile);
+}
+
 /* Print IN_RTX onto OUTFILE.  This is the recursive part of printing.  */
 
 static void
@@ -456,12 +478,9 @@ print_rtx (in_rtx)
     case MEM:
       fputs (" [", outfile);
       fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, MEM_ALIAS_SET (in_rtx));
-      if (MEM_DECL (in_rtx))
-       fprintf (outfile, " %s",
-                DECL_NAME (MEM_DECL (in_rtx))
-                ? IDENTIFIER_POINTER (DECL_NAME (MEM_DECL (in_rtx)))
-                : TREE_CODE (MEM_DECL (in_rtx)) == RESULT_DECL ? "<result>"
-                : "<anonymous>");
+
+      if (MEM_EXPR (in_rtx))
+       print_mem_expr (outfile, MEM_EXPR (in_rtx));
 
       if (MEM_OFFSET (in_rtx))
        {
index fa17d53c80f437a13c910ee130ce8b38aa427769..58019b042066268a2199c4f42a6a964b99f9db71 100644 (file)
@@ -2059,7 +2059,7 @@ alter_reg (i, from_reg)
          if (from_reg != -1 && spill_stack_slot[from_reg] == x)
            x = copy_rtx (x);
 
-         set_mem_decl (x, REGNO_DECL (i));
+         set_mem_expr (x, REGNO_DECL (i));
        }
 
       /* Save the stack slot for later.  */
index 31dabb86dd05573bb1923131a71c3a6b198d39fb..baafcdce2b50ac238b842c213ee54768030cb51f 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -92,7 +92,7 @@ typedef struct
 typedef struct
 {
   HOST_WIDE_INT alias;         /* Memory alias set.  */
-  tree decl;                   /* decl corresponding to MEM.  */
+  tree expr;                   /* expr corresponding to MEM.  */
   rtx offset;                  /* Offset from start of DECL, as CONST_INT.  */
   rtx size;                    /* Size in bytes, as a CONST_INT.  */
   unsigned int align;          /* Alignment of MEM in bits.  */
@@ -904,10 +904,10 @@ extern unsigned int subreg_regno  PARAMS ((rtx));
 #define MEM_ALIAS_SET(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->alias)
 
 /* For a MEM rtx, the decl it is known to refer to, if it is known to
-   refer to part of a DECL.  */
-#define MEM_DECL(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->decl)
+   refer to part of a DECL.  It may also be a COMPONENT_REF.  */
+#define MEM_EXPR(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->expr)
 
-/* For a MEM rtx, the offset from the start of MEM_DECL, if known, as a
+/* For a MEM rtx, the offset from the start of MEM_EXPR, if known, as a
    RTX that is always a CONST_INT.  */
 #define MEM_OFFSET(RTX) (MEM_ATTRS (RTX) == 0 ? 0 : MEM_ATTRS (RTX)->offset)
 
@@ -1865,6 +1865,7 @@ extern void debug_rtx_list                PARAMS ((rtx, int));
 extern void debug_rtx_range            PARAMS ((rtx, rtx));
 extern rtx debug_rtx_find              PARAMS ((rtx, int));
 #ifdef BUFSIZ
+extern void print_mem_expr             PARAMS ((FILE *, tree));
 extern void print_rtl                  PARAMS ((FILE *, rtx));
 extern void print_simple_rtl           PARAMS ((FILE *, rtx));
 extern int print_rtl_single            PARAMS ((FILE *, rtx));