Mikael Morin wrote:
I don't see how I could. The scalarizer's purpose is translating array
statements like foo(:,:) = bar(:,:), where the rank at least is supposed
known, so that we know how many nested loops we have to generate. If
the number of loops is known at runtime only, hem, I don't see what code
we could generate. We could probably produce something with complex
conditions and gotos in a single loop, but it seems to me far too
convoluted, and too big a change, in an area that already doesn't lack
complexity without it.
On the other hand, if I look at what should be supported, it doesn't
look that bad.
Concurred to both.
There are only full array references, so gfc_conv_expr_descriptor with the flag
se->descriptor_only should do the right thing (i.e. nothing).
That looks kind of okay for SHAPE/LBOUND/UBOUND, but we still need to
create a single loop for filling the rank-one array with the values.
Class vs. type should be (correct me if I'm wrong) a matter of
decorating/undecorating with a class container.
No, that's only simple for TYPE -> CLASS.
Additionally, always if CLASS are involved for arrays with descriptor,
it is not that trival: gfortran has "_data, _vptr" in the class
container - and "_data" is the array descriptor. Hence, the offset from
the beginning of the class container to _vptr varies depending on the
size of the descriptor (i.e. its rank). However, with some copying
that's handled by my patch (approved part).
Worsed it the CLASS->TYPE: If the actual type is not the declared type
but one requires that the TYPE is packed ("contiguous" attribute), one
needs to pack the actual argument. That's currently done via the
scalarizer. (It is also done if the dummy is not contiguous as gfortran
only has a stride and not a byte-wise stride multiplier.)
As for the contiguous/non-contiguous matter, I propose using libgfortran's
internal_{,un}pack and away with it.
Hmm, maybe. I have to check the code.
Another item I really want to have implemented, but it is outside the
scope of the TS29113, but extremely handy internally is the following:
subroutine final_subroutine_wrapper (x)
type(t) :: x
if (rank(x) == 3) then
call rank_3_finalizer (x)
else
call scalar_elemental_finalizer (x)
end subroutine
end
Here, one has to walk "x" for the elemental subroutine. Though, it could
be probably simpler than I feared: "x" does not have component or array
references and it is a whole array. Thus, one can probably simple walk
the array by running
do i = 0, element_sizeof(x)-1
call scalar_elemental_finalizer (x->data + i*elem_sizeof(x))
end do
I have to think about issues with regards to contiguity and strides, but
semantically, "x" is contiguous - the question is only whether it can be
noncontiguous, e.g. when calling:
call parent_final_wrapper (x%parent)
One could do it by packing a temporary - we probably have to do so as we
do not have byte strides, otherwise, one could probably avoid it as only
the first stride multiplier matters.
Now about the implementation, I guess the devil is in the details.
I'll see if there is something that I obviously forgot or something to
do in gfc_conv_expr_descriptor. Maybe that one (not the whole
scalarizer) could use a fix.
I will try to generate a stripped down patch, which fixes the issues you
raised and ignores the scalarizer. That will make it easier to look at
the other parts as then the diff is more readable.
Thanks for your thoughts.
Tobias