[gcc(refs/users/mikael/heads/refactor_descriptor_v08)] Extraction build_array_ref

Mikael Morin mikael@gcc.gnu.org
Mon Sep 22 09:41:59 GMT 2025


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

commit e715877472ae527cdea32235d1484955f3a73ef8
Author: Mikael Morin <mikael@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 486d944d5132..71e5fa59bf39 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.  */


More information about the Gcc-cvs mailing list