LCOV - code coverage report
Current view: top level - gcc/fortran - trans-descriptor.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 99.2 % 374 371
Test Date: 2026-09-12 16:25:28 Functions: 100.0 % 59 59
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Copyright (C) 2002-2025 Free Software Foundation, Inc.
       2              : 
       3              : This file is part of GCC.
       4              : 
       5              : GCC is free software; you can redistribute it and/or modify it under
       6              : the terms of the GNU General Public License as published by the Free
       7              : Software Foundation; either version 3, or (at your option) any later
       8              : version.
       9              : 
      10              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : for more details.
      14              : 
      15              : You should have received a copy of the GNU General Public License
      16              : along with GCC; see the file COPYING3.  If not see
      17              : <http://www.gnu.org/licenses/>.  */
      18              : 
      19              : 
      20              : #include "config.h"
      21              : #include "system.h"
      22              : #include "coretypes.h"
      23              : #include "tree.h"
      24              : #include "fold-const.h"
      25              : #include "gfortran.h"
      26              : #include "trans.h"
      27              : #include "trans-const.h"
      28              : #include "trans-types.h"
      29              : #include "trans-array.h"
      30              : 
      31              : 
      32              : /* Array descriptor low level access routines.
      33              :  ******************************************************************************/
      34              : 
      35              : /* Build expressions to access the members of an array descriptor.
      36              :    It's surprisingly easy to mess up here, so never access
      37              :    an array descriptor by "brute force", always use these
      38              :    functions.  This also avoids problems if we change the format
      39              :    of an array descriptor.
      40              : 
      41              :    To understand these magic numbers, look at the comments
      42              :    before gfc_build_array_type() in trans-types.cc.
      43              : 
      44              :    The code within these defines should be the only code which knows the format
      45              :    of an array descriptor.
      46              : 
      47              :    Any code just needing to read obtain the bounds of an array should use
      48              :    gfc_conv_array_* rather than the following functions as these will return
      49              :    know constant values, and work with arrays which do not have descriptors.
      50              : 
      51              :    Don't forget to #undef these!  */
      52              : 
      53              : #define DATA_FIELD 0
      54              : #define OFFSET_FIELD 1
      55              : #define DTYPE_FIELD 2
      56              : #define SPAN_FIELD 3
      57              : #define DIMENSION_FIELD 4
      58              : #define CAF_TOKEN_FIELD 5
      59              : 
      60              : #define STRIDE_SUBFIELD 0
      61              : #define LBOUND_SUBFIELD 1
      62              : #define UBOUND_SUBFIELD 2
      63              : 
      64              : #define GFC_DTYPE_ELEM_LEN 0
      65              : #define GFC_DTYPE_VERSION 1
      66              : #define GFC_DTYPE_RANK 2
      67              : #define GFC_DTYPE_TYPE 3
      68              : #define GFC_DTYPE_ATTRIBUTE 4
      69              : 
      70              : 
      71              : /* Get FIELD_IDX'th field in struct TYPE.  */
      72              : 
      73              : static tree
      74      2081461 : get_type_field (tree type, unsigned field_idx)
      75              : {
      76      2081461 :   tree field = gfc_advance_chain (TYPE_FIELDS (type), field_idx);
      77      2081461 :   gcc_assert (field != NULL_TREE);
      78              : 
      79      2081461 :   return field;
      80              : }
      81              : 
      82              : 
      83              : /* Return a reference to the FIELD_IDX-th field of the descriptor DESC.  */
      84              : 
      85              : static tree
      86      2081233 : gfc_get_descriptor_field (tree desc, unsigned field_idx)
      87              : {
      88      2081233 :   tree type = TREE_TYPE (desc);
      89      2081233 :   gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
      90              : 
      91      2081233 :   tree field = get_type_field (type, field_idx);
      92              : 
      93      2081233 :   return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
      94      2081233 :                           desc, field, NULL_TREE);
      95              : }
      96              : 
      97              : 
      98              : /* Return a reference to the data field of the array descriptor DESC.  */
      99              : 
     100              : static tree
     101       459204 : conv_descriptor_data (tree desc)
     102              : {
     103            0 :   return gfc_get_descriptor_field (desc, DATA_FIELD);
     104              : }
     105              : 
     106              : /* This provides READ-ONLY access to the data field.  The field itself
     107              :    doesn't have the proper type.  */
     108              : 
     109              : tree
     110       295236 : gfc_conv_descriptor_data_get (tree desc)
     111              : {
     112       295236 :   tree type = TREE_TYPE (desc);
     113       295236 :   if (TREE_CODE (type) == REFERENCE_TYPE)
     114            0 :     gcc_unreachable ();
     115              : 
     116       295236 :   tree data = conv_descriptor_data (desc);
     117       295236 :   return fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), data);
     118              : }
     119              : 
     120              : /* This provides WRITE access to the data field.  */
     121              : 
     122              : void
     123       163968 : gfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value)
     124              : {
     125       163968 :   tree data = conv_descriptor_data (desc);
     126       163968 :   gfc_add_modify (block, data, fold_convert (TREE_TYPE (data), value));
     127       163968 : }
     128              : 
     129              : 
     130              : /* Return a reference to the offset field of the array descriptor DESC.  */
     131              : 
     132              : static tree
     133       213037 : conv_descriptor_offset (tree desc)
     134              : {
     135       213037 :   tree field = gfc_get_descriptor_field (desc, OFFSET_FIELD);
     136       213037 :   gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
     137       213037 :   return field;
     138              : }
     139              : 
     140              : /* Return the offset value of the array descriptor DESC.  */
     141              : 
     142              : tree
     143        79431 : gfc_conv_descriptor_offset_get (tree desc)
     144              : {
     145        79431 :   return conv_descriptor_offset (desc);
     146              : }
     147              : 
     148              : /* Add code to BLOCK assigning VALUE to the offset field of the array descriptor
     149              :    DESC.  */
     150              : 
     151              : void
     152       133606 : gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc, tree value)
     153              : {
     154       133606 :   tree t = conv_descriptor_offset (desc);
     155       133606 :   gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
     156       133606 : }
     157              : 
     158              : 
     159              : /* Return a reference to the dtype field of the array descriptor DESC.  */
     160              : 
     161              : static tree
     162       181230 : conv_descriptor_dtype (tree desc)
     163              : {
     164       181230 :   tree field = gfc_get_descriptor_field (desc, DTYPE_FIELD);
     165       181230 :   gcc_assert (TREE_TYPE (field) == get_dtype_type_node ());
     166       181230 :   return field;
     167              : }
     168              : 
     169              : /* Return the dtype value of the array descriptor DESC.  */
     170              : 
     171              : tree
     172         3398 : gfc_conv_descriptor_dtype_get (tree desc)
     173              : {
     174         3398 :   return conv_descriptor_dtype (desc);
     175              : }
     176              : 
     177              : /* Add code to BLOCK assigning VALUE to the dtype field of the array descriptor
     178              :    DESC.  */
     179              : 
     180              : void
     181       144337 : gfc_conv_descriptor_dtype_set (stmtblock_t *block, tree desc, tree value)
     182              : {
     183       144337 :   location_t loc = input_location;
     184       144337 :   tree t = conv_descriptor_dtype (desc);
     185       144337 :   gfc_add_modify_loc (loc, block, t,
     186       144337 :                       fold_convert_loc (loc, TREE_TYPE (t), value));
     187       144337 : }
     188              : 
     189              : 
     190              : /* Return a reference to the span field of the array descriptor DESC.  */
     191              : 
     192              : static tree
     193       163377 : conv_descriptor_span (tree desc)
     194              : {
     195       163377 :   tree field = gfc_get_descriptor_field (desc, SPAN_FIELD);
     196       163377 :   gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
     197       163377 :   return field;
     198              : }
     199              : 
     200              : /* Return the span value of the array descriptor DESC.  */
     201              : 
     202              : tree
     203        37720 : gfc_conv_descriptor_span_get (tree desc)
     204              : {
     205        37720 :   return conv_descriptor_span (desc);
     206              : }
     207              : 
     208              : /* Add code to BLOCK assigning VALUE to the span field of the array descriptor
     209              :    DESC.  */
     210              : 
     211              : void
     212       125657 : gfc_conv_descriptor_span_set (stmtblock_t *block, tree desc, tree value)
     213              : {
     214       125657 :   tree t = conv_descriptor_span (desc);
     215       125657 :   gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
     216       125657 : }
     217              : 
     218              : 
     219              : /* Return a reference to the rank field of the array descriptor DESC.  */
     220              : 
     221              : static tree
     222        22713 : conv_descriptor_rank (tree desc)
     223              : {
     224        22713 :   tree tmp;
     225        22713 :   tree dtype;
     226              : 
     227        22713 :   dtype = conv_descriptor_dtype (desc);
     228        22713 :   tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_RANK);
     229        22713 :   gcc_assert (tmp != NULL_TREE
     230              :               && TREE_TYPE (tmp) == gfc_array_dim_rank_type);
     231        22713 :   return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
     232        22713 :                           dtype, tmp, NULL_TREE);
     233              : }
     234              : 
     235              : /* Return the rank value of the array descriptor DESC.  */
     236              : 
     237              : tree
     238        21849 : gfc_conv_descriptor_rank_get (tree desc)
     239              : {
     240        21849 :   return conv_descriptor_rank (desc);
     241              : }
     242              : 
     243              : /* Add code to BLOCK assigning VALUE to the rank field of the array descriptor
     244              :    DESC.  */
     245              : 
     246              : void
     247          864 : gfc_conv_descriptor_rank_set (stmtblock_t *block, tree desc, tree value)
     248              : {
     249          864 :   location_t loc = input_location;
     250          864 :   tree t = conv_descriptor_rank (desc);
     251          864 :   gfc_add_modify_loc (loc, block, t,
     252          864 :                       fold_convert_loc (loc, TREE_TYPE (t), value));
     253          864 : }
     254              : 
     255              : /* Add code to BLOCK assigning VALUE to the rank field of the array descriptor
     256              :    DESC.  */
     257              : 
     258              : void
     259          277 : gfc_conv_descriptor_rank_set (stmtblock_t *block, tree desc, int value)
     260              : {
     261          277 :   gfc_conv_descriptor_rank_set (block, desc, gfc_rank_cst[value]);
     262          277 : }
     263              : 
     264              : 
     265              : /* Return a reference to the format version field of the array descriptor
     266              :    DESC.  */
     267              : 
     268              : static tree
     269          127 : conv_descriptor_version (tree desc)
     270              : {
     271          127 :   tree tmp;
     272          127 :   tree dtype;
     273              : 
     274          127 :   dtype = conv_descriptor_dtype (desc);
     275          127 :   tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_VERSION);
     276          127 :   gcc_assert (tmp != NULL_TREE
     277              :               && TREE_TYPE (tmp) == integer_type_node);
     278          127 :   return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
     279          127 :                           dtype, tmp, NULL_TREE);
     280              : }
     281              : 
     282              : /* Return the format version value of the array descriptor DESC.  */
     283              : 
     284              : tree
     285           48 : gfc_conv_descriptor_version_get (tree desc)
     286              : {
     287           48 :   return conv_descriptor_version (desc);
     288              : }
     289              : 
     290              : /* Add code to BLOCK assigning VALUE to the format version field of the array
     291              :    descriptor DESC.  */
     292              : 
     293              : void
     294           79 : gfc_conv_descriptor_version_set (stmtblock_t *block, tree desc, tree value)
     295              : {
     296           79 :   location_t loc = input_location;
     297           79 :   tree t = conv_descriptor_version (desc);
     298           79 :   gfc_add_modify_loc (loc, block, t,
     299           79 :                       fold_convert_loc (loc, TREE_TYPE (t), value));
     300           79 : }
     301              : 
     302              : 
     303              : /* Return a reference to the element length field of the array descriptor
     304              :    DESC.  */
     305              : 
     306              : static tree
     307        10468 : conv_descriptor_elem_len (tree desc)
     308              : {
     309        10468 :   tree tmp;
     310        10468 :   tree dtype;
     311              : 
     312        10468 :   dtype = conv_descriptor_dtype (desc);
     313        10468 :   tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)),
     314              :                            GFC_DTYPE_ELEM_LEN);
     315        10468 :   gcc_assert (tmp != NULL_TREE
     316              :               && TREE_TYPE (tmp) == size_type_node);
     317        10468 :   return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
     318        10468 :                           dtype, tmp, NULL_TREE);
     319              : }
     320              : 
     321              : /* Return the element length value of the array descriptor DESC.  */
     322              : 
     323              : tree
     324        10034 : gfc_conv_descriptor_elem_len_get (tree desc)
     325              : {
     326        10034 :   return conv_descriptor_elem_len (desc);
     327              : }
     328              : 
     329              : /* Add code to BLOCK assigning VALUE to the element length field of the array
     330              :    descriptor DESC.  */
     331              : 
     332              : void
     333          434 : gfc_conv_descriptor_elem_len_set (stmtblock_t *block, tree desc, tree value)
     334              : {
     335          434 :   location_t loc = input_location;
     336          434 :   tree t = conv_descriptor_elem_len (desc);
     337          434 :   gfc_add_modify_loc (loc, block, t,
     338          434 :                       fold_convert_loc (loc, TREE_TYPE (t), value));
     339          434 : }
     340              : 
     341              : 
     342              : /* Return a reference to the type discriminator field of the array descriptor
     343              :    DESC.  */
     344              : 
     345              : static tree
     346          187 : conv_descriptor_type (tree desc)
     347              : {
     348          187 :   tree tmp;
     349          187 :   tree dtype;
     350              : 
     351          187 :   dtype = conv_descriptor_dtype (desc);
     352          187 :   tmp = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (dtype)), GFC_DTYPE_TYPE);
     353          187 :   gcc_assert (tmp!= NULL_TREE
     354              :               && TREE_TYPE (tmp) == signed_char_type_node);
     355          187 :   return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (tmp),
     356          187 :                           dtype, tmp, NULL_TREE);
     357              : }
     358              : 
     359              : /* Return the type discriminator value of the array descriptor DESC.  */
     360              : 
     361              : tree
     362           54 : gfc_conv_descriptor_type_get (tree desc)
     363              : {
     364           54 :   return conv_descriptor_type (desc);
     365              : }
     366              : 
     367              : /* Add code to BLOCK assigning VALUE to the type discriminator field of the
     368              :    array descriptor DESC.  */
     369              : 
     370              : void
     371          133 : gfc_conv_descriptor_type_set (stmtblock_t *block, tree desc, tree value)
     372              : {
     373          133 :   location_t loc = input_location;
     374          133 :   tree t = conv_descriptor_type (desc);
     375          133 :   gfc_add_modify_loc (loc, block, t,
     376          133 :                       fold_convert_loc (loc, TREE_TYPE (t), value));
     377          133 : }
     378              : 
     379              : /* Add code to BLOCK assigning VALUE to the type discriminator field of the
     380              :    array descriptor DESC.  */
     381              : 
     382              : void
     383          114 : gfc_conv_descriptor_type_set (stmtblock_t *block, tree desc, int value)
     384              : {
     385          114 :   tree type = TREE_TYPE (desc);
     386          114 :   gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
     387              : 
     388          114 :   tree dtype = get_type_field (type, DTYPE_FIELD);
     389          114 :   tree field = get_type_field (TREE_TYPE (dtype), GFC_DTYPE_TYPE);
     390          114 :   tree type_value = build_int_cst (TREE_TYPE (field), value);
     391              : 
     392          114 :   gfc_conv_descriptor_type_set (block, desc, type_value);
     393          114 : }
     394              : 
     395              : /* Return a statement assigning VALUE to the type discriminator field of the
     396              :    array descriptor DESC.  */
     397              : 
     398              : tree
     399           19 : gfc_conv_descriptor_type_set (tree desc, tree value)
     400              : {
     401           19 :   stmtblock_t block;
     402              : 
     403           19 :   gfc_init_block (&block);
     404           19 :   gfc_conv_descriptor_type_set (&block, desc, value);
     405           19 :   return gfc_finish_block (&block);
     406              : }
     407              : 
     408              : /* Return a statement assigning VALUE to the type discriminator field of the
     409              :    array descriptor DESC.  */
     410              : 
     411              : tree
     412          114 : gfc_conv_descriptor_type_set (tree desc, int value)
     413              : {
     414          114 :   stmtblock_t block;
     415              : 
     416          114 :   gfc_init_block (&block);
     417          114 :   gfc_conv_descriptor_type_set (&block, desc, value);
     418          114 :   return gfc_finish_block (&block);
     419              : }
     420              : 
     421              : 
     422              : /* Return a reference to the array of dimension descriptors of the array
     423              :    descriptor DESC.  */
     424              : 
     425              : tree
     426      1061957 : gfc_get_descriptor_dimension (tree desc)
     427              : {
     428      1061957 :   tree field = gfc_get_descriptor_field (desc, DIMENSION_FIELD);
     429      1061957 :   gcc_assert (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
     430              :               && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);
     431      1061957 :   return field;
     432              : }
     433              : 
     434              : 
     435              : /* Return a reference to the dimension descriptor for the (zero-based) dimension
     436              :    DIM of the array descriptor DESC.  */
     437              : 
     438              : static tree
     439      1057703 : conv_descriptor_dimension (tree desc, tree dim)
     440              : {
     441      1057703 :   tree tmp;
     442              : 
     443      1057703 :   tmp = gfc_get_descriptor_dimension (desc);
     444              : 
     445      1057703 :   return gfc_build_array_ref (tmp, dim, NULL_TREE, true);
     446              : }
     447              : 
     448              : 
     449              : /* Return a reference to the coarray token field of the array descriptor
     450              :    DESC.  */
     451              : 
     452              : tree
     453         2428 : gfc_conv_descriptor_token (tree desc)
     454              : {
     455         2428 :   gcc_assert (flag_coarray == GFC_FCOARRAY_LIB);
     456         2428 :   tree field = gfc_get_descriptor_field (desc, CAF_TOKEN_FIELD);
     457              :   /* Should be a restricted pointer - except in the finalization wrapper.  */
     458         2428 :   gcc_assert (TREE_TYPE (field) == prvoid_type_node
     459              :               || TREE_TYPE (field) == pvoid_type_node);
     460         2428 :   return field;
     461              : }
     462              : 
     463              : /* Add code to BLOCK assigning VALUE to the coarray token field of the array
     464              :    descriptor DESC.  */
     465              : 
     466              : void
     467          597 : gfc_conv_descriptor_token_set (stmtblock_t *block, tree desc, tree value)
     468              : {
     469          597 :   location_t loc = input_location;
     470          597 :   tree t = gfc_conv_descriptor_token (desc);
     471          597 :   gfc_add_modify_loc (loc, block, t,
     472          597 :                       fold_convert_loc (loc, TREE_TYPE (t), value));
     473          597 : }
     474              : 
     475              : 
     476              : /* Return a reference to the FIELD_IDX'th subfield of the dimension descriptor
     477              :    of the (zero-based) dimension DIM of the array descriptor DESC.  */
     478              : 
     479              : static tree
     480      1057703 : gfc_conv_descriptor_subfield (tree desc, tree dim, unsigned field_idx)
     481              : {
     482      1057703 :   tree tmp = conv_descriptor_dimension (desc, dim);
     483      1057703 :   tree field = gfc_advance_chain (TYPE_FIELDS (TREE_TYPE (tmp)), field_idx);
     484      1057703 :   gcc_assert (field != NULL_TREE);
     485              : 
     486      1057703 :   return fold_build3_loc (input_location, COMPONENT_REF, TREE_TYPE (field),
     487      1057703 :                           tmp, field, NULL_TREE);
     488              : }
     489              : 
     490              : 
     491              : /* Return a reference to the stride field of the (zero-based) dimension DIM of
     492              :    the array descriptor DESC.  */
     493              : 
     494              : static tree
     495       282374 : conv_descriptor_stride (tree desc, tree dim)
     496              : {
     497       282374 :   tree field = gfc_conv_descriptor_subfield (desc, dim, STRIDE_SUBFIELD);
     498       282374 :   gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
     499       282374 :   return field;
     500              : }
     501              : 
     502              : /* Return the stride value for the (zero-based) dimension DIM of the array
     503              :    descriptor DESC.  */
     504              : 
     505              : tree
     506       174899 : gfc_conv_descriptor_stride_get (tree desc, tree dim)
     507              : {
     508       174899 :   tree type = TREE_TYPE (desc);
     509       174899 :   gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
     510       174899 :   if (integer_zerop (dim)
     511       174899 :       && (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE
     512        45314 :           || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE_CONT
     513        44227 :           || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_CONT
     514        44071 :           || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_ALLOCATABLE
     515        43921 :           || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_POINTER_CONT
     516        43921 :           || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT))
     517        74065 :     return gfc_index_one_node;
     518              : 
     519       100834 :   return conv_descriptor_stride (desc, dim);
     520              : }
     521              : 
     522              : /* Add code to BLOCK assigning VALUE to the stride field of the (zero-based)
     523              :    dimension DIM of the array descriptor DESC.  */
     524              : 
     525              : void
     526       181540 : gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
     527              :                                 tree dim, tree value)
     528              : {
     529       181540 :   tree t = conv_descriptor_stride (desc, dim);
     530       181540 :   gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
     531       181540 : }
     532              : 
     533              : 
     534              : /* Return a reference to the lower bound field of the (zero-based) dimension DIM
     535              :    of the array descriptor DESC.  */
     536              : 
     537              : static tree
     538       402433 : conv_descriptor_lbound (tree desc, tree dim)
     539              : {
     540       402433 :   tree field = gfc_conv_descriptor_subfield (desc, dim, LBOUND_SUBFIELD);
     541       402433 :   gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
     542       402433 :   return field;
     543              : }
     544              : 
     545              : /* Return the lower bound value for the (zero-based) dimension DIM of the array
     546              :    descriptor DESC.  */
     547              : 
     548              : tree
     549       215984 : gfc_conv_descriptor_lbound_get (tree desc, tree dim)
     550              : {
     551       215984 :   return conv_descriptor_lbound (desc, dim);
     552              : }
     553              : 
     554              : /* Add code to BLOCK assigning VALUE to the lower bound field of the
     555              :    (zero-based) dimension DIM of the array descriptor DESC.  */
     556              : 
     557              : void
     558       186449 : gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
     559              :                                 tree dim, tree value)
     560              : {
     561       186449 :   tree t = conv_descriptor_lbound (desc, dim);
     562       186449 :   gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
     563       186449 : }
     564              : 
     565              : 
     566              : /* Return a reference to the upper bound field of the (zero-based) dimension DIM
     567              :    of the array descriptor DESC.  */
     568              : 
     569              : static tree
     570       372896 : conv_descriptor_ubound (tree desc, tree dim)
     571              : {
     572       372896 :   tree field = gfc_conv_descriptor_subfield (desc, dim, UBOUND_SUBFIELD);
     573       372896 :   gcc_assert (TREE_TYPE (field) == gfc_array_index_type);
     574       372896 :   return field;
     575              : }
     576              : 
     577              : /* Return the upper bound value for the (zero-based) dimension DIM of the array
     578              :    descriptor DESC.  */
     579              : 
     580              : tree
     581       186731 : gfc_conv_descriptor_ubound_get (tree desc, tree dim)
     582              : {
     583       186731 :   return conv_descriptor_ubound (desc, dim);
     584              : }
     585              : 
     586              : /* Add code to BLOCK assigning VALUE to the upper bound field of the
     587              :    (zero-based) dimension DIM of the array descriptor DESC.  */
     588              : 
     589              : void
     590       186165 : gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
     591              :                                 tree dim, tree value)
     592              : {
     593       186165 :   tree t = conv_descriptor_ubound (desc, dim);
     594       186165 :   gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
     595       186165 : }
     596              : 
     597              : 
     598              : /* Obtain offsets for trans-types.cc(gfc_get_array_descr_info).  */
     599              : 
     600              : void
     601       280856 : gfc_get_descriptor_offsets_for_info (const_tree desc_type, tree *data_off,
     602              :                                      tree *rank_off, tree *span_off,
     603              :                                      tree *dim_off, tree *dim_size,
     604              :                                      tree *stride_suboff, tree *lower_suboff,
     605              :                                      tree *upper_suboff)
     606              : {
     607       280856 :   tree field;
     608       280856 :   tree type;
     609              : 
     610       280856 :   type = TYPE_MAIN_VARIANT (desc_type);
     611       280856 :   tree fields = TYPE_FIELDS (type);
     612       280856 :   field = gfc_advance_chain (fields, DATA_FIELD);
     613       280856 :   *data_off = byte_position (field);
     614       280856 :   field = gfc_advance_chain (fields, DTYPE_FIELD);
     615       280856 :   tree dtype_off = byte_position (field);
     616       280856 :   type = TREE_TYPE (field);
     617       280856 :   field = gfc_advance_chain (TYPE_FIELDS (type), GFC_DTYPE_RANK);
     618       280856 :   tree rank_suboff = byte_position (field);
     619       280856 :   *rank_off = fold_build2 (PLUS_EXPR, TREE_TYPE (dtype_off), dtype_off,
     620              :                            rank_suboff);
     621       280856 :   field = gfc_advance_chain (fields, SPAN_FIELD);
     622       280856 :   *span_off = byte_position (field);
     623       280856 :   field = gfc_advance_chain (fields, DIMENSION_FIELD);
     624       280856 :   *dim_off = byte_position (field);
     625       280856 :   type = TREE_TYPE (TREE_TYPE (field));
     626       280856 :   *dim_size = TYPE_SIZE_UNIT (type);
     627       280856 :   field = gfc_advance_chain (TYPE_FIELDS (type), STRIDE_SUBFIELD);
     628       280856 :   *stride_suboff = byte_position (field);
     629       280856 :   field = gfc_advance_chain (TYPE_FIELDS (type), LBOUND_SUBFIELD);
     630       280856 :   *lower_suboff = byte_position (field);
     631       280856 :   field = gfc_advance_chain (TYPE_FIELDS (type), UBOUND_SUBFIELD);
     632       280856 :   *upper_suboff = byte_position (field);
     633       280856 : }
     634              : 
     635              : 
     636              : /* Array descriptor higher level routines.
     637              :  ******************************************************************************/
     638              : 
     639              : /* Return a constructor for a descriptor dtype with the caracteristics given by
     640              :    the arguments.  */
     641              : 
     642              : tree
     643       145806 : gfc_build_dtype_constructor (tree size, int type, int rank)
     644              : {
     645       145806 :   tree field;
     646       145806 :   vec<constructor_elt, va_gc> *v = NULL;
     647              : 
     648       145806 :   gcc_assert (size);
     649              : 
     650       145806 :   STRIP_NOPS (size);
     651       145806 :   size = fold_convert (size_type_node, size);
     652       145806 :   tree dtype_type_node = get_dtype_type_node ();
     653       145806 :   field = gfc_advance_chain (TYPE_FIELDS (dtype_type_node),
     654              :                              GFC_DTYPE_ELEM_LEN);
     655       145806 :   CONSTRUCTOR_APPEND_ELT (v, field,
     656              :                           fold_convert (TREE_TYPE (field), size));
     657       145806 :   field = gfc_advance_chain (TYPE_FIELDS (dtype_type_node),
     658              :                              GFC_DTYPE_VERSION);
     659       145806 :   CONSTRUCTOR_APPEND_ELT (v, field,
     660              :                           build_zero_cst (TREE_TYPE (field)));
     661              : 
     662       145806 :   field = gfc_advance_chain (TYPE_FIELDS (dtype_type_node),
     663              :                              GFC_DTYPE_RANK);
     664       145806 :   if (rank >= 0)
     665       145219 :     CONSTRUCTOR_APPEND_ELT (v, field,
     666              :                             build_int_cst (TREE_TYPE (field), rank));
     667              : 
     668       145806 :   field = gfc_advance_chain (TYPE_FIELDS (dtype_type_node),
     669              :                              GFC_DTYPE_TYPE);
     670       145806 :   CONSTRUCTOR_APPEND_ELT (v, field,
     671              :                           build_int_cst (TREE_TYPE (field), type));
     672              : 
     673       145806 :   return build_constructor (dtype_type_node, v);
     674              : }
     675              : 
     676              : 
     677              : /* Build a null array descriptor constructor.  */
     678              : 
     679              : tree
     680         1124 : gfc_build_null_descriptor (tree type)
     681              : {
     682         1124 :   tree field;
     683         1124 :   tree tmp;
     684              : 
     685         1124 :   gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
     686         1124 :   gcc_assert (DATA_FIELD == 0);
     687         1124 :   field = TYPE_FIELDS (type);
     688              : 
     689              :   /* Set a NULL data pointer.  */
     690         1124 :   tmp = build_constructor_single (type, field, null_pointer_node);
     691         1124 :   TREE_CONSTANT (tmp) = 1;
     692              :   /* All other fields are ignored.  */
     693              : 
     694         1124 :   return tmp;
     695              : }
     696              : 
     697              : 
     698              : /* Cleanup those #defines.  */
     699              : 
     700              : #undef DATA_FIELD
     701              : #undef OFFSET_FIELD
     702              : #undef DTYPE_FIELD
     703              : #undef SPAN_FIELD
     704              : #undef DIMENSION_FIELD
     705              : #undef CAF_TOKEN_FIELD
     706              : 
     707              : #undef STRIDE_SUBFIELD
     708              : #undef LBOUND_SUBFIELD
     709              : #undef UBOUND_SUBFIELD
     710              : 
     711              : #undef GFC_DTYPE_ELEM_LEN
     712              : #undef GFC_DTYPE_VERSION
     713              : #undef GFC_DTYPE_RANK
     714              : #undef GFC_DTYPE_TYPE
     715              : #undef GFC_DTYPE_ATTRIBUTE
     716              : 
     717              : 
     718              : /* Add code to BLOCK implementing the pointer assigment from NULL() to the
     719              :    pointer represented by the array descriptor DESCR.  */
     720              : 
     721              : void
     722          692 : gfc_nullify_descriptor (stmtblock_t *block, tree descr)
     723              : {
     724          692 :   gfc_conv_descriptor_data_set (block, descr, null_pointer_node);
     725          692 : }
     726              : 
     727              : 
     728              : /* Add code to BLOCK default-initializing array function result descriptor
     729              :    DESCR.  This is used for the initialization of polymorphic allocatable
     730              :    function results.  */
     731              : 
     732              : void
     733           34 : gfc_init_result_descriptor (stmtblock_t *block, tree descr)
     734              : {
     735           34 :   gfc_conv_descriptor_data_set (block, descr, null_pointer_node);
     736           34 : }
     737              : 
     738              : 
     739              : /* Add code to BLOCK initializing array descriptor DESCR so that it represents
     740              :    an absent actual argument associated with an optional dummy.  */
     741              : 
     742              : void
     743          696 : gfc_init_absent_descriptor (stmtblock_t *block, tree descr)
     744              : {
     745          696 :   gfc_conv_descriptor_data_set (block, descr, null_pointer_node);
     746          696 : }
     747              : 
     748              : 
     749              : /* Add code to BLOCK initializing the array descriptor DESCR corresponding to
     750              :    the array variable SYM.  This is only used for variables needing a default
     751              :    initialization of their descriptor.  Typically allocatable (array) variables,
     752              :    that have an initial status of unallocated, are among them; they need their
     753              :    data pointer set to nullptr.  */
     754              : 
     755              : void
     756        12029 : gfc_init_descriptor_variable (stmtblock_t *block, gfc_symbol *sym, tree descr)
     757              : {
     758              :   /* NULLIFY the data pointer for non-saved allocatables, or for non-saved
     759              :      pointers when -fcheck=pointer is specified.  */
     760        12029 :   if (!sym->attr.save
     761        12016 :       && (sym->attr.allocatable
     762         3285 :           || (sym->attr.pointer && (gfc_option.rtcheck & GFC_RTCHECK_POINTER))))
     763              :     {
     764         8774 :       gfc_conv_descriptor_data_set (block, descr, null_pointer_node);
     765         8774 :       if (flag_coarray == GFC_FCOARRAY_LIB && sym->attr.codimension)
     766          171 :         gfc_conv_descriptor_token_set (block, descr, null_pointer_node);
     767              :     }
     768              : 
     769        12029 :   gcc_assert (sym->as && sym->as->rank>=0);
     770        12029 :   tree etype = gfc_get_element_type (TREE_TYPE (descr));
     771        12029 :   gfc_conv_descriptor_dtype_set (block, descr,
     772        12029 :                                  gfc_get_dtype_rank_type (sym->as->rank,
     773              :                                                           etype));
     774        12029 : }
     775              : 
     776              : 
     777              : /* Create a fresh array descriptor copied from SOURCE_DESCR, with a cleared data
     778              :    pointer and a possibly different dtype value.  Set the dtype field to DTYPE
     779              :    if different from NULL_TREE; otherwise set it with a default value built
     780              :    using SOURCE_DESCR's type.  Add the copying code and any other initialization
     781              :    to BLOCK and return the descriptor declaration.
     782              : 
     783              :    The descriptor created by this function is used to pass to intrinsic
     784              :    functions from the library, when the result is assigned to a reallocatable
     785              :    variable.  The left hand side variable descriptor is not passed directly to
     786              :    the library, and the unallocated descriptor this function creates is passed
     787              :    instead.  Allocation happens in the library; deallocation of the left hand
     788              :    side variable data, if any, and correct bounds mapping happen outside the
     789              :    library, after the function returns.  */
     790              : 
     791              : tree
     792         2137 : gfc_create_unallocated_library_result_descriptor (stmtblock_t *block,
     793              :                                                   tree source_descr, tree dtype)
     794              : {
     795              :   /* Unallocated, the descriptor does not have a dtype.  */
     796         2137 :   if (dtype == NULL_TREE)
     797         2124 :     dtype = gfc_get_dtype (TREE_TYPE (source_descr));
     798              : 
     799         2137 :   gfc_conv_descriptor_dtype_set (block, source_descr, dtype);
     800              : 
     801         2137 :   tree res_desc = gfc_evaluate_now (source_descr, block);
     802         2137 :   gfc_conv_descriptor_data_set (block, res_desc, null_pointer_node);
     803              : 
     804         2137 :   return res_desc;
     805              : }
     806              : 
     807              : 
     808              : /* Create a new descriptor to represent a null actual argument of type TS and
     809              :    rank RANK passed to a dummy argument having attributes ATTR.  Add
     810              :    initialization code to BLOCK and return the descriptor declaration.  */
     811              : 
     812              : tree
     813          264 : gfc_create_null_actual_descriptor (stmtblock_t *block, gfc_typespec *ts,
     814              :                                    symbol_attribute attr, int rank)
     815              : {
     816          264 :   tree etype = gfc_typenode_for_spec (ts);
     817              : 
     818          264 :   enum gfc_array_kind akind;
     819              : 
     820          264 :   if (attr.pointer)
     821              :     akind = GFC_ARRAY_POINTER_CONT;
     822           96 :   else if (attr.allocatable)
     823              :     akind = GFC_ARRAY_ALLOCATABLE;
     824              :   else
     825            0 :     akind = GFC_ARRAY_ASSUMED_SHAPE_CONT;
     826              : 
     827          264 :   tree lower[GFC_MAX_DIMENSIONS];
     828          264 :   tree upper[GFC_MAX_DIMENSIONS];
     829          264 :   memset (&lower, 0, rank * sizeof (lower[0]));
     830          264 :   memset (&upper, 0, rank * sizeof (upper[0]));
     831              : 
     832          432 :   tree type = gfc_get_array_type_bounds (etype, rank, 0, lower, upper, 1,
     833              :                                          akind, !(attr.pointer || attr.target));
     834          264 :   tree desc = gfc_create_var (type, "desc");
     835          264 :   DECL_ARTIFICIAL (desc) = 1;
     836              : 
     837          264 :   gfc_conv_descriptor_dtype_set (block, desc,
     838              :                                  gfc_get_dtype_rank_type (rank, etype));
     839          264 :   gfc_conv_descriptor_data_set (block, desc, null_pointer_node);
     840          264 :   gfc_conv_descriptor_span_set (block, desc,
     841              :                                 gfc_conv_descriptor_elem_len_get (desc));
     842              : 
     843          264 :   return desc;
     844              : }
     845              : 
     846              : 
     847              : /* For an array descriptor, get the total number of elements.  This is just
     848              :    the product of the extents along from_dim to to_dim.  */
     849              : 
     850              : static tree
     851         1973 : gfc_conv_descriptor_size_1 (tree desc, int from_dim, int to_dim)
     852              : {
     853         1973 :   tree res;
     854         1973 :   int dim;
     855              : 
     856         1973 :   res = gfc_index_one_node;
     857              : 
     858         4815 :   for (dim = from_dim; dim < to_dim; ++dim)
     859              :     {
     860         2842 :       tree lbound;
     861         2842 :       tree ubound;
     862         2842 :       tree extent;
     863              : 
     864         2842 :       lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
     865         2842 :       ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
     866              : 
     867         2842 :       extent = gfc_conv_array_extent_dim (lbound, ubound, NULL);
     868         2842 :       res = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
     869              :                              res, extent);
     870              :     }
     871              : 
     872         1973 :   return res;
     873              : }
     874              : 
     875              : 
     876              : /* Full size of an array.  */
     877              : 
     878              : tree
     879         1909 : gfc_conv_descriptor_size (tree desc, int rank)
     880              : {
     881         1909 :   return gfc_conv_descriptor_size_1 (desc, 0, rank);
     882              : }
     883              : 
     884              : 
     885              : /* Size of a coarray for all dimensions but the last.  */
     886              : 
     887              : tree
     888           64 : gfc_conv_descriptor_cosize (tree desc, int rank, int corank)
     889              : {
     890           64 :   return gfc_conv_descriptor_size_1 (desc, rank, rank + corank - 1);
     891              : }
     892              : 
     893              : 
     894              : /* Modify a descriptor such that the lbound of a given dimension is the value
     895              :    specified.  This also updates ubound and offset accordingly.  */
     896              : 
     897              : void
     898         1009 : gfc_conv_shift_descriptor_lbound (stmtblock_t* block, tree desc,
     899              :                                   int dim, tree new_lbound)
     900              : {
     901         1009 :   tree offs, ubound, lbound, stride;
     902         1009 :   tree diff, offs_diff;
     903              : 
     904         1009 :   new_lbound = fold_convert (gfc_array_index_type, new_lbound);
     905              : 
     906         1009 :   offs = gfc_conv_descriptor_offset_get (desc);
     907         1009 :   lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[dim]);
     908         1009 :   ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[dim]);
     909         1009 :   stride = gfc_conv_descriptor_stride_get (desc, gfc_rank_cst[dim]);
     910              : 
     911              :   /* Get difference (new - old) by which to shift stuff.  */
     912         1009 :   diff = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
     913              :                           new_lbound, lbound);
     914              : 
     915              :   /* Shift ubound and offset accordingly.  This has to be done before
     916              :      updating the lbound, as they depend on the lbound expression!  */
     917         1009 :   ubound = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
     918              :                             ubound, diff);
     919         1009 :   gfc_conv_descriptor_ubound_set (block, desc, gfc_rank_cst[dim], ubound);
     920         1009 :   offs_diff = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
     921              :                                diff, stride);
     922         1009 :   offs = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
     923              :                           offs, offs_diff);
     924         1009 :   gfc_conv_descriptor_offset_set (block, desc, offs);
     925              : 
     926              :   /* Finally set lbound to value we want.  */
     927         1009 :   gfc_conv_descriptor_lbound_set (block, desc, gfc_rank_cst[dim], new_lbound);
     928         1009 : }
     929              : 
     930              : 
     931              : void
     932         1778 : gfc_copy_descriptor (stmtblock_t *block, tree dst, tree src, int rank)
     933              : {
     934         1778 :   int n;
     935         1778 :   tree dim;
     936         1778 :   tree tmp;
     937         1778 :   tree tmp2;
     938         1778 :   tree size;
     939         1778 :   tree offset;
     940              : 
     941         1778 :   offset = gfc_index_zero_node;
     942              : 
     943              :   /* Use memcpy to copy the descriptor.  The size is the minimum of
     944              :      the sizes of 'src' and 'dst'. This avoids a non-trivial conversion.  */
     945         1778 :   tmp = TYPE_SIZE_UNIT (TREE_TYPE (src));
     946         1778 :   tmp2 = TYPE_SIZE_UNIT (TREE_TYPE (dst));
     947         1778 :   size = fold_build2_loc (input_location, MIN_EXPR,
     948         1778 :                           TREE_TYPE (tmp), tmp, tmp2);
     949         1778 :   tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
     950         1778 :   tmp = build_call_expr_loc (input_location, tmp, 3,
     951              :                              gfc_build_addr_expr (NULL_TREE, dst),
     952              :                              gfc_build_addr_expr (NULL_TREE, src),
     953              :                              fold_convert (size_type_node, size));
     954         1778 :   gfc_add_expr_to_block (block, tmp);
     955              : 
     956              :   /* Set the offset correctly.  */
     957         8792 :   for (n = 0; n < rank; n++)
     958              :     {
     959         5236 :       dim = gfc_rank_cst[n];
     960         5236 :       tmp = gfc_conv_descriptor_lbound_get (src, dim);
     961         5236 :       tmp2 = gfc_conv_descriptor_stride_get (src, dim);
     962         5236 :       tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
     963              :                              tmp, tmp2);
     964         5236 :       offset = fold_build2_loc (input_location, MINUS_EXPR,
     965         5236 :                         TREE_TYPE (offset), offset, tmp);
     966         5236 :       offset = gfc_evaluate_now (offset, block);
     967              :     }
     968              : 
     969         1778 :   gfc_conv_descriptor_offset_set (block, dst, offset);
     970         1778 : }
     971              : 
     972              : 
     973              : /* Extend the data in array DESC by EXTRA elements.  */
     974              : 
     975              : void
     976         1066 : gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
     977              : {
     978         1066 :   tree arg0, arg1;
     979         1066 :   tree tmp;
     980         1066 :   tree size;
     981         1066 :   tree ubound;
     982              : 
     983         1066 :   if (integer_zerop (extra))
     984              :     return;
     985              : 
     986         1036 :   ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
     987              : 
     988              :   /* Add EXTRA to the upper bound.  */
     989         1036 :   tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
     990              :                          ubound, extra);
     991         1036 :   gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
     992              : 
     993              :   /* Get the value of the current data pointer.  */
     994         1036 :   arg0 = gfc_conv_descriptor_data_get (desc);
     995              : 
     996              :   /* Calculate the new array size.  */
     997         1036 :   size = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
     998         1036 :   tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
     999              :                          ubound, gfc_index_one_node);
    1000         1036 :   arg1 = fold_build2_loc (input_location, MULT_EXPR, size_type_node,
    1001              :                           fold_convert (size_type_node, tmp),
    1002              :                           fold_convert (size_type_node, size));
    1003              : 
    1004              :   /* Call the realloc() function.  */
    1005         1036 :   tmp = gfc_call_realloc (pblock, arg0, arg1);
    1006         1036 :   gfc_conv_descriptor_data_set (pblock, desc, tmp);
    1007              : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.