Message ID | 20180524043553.23569-1-gabriel@inconstante.eti.br |
---|---|
Headers | show |
Series | *printf/*scanf functions for the long double migration on powerpc64le | expand |
I'll comment on general design questions around (1) what the new ABIs should be for IEEE 128-bit long double, (2) how the installed headers should arrange for those ABIs to be used and (3) how those ABIs should be implemented. The general principle is that public APIs that are supported for IBM long double should be supported just the same for IEEE 128-bit long double. This in turn requires corresponding ABIs to be included in glibc. Note that this only applies to ABIs accessible from *public* APIs - generally, ones used via calling functions or macros that are declared in public headers with a name not starting with '_'. For (1), there are several different groups of ABIs that involve long double in some way: (a) ABIs parametrized by floating-point format, (b) ABIs parametrized by floating-point type, (c) ABIs not parametrized by floating-point type, but still involving long double in some way. (a) has already been discussed - these are ABIs such as __issignaling* and __*_finite, and corresponding *f128 versions already exist and are in the implementation namespace, so no new ABI additions are needed to support IEEE 128-bit long double (beyond maybe the odd special case such as __scalf128_finite). (b) has also already been discussed - most of these are libm functions, and while the *f128 versions already exist, there is still a use for adding new versions (such as __*ieee128 or __ieee128_*) as aliases of the *f128 functions, because *f128 aren't in the C11 implementation namespace, and a few such functions that are somewhat obsolescent (but still supported as APIs for long double) so don't have *f128 API variants. There are a few complications to consider there such as whether calls to gammal for IEEE 128-bit long double can map to the same ABI as lgammal (more complicated headers, fewer new ABIs), and similarly whether calls to finitel (and other such legacy classification *functions*) for IEEE 128-bit long double can map to the existing __finitef128 (etc.). There are also libc functions in group (b), some of which already have *f128 variants (e.g. strtof128) and some of which don't because of obsolescence but are still supported APIs (e.g. qecvt). Somewhere between (b) and (c) are the nexttoward functions - parametrized on a floating-point type but with an argument with is always long double (and thus needing special variants and redirection logic for IEEE 128-bit long double - new variants of nexttowardf and nexttoward are needed, while nexttowardl could be redirected to the same function as nextafterl). The main point of the present patch series is functions in class (c), involving long double only implicitly. These are functions in the printf, scanf *and strfmon* families (including, for example, a few functions such as printf_size - not just functions with "..." variable arguments or taking a va_list for such arguments; and note that syslog, for example, is in the printf family for this purpose). Every such public ABI needs a corresponding new ABI variant for IEEE 128-bit long double. Now, the set of such __nldbl_* ABIs for such functions for -mlong-double-64 is a plausible starting point for identifying relevant ABIs. But it's only a starting point: there are functions that are missing __nldbl_* ABIs but should have them, and there are __nldbl_* ABIs for which the need is questionable. For the former, as previously discussed, the printf-like argp.h, err.h and error.h functions, at least, are missing __nldbl_* variants for -mlong-double-64. For reasons explained below, I think fixing this will be needed as part of the preparation for adding IEEE 128-bit long double variants of those functions. For the latter, for example, your patch 4 adds public ABIs for __ieee128___printf_fp, __ieee128__IO_vfprintf and __ieee128_vfprintf. There is certainly no need for __ieee128__IO_vfprintf, since _IO_vfprintf is not declared in any installed header since we stopped installing libio.h. But even if _IO_vfprintf were a public API, it *still* wouldn't need __ieee128__IO_vfprintf, because the semantics of _IO_vfprintf are exactly those of vfprintf, so just having __ieee128_vfprintf suffices. And __printf_fp isn't declared in any installed header, a strong indication that it is not a public API or ABI and so no export of __ieee128___printf_fp is needed either. (The comment in stdio-common/Versions on __printf_fp says "functions used in other libraries", but as far as I can tell it's *not* in fact now used in any other glibc library - and in any case, being used in another glibc library would only justify an export at GLIBC_PRIVATE under current practice.) So the __nldbl_* exports need reviewing to identify which are actually relevant for new long double formats, and my guess is that __nldbl__IO_fprintf __nldbl__IO_printf __nldbl__IO_sprintf __nldbl__IO_sscanf __nldbl__IO_vfprintf __nldbl__IO_vfscanf __nldbl__IO_vsprintf __nldbl___asprintf __nldbl___printf_fp __nldbl___strfmon_l __nldbl___vfscanf __nldbl___vsnprintf __nldbl___vsscanf __nldbl___vstrfmon __nldbl___vstrfmon_l all in fact are not needed for new formats - either because the non-__nldbl versions aren't exported at all (__vstrfrmon, __vstrfmon_l - the __nldbl_* versions exist only for use from libnldbl_nonshared.a, I think), or because the non-__nldbl versions are not actually public APIs (__printf_fp), or because the functions exactly alias variants without __ or _IO_ (and with an __ieee128_ prefix you're automatically in the implementation namespace and so don't need such aliases). Now for (2), the installed headers. We have, for example, libio/bits/stdio-ldbl.h (installed as bits/stdio-ldbl.h), with a series of __LDBL_REDIR_DECL and __LDBL_REDIR1_DECL calls to redirect particular functions to __nldbl_*. My claim is that *the same* headers should be reused, installed under additional conditions, to handle redirections to __ieee128_*. * You'd need to have a different definition of __LDBL_REDIR_DECL that adds the __ieee128_ prefix instead of __nldbl_. * You'd need to change __LDBL_REDIR1_DECL, so that either it takes both the -mlong-double-64 and -mabi=ieeelongdouble function names as arguments, or so that there are two variants (one that gets called with arguments e.g. (scanf, __isoc99_scanf), in the case where __nldbl_ and __ieee128_ are the appropriate prefixes; one that gets called with arguments e.g. (strtold, strtod), as at present, where the second argument is the right name for -mlong-double-64 but __ieee128_ plus the first argument is the right name for -mabi=ieeelongdouble). * And you'd need to change a few calls for cases where I've said above to eliminate ABIs that exist for __nldbl_*, e.g. "__LDBL_REDIR_DECL (__asprintf)", so that it uses the first new variant of __LDBL_REDIR1_DECL to generate calls to __nldbl_asprintf / __ieee128_asprintf, because __ieee128___asprintf wouldn't exist. * Of course where the present includes of these bits/*ldbl.h headers are conditional on __LDBL_COMPAT, you'd need separate header conditions for "compat for long double = double", "long double = IEEE 128" and "*some* remapping of long double names, which might be either of the above, is in effect", and to update all the tests of __LDBL_COMPAT in the existing installed headers. * And you need a few new bits/*ldbl.h headers for argp.h, err.h and error.h. Using a shared mechanism for both __nldbl_* and __ieee128_* is why I said above that fixing the lack of __nldbl_* for those functions is a prerequisite to be able to add __ieee128_* for them. I think doing things that way - shared long double redirection headers, with only the definitions of macros such as __LDBL_REDIR_DECL being different in the new IEEE 128-bit case - is clearly much cleaner than having a separate set of redirection headers for the new case. We've had enough problems in the past with feature test macro tests in *-ldbl.h getting out of sync with those in the including headers, we don't want to add a third place that also needs feature test macro handling kept in sync. (Of course that would mean you can't have redirections for some but not all functions in the installed headers as a transitional state, because such redirections would automatically be present for all or none of the relevant functions.) Now for (3), how the __ieee128_* for printf / scanf / strfmon functions are implemented. As previously discussed, the approach used for many of the __nldbl_* functions, of setting a TLS variable __no_long_double, is not a good one to emulate. But that does not necessarily mean the two sets of functions should be implemented in different ways. The key question to answer is: is the best way to implement __ieee128_* the same as or different from the best way to implement __nldbl_*? If they are the same, changing how __nldbl_* are implemented may well be good preparation for implementing __ieee128_*. Specifically, Zack sent a patch series to move away from __no_long_double to explicit flags passed to internal functions. So if there's some reason why you think such explicit flags are not the best approach for implementing __ieee128_*, but are the best approach for __nldbl_* you need to explain why you think that's the case. Otherwise, if explicit flags would be appropriate for __ieee128_*, it would seem to make sense to work on getting Zack's patches into glibc (for example, updating them for your review comments and reposting them, if he hasn't had time to update them himself) as preparation for __ieee128_* being able to use such flags. (I'm presuming you do think the explicit flags are the right approach for __nldbl_* since you didn't mention otherwise in your reviews of some of Zack's patches.) I note that, for example, __printf_fp *already* supports _Float128. So it really ought not be necessary to build a second copy of it at all, if you can make vfprintf for IEEE 128-bit long double (however implemented) pass appropriate data structures for the existing __printf_fp to behave as required.
Hi, Joseph, Thanks for your detailed reply and explanations... On Thu, 24 May 2018, Joseph Myers wrote: >Now, the set of such __nldbl_* ABIs for such functions for >-mlong-double-64 is a plausible starting point for identifying relevant >ABIs. But it's only a starting point: there are functions that are >missing __nldbl_* ABIs but should have them, and there are __nldbl_* ABIs >for which the need is questionable. > >For the former, as previously discussed, the printf-like argp.h, err.h and >error.h functions, at least, are missing __nldbl_* variants for >-mlong-double-64. For reasons explained below, I think fixing this will >be needed as part of the preparation for adding IEEE 128-bit long double >variants of those functions. > >For the latter, for example, your patch 4 adds public ABIs for >__ieee128___printf_fp, __ieee128__IO_vfprintf and __ieee128_vfprintf. >There is certainly no need for __ieee128__IO_vfprintf, since _IO_vfprintf >is not declared in any installed header since we stopped installing >libio.h. But even if _IO_vfprintf were a public API, it *still* wouldn't >need __ieee128__IO_vfprintf, because the semantics of _IO_vfprintf are >exactly those of vfprintf, so just having __ieee128_vfprintf suffices. Yes, indeed. And you have already explained that before, so, sorry about that (I could try to explain myself saying that I induced myself to error, because I was thinking of additions to the ABI for the *IBM* format, but now I finally understood that even in that case there would be no need for new *_IO_* symbols. Really sorry). >And __printf_fp isn't declared in any installed header, a strong >indication that it is not a public API or ABI and so no export of >__ieee128___printf_fp is needed either. (The comment in >stdio-common/Versions on __printf_fp says "functions used in other >libraries", but as far as I can tell it's *not* in fact now used in any >other glibc library - and in any case, being used in another glibc library >would only justify an export at GLIBC_PRIVATE under current practice.) Yes. Sorry about this, too. >I think doing things that way - shared long double redirection headers, >with only the definitions of macros such as __LDBL_REDIR_DECL being >different in the new IEEE 128-bit case - is clearly much cleaner than >having a separate set of redirection headers for the new case. We've had >enough problems in the past with feature test macro tests in *-ldbl.h >getting out of sync with those in the including headers, we don't want to >add a third place that also needs feature test macro handling kept in >sync. > >(Of course that would mean you can't have redirections for some but not >all functions in the installed headers as a transitional state, because >such redirections would automatically be present for all or none of the >relevant functions.) OK. I'll probably keep this header (stdio-ieee128.h) in a *local branch*, because it allows us to progress in smaller sets of functions. In future patch submissions (before all functions are ready), I'll not send it, but I could make it available if someone wants to test the functions. Then, when all functions are ready, we'll send a patch to do as you suggested (i.e.: one which adjusts bits/stdio-ldbl.h with no extra headers). >Now for (3), how the __ieee128_* for printf / scanf / strfmon functions >are implemented. As previously discussed, the approach used for many of >the __nldbl_* functions, of setting a TLS variable __no_long_double, is >not a good one to emulate. But that does not necessarily mean the two >sets of functions should be implemented in different ways. The key >question to answer is: is the best way to implement __ieee128_* the same >as or different from the best way to implement __nldbl_*? If they are the >same, changing how __nldbl_* are implemented may well be good preparation >for implementing __ieee128_*. > >Specifically, Zack sent a patch series to move away from __no_long_double >to explicit flags passed to internal functions. So if there's some reason >why you think such explicit flags are not the best approach for >implementing __ieee128_*, but are the best approach for __nldbl_* you need >to explain why you think that's the case. Otherwise, if explicit flags >would be appropriate for __ieee128_*, it would seem to make sense to work >on getting Zack's patches into glibc (for example, updating them for your >review comments and reposting them, if he hasn't had time to update them >himself) as preparation for __ieee128_* being able to use such flags. >(I'm presuming you do think the explicit flags are the right approach for >__nldbl_* since you didn't mention otherwise in your reviews of some of >Zack's patches.) You presumed correctly, indeed. I think that Zack's proposal is the right thing to have in the end. However, I also expected that rebuilding these files with -mabi=ieeelongdouble had the advantage of being potentially easier to get right, because I wouldn't need to touch anything from the current implementation. Besides that, I also expect that it will be faster to get done, because it only adds files to the build, and since this is useful for POWER9 users, getting it done sooner than later is something that we need. Taking this "timing" perspective into account and also that there seems to be other problems that would need fixing before Zack's proposal can be fully complete [1], would it be OK to have these functions added as new implementations in a first step? Afterwards, with "timing" concerns out of the way, we could work together (if Zack is OK with that) on the cleanup (for nldbl and ieee128-on-powerpc). [1] https://sourceware.org/ml/libc-alpha/2018-03/msg00554.html >I note that, for example, __printf_fp *already* supports _Float128. So it >really ought not be necessary to build a second copy of it at all, if you >can make vfprintf for IEEE 128-bit long double (however implemented) pass >appropriate data structures for the existing __printf_fp to behave as >required. For the same reason (getting the new format available sooner than later), I thought of starting with a copy of vfprintf (adjusted to use a copy of __printf_fp).
On Mon, 28 May 2018, Gabriel F. T. Gomes wrote: > You presumed correctly, indeed. I think that Zack's proposal is the right > thing to have in the end. However, I also expected that rebuilding these > files with -mabi=ieeelongdouble had the advantage of being potentially > easier to get right, because I wouldn't need to touch anything from the > current implementation. Besides that, I also expect that it will be > faster to get done, because it only adds files to the build, and since this > is useful for POWER9 users, getting it done sooner than later is something > that we need. > > Taking this "timing" perspective into account and also that there seems to > be other problems that would need fixing before Zack's proposal can be > fully complete [1], would it be OK to have these functions added as new > implementations in a first step? Afterwards, with "timing" concerns out > of the way, we could work together (if Zack is OK with that) on the > cleanup (for nldbl and ieee128-on-powerpc). > > [1] https://sourceware.org/ml/libc-alpha/2018-03/msg00554.html I don't think tests for hidden annotation issues (or fixes for existing such issues) are needed in order to make the move to explicit flags here; the patches just need reviewing / updating to follow the rules described at <https://sourceware.org/ml/libc-alpha/2018-03/msg00552.html> for any new internal functions they add. I'm also not convinced that building files twice, and making sure that all calls within those files end up pointed to the new ieee128 internal functions when needed, is any easier to get right than passing explicit flags, and making sure that calls within those files call appropriate other internal functions that take those flags - especially given that Zack's patches already do most of what's required regarding passing those flags around (new work for argp.h / err.h / error.h printf-like functions being needed in any case). So rather than going down the dead-end route of building the files twice and so complicating the subsequent cleanup to use explicit flags, I think the support for explicit flags (along the lines of Zack's patches) should be added first. That is, first in the commit sequence on master. You could of course maintain multiple public branches, one with the latest version of Zack's patches and one with ieee128 patches built on top of that, working on them in parallel and posting for review patches from each branch as and when they are ready, with patches from the ieee128 branch not actually being able to go on master until all the changes they depend on are also in master. Some changes could be independent of both of the above to some extent - for example, the argp.h / err.h / error.h ldbl-opt support, or the header changes to support calling appropriate ieee128 functions on the basis that the actual changes defining new macros to activate the new header code for powerpc64le would go in last of all along with the actual addition of all the new functions to the ABI. So there could be rather more than two branches involved while development is active, all being developed and having patches posted, reviewed and revised in parallel.
On Thu, May 31, 2018 at 5:23 PM, Joseph Myers <joseph@codesourcery.com> wrote: > On Mon, 28 May 2018, Gabriel F. T. Gomes wrote: > >> You presumed correctly, indeed. I think that Zack's proposal is the right >> thing to have in the end. ... > I don't think tests for hidden annotation issues (or fixes for existing > such issues) are needed in order to make the move to explicit flags here; > the patches just need reviewing / updating to follow the rules described > at <https://sourceware.org/ml/libc-alpha/2018-03/msg00552.html> for any > new internal functions they add. For the record, I might not get to it but it is my intention to update my __no_long_double removal patchset this weekend, adding appropriate hidden annotations and addressing any other review comments that are still outstanding. I did write some tests to expose existing issues with missing hidden annotations; the problem was they exposed a _lot_ of missing hidden annotations, and fixing them all, well, that rabbit hole bottomed out at Adhemerval's thread cancellation patches! zw