https://gcc.gnu.org/g:195f86fb212fe08920bc5eb42a2481bcd8447003
commit 195f86fb212fe08920bc5eb42a2481bcd8447003 Author: Mikael Morin <mik...@gcc.gnu.org> Date: Wed Jul 23 17:07:24 2025 +0200 Extraction gfc_conv_remap_descriptor Diff: --- gcc/fortran/trans-descriptor.cc | 104 ++++++++++++++++++++++++++++++++++++++++ gcc/fortran/trans-descriptor.h | 3 +- gcc/fortran/trans-expr.cc | 2 + 3 files changed, 108 insertions(+), 1 deletion(-) diff --git a/gcc/fortran/trans-descriptor.cc b/gcc/fortran/trans-descriptor.cc index 61752f087b59..e72720967e6d 100644 --- a/gcc/fortran/trans-descriptor.cc +++ b/gcc/fortran/trans-descriptor.cc @@ -1047,3 +1047,107 @@ gfc_copy_sequence_descriptor (stmtblock_t *block, tree dest, tree src, int rank) gfc_conv_descriptor_offset_set (block, dest, gfc_index_zero_node); } + +void +gfc_conv_remap_descriptor (stmtblock_t *block, tree dest, int dest_rank, + tree src, int src_rank, gfc_array_ref *ar) +{ + /* Set dtype. */ + gfc_conv_descriptor_dtype_set (block, dest, + gfc_get_dtype (TREE_TYPE (dest))); + + /* Copy data pointer. */ + gfc_conv_descriptor_data_set (block, dest, + gfc_conv_descriptor_data_get (src)); + + /* Copy the span. */ + tree span; + if (VAR_P (src) + && GFC_DECL_PTR_ARRAY_P (src)) + span = gfc_conv_descriptor_span_get (src); + else + { + tree tmp = TREE_TYPE (src); + tmp = TYPE_SIZE_UNIT (gfc_get_element_type (tmp)); + span = fold_convert (gfc_array_index_type, tmp); + } + gfc_conv_descriptor_span_set (block, dest, span); + + /* Copy offset but adjust it such that it would correspond + to a lbound of zero. */ + if (src_rank == -1) + gfc_conv_descriptor_offset_set (block, dest, + gfc_index_zero_node); + else + { + tree offs = gfc_conv_descriptor_offset_get (src); + for (int dim = 0; dim < src_rank; ++dim) + { + tree stride = gfc_conv_descriptor_stride_get (src, gfc_rank_cst[dim]); + tree lbound = gfc_conv_descriptor_lbound_get (src, gfc_rank_cst[dim]); + tree tmp = fold_build2_loc (input_location, MULT_EXPR, + gfc_array_index_type, stride, lbound); + offs = fold_build2_loc (input_location, PLUS_EXPR, + gfc_array_index_type, offs, tmp); + } + gfc_conv_descriptor_offset_set (block, dest, offs); + } + + /* Set the bounds as declared for the LHS and calculate strides as + well as another offset update accordingly. */ + tree stride = gfc_conv_descriptor_stride_get (src, gfc_rank_cst[0]); + for (int dim = 0; dim < dest_rank; ++dim) + { + gfc_se lower_se; + gfc_se upper_se; + + gcc_assert (ar->start[dim] && ar->end[dim]); + + if (ar->start[dim]->expr_type != EXPR_CONSTANT + || ar->start[dim]->expr_type != EXPR_VARIABLE) + gfc_resolve_expr (ar->start[dim]); + if (ar->end[dim]->expr_type != EXPR_CONSTANT + || ar->end[dim]->expr_type != EXPR_VARIABLE) + gfc_resolve_expr (ar->end[dim]); + + /* Convert declared bounds. */ + gfc_init_se (&lower_se, NULL); + gfc_init_se (&upper_se, NULL); + gfc_conv_expr (&lower_se, ar->start[dim]); + gfc_conv_expr (&upper_se, ar->end[dim]); + + gfc_add_block_to_block (block, &lower_se.pre); + gfc_add_block_to_block (block, &upper_se.pre); + + tree lbound = fold_convert (gfc_array_index_type, lower_se.expr); + tree ubound = fold_convert (gfc_array_index_type, upper_se.expr); + + lbound = gfc_evaluate_now (lbound, block); + ubound = gfc_evaluate_now (ubound, block); + + gfc_add_block_to_block (block, &lower_se.post); + gfc_add_block_to_block (block, &upper_se.post); + + /* Set bounds in descriptor. */ + gfc_conv_descriptor_lbound_set (block, dest, gfc_rank_cst[dim], lbound); + gfc_conv_descriptor_ubound_set (block, dest, gfc_rank_cst[dim], ubound); + + /* Set stride. */ + stride = gfc_evaluate_now (stride, block); + gfc_conv_descriptor_stride_set (block, dest, gfc_rank_cst[dim], stride); + + /* Update offset. */ + tree offs = gfc_conv_descriptor_offset_get (dest); + tree tmp = fold_build2_loc (input_location, MULT_EXPR, + gfc_array_index_type, lbound, stride); + offs = fold_build2_loc (input_location, MINUS_EXPR, + gfc_array_index_type, offs, tmp); + offs = gfc_evaluate_now (offs, block); + gfc_conv_descriptor_offset_set (block, dest, offs); + + /* Update stride. */ + tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL); + stride = fold_build2_loc (input_location, MULT_EXPR, + gfc_array_index_type, stride, tmp); + } +} diff --git a/gcc/fortran/trans-descriptor.h b/gcc/fortran/trans-descriptor.h index ac7960589abb..955778a3f412 100644 --- a/gcc/fortran/trans-descriptor.h +++ b/gcc/fortran/trans-descriptor.h @@ -107,6 +107,7 @@ void gfc_conv_shift_descriptor (stmtblock_t *, tree, const gfc_array_ref &); /* Build a null array descriptor constructor. */ void gfc_nullify_descriptor (stmtblock_t *block, tree); void gfc_copy_sequence_descriptor (stmtblock_t *, tree, tree, int); - +void gfc_conv_remap_descriptor (stmtblock_t *, tree, int, tree, int, + gfc_array_ref *); #endif /* GFC_TRANS_DESCRIPTOR_H */ diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 03747e7a5beb..dde4e98986b4 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -11226,6 +11226,8 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) /* Do rank remapping. We already have the RHS's descriptor converted in rse and now have to build the correct LHS descriptor for it. */ + gfc_conv_remap_descriptor (&block, desc, expr1->rank, + rse.expr, expr2->rank, &remap->u.ar); tree data, span; tree offs, stride;