https://gcc.gnu.org/g:d9423e6e9442366d707575aed2bebff537d77642

commit d9423e6e9442366d707575aed2bebff537d77642
Author: Mikael Morin <mik...@gcc.gnu.org>
Date:   Mon Sep 22 11:12:09 2025 +0200

    Extraction build_array_ref

Diff:
---
 gcc/fortran/trans-array.cc | 223 ++++++++++++++++++++++++++++-----------------
 1 file changed, 141 insertions(+), 82 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 4378cd00253b..ea8d39deeb8f 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -3452,21 +3452,6 @@ array_bound_check_elemental (gfc_se * se, gfc_ss * ss, 
gfc_expr * expr)
 }
 
 
-static tree
-build_array_ref (gfc_array_ref_info * array_ref)
-{
-  switch (array_ref->access)
-    {
-    case gfc_array_ref_info::ARRAY_INDEX:
-      break;
-    case gfc_array_ref_info::POINTER_OFFSET:
-      break;
-    }
-  
-  return NULL_TREE;
-}
-
-
 /* Add T to the offset pair *OFFSET, *CST_OFFSET.  */
 
 void
@@ -3654,16 +3639,12 @@ conv_array_index_offset (gfc_se * se, gfc_ss * ss, int 
dim, int i,
 }
 
 
-/* Build a scalarized array reference using the vptr 'size'.  */
-
 static bool
-build_class_array_ref (gfc_se *se, tree base, tree index)
+is_class_array_ref (tree base, gfc_expr *expr, tree *class_descr)
 {
-  tree size;
   tree decl = NULL_TREE;
   tree tmp;
-  gfc_expr *expr = se->ss->info->expr;
-  gfc_expr *class_expr;
+  gfc_expr *class_expr = nullptr;
   gfc_typespec *ts;
   gfc_symbol *sym;
 
@@ -3687,7 +3668,7 @@ build_class_array_ref (gfc_se *se, tree base, tree index)
       class_expr = gfc_find_and_cut_at_last_class_ref (expr, false, &ts);
 
       if (!ts)
-       return false;
+       goto give_up;
 
       sym = (!class_expr && expr) ? expr->symtree->n.sym : NULL;
       if (sym && sym->attr.function
@@ -3716,6 +3697,31 @@ build_class_array_ref (gfc_se *se, tree base, tree index)
        return false;
     }
 
+  if (class_descr)
+    *class_descr = decl;
+  if (class_expr != nullptr)
+    gfc_free_expr (class_expr);
+  return true;
+
+give_up:
+  if (class_expr != nullptr)
+    gfc_free_expr (class_expr);
+  return false;
+}
+
+
+/* Build a scalarized array reference using the vptr 'size'.  */
+
+static bool
+build_class_array_ref (gfc_se *se, tree base, tree index)
+{
+  tree size;
+  tree decl = NULL_TREE;
+  gfc_expr *expr = se->ss->info->expr;
+
+  if (!is_class_array_ref (base, expr, &decl))
+    return false;
+
   se->class_vptr = gfc_evaluate_now (gfc_class_vptr_get (decl), &se->pre);
 
   size = gfc_class_vtab_size_get (decl);
@@ -3771,6 +3777,106 @@ non_negative_strides_array_p (tree expr)
 }
 
 
+enum gfc_array_ref_sort
+{
+  /* A regular array reference.  */
+  ARS_REGULAR_ARRAY_REF,
+  /* Pointer arithmetics, with the element size picked from the class
+     descriptor's _size field.  */
+  ARS_CLASS_PTR_ARITH,
+  /* Pointer arithmetics, with the element size picked from the array
+     descriptor's span field.  */
+  ARS_SPANNED_PTR_ARITH,
+  /* Pointer arithmetics, using the CFI descriptor's sm fields.  */
+  ARS_CFI_PTR_ARITH
+};
+
+
+static gfc_array_ref_sort
+classify_array_ref (tree array, tree ref_base, gfc_expr *expr,
+                   gfc_array_ref *ar, bool tmp_array)
+{
+  if (is_class_array_ref (ref_base, expr, nullptr))
+    return ARS_CLASS_PTR_ARITH;
+
+  if (get_CFI_desc (NULL, expr, nullptr, ar))
+    return ARS_CFI_PTR_ARITH;
+
+  if (is_pointer_array (array)
+      || (expr && expr->ts.deferred && array
+         && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (array))))
+    return ARS_SPANNED_PTR_ARITH;
+
+  if (tmp_array || non_negative_strides_array_p (array))
+    return ARS_SPANNED_PTR_ARITH;
+
+  return ARS_REGULAR_ARRAY_REF;
+}
+
+
+static void
+build_array_ref (gfc_se *se, tree array, tree ref_base, gfc_expr *expr,
+                gfc_array_ref *ar, bool is_temp_array, tree index)
+{
+  switch (classify_array_ref (array, ref_base, expr, ar, is_temp_array))
+    {
+
+    case ARS_CLASS_PTR_ARITH:
+      {
+       bool success = build_class_array_ref (se, ref_base, index);
+       gcc_assert (success);
+      }
+      break;
+
+    case ARS_CFI_PTR_ARITH:
+      {
+       tree cfi_decl = NULL_TREE;
+       if (get_CFI_desc (NULL, expr, &cfi_decl, ar))
+         cfi_decl = build_fold_indirect_ref_loc (input_location, cfi_decl);
+       bool non_negative_stride = is_temp_array
+                                  || non_negative_strides_array_p (array);
+       se->expr = gfc_build_array_ref (ref_base, index, non_negative_stride,
+                                       cfi_decl);
+      }
+      break;
+
+    case ARS_SPANNED_PTR_ARITH:
+      {
+       tree decl = NULL_TREE;
+       if (is_pointer_array (array)
+           || (expr && expr->ts.deferred && array
+               && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (array))))
+         {
+           if (TREE_CODE (array) == COMPONENT_REF)
+             decl = array;
+           else if (INDIRECT_REF_P (array))
+             decl = TREE_OPERAND (array, 0);
+
+           if (decl == NULL_TREE)
+             decl = array;
+         }
+
+       bool non_negative_stride = is_temp_array
+                                  || non_negative_strides_array_p (array);
+       se->expr = gfc_build_array_ref (ref_base, index, non_negative_stride,
+                                       decl);
+      }
+      break;
+
+    case ARS_REGULAR_ARRAY_REF:
+      {
+       bool non_negative_stride = is_temp_array
+                                  || non_negative_strides_array_p (array);
+       se->expr = gfc_build_array_ref (ref_base, index, non_negative_stride);
+      }
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
+
 /* Build a scalarized reference to an array.  */
 
 static void
@@ -3778,7 +3884,6 @@ gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref 
* ar,
                               bool tmp_array = false)
 {
   gfc_array_info *info;
-  tree decl = NULL_TREE;
   tree base;
   gfc_ss *ss;
   gfc_expr *expr;
@@ -3797,32 +3902,7 @@ gfc_conv_scalarized_array_ref (gfc_se * se, 
gfc_array_ref * ar,
 
   base = build_fold_indirect_ref_loc (input_location, info->current_elem.base);
 
-  /* Use the vptr 'size' field to access the element of a class array.  */
-  if (build_class_array_ref (se, base, index))
-    return;
-
-  if (get_CFI_desc (NULL, expr, &decl, ar))
-    decl = build_fold_indirect_ref_loc (input_location, decl);
-
-  /* A pointer array component can be detected from its field decl. Fix
-     the descriptor, mark the resulting variable decl and pass it to
-     gfc_build_array_ref.  */
-  if (is_pointer_array (info->descriptor)
-      || (expr && expr->ts.deferred && info->descriptor
-         && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (info->descriptor))))
-    {
-      if (TREE_CODE (info->descriptor) == COMPONENT_REF)
-       decl = info->descriptor;
-      else if (INDIRECT_REF_P (info->descriptor))
-       decl = TREE_OPERAND (info->descriptor, 0);
-
-      if (decl == NULL_TREE)
-       decl = info->descriptor;
-    }
-
-  bool non_negative_stride = tmp_array
-                            || non_negative_strides_array_p (info->descriptor);
-  se->expr = gfc_build_array_ref (base, index, non_negative_stride, decl);
+  build_array_ref (se, info->descriptor, base, expr, ar, tmp_array, index);
 }
 
 
@@ -3837,39 +3917,13 @@ gfc_conv_tmp_array_ref (gfc_se * se)
 }
 
 
-static tree
-build_array_ref (tree desc, tree offset, tree decl, tree vptr)
+static void
+build_array_ref (gfc_se *se, tree array, gfc_expr *expr, gfc_array_ref *ar,
+                tree index)
 {
-  tree tmp;
-  tree type;
-  tree cdesc;
-
-  /* For class arrays the class declaration is stored in the saved
-     descriptor.  */
-  if (INDIRECT_REF_P (desc)
-      && DECL_LANG_SPECIFIC (TREE_OPERAND (desc, 0))
-      && GFC_DECL_SAVED_DESCRIPTOR (TREE_OPERAND (desc, 0)))
-    cdesc = gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (
-                                 TREE_OPERAND (desc, 0)));
-  else
-    cdesc = desc;
-
-  /* Class container types do not always have the GFC_CLASS_TYPE_P
-     but the canonical type does.  */
-  if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (cdesc))
-      && TREE_CODE (cdesc) == COMPONENT_REF)
-    {
-      type = TREE_TYPE (TREE_OPERAND (cdesc, 0));
-      if (TYPE_CANONICAL (type)
-         && GFC_CLASS_TYPE_P (TYPE_CANONICAL (type)))
-       vptr = gfc_class_vptr_get (TREE_OPERAND (cdesc, 0));
-    }
-
-  tmp = gfc_conv_array_data (desc);
+  tree tmp = gfc_conv_array_data (array);
   tmp = build_fold_indirect_ref_loc (input_location, tmp);
-  tmp = gfc_build_array_ref (tmp, offset, non_negative_strides_array_p (desc),
-                            decl, vptr);
-  return tmp;
+  build_array_ref (se, array, tmp, expr, ar, false, index);
 }
 
 
@@ -4064,7 +4118,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, 
gfc_expr *expr,
     }
 
   free (var_name);
-  se->expr = build_array_ref (se->expr, index, decl, se->class_vptr);
+  build_array_ref (se, se->expr, expr, ar, index);
 }
 
 
@@ -7146,7 +7200,12 @@ gfc_get_dataptr_offset (stmtblock_t *block, tree parm, 
tree desc, tree offset,
        return;
     }
 
-  tmp = build_array_ref (desc, offset, NULL, NULL);
+  gfc_se se;
+  gfc_init_se (&se, nullptr);
+  build_array_ref (&se, desc, expr, gfc_find_array_ref (expr, false), offset);
+  gfc_add_block_to_block (block, &se.pre);
+  tmp = gfc_evaluate_now (se.expr, block);
+  gfc_add_block_to_block (block, &se.post);
 
   /* Offset the data pointer for pointer assignments from arrays with
      subreferences; e.g. my_integer => my_type(:)%integer_component.  */

Reply via email to