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)
endMy 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 ?