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.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
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!
flang/docs/PolymorphicEntities.md | ||
---|---|---|
55 | 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(*). | |
57 | 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. | |
108 | It was more suggested as a syntactic sugar but we can stick with !fir.type<none> as well. | |
491 | Yes. Listing it here is for the sake of completeness. |
flang/docs/PolymorphicEntities.md | ||
---|---|---|
4 | 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 | |
52 | type(*) entities are also polymorphic. Does FIR represented type(*) entries as a class type? | |
107 | 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..." |
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