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

commit ed2b5eb97ccdfe214b7389b9a19fd90977faf96f
Author: Mikael Morin <mik...@gcc.gnu.org>
Date:   Wed Jun 18 17:31:23 2025 +0200

    Déplacement fonctions descripteur vers fichier séparé

Diff:
---
 gcc/fortran/Make-lang.in        |   7 +-
 gcc/fortran/trans-array.cc      | 515 +-------------------------------------
 gcc/fortran/trans-descriptor.cc | 534 ++++++++++++++++++++++++++++++++++++++++
 gcc/fortran/trans-descriptor.h  |  67 +++++
 4 files changed, 610 insertions(+), 513 deletions(-)

diff --git a/gcc/fortran/Make-lang.in b/gcc/fortran/Make-lang.in
index 5b2f921bf2ef..2ddb0366e9dc 100644
--- a/gcc/fortran/Make-lang.in
+++ b/gcc/fortran/Make-lang.in
@@ -63,9 +63,10 @@ F95_PARSER_OBJS = fortran/arith.o fortran/array.o 
fortran/bbt.o \
 F95_OBJS = $(F95_PARSER_OBJS) $(FORTRAN_TARGET_OBJS) \
     fortran/convert.o fortran/dependency.o fortran/f95-lang.o \
     fortran/trans.o fortran/trans-array.o fortran/trans-common.o \
-    fortran/trans-const.o fortran/trans-decl.o fortran/trans-expr.o \
-    fortran/trans-intrinsic.o fortran/trans-io.o fortran/trans-openmp.o \
-    fortran/trans-stmt.o fortran/trans-types.o fortran/frontend-passes.o
+    fortran/trans-const.o fortran/trans-decl.o fortran/trans-descriptor.o \
+    fortran/trans-expr.o fortran/trans-intrinsic.o fortran/trans-io.o \
+    fortran/trans-openmp.o fortran/trans-stmt.o fortran/trans-types.o \
+    fortran/frontend-passes.o
 
 fortran_OBJS = $(F95_OBJS) fortran/gfortranspec.o
 
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 960613167f72..8d90bec0d85f 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -92,6 +92,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "trans-array.h"
 #include "trans-const.h"
 #include "dependency.h"
+#include "trans-descriptor.h"
 
 static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor_base);
 
@@ -106,466 +107,6 @@ gfc_array_dataptr_type (tree desc)
   return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));
 }
 
-/* Build expressions to access members of the CFI descriptor.  */
-#define CFI_FIELD_BASE_ADDR 0
-#define CFI_FIELD_ELEM_LEN 1
-#define CFI_FIELD_VERSION 2
-#define CFI_FIELD_RANK 3
-#define CFI_FIELD_ATTRIBUTE 4
-#define CFI_FIELD_TYPE 5
-#define CFI_FIELD_DIM 6
-
-#define CFI_DIM_FIELD_LOWER_BOUND 0
-#define CFI_DIM_FIELD_EXTENT 1
-#define CFI_DIM_FIELD_SM 2
-
-static tree
-gfc_get_cfi_descriptor_field (tree desc, unsigned field_idx)
-{
-  tree type = TREE_TYPE (desc);
-  gcc_assert (TREE_CODE (type) == RECORD_TYPE
-             && TYPE_FIELDS (type)
-             && (strcmp ("base_addr",
-                        IDENTIFIER_POINTER (DECL_NAME (TYPE_FIELDS (type))))
-                 == 0));
-  tree field = gfc_advance_chain (TYPE_FIELDS (type), field_idx);
-  gcc_assert (field != NULL_TREE);
-
-  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
-                         desc, field, NULL_TREE);
-}
-
-tree
-gfc_get_cfi_desc_base_addr (tree desc)
-{
-  return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_BASE_ADDR);
-}
-
-tree
-gfc_get_cfi_desc_elem_len (tree desc)
-{
-  return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_ELEM_LEN);
-}
-
-tree
-gfc_get_cfi_desc_version (tree desc)
-{
-  return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_VERSION);
-}
-
-tree
-gfc_get_cfi_desc_rank (tree desc)
-{
-  return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_RANK);
-}
-
-tree
-gfc_get_cfi_desc_type (tree desc)
-{
-  return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_TYPE);
-}
-
-tree
-gfc_get_cfi_desc_attribute (tree desc)
-{
-  return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_ATTRIBUTE);
-}
-
-static tree
-gfc_get_cfi_dim_item (tree desc, tree idx, unsigned field_idx)
-{
-  tree tmp = gfc_get_cfi_descriptor_field (desc, CFI_FIELD_DIM);
-  tmp = gfc_build_array_ref (tmp, idx, NULL_TREE, true);
-  tree field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), field_idx);
-  gcc_assert (field != NULL_TREE);
-  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
-                         tmp, field, NULL_TREE);
-}
-
-tree
-gfc_get_cfi_dim_lbound (tree desc, tree idx)
-{
-  return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_LOWER_BOUND);
-}
-
-tree
-gfc_get_cfi_dim_extent (tree desc, tree idx)
-{
-  return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_EXTENT);
-}
-
-tree
-gfc_get_cfi_dim_sm (tree desc, tree idx)
-{
-  return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_SM);
-}
-
-#undef CFI_FIELD_BASE_ADDR
-#undef CFI_FIELD_ELEM_LEN
-#undef CFI_FIELD_VERSION
-#undef CFI_FIELD_RANK
-#undef CFI_FIELD_ATTRIBUTE
-#undef CFI_FIELD_TYPE
-#undef CFI_FIELD_DIM
-
-#undef CFI_DIM_FIELD_LOWER_BOUND
-#undef CFI_DIM_FIELD_EXTENT
-#undef CFI_DIM_FIELD_SM
-
-/* Build expressions to access the members of an array descriptor.
-   It's surprisingly easy to mess up here, so never access
-   an array descriptor by "brute force", always use these
-   functions.  This also avoids problems if we change the format
-   of an array descriptor.
-
-   To understand these magic numbers, look at the comments
-   before gfc_build_array_type() in trans-types.cc.
-
-   The code within these defines should be the only code which knows the format
-   of an array descriptor.
-
-   Any code just needing to read obtain the bounds of an array should use
-   gfc_conv_array_* rather than the following functions as these will return
-   know constant values, and work with arrays which do not have descriptors.
-
-   Don't forget to #undef these!  */
-
-#define DATA_FIELD 0
-#define OFFSET_FIELD 1
-#define DTYPE_FIELD 2
-#define SPAN_FIELD 3
-#define DIMENSION_FIELD 4
-#define CAF_TOKEN_FIELD 5
-
-#define STRIDE_SUBFIELD 0
-#define LBOUND_SUBFIELD 1
-#define UBOUND_SUBFIELD 2
-
-static tree
-gfc_get_descriptor_field (tree desc, unsigned field_idx)
-{
-  tree type = TREE_TYPE (desc);
-  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
-
-  tree field = gfc_advance_chain (TYPE_FIELDS (type), field_idx);
-  gcc_assert (field != NULL_TREE);
-
-  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
-                         desc, field, NULL_TREE);
-}
-
-/* This provides READ-ONLY access to the data field.  The field itself
-   doesn't have the proper type.  */
-
-tree
-gfc_conv_descriptor_data_get (tree desc)
-{
-  tree type = TREE_TYPE (desc);
-  if (TREE_CODE (type) == REFERENCE_TYPE)
-    gcc_unreachable ();
-
-  tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
-  return fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), field);
-}
-
-/* This provides WRITE access to the data field.
-
-   TUPLES_P is true if we are generating tuples.
-
-   This function gets called through the following macros:
-     gfc_conv_descriptor_data_set
-     gfc_conv_descriptor_data_set.  */
-
-void
-gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
-{
-  tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
-  gfc_add_modify (block, field, fold_convert (TREE_TYPE (field), value));
-}
-
-
-/* This provides address access to the data field.  This should only be
-   used by array allocation, passing this on to the runtime.  */
-
-tree
-gfc_conv_descriptor_data_addr (tree desc)
-{
-  tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
-  return gfc_build_addr_expr (NULL_TREE, field);
-}
-
-static tree
-gfc_conv_descriptor_offset (tree desc)
-{
-  tree field = gfc_get_descriptor_field (desc, OFFSET_FIELD);
-  gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
-  return field;
-}
-
-tree
-gfc_conv_descriptor_offset_get (tree desc)
-{
-  return gfc_conv_descriptor_offset (desc);
-}
-
-void
-gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc,
-                               tree value)
-{
-  tree t = gfc_conv_descriptor_offset (desc);
-  gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
-}
-
-
-tree
-gfc_conv_descriptor_dtype (tree desc)
-{
-  tree field = gfc_get_descriptor_field (desc, DTYPE_FIELD);
-  gcc_assert (TREE_TYPE (field) == get_dtype_type_node ());
-  return field;
-}
-
-static tree
-gfc_conv_descriptor_span (tree desc)
-{
-  tree field = gfc_get_descriptor_field (desc, SPAN_FIELD);
-  gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
-  return field;
-}
-
-tree
-gfc_conv_descriptor_span_get (tree desc)
-{
-  return gfc_conv_descriptor_span (desc);
-}
-
-void
-gfc_conv_descriptor_span_set (stmtblock_t *block, tree desc,
-                               tree value)
-{
-  tree t = gfc_conv_descriptor_span (desc);
-  gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
-}
-
-
-tree
-gfc_conv_descriptor_rank (tree desc)
-{
-  tree tmp;
-  tree dtype;
-
-  dtype = gfc_conv_descriptor_dtype (desc);
-  tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_RANK);
-  gcc_assert (tmp != NULL_TREE
-             && TREE_TYPE (tmp) == signed_char_type_node);
-  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
-                         dtype, tmp, NULL_TREE);
-}
-
-
-tree
-gfc_conv_descriptor_version (tree desc)
-{
-  tree tmp;
-  tree dtype;
-
-  dtype = gfc_conv_descriptor_dtype (desc);
-  tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_VERSION);
-  gcc_assert (tmp != NULL_TREE
-             && TREE_TYPE (tmp) == integer_type_node);
-  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
-                         dtype, tmp, NULL_TREE);
-}
-
-
-/* Return the element length from the descriptor dtype field.  */
-
-tree
-gfc_conv_descriptor_elem_len (tree desc)
-{
-  tree tmp;
-  tree dtype;
-
-  dtype = gfc_conv_descriptor_dtype (desc);
-  tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)),
-                          GFC_DTYPE_ELEM_LEN);
-  gcc_assert (tmp != NULL_TREE
-             && TREE_TYPE (tmp) == size_type_node);
-  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
-                         dtype, tmp, NULL_TREE);
-}
-
-
-tree
-gfc_conv_descriptor_attribute (tree desc)
-{
-  tree tmp;
-  tree dtype;
-
-  dtype = gfc_conv_descriptor_dtype (desc);
-  tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)),
-                          GFC_DTYPE_ATTRIBUTE);
-  gcc_assert (tmp!= NULL_TREE
-             && TREE_TYPE (tmp) == short_integer_type_node);
-  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
-                         dtype, tmp, NULL_TREE);
-}
-
-tree
-gfc_conv_descriptor_type (tree desc)
-{
-  tree tmp;
-  tree dtype;
-
-  dtype = gfc_conv_descriptor_dtype (desc);
-  tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_TYPE);
-  gcc_assert (tmp!= NULL_TREE
-             && TREE_TYPE (tmp) == signed_char_type_node);
-  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
-                         dtype, tmp, NULL_TREE);
-}
-
-tree
-gfc_get_descriptor_dimension (tree desc)
-{
-  tree field = gfc_get_descriptor_field (desc, DIMENSION_FIELD);
-  gcc_assert (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
-             && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
-  return field;
-}
-
-
-static tree
-gfc_conv_descriptor_dimension (tree desc, tree dim)
-{
-  tree tmp;
-
-  tmp = gfc_get_descriptor_dimension (desc);
-
-  return gfc_build_array_ref (tmp, dim, NULL_TREE, true);
-}
-
-
-tree
-gfc_conv_descriptor_token (tree desc)
-{
-  gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
-  tree field = gfc_get_descriptor_field (desc, CAF_TOKEN_FIELD);
-  /* Should be a restricted pointer - except in the finalization wrapper.  */
-  gcc_assert (TREE_TYPE (field) == prvoid_type_node
-             || TREE_TYPE (field) == pvoid_type_node);
-  return field;
-}
-
-static tree
-gfc_conv_descriptor_subfield (tree desc, tree dim, unsigned field_idx)
-{
-  tree tmp = gfc_conv_descriptor_dimension (desc, dim);
-  tree field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), field_idx);
-  gcc_assert (field != NULL_TREE);
-
-  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
-                         tmp, field, NULL_TREE);
-}
-
-static tree
-gfc_conv_descriptor_stride (tree desc, tree dim)
-{
-  tree field = gfc_conv_descriptor_subfield (desc, dim, STRIDE_SUBFIELD);
-  gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
-  return field;
-}
-
-tree
-gfc_conv_descriptor_stride_get (tree desc, tree dim)
-{
-  tree type = TREE_TYPE (desc);
-  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
-  if (integer_zerop (dim)
-      && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
-         || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT
-         || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_CONT
-         || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_ALLOCATABLE
-         || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_POINTER_CONT
-         || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
-    return gfc_index_one_node;
-
-  return gfc_conv_descriptor_stride (desc, dim);
-}
-
-void
-gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
-                               tree dim, tree value)
-{
-  tree t = gfc_conv_descriptor_stride (desc, dim);
-  gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
-}
-
-static tree
-gfc_conv_descriptor_lbound (tree desc, tree dim)
-{
-  tree field = gfc_conv_descriptor_subfield (desc, dim, LBOUND_SUBFIELD);
-  gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
-  return field;
-}
-
-tree
-gfc_conv_descriptor_lbound_get (tree desc, tree dim)
-{
-  return gfc_conv_descriptor_lbound (desc, dim);
-}
-
-void
-gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
-                               tree dim, tree value)
-{
-  tree t = gfc_conv_descriptor_lbound (desc, dim);
-  gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
-}
-
-static tree
-gfc_conv_descriptor_ubound (tree desc, tree dim)
-{
-  tree field = gfc_conv_descriptor_subfield (desc, dim, UBOUND_SUBFIELD);
-  gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
-  return field;
-}
-
-tree
-gfc_conv_descriptor_ubound_get (tree desc, tree dim)
-{
-  return gfc_conv_descriptor_ubound (desc, dim);
-}
-
-void
-gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
-                               tree dim, tree value)
-{
-  tree t = gfc_conv_descriptor_ubound (desc, dim);
-  gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
-}
-
-/* Build a null array descriptor constructor.  */
-
-tree
-gfc_build_null_descriptor (tree type)
-{
-  tree field;
-  tree tmp;
-
-  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
-  gcc_assert (DATA_FIELD == 0);
-  field = TYPE_FIELDS (type);
-
-  /* Set a NULL data pointer.  */
-  tmp = build_constructor_single (type, field, null_pointer_node);
-  TREE_CONSTANT (tmp) = 1;
-  /* All other fields are ignored.  */
-
-  return tmp;
-}
-
-
 /* Modify a descriptor such that the lbound of a given dimension is the value
    specified.  This also updates ubound and offset accordingly.  */
 
@@ -603,51 +144,6 @@ gfc_conv_shift_descriptor_lbound (stmtblock_t* block, tree 
desc,
 }
 
 
-/* Obtain offsets for trans-types.cc(gfc_get_array_descr_info).  */
-
-void
-gfc_get_descriptor_offsets_for_info (const_tree desc_type, tree *data_off,
-                                    tree *dtype_off, tree *span_off,
-                                    tree *dim_off, tree *dim_size,
-                                    tree *stride_suboff, tree *lower_suboff,
-                                    tree *upper_suboff)
-{
-  tree field;
-  tree type;
-
-  type = TYPE_MAIN_VARIANT (desc_type);
-  field = gfc_advance_chain (TYPE_FIELDS (type), DATA_FIELD);
-  *data_off = byte_position (field);
-  field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
-  *dtype_off = byte_position (field);
-  field = gfc_advance_chain (TYPE_FIELDS (type), SPAN_FIELD);
-  *span_off = byte_position (field);
-  field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
-  *dim_off = byte_position (field);
-  type = TREE_TYPE (TREE_TYPE (field));
-  *dim_size = TYPE_SIZE_UNIT (type);
-  field = gfc_advance_chain (TYPE_FIELDS (type), STRIDE_SUBFIELD);
-  *stride_suboff = byte_position (field);
-  field = gfc_advance_chain (TYPE_FIELDS (type), LBOUND_SUBFIELD);
-  *lower_suboff = byte_position (field);
-  field = gfc_advance_chain (TYPE_FIELDS (type), UBOUND_SUBFIELD);
-  *upper_suboff = byte_position (field);
-}
-
-
-/* Cleanup those #defines.  */
-
-#undef DATA_FIELD
-#undef OFFSET_FIELD
-#undef DTYPE_FIELD
-#undef SPAN_FIELD
-#undef DIMENSION_FIELD
-#undef CAF_TOKEN_FIELD
-#undef STRIDE_SUBFIELD
-#undef LBOUND_SUBFIELD
-#undef UBOUND_SUBFIELD
-
-
 /* Mark a SS chain as used.  Flags specifies in which loops the SS is used.
    flags & 1 = Main loop body.
    flags & 2 = temp copy loop.  */
@@ -11566,8 +11062,8 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo 
*loop,
                                          gfc_index_zero_node);
        }
 
-      tmp = gfc_conv_descriptor_offset (desc);
-      gfc_add_modify (&loop_pre_block, tmp, gfc_index_zero_node);
+      gfc_conv_descriptor_offset_set (&loop_pre_block, desc,
+                                     gfc_index_zero_node);
 
       tmp = fold_build2_loc (input_location, EQ_EXPR,
                             logical_type_node, array1,
@@ -11732,11 +11228,10 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo 
*loop,
   /* Set the lhs descriptor and scalarizer offsets.  For rank > 1,
      the array offset is saved and the info.offset is used for a
      running offset.  Use the saved_offset instead.  */
-  tmp = gfc_conv_descriptor_offset (desc);
-  gfc_add_modify (&fblock, tmp, offset);
+  gfc_conv_descriptor_offset_set (&fblock, desc, offset);
   if (linfo->saved_offset
       && VAR_P (linfo->saved_offset))
-    gfc_add_modify (&fblock, linfo->saved_offset, tmp);
+    gfc_add_modify (&fblock, linfo->saved_offset, offset);
 
   /* Now set the deltas for the lhs.  */
   for (n = 0; n < expr1->rank; n++)
diff --git a/gcc/fortran/trans-descriptor.cc b/gcc/fortran/trans-descriptor.cc
new file mode 100644
index 000000000000..30093a74ae58
--- /dev/null
+++ b/gcc/fortran/trans-descriptor.cc
@@ -0,0 +1,534 @@
+/* Copyright (C) 2002-2025 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+      
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "fold-const.h"
+#include "gfortran.h"
+#include "trans.h"
+#include "trans-const.h"
+#include "trans-types.h"
+
+
+/* Build expressions to access members of the CFI descriptor.  */
+#define CFI_FIELD_BASE_ADDR 0
+#define CFI_FIELD_ELEM_LEN 1
+#define CFI_FIELD_VERSION 2
+#define CFI_FIELD_RANK 3
+#define CFI_FIELD_ATTRIBUTE 4
+#define CFI_FIELD_TYPE 5
+#define CFI_FIELD_DIM 6
+
+#define CFI_DIM_FIELD_LOWER_BOUND 0
+#define CFI_DIM_FIELD_EXTENT 1
+#define CFI_DIM_FIELD_SM 2
+
+static tree
+gfc_get_cfi_descriptor_field (tree desc, unsigned field_idx)
+{
+  tree type = TREE_TYPE (desc);
+  gcc_assert (TREE_CODE (type) == RECORD_TYPE
+             && TYPE_FIELDS (type)
+             && (strcmp ("base_addr",
+                        IDENTIFIER_POINTER (DECL_NAME (TYPE_FIELDS (type))))
+                 == 0));
+  tree field = gfc_advance_chain (TYPE_FIELDS (type), field_idx);
+  gcc_assert (field != NULL_TREE);
+
+  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
+                         desc, field, NULL_TREE);
+}
+
+tree
+gfc_get_cfi_desc_base_addr (tree desc)
+{
+  return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_BASE_ADDR);
+}
+
+tree
+gfc_get_cfi_desc_elem_len (tree desc)
+{
+  return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_ELEM_LEN);
+}
+
+tree
+gfc_get_cfi_desc_version (tree desc)
+{
+  return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_VERSION);
+}
+
+tree
+gfc_get_cfi_desc_rank (tree desc)
+{
+  return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_RANK);
+}
+
+tree
+gfc_get_cfi_desc_type (tree desc)
+{
+  return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_TYPE);
+}
+
+tree
+gfc_get_cfi_desc_attribute (tree desc)
+{
+  return gfc_get_cfi_descriptor_field (desc, CFI_FIELD_ATTRIBUTE);
+}
+
+static tree
+gfc_get_cfi_dim_item (tree desc, tree idx, unsigned field_idx)
+{
+  tree tmp = gfc_get_cfi_descriptor_field (desc, CFI_FIELD_DIM);
+  tmp = gfc_build_array_ref (tmp, idx, NULL_TREE, true);
+  tree field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), field_idx);
+  gcc_assert (field != NULL_TREE);
+  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
+                         tmp, field, NULL_TREE);
+}
+
+tree
+gfc_get_cfi_dim_lbound (tree desc, tree idx)
+{
+  return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_LOWER_BOUND);
+}
+
+tree
+gfc_get_cfi_dim_extent (tree desc, tree idx)
+{
+  return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_EXTENT);
+}
+
+tree
+gfc_get_cfi_dim_sm (tree desc, tree idx)
+{
+  return gfc_get_cfi_dim_item (desc, idx, CFI_DIM_FIELD_SM);
+}
+
+#undef CFI_FIELD_BASE_ADDR
+#undef CFI_FIELD_ELEM_LEN
+#undef CFI_FIELD_VERSION
+#undef CFI_FIELD_RANK
+#undef CFI_FIELD_ATTRIBUTE
+#undef CFI_FIELD_TYPE
+#undef CFI_FIELD_DIM
+
+#undef CFI_DIM_FIELD_LOWER_BOUND
+#undef CFI_DIM_FIELD_EXTENT
+#undef CFI_DIM_FIELD_SM
+
+/* Build expressions to access the members of an array descriptor.
+   It's surprisingly easy to mess up here, so never access
+   an array descriptor by "brute force", always use these
+   functions.  This also avoids problems if we change the format
+   of an array descriptor.
+
+   To understand these magic numbers, look at the comments
+   before gfc_build_array_type() in trans-types.cc.
+
+   The code within these defines should be the only code which knows the format
+   of an array descriptor.
+
+   Any code just needing to read obtain the bounds of an array should use
+   gfc_conv_array_* rather than the following functions as these will return
+   know constant values, and work with arrays which do not have descriptors.
+
+   Don't forget to #undef these!  */
+
+#define DATA_FIELD 0
+#define OFFSET_FIELD 1
+#define DTYPE_FIELD 2
+#define SPAN_FIELD 3
+#define DIMENSION_FIELD 4
+#define CAF_TOKEN_FIELD 5
+
+#define STRIDE_SUBFIELD 0
+#define LBOUND_SUBFIELD 1
+#define UBOUND_SUBFIELD 2
+
+static tree
+gfc_get_descriptor_field (tree desc, unsigned field_idx)
+{
+  tree type = TREE_TYPE (desc);
+  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
+
+  tree field = gfc_advance_chain (TYPE_FIELDS (type), field_idx);
+  gcc_assert (field != NULL_TREE);
+
+  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
+                         desc, field, NULL_TREE);
+}
+
+/* This provides READ-ONLY access to the data field.  The field itself
+   doesn't have the proper type.  */
+
+tree
+gfc_conv_descriptor_data_get (tree desc)
+{
+  tree type = TREE_TYPE (desc);
+  if (TREE_CODE (type) == REFERENCE_TYPE)
+    gcc_unreachable ();
+
+  tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
+  return fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), field);
+}
+
+/* This provides WRITE access to the data field.
+
+   TUPLES_P is true if we are generating tuples.
+
+   This function gets called through the following macros:
+     gfc_conv_descriptor_data_set
+     gfc_conv_descriptor_data_set.  */
+
+void
+gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
+{
+  tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
+  gfc_add_modify (block, field, fold_convert (TREE_TYPE (field), value));
+}
+
+
+/* This provides address access to the data field.  This should only be
+   used by array allocation, passing this on to the runtime.  */
+
+tree
+gfc_conv_descriptor_data_addr (tree desc)
+{
+  tree field = gfc_get_descriptor_field (desc, DATA_FIELD);
+  return gfc_build_addr_expr (NULL_TREE, field);
+}
+
+tree
+gfc_conv_descriptor_offset (tree desc)
+{
+  tree field = gfc_get_descriptor_field (desc, OFFSET_FIELD);
+  gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
+  return field;
+}
+
+tree
+gfc_conv_descriptor_offset_get (tree desc)
+{
+  return gfc_conv_descriptor_offset (desc);
+}
+
+void
+gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc,
+                               tree value)
+{
+  tree t = gfc_conv_descriptor_offset (desc);
+  gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
+}
+
+
+tree
+gfc_conv_descriptor_dtype (tree desc)
+{
+  tree field = gfc_get_descriptor_field (desc, DTYPE_FIELD);
+  gcc_assert (TREE_TYPE (field) == get_dtype_type_node ());
+  return field;
+}
+
+static tree
+gfc_conv_descriptor_span (tree desc)
+{
+  tree field = gfc_get_descriptor_field (desc, SPAN_FIELD);
+  gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
+  return field;
+}
+
+tree
+gfc_conv_descriptor_span_get (tree desc)
+{
+  return gfc_conv_descriptor_span (desc);
+}
+
+void
+gfc_conv_descriptor_span_set (stmtblock_t *block, tree desc,
+                               tree value)
+{
+  tree t = gfc_conv_descriptor_span (desc);
+  gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
+}
+
+
+tree
+gfc_conv_descriptor_rank (tree desc)
+{
+  tree tmp;
+  tree dtype;
+
+  dtype = gfc_conv_descriptor_dtype (desc);
+  tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_RANK);
+  gcc_assert (tmp != NULL_TREE
+             && TREE_TYPE (tmp) == signed_char_type_node);
+  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
+                         dtype, tmp, NULL_TREE);
+}
+
+
+tree
+gfc_conv_descriptor_version (tree desc)
+{
+  tree tmp;
+  tree dtype;
+
+  dtype = gfc_conv_descriptor_dtype (desc);
+  tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_VERSION);
+  gcc_assert (tmp != NULL_TREE
+             && TREE_TYPE (tmp) == integer_type_node);
+  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
+                         dtype, tmp, NULL_TREE);
+}
+
+
+/* Return the element length from the descriptor dtype field.  */
+
+tree
+gfc_conv_descriptor_elem_len (tree desc)
+{
+  tree tmp;
+  tree dtype;
+
+  dtype = gfc_conv_descriptor_dtype (desc);
+  tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)),
+                          GFC_DTYPE_ELEM_LEN);
+  gcc_assert (tmp != NULL_TREE
+             && TREE_TYPE (tmp) == size_type_node);
+  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
+                         dtype, tmp, NULL_TREE);
+}
+
+
+tree
+gfc_conv_descriptor_attribute (tree desc)
+{
+  tree tmp;
+  tree dtype;
+
+  dtype = gfc_conv_descriptor_dtype (desc);
+  tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)),
+                          GFC_DTYPE_ATTRIBUTE);
+  gcc_assert (tmp!= NULL_TREE
+             && TREE_TYPE (tmp) == short_integer_type_node);
+  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
+                         dtype, tmp, NULL_TREE);
+}
+
+tree
+gfc_conv_descriptor_type (tree desc)
+{
+  tree tmp;
+  tree dtype;
+
+  dtype = gfc_conv_descriptor_dtype (desc);
+  tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_TYPE);
+  gcc_assert (tmp!= NULL_TREE
+             && TREE_TYPE (tmp) == signed_char_type_node);
+  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
+                         dtype, tmp, NULL_TREE);
+}
+
+tree
+gfc_get_descriptor_dimension (tree desc)
+{
+  tree field = gfc_get_descriptor_field (desc, DIMENSION_FIELD);
+  gcc_assert (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
+             && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
+  return field;
+}
+
+
+tree
+gfc_conv_descriptor_dimension (tree desc, tree dim)
+{
+  tree tmp;
+
+  tmp = gfc_get_descriptor_dimension (desc);
+
+  return gfc_build_array_ref (tmp, dim, NULL_TREE, true);
+}
+
+
+tree
+gfc_conv_descriptor_token (tree desc)
+{
+  gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
+  tree field = gfc_get_descriptor_field (desc, CAF_TOKEN_FIELD);
+  /* Should be a restricted pointer - except in the finalization wrapper.  */
+  gcc_assert (TREE_TYPE (field) == prvoid_type_node
+             || TREE_TYPE (field) == pvoid_type_node);
+  return field;
+}
+
+static tree
+gfc_conv_descriptor_subfield (tree desc, tree dim, unsigned field_idx)
+{
+  tree tmp = gfc_conv_descriptor_dimension (desc, dim);
+  tree field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), field_idx);
+  gcc_assert (field != NULL_TREE);
+
+  return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
+                         tmp, field, NULL_TREE);
+}
+
+static tree
+gfc_conv_descriptor_stride (tree desc, tree dim)
+{
+  tree field = gfc_conv_descriptor_subfield (desc, dim, STRIDE_SUBFIELD);
+  gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
+  return field;
+}
+
+tree
+gfc_conv_descriptor_stride_get (tree desc, tree dim)
+{
+  tree type = TREE_TYPE (desc);
+  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
+  if (integer_zerop (dim)
+      && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
+         || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT
+         || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_CONT
+         || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_ALLOCATABLE
+         || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_POINTER_CONT
+         || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
+    return gfc_index_one_node;
+
+  return gfc_conv_descriptor_stride (desc, dim);
+}
+
+void
+gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
+                               tree dim, tree value)
+{
+  tree t = gfc_conv_descriptor_stride (desc, dim);
+  gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
+}
+
+static tree
+gfc_conv_descriptor_lbound (tree desc, tree dim)
+{
+  tree field = gfc_conv_descriptor_subfield (desc, dim, LBOUND_SUBFIELD);
+  gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
+  return field;
+}
+
+tree
+gfc_conv_descriptor_lbound_get (tree desc, tree dim)
+{
+  return gfc_conv_descriptor_lbound (desc, dim);
+}
+
+void
+gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
+                               tree dim, tree value)
+{
+  tree t = gfc_conv_descriptor_lbound (desc, dim);
+  gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
+}
+
+static tree
+gfc_conv_descriptor_ubound (tree desc, tree dim)
+{
+  tree field = gfc_conv_descriptor_subfield (desc, dim, UBOUND_SUBFIELD);
+  gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
+  return field;
+}
+
+tree
+gfc_conv_descriptor_ubound_get (tree desc, tree dim)
+{
+  return gfc_conv_descriptor_ubound (desc, dim);
+}
+
+void
+gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
+                               tree dim, tree value)
+{
+  tree t = gfc_conv_descriptor_ubound (desc, dim);
+  gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
+}
+
+
+/* Build a null array descriptor constructor.  */
+
+tree
+gfc_build_null_descriptor (tree type)
+{
+  tree field;
+  tree tmp;
+
+  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
+  gcc_assert (DATA_FIELD == 0);
+  field = TYPE_FIELDS (type);
+
+  /* Set a NULL data pointer.  */
+  tmp = build_constructor_single (type, field, null_pointer_node);
+  TREE_CONSTANT (tmp) = 1;
+  /* All other fields are ignored.  */
+
+  return tmp;
+}
+
+
+/* Obtain offsets for trans-types.cc(gfc_get_array_descr_info).  */
+
+void
+gfc_get_descriptor_offsets_for_info (const_tree desc_type, tree *data_off,
+                                    tree *dtype_off, tree *span_off,
+                                    tree *dim_off, tree *dim_size,
+                                    tree *stride_suboff, tree *lower_suboff,
+                                    tree *upper_suboff)
+{
+  tree field;
+  tree type;
+
+  type = TYPE_MAIN_VARIANT (desc_type);
+  field = gfc_advance_chain (TYPE_FIELDS (type), DATA_FIELD);
+  *data_off = byte_position (field);
+  field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);
+  *dtype_off = byte_position (field);
+  field = gfc_advance_chain (TYPE_FIELDS (type), SPAN_FIELD);
+  *span_off = byte_position (field);
+  field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);
+  *dim_off = byte_position (field);
+  type = TREE_TYPE (TREE_TYPE (field));
+  *dim_size = TYPE_SIZE_UNIT (type);
+  field = gfc_advance_chain (TYPE_FIELDS (type), STRIDE_SUBFIELD);
+  *stride_suboff = byte_position (field);
+  field = gfc_advance_chain (TYPE_FIELDS (type), LBOUND_SUBFIELD);
+  *lower_suboff = byte_position (field);
+  field = gfc_advance_chain (TYPE_FIELDS (type), UBOUND_SUBFIELD);
+  *upper_suboff = byte_position (field);
+}
+
+
+/* Cleanup those #defines.  */
+
+#undef DATA_FIELD
+#undef OFFSET_FIELD
+#undef DTYPE_FIELD
+#undef SPAN_FIELD
+#undef DIMENSION_FIELD
+#undef CAF_TOKEN_FIELD
+#undef STRIDE_SUBFIELD
+#undef LBOUND_SUBFIELD
+#undef UBOUND_SUBFIELD
diff --git a/gcc/fortran/trans-descriptor.h b/gcc/fortran/trans-descriptor.h
new file mode 100644
index 000000000000..f60a32c7131c
--- /dev/null
+++ b/gcc/fortran/trans-descriptor.h
@@ -0,0 +1,67 @@
+/* Copyright (C) 2002-2025 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+tree gfc_get_cfi_desc_base_addr (tree desc);
+tree gfc_get_cfi_desc_elem_len (tree desc);
+tree gfc_get_cfi_desc_version (tree desc);
+tree gfc_get_cfi_desc_rank (tree desc);
+tree gfc_get_cfi_desc_type (tree desc);
+tree gfc_get_cfi_desc_attribute (tree desc);
+
+tree gfc_get_cfi_dim_lbound (tree desc, tree idx);
+tree gfc_get_cfi_dim_extent (tree desc, tree idx);
+tree gfc_get_cfi_dim_sm (tree desc, tree idx);
+
+
+tree gfc_conv_descriptor_data_addr (tree desc);
+tree gfc_conv_descriptor_dtype (tree desc);
+tree gfc_conv_descriptor_rank (tree desc);
+tree gfc_conv_descriptor_version (tree desc);
+tree gfc_conv_descriptor_elem_len (tree desc);
+tree gfc_conv_descriptor_attribute (tree desc);
+tree gfc_conv_descriptor_type (tree desc);
+tree gfc_get_descriptor_dimension (tree desc);
+tree gfc_conv_descriptor_dimension (tree desc, tree dim);
+tree gfc_conv_descriptor_token (tree desc);
+tree gfc_conv_descriptor_offset (tree desc);
+
+tree gfc_conv_descriptor_data_get (tree desc);
+tree gfc_conv_descriptor_offset_get (tree desc);
+tree gfc_conv_descriptor_span_get (tree desc);
+
+tree gfc_conv_descriptor_stride_get (tree desc, tree dim);
+tree gfc_conv_descriptor_lbound_get (tree desc, tree dim);
+tree gfc_conv_descriptor_ubound_get (tree desc, tree dim);
+
+void gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value);
+void gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc, tree 
value);
+void gfc_conv_descriptor_span_set (stmtblock_t *block, tree desc, tree value);
+void gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc, tree dim, 
tree value);
+void gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc, tree dim, 
tree value);
+void gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc, tree dim, 
tree value);
+
+tree gfc_build_null_descriptor (tree type);
+
+void
+gfc_get_descriptor_offsets_for_info (const_tree desc_type, tree *data_off,
+                                    tree *dtype_off, tree *span_off,
+                                    tree *dim_off, tree *dim_size,
+                                    tree *stride_suboff, tree *lower_suboff,
+                                    tree *upper_suboff);
+

Reply via email to