The point is that LAPACK uses characters as control arguments in multiple places and we don't write the LAPACK Fortran routines. It has long been known that general character strings was a portability issue but many (not just R people) have thought that length-one character were safe to pass as char* pointers. So "avoid" is not really an option if we want to use LAPACK functionality at all. Workarounds/solutions include: - disable certain optimizations -- works for now, but doesn't remove the root cause so seems generally fragile - "onion-skin" all LAPACK routines to call via a Fortran routine that converts integer arguments to the required character -- possible, but it adds overhead and there are hundreds of routines (and it would be kind of ugly!). - modify LAPACK itself similarly -- requires naming change of routines as per the license, and there are still hundreds of routines; avoids overhead, but creates maintenance nightmare to keep up with changes in LAPACK - change all prototypes and calls to follow gfortran calling conventions -- still a lot of work since each char* arguments need to be supplemented by a length going at the end of the arglist. If gfortran was the only compiler around, I'd say this would be the least painful route, but still no fun since it requires changes to a lot of user code (in packages too). It is not clear if this approach works with other Fortrans. - figure out Fortran2003 specification for C/Fortran interoperability -- this _sounds_ like the right solution, but I don't think many understand how to use it and what is implied (in particular, will it require making changes to LAPACK itself?) - move towards the LAPACKE C interface -- but that also adds onionskin overhead and ultimately calls Fortran in essentially the same way as R does, so doesn't really solve anything at all (unless we can shift responsibility for sorting things out onto the LAPACK team, but I kind of expect that they do not want it.) - twist the arms of the gfortran team to do something that keeps old code working. Compiler engineers understandably hate that sort of thing, but I seem to recall some precedent (pointer alignment, back in the dark ages?). -pd> On 4 May 2019, at 16:49 , Berend Hasselman <bhh at xs4all.nl> wrote: > > Hi, Thomas, Tomas, > > Doesn't this issue demonstrate the warning and advice given in the last paragraph of section 6.6 > of the "Writing R Extensions" manual: > > <ref> > Passing character strings from C to Fortran or vice versa is not portable (and to Fortran 90 or later is even less so). We have found that it helps to ensure that a C string to be passed is followed by several nuls (and not just the one needed as a C terminator). But for maximal portability character strings in Fortran should be avoided. > </ref> > > Avoid. > > Berend > >> On 3 May 2019, at 19:25, Thomas K?nig <tk at tkoenig.net> wrote: >> >> Hi Tomas, >> >> thanks a lot for your analysis. I have created >> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90329 >> for this, and put you in CC (if your e-mail address >> for GCC bugzilla is still current). >> >> Regards >> >> Thomas >> >> ______________________________________________ >> R-devel at r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel-- Peter Dalgaard, Professor, Center for Statistics, Copenhagen Business School Solbjerg Plads 3, 2000 Frederiksberg, Denmark Phone: (+45)38153501 Office: A 4.23 Email: pd.mes at cbs.dk Priv: PDalgd at gmail.com
Hi Peter, we (the gfortran team) are currently discussing this at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90329 . I invite everybody who has an interest in this topic to take part in the discussion there.> Workarounds/solutions include: > > - disable certain optimizations -- works for now, but doesn't remove the root cause so seems generally fragileThat looks like a short-term solutuion that could work (at least for x86_64 using the standard Unix ABI). And yes, it is fragile. And whatever other solution people come up with, it will still be fragile unless the caller and the callee agree. The root cause is that the Fortran LAPACK routines are called from C via an incompatible call signature.> - "onion-skin" all LAPACK routines to call via a Fortran routine that converts integer arguments to the required character -- possible, but it adds overhead and there are hundreds of routines (and it would be kind of ugly!).I agree.> - modify LAPACK itself similarly -- requires naming change of routines as per the license, and there are still hundreds of routines; avoids overhead, but creates maintenance nightmare to keep up with changes in LAPACKI agree that this is not a preferred option.> - change all prototypes and calls to follow gfortran calling conventions -- still a lot of work since each char* arguments need to be supplemented by a length going at the end of the arglist. If gfortran was the only compiler around, I'd say this would be the least painful route, but still no fun since it requires changes to a lot of user code (in packages too). It is not clear if this approach works with other Fortrans.The interesting thing is that this convention goes back to at least f2c, which was modeled on the very first Unix compiler.> - figure out Fortran2003 specification for C/Fortran interoperability -- this _sounds_ like the right solution, but I don't think many understand how to use it and what is implied (in particular, will it require making changes to LAPACK itself?)That would actually be fairly easy. If you declare the subroutines BIND(C), as in subroutine foo(a,b) BIND(C,name="foo_") real a character*1 b end you will get the calling signature that you already have in your C sources. This also has the advantage of being standards compliant, and would be probably be the preferred method.> - move towards the LAPACKE C interface -- but that also adds onionskin overhead and ultimately calls Fortran in essentially the same way as R does, so doesn't really solve anything at all (unless we can shift responsibility for sorting things out onto the LAPACK team, but I kind of expect that they do not want it.)I suspect that they will hit the issue, too.> - twist the arms of the gfortran team to do something that keeps old code working. Compiler engineers understandably hate that sort of thing, but I seem to recall some precedent (pointer alignment, back in the dark ages?).We're willing to do reasonable things :-) but so far all of the options we have come up with have very serious drawbacks (see the link to the PR at the top). If you come up with a suggestion, we'd be more than happy to look at it. I think the best option would really be to use BIND(C). Regards Thomas
On Sat, May 04, 2019 at 06:05:48PM +0200, peter dalgaard wrote:> > - figure out Fortran2003 specification for C/Fortran interoperability > -- this _sounds_ like the right solution, but I don't think many > understand how to use it and what is implied (in particular, will it > require making changes to LAPACK itself?)This is probably the best solution as it should allow portability to any Fortran processor that supports F2003 or newer standard. See the gtk-fortran project. It has a python program that was used to generate the needed ISO C interfaces. -- Steve
On Sat, May 04, 2019 at 06:42:47PM +0200, Thomas K?nig wrote:> > > - figure out Fortran2003 specification for C/Fortran interoperability > > -- this _sounds_ like the right solution, but I don't think many > > understand how to use it and what is implied (in particular, will > > it require making changes to LAPACK itself?) > > That would actually be fairly easy. If you declare the subroutines > BIND(C), as in > > subroutine foo(a,b) BIND(C,name="foo_") > real a > character*1 b > end > > you will get the calling signature that you already have in your C > sources. > > This also has the advantage of being standards compliant, and would be > probably be the preferred method. >With the caveat that one may need to use the VALUE attribute to account for pass-by-value vs pass-by-reference. -- Steve