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

Reply via email to