This is an archive of the discontinued LLVM Phabricator instance.

[flang][docs] Add lowering design doc for polymorphic entities
ClosedPublic

Authored by clementval on Aug 9 2022, 11:58 AM.

Details

Summary

This document aims to give insights at the representation of polymorphic
entities in FIR and how polymorphic related constructs and features are lowered
to FIR.

Diff Detail

Event Timeline

clementval created this revision.Aug 9 2022, 11:58 AM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptAug 9 2022, 11:58 AM
clementval requested review of this revision.Aug 9 2022, 11:58 AM
razvanlupusoru accepted this revision.Aug 15 2022, 7:57 AM
razvanlupusoru added a subscriber: razvanlupusoru.

The design looks very well thought out and solid! I especially like that you added FIR syntax for allowing possibility to replace dynamic calls beyond the frontend. I have looked through this design document in detail and it is all sensible. This is great!

This revision is now accepted and ready to land.Aug 15 2022, 7:57 AM
schweitz added inline comments.
flang/docs/PolymorphicEntities.md
56

Why do you need a new type?

58

That's not a real distinction, since box type allowed this.

schweitz added inline comments.Aug 15 2022, 8:14 AM
flang/docs/PolymorphicEntities.md
109

Again, not sure why a new type is needed here. What is the semantic difference between this and !fir.type<none>?

492

Invalid type trees will be caught in the front end's semantics checking, right?

clementval marked 4 inline comments as done.Aug 15 2022, 8:50 AM
clementval added inline comments.
flang/docs/PolymorphicEntities.md
56

First of all it will make the IR cleaner and also there are some cases where we would need to be able to distinguish between CLASS(T) and TYPE(T)

Taking an example brought be @jeanPerier in one of our discussion:

module m
  type t
    integer :: i
  contains
   procedure, nopass :: p => foo
  end type
contains
subroutine foo()
  print *, "I am foo"
end subroutine

subroutine non_polymorphic(x)
  type(t) :: x(:)
  ! Could be simplified to call foo() after inlining of polymorphic(x)
  call polymorphic(x)
end subroutine

subroutine polymorphic(x)
  type(t) :: x(:)
  call x%p()
end subroutine
end module

If we do "manual inlining at the Fortran level" of the polymorphic in non_polymorphic, we would write the following, and x%p would be resolved to foo since x is a TYPE(t):

subroutine non_polymorphic(x)
  type(t) :: x(:)
  call x%p
end subroutine

If we do not have the fir.class type the current representation would be:

func.func @_QMmPnon_polymorphic(%arg0: !fir.box<!fir.array<?x!fir.type<_QMmTt{i:i32}>>> {fir.bindc_name = "x"}) {
  fir.call @_QMmPpolymorphic(%arg0) : (!fir.box<!fir.array<?x!fir.type<_QMmTt{i:i32}>>>) -> ()
  return
}

func.func @_QMmPpolymorphic(%arg0: !fir.box<!fir.array<?x!fir.type<_QMmTt{i:i32}>>> {fir.bindc_name = "x"}) {
  %1 = fir.dispatch "p"(%arg0) : (!fir.box<!fir.array<?x!fir.type<_QMmTt{i:i32}>>>) -> () {fir.nopass}
  return
}

And with this representation, the best we can hope after inlining in _QMmPnon_polymorphic is:

func.func @_QMmPnon_polymorphic(%arg0: !fir.box<!fir.array<?x!fir.type<_QMmTt{i:i32}>>> {fir.bindc_name = "x"}) {
  %1 = fir.dispatch "p"(%arg0) : (!fir.box<!fir.array<?x!fir.type<_QMmTt{i:i32}>>>) -> ()
  return
}

There is no way to tell that %arg0 dynamic type must be _QMmTt here since we cannot assume that the dynamic type inside a !fir.box is the one from the fir.type (otherwise, FIR would badly resolve the dispatch in _QMmPpolymorphic since the context/information is exactly the same as in this new _QMmPnon_polymorphic).

It also gives information to some FIR operations that need it. See the fir.load part below in the document.

Also it helps to make the difference between CLASS(*) and TYPE(*).

58

You are right, it does allow it but here the fir.class kind of mark the entities as a polymorphic one and helps to deals with this kind of entities in some FIR operations.

109

It was more suggested as a syntactic sugar but we can stick with !fir.type<none> as well.

492

Yes. Listing it here is for the sake of completeness.

klausler accepted this revision.Aug 15 2022, 8:56 AM
This revision was automatically updated to reflect the committed changes.
clementval marked 4 inline comments as done.
rouson added a subscriber: rouson.Sep 14 2022, 7:09 PM
rouson added inline comments.
flang/docs/PolymorphicEntities.md
3

To be more specific, I would write the following:

A polymorphic entity is a data entity that can be of different dynamic type during the

51

type(*) entities are also polymorphic. Does FIR represented type(*) entries as a class type?

106

The standard refers to type(*) entities as unlimited polymorphic so possibly this needs to be edited to say, "It's not part of polymorphic entities in FIR..."

clementval marked 3 inline comments as done.Sep 18 2022, 11:54 PM
clementval added inline comments.
flang/docs/PolymorphicEntities.md
3

Feel free to send an update for this.

51

No they are represented with fir.type.

106

I'll update this.