https://gcc.gnu.org/g:ad9f0cbaac70cc00308c0e1ecfdf8df531048307
commit ad9f0cbaac70cc00308c0e1ecfdf8df531048307 Author: Mikael Morin <mik...@gcc.gnu.org> Date: Tue Jul 22 11:16:59 2025 +0200 Extraction gfc_conv_shift_subarray_descriptor Diff: --- gcc/fortran/trans-descriptor.cc | 83 +++++++++++++++++++++++++++++++++++++++++ gcc/fortran/trans-descriptor.h | 1 + gcc/fortran/trans-expr.cc | 83 +---------------------------------------- 3 files changed, 85 insertions(+), 82 deletions(-) diff --git a/gcc/fortran/trans-descriptor.cc b/gcc/fortran/trans-descriptor.cc index 030d49fba5af..08b7b3087a06 100644 --- a/gcc/fortran/trans-descriptor.cc +++ b/gcc/fortran/trans-descriptor.cc @@ -1491,3 +1491,86 @@ gfc_set_descriptor_with_shape (stmtblock_t *block, tree desc, gfc_conv_descriptor_offset_set (block, desc, offset); } + +void +gfc_set_subarray_descriptor (stmtblock_t *block, tree descr, tree value, + gfc_expr *value_expr) +{ + if (value_expr->expr_type != EXPR_VARIABLE) + gfc_conv_descriptor_data_set (block, value, + null_pointer_node); + + /* We need to know if the argument of a conversion function is a + variable, so that the correct lower bound can be used. */ + gfc_expr *arg = nullptr; + if (value_expr->expr_type == EXPR_FUNCTION + && value_expr->value.function.isym + && value_expr->value.function.isym->conversion + && value_expr->value.function.actual->expr + && value_expr->value.function.actual->expr->expr_type == EXPR_VARIABLE) + arg = value_expr->value.function.actual->expr; + + /* Obtain the array spec of full array references. */ + gfc_array_spec *as; + if (arg) + as = gfc_get_full_arrayspec_from_expr (arg); + else + as = gfc_get_full_arrayspec_from_expr (value_expr); + + /* Shift the lbound and ubound of temporaries to being unity, + rather than zero, based. Always calculate the offset. */ + gfc_conv_descriptor_offset_set (block, descr, gfc_index_zero_node); + tree offset = gfc_conv_descriptor_offset_get (descr); + tree tmp2 = gfc_create_var (gfc_array_index_type, NULL); + + for (int n = 0; n < value_expr->rank; n++) + { + tree span; + tree lbound; + + /* Obtain the correct lbound - ISO/IEC TR 15581:2001 page 9. + TODO It looks as if gfc_conv_expr_descriptor should return + the correct bounds and that the following should not be + necessary. This would simplify gfc_conv_intrinsic_bound + as well. */ + if (as && as->lower[n]) + { + gfc_se lbse; + gfc_init_se (&lbse, NULL); + gfc_conv_expr (&lbse, as->lower[n]); + gfc_add_block_to_block (block, &lbse.pre); + lbound = gfc_evaluate_now (lbse.expr, block); + } + else if (as && arg) + { + tree tmp = gfc_get_symbol_decl (arg->symtree->n.sym); + lbound = gfc_conv_descriptor_lbound_get (tmp, gfc_rank_cst[n]); + } + else if (as) + lbound = gfc_conv_descriptor_lbound_get (descr, gfc_rank_cst[n]); + else + lbound = gfc_index_one_node; + + lbound = fold_convert (gfc_array_index_type, lbound); + + /* Shift the bounds and set the offset accordingly. */ + tree tmp = gfc_conv_descriptor_ubound_get (descr, gfc_rank_cst[n]); + span = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, + tmp, gfc_conv_descriptor_lbound_get (descr, gfc_rank_cst[n])); + tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, + span, lbound); + gfc_conv_descriptor_ubound_set (block, descr, gfc_rank_cst[n], tmp); + gfc_conv_descriptor_lbound_set (block, descr, gfc_rank_cst[n], lbound); + + tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, + gfc_conv_descriptor_lbound_get (descr, + gfc_rank_cst[n]), + gfc_conv_descriptor_stride_get (descr, + gfc_rank_cst[n])); + gfc_add_modify (block, tmp2, tmp); + tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, + offset, tmp2); + gfc_conv_descriptor_offset_set (block, descr, tmp); + } +} + diff --git a/gcc/fortran/trans-descriptor.h b/gcc/fortran/trans-descriptor.h index 467d22511fd3..087864bf664d 100644 --- a/gcc/fortran/trans-descriptor.h +++ b/gcc/fortran/trans-descriptor.h @@ -120,5 +120,6 @@ gfc_set_descriptor (stmtblock_t *block, tree dest, tree src, gfc_expr *src_expr, void gfc_set_contiguous_descriptor (stmtblock_t *, tree, tree, tree); void gfc_set_descriptor_with_shape (stmtblock_t *, tree, tree, gfc_expr *, locus *); +void gfc_set_subarray_descriptor (stmtblock_t *, tree, tree, gfc_expr *); #endif /* GFC_TRANS_DESCRIPTOR_H */ diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 37329ad8d81e..b44a0671d5d5 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -9487,11 +9487,7 @@ gfc_trans_alloc_subarray_assign (tree dest, gfc_component * cm, { gfc_se se; stmtblock_t block; - tree offset; - int n; tree tmp; - tree tmp2; - gfc_array_spec *as; gfc_expr *arg = NULL; gfc_start_block (&block); @@ -9552,84 +9548,7 @@ gfc_trans_alloc_subarray_assign (tree dest, gfc_component * cm, gfc_add_expr_to_block (&block, tmp); gfc_add_block_to_block (&block, &se.post); - if (expr->expr_type != EXPR_VARIABLE) - gfc_conv_descriptor_data_set (&block, se.expr, - null_pointer_node); - - /* We need to know if the argument of a conversion function is a - variable, so that the correct lower bound can be used. */ - if (expr->expr_type == EXPR_FUNCTION - && expr->value.function.isym - && expr->value.function.isym->conversion - && expr->value.function.actual->expr - && expr->value.function.actual->expr->expr_type == EXPR_VARIABLE) - arg = expr->value.function.actual->expr; - - /* Obtain the array spec of full array references. */ - if (arg) - as = gfc_get_full_arrayspec_from_expr (arg); - else - as = gfc_get_full_arrayspec_from_expr (expr); - - /* Shift the lbound and ubound of temporaries to being unity, - rather than zero, based. Always calculate the offset. */ - gfc_conv_descriptor_offset_set (&block, dest, gfc_index_zero_node); - offset = gfc_conv_descriptor_offset_get (dest); - tmp2 =gfc_create_var (gfc_array_index_type, NULL); - - for (n = 0; n < expr->rank; n++) - { - tree span; - tree lbound; - - /* Obtain the correct lbound - ISO/IEC TR 15581:2001 page 9. - TODO It looks as if gfc_conv_expr_descriptor should return - the correct bounds and that the following should not be - necessary. This would simplify gfc_conv_intrinsic_bound - as well. */ - if (as && as->lower[n]) - { - gfc_se lbse; - gfc_init_se (&lbse, NULL); - gfc_conv_expr (&lbse, as->lower[n]); - gfc_add_block_to_block (&block, &lbse.pre); - lbound = gfc_evaluate_now (lbse.expr, &block); - } - else if (as && arg) - { - tmp = gfc_get_symbol_decl (arg->symtree->n.sym); - lbound = gfc_conv_descriptor_lbound_get (tmp, - gfc_rank_cst[n]); - } - else if (as) - lbound = gfc_conv_descriptor_lbound_get (dest, - gfc_rank_cst[n]); - else - lbound = gfc_index_one_node; - - lbound = fold_convert (gfc_array_index_type, lbound); - - /* Shift the bounds and set the offset accordingly. */ - tmp = gfc_conv_descriptor_ubound_get (dest, gfc_rank_cst[n]); - span = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, - tmp, gfc_conv_descriptor_lbound_get (dest, gfc_rank_cst[n])); - tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type, - span, lbound); - gfc_conv_descriptor_ubound_set (&block, dest, - gfc_rank_cst[n], tmp); - gfc_conv_descriptor_lbound_set (&block, dest, - gfc_rank_cst[n], lbound); - - tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type, - gfc_conv_descriptor_lbound_get (dest, - gfc_rank_cst[n]), - gfc_conv_descriptor_stride_get (dest, - gfc_rank_cst[n])); - gfc_add_modify (&block, tmp2, tmp); - tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type, - offset, tmp2); - gfc_conv_descriptor_offset_set (&block, dest, tmp); - } + gfc_set_subarray_descriptor (&block, dest, se.expr, expr); if (arg) {