https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90329

--- Comment #31 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
(In reply to Thomas Koenig from comment #30)
> Hi Jakub,
> 
> > Untested workaround that isn't a too big hammer.  This should just avoid
> > tail calls in functions where the hidden string arguments for
> > character(len=constant) dummy arguments are passed partially or fully on the
> > stack and the callee needs to pass anything on the stack and thus might
> > clobber that.
> 
> Thanks for taking this on!
> 
> Two remarks: It should be possible to have this workaround in place
> only when there is no explicit interface for the called routine.
> No need to penalize modern, correct Fortran for this.

First of all, the thing is that we don't have just caller and callee to
consider in this case, but 3 functions, some C/C++ function (C caller below)
calls incorrectly prototyped (or for C unprototyped) Fortran function (Fortran
caller bellow) and that function calls some other function in a position where
tail call is considered (callee bellow).
I don't see how having a properly interfaced callee (and it doesn't matter if
that one is implemented in Fortran or C or C++ or any other language) matters
to whether we need to do this workaround or not.
The bug is in the incorrect prototype visible in the C caller and the incorrect
(insufficient number) of arguments in that call.
Even if the callee function has proper interface, if we tail call it, we will
clobber the argument area of the Fortran caller in the C caller.
And it doesn't really matter what arguments the callee has, it could very well
be:
subroutine foo (a, b, c, d, e, f)
  character(len=1) :: a
  integer(kind=8) :: b, c, d, e, f
  interface
    subroutine bar (g, h, i, j, k, l, m)
      integer(kind=8) :: g, h, i, j, k, l, m
    end subroutine bar
  end interface
  call bar (b, c, d, e, f, 2, 3)
end subroutine foo
Here if we tail call bar from foo, which we generally on x86_64 can, because
the caller has 6 normal arguments + 1 artificial hidden string length, and
the callee has 7 normal arguments, in both cases 6 go in registers, the 7th in
a stack slot, then the argument stack area is equal size (for tail call it is
enough if the callee stack area is smaller or equal than caller's).

> And I would like to have the Fortran part behind an option, so
> people could disable this pessimization if they start using the
> correct prototypes.

Agreed, just no idea how to call that option and how much to express in the
option name that it is a workaround for undefined behavior.

> Ideally, the compiler could warn about this. It already does so
> if you use -flto, but without LTO, the warning would have to
> be emitted from the C compiler, and I see no even halfway sane
> way of doing it.

This can be diagnosed only with LTO (but it already is I think) or perhaps with
some debug info parsing and analysis tool that would inspect debug info of the
whole app and all libraries and complain.  It is the same thing as
extern int baz (int x, int y);
int foo (int x, int y)
{
  return baz (x + y, 0);
}
in one C TU and
extern int foo (int x);
int bar (void) { return foo (10); }
in another one, we don't diagnose that without LTO either and can't.

Reply via email to