Lower call with polymorphic entities to fir.dispatch operation. This patch only
focus one lowering with simple scalar polymorphic entities. A follow-up patch
will deal with allocatble, pointer and array of polymorphic entities as they
require box manipulation for the passed-object.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
flang/lib/Lower/ConvertExpr.cpp | ||
---|---|---|
2756 | What about changing the if (ultimateSymbol.attrs().test(Fortran::semantics::Attr::NOPASS) into if ( std::optional<unsigned> passArg = caller.getPassArgIndex()) { ... (and reverse the regions) so that there is no questions about "*passArg" being safe ? | |
flang/lib/Lower/Mangler.cpp | ||
159 | This may be introducing some weird collision risks. As I understand it, we do not care about the mangling here since dispatch uses the fortran name. I guess you need this because the CallInterface wants to declare some fir.func op that is not actually used. The collision risk I see should be illustrated by the program below that I think will hit a bad convert from fir.ref<f32> to fir.box<> in a piece of code that has nothing to do with your changes. module m type p1 integer :: a integer :: b contains procedure, nopass :: foo => bar end type contains subroutine check_dispatch(p, x) class(p1) :: p real :: x(:) call p%foo(x) end subroutine subroutine bar(x) real :: x(:) end subroutine end module real :: x ! unrelated to foo from module m, yet due to function name clash in MLIR, ! I think it will collide and use the same argument types of bar, ! trying to cast the argument to a fir.box as if the mismatch was a simple implicit interface issue. call foo(x) end My suggestion is to skip the func creation in the CalllerInterface (like this done for function pointers). | |
flang/lib/Optimizer/Builder/FIRBuilder.cpp | ||
472 | OK, the pattern you showed me makes more sense to me now. But this code is broken for now here, right ? How can the new embox get the correct dynamic type from the original fir.coordinate_of fir.class base ? |
flang/lib/Lower/ConvertExpr.cpp | ||
---|---|---|
2756 | Yeah it works too. I'll update it. | |
flang/lib/Lower/Mangler.cpp | ||
159 | Right it was needed only because of the func creation. I'll just skip it. | |
flang/lib/Optimizer/Builder/FIRBuilder.cpp | ||
472 | Yes this is left over from a previous attempt. I'll remove it from this patch and add it back when it is functional. |
flang/lib/Lower/Mangler.cpp | ||
---|---|---|
159 | Using the actual procedure name for mangling should also work and avoid collision. |
Jean is the expert on the content, but I can confirm that all builds and tests correctly and looks good.
flang/lib/Lower/Mangler.cpp | ||
---|---|---|
159 | Why not, but then I think this should use return mangleName(procBinding.symbol(), keepExternalInScope) so that the scope is correctly mangled. Otherwise, I think this may still conflict if you update "bar" in my example above to be called "foo" (BTW, I think you can use the lambda argument directly for the details instead of getting it back from the ultimate symbol). One point where I am less sure of, is what would happen with DEFERRED procedures. They do not exist (the type extending the abstract type will actually define the bindings). So I am not sure if this can lead to some weird scenario. I could not find one, because I think whatever conflicting procedure in that case would be declared before the dispatch call is processed (because it would not be possible to call a procedure with such name with an implicit procedure, and only implicit call lead to "on the fly" func declaration attempts). You might still want to double check this is OK: module m interface subroutine bar(x) real :: x(:) end subroutine end interface type, abstract :: p1 integer :: a integer :: b contains procedure(bar), deferred, nopass :: foo end type contains subroutine check_dispatch(p, x) class(p1) :: p real :: x(:) call p%foo(x) end subroutine subroutine foo(x) real :: x end subroutine end module use m real :: x call foo(x) end |
flang/lib/Lower/Mangler.cpp | ||
---|---|---|
159 | I updated to return mangleName. I'm not finding one either. The above example behave correctly with the current lowering so I guess we should be fine unless we find another corner case. |
What about changing the if (ultimateSymbol.attrs().test(Fortran::semantics::Attr::NOPASS) into if ( std::optional<unsigned> passArg = caller.getPassArgIndex()) { ... (and reverse the regions) so that there is no questions about "*passArg" being safe ?