Create and use first-versions.h with macros for function symbol versions

Message ID alpine.DEB.2.20.1704210912040.7114@digraph.polyomino.org.uk
State New
Headers show

Commit Message

Joseph Myers April 21, 2017, 9:13 a.m.
This patch arranges for the glibc build to generate a header
first-versions.h that defines macros for the earliest symbol version
in which each public symbol (GLIBC_[0-9]* symbol version, name only
uses C identifier characters) is available.

This is used in sysdeps/ieee754/ldbl-opt/math-type-macros-double.h to
replace the manually defined LDOUBLE_*_libm_version macros for various
functions defined using type-generic templates, the purpose of which
is to use in LONG_DOUBLE_COMPAT tests "was this function originally
added before glibc supported long double != double on this platform?".
As discussed in
<https://sourceware.org/ml/libc-alpha/2016-12/msg00246.html>, I expect
this to be useful more generally in reducing the amount of
special-case code needed in ldbl-opt and ldbl-64-128.

Tested with build-many-glibcs.py that installed stripped shared
libraries are unchanged by this patch.

2017-04-21  Joseph Myers  <joseph@codesourcery.com>

	* scripts/versions.awk: Generate first-versions.h.
	* sysdeps/ieee754/ldbl-opt/math-type-macros-double.h: Include
	<first-versions.h>.
	(LDOUBLE_cabsl_libm_version): Remove macro.
	(LDOUBLE_cargl_libm_version): Likewise.
	(LDOUBLE_cimagl_libm_version): Likewise.
	(LDOUBLE_conjl_libm_version): Likewise.
	(LDOUBLE_creall_libm_version): Likewise.
	(LDOUBLE_cacosl_libm_version): Likewise.
	(LDOUBLE_cacoshl_libm_version): Likewise.
	(LDOUBLE_ccosl_libm_version): Likewise.
	(LDOUBLE_ccoshl_libm_version): Likewise.
	(LDOUBLE_casinl_libm_version): Likewise.
	(LDOUBLE_csinl_libm_version): Likewise.
	(LDOUBLE_casinhl_libm_version): Likewise.
	(LDOUBLE_csinhl_libm_version): Likewise.
	(LDOUBLE_catanl_libm_version): Likewise.
	(LDOUBLE_catanhl_libm_version): Likewise.
	(LDOUBLE_ctanl_libm_version): Likewise.
	(LDOUBLE_ctanhl_libm_version): Likewise.
	(LDOUBLE_cexpl_libm_version): Likewise.
	(LDOUBLE_clogl_libm_version): Likewise.
	(LDOUBLE_cprojl_libm_version): Likewise.
	(LDOUBLE_csqrtl_libm_version): Likewise.
	(LDOUBLE_cpowl_libm_version): Likewise.
	(LDOUBLE_clog10l_libm_version): Likewise.
	(LDOUBLE___clog10l_libm_version): Likewise.
	(LDOUBLE_fdiml_libm_version): Likewise.
	(LDOUBLE_fmaxl_libm_version): Likewise.
	(LDOUBLE_fminl_libm_version): Likewise.
	(LDOUBLE_ilogbl_libm_version): Likewise.
	(LDOUBLE_nanl_libm_version): Likewise.
	[!M_LIBM_NEED_COMPAT] (M_LIBM_NEED_COMPAT): Use
	FIRST_VERSION_libm_* macros.
	[!declare_mgen_libm_compat] (declare_mgen_libm_compat): Likewise.
	* Makerules [$(build-shared) = yes && !avoid-generated]
	(before-compile): Add $(common-objpfx)first-versions.h.
	[$(build-shared) = yes && !avoid-generated]
	($(common-objpfx)first-versions.h): New target.
	($(common-objpfx)sysd-versions): Depend on and change to rule for
	building $(common-objpfx)versions.stmp.

Comments

Florian Weimer April 21, 2017, 9:22 a.m. | #1
On 04/21/2017 11:13 AM, Joseph Myers wrote:
> This patch arranges for the glibc build to generate a header
> first-versions.h that defines macros for the earliest symbol version
> in which each public symbol (GLIBC_[0-9]* symbol version, name only
> uses C identifier characters) is available.

Is this the version used in the fourth argument to the compat_symbol 
macro?  Maybe we can use this mechanism to remove that argument, too, to 
avoid potential mistakes there?

Thanks,
Florian
Joseph Myers April 21, 2017, 9:31 a.m. | #2
On Fri, 21 Apr 2017, Florian Weimer wrote:

> On 04/21/2017 11:13 AM, Joseph Myers wrote:
> > This patch arranges for the glibc build to generate a header
> > first-versions.h that defines macros for the earliest symbol version
> > in which each public symbol (GLIBC_[0-9]* symbol version, name only
> > uses C identifier characters) is available.
> 
> Is this the version used in the fourth argument to the compat_symbol macro?

Not necessarily.  It's possible for a function to have three or more 
versions (or two versions, both of which are compat symbols), in which 
case the fourth argument to compat_symbol, when creating the second and 
later compat versions, will not be the same as the version number in this 
header.

It's true that in many cases there will only be one compat version of a 
function, in which case the version from this header is the right one to 
use with compat_symbol, so we could have a common-case compat_symbol 
variant that takes fewer arguments.  Of course, the conditioning 
SHLIB_COMPAT calls also involve a second version that varies per symbol - 
the version in which the previous symbol variant was obsoleted - but in 
the long double cases I'm simplifying, that version is always 
LONG_DOUBLE_COMPAT_VERSION.
Andreas Schwab April 21, 2017, 12:45 p.m. | #3
On Apr 21 2017, Joseph Myers <joseph@codesourcery.com> wrote:

> This patch arranges for the glibc build to generate a header
> first-versions.h that defines macros for the earliest symbol version
> in which each public symbol (GLIBC_[0-9]* symbol version, name only
> uses C identifier characters) is available.
>
> This is used in sysdeps/ieee754/ldbl-opt/math-type-macros-double.h to
> replace the manually defined LDOUBLE_*_libm_version macros for various
> functions defined using type-generic templates, the purpose of which
> is to use in LONG_DOUBLE_COMPAT tests "was this function originally
> added before glibc supported long double != double on this platform?".

This won't always be the first version of a symbol, so the first version
can be non-fitting.

Andreas.
Joseph Myers April 21, 2017, 3:42 p.m. | #4
On Fri, 21 Apr 2017, Andreas Schwab wrote:

> On Apr 21 2017, Joseph Myers <joseph@codesourcery.com> wrote:
> 
> > This patch arranges for the glibc build to generate a header
> > first-versions.h that defines macros for the earliest symbol version
> > in which each public symbol (GLIBC_[0-9]* symbol version, name only
> > uses C identifier characters) is available.
> >
> > This is used in sysdeps/ieee754/ldbl-opt/math-type-macros-double.h to
> > replace the manually defined LDOUBLE_*_libm_version macros for various
> > functions defined using type-generic templates, the purpose of which
> > is to use in LONG_DOUBLE_COMPAT tests "was this function originally
> > added before glibc supported long double != double on this platform?".
> 
> This won't always be the first version of a symbol, so the first version
> can be non-fitting.

For all the functions where the FIRST_VERSION_libm_* macros are used by my 
patch (which are functions built from type-generic templates), for all 
platforms currently supported by glibc, the version in question is right 
(as evidenced by unchanged stripped binaries).

For the test "was this function originally added before glibc supported 
long double != double on this platform?", a simple comparison of the first 
version for that function with the version where long double != double 
support *does* always suffice.

It's true that if there was more than one symbol version for long double = 
double before long double != double support was added, then generating the 
compat symbols (as opposed to telling whether any such symbols are needed) 
would be more complicated (that is, the default declare_mgen_libm_compat 
definition would not suffice).  For example, if a platform with long 
double = double were to gain distinct long double support now, the symbol 
versioning support for lgamma might be more complicated.  But for all the 
existing functions using FIRST_VERSION_libm_*, and I think for the vast 
bulk of other libm functions that currently have special ldbl-opt versions 
to handle symbol versioning for such a change, there is only one version 
before that change and so logic based on the first version suffices.
Andreas Schwab April 21, 2017, 6:08 p.m. | #5
On Apr 21 2017, Joseph Myers <joseph@codesourcery.com> wrote:

> For example, if a platform with long double = double were to gain
> distinct long double support now, the symbol versioning support for
> lgamma might be more complicated.

So what's the benefit if it cannot be generalized?

Andreas.
Joseph Myers April 21, 2017, 6:13 p.m. | #6
On Fri, 21 Apr 2017, Andreas Schwab wrote:

> On Apr 21 2017, Joseph Myers <joseph@codesourcery.com> wrote:
> 
> > For example, if a platform with long double = double were to gain
> > distinct long double support now, the symbol versioning support for
> > lgamma might be more complicated.
> 
> So what's the benefit if it cannot be generalized?

It can readily be made to cover the vast bulk of the cases where special 
symbol version handling is needed for each libm function affected by a 
change of long double format, leaving only a limited number of special 
cases that may still need to do things manually.

An underlying objective is to have common macros meaning "set up all the 
aliases and symbol versioning for this binary64 function" or "set up all 
the aliases and symbol versioning for this binary128 function", so that 
changing the definitions of those macros then accomplishes a large part of 
adding TS 18661-3 *f64 / *f128 / *f32x / *f64x aliases.  To achieve that 
goal it doesn't need to cover every last function.
Joseph Myers April 27, 2017, 7:57 p.m. | #7
Ping.  This patch 
<https://sourceware.org/ml/libc-alpha/2017-04/msg00447.html> is pending 
review.
Joseph Myers May 3, 2017, 4:31 p.m. | #8
Ping^2.  This patch 
<https://sourceware.org/ml/libc-alpha/2017-04/msg00447.html> is still 
pending review.
Joseph Myers May 11, 2017, 11:03 a.m. | #9
Ping^3.  This patch 
<https://sourceware.org/ml/libc-alpha/2017-04/msg00447.html> is still 
pending review.
Florian Weimer May 12, 2017, 9:32 a.m. | #10
On 04/21/2017 11:13 AM, Joseph Myers wrote:
> This patch arranges for the glibc build to generate a header
> first-versions.h that defines macros for the earliest symbol version
> in which each public symbol (GLIBC_[0-9]* symbol version, name only
> uses C identifier characters) is available.

This looks okay to me.

Andreas, do you sustain your objections to this patch?

Thanks,
Florian

Patch

diff --git a/Makerules b/Makerules
index 7f0eef8..2ebb8e0 100644
--- a/Makerules
+++ b/Makerules
@@ -105,6 +105,11 @@  $(common-objpfx)%.latest: $(common-objpfx)abi-versions.h
 	sed -n '/ VERSION_$*_/{s/^.*_\([A-Z0-9_]*\).*$$/\1/;h;};$${g;p;}' \
 	    $(common-objpfx)abi-versions.h > $@T
 	mv -f $@T $@
+
+# first-versions.h provides macros used in various symbol versioning
+# macro calls.
+before-compile := $(common-objpfx)first-versions.h $(before-compile)
+$(common-objpfx)first-versions.h: $(common-objpfx)versions.stmp
 endif # avoid-generated
 endif # $(build-shared) = yes
 
@@ -458,7 +463,8 @@  $(common-objpfx)Versions.all: $(..)scripts/firstversions.awk \
 $(common-objpfx)Versions.v.i: $(wildcard $(subdirs:%=$(..)%/Versions)) \
 			      $(wildcard $(sysdirs:%=%/Versions)) \
 			      $(sysd-versions-force)
-$(common-objpfx)sysd-versions: $(common-objpfx)Versions.all \
+$(common-objpfx)sysd-versions: $(common-objpfx)versions.stmp
+$(common-objpfx)versions.stmp: $(common-objpfx)Versions.all \
 			       $(common-objpfx)Versions.v \
 			       $(..)scripts/versions.awk
 	( echo 'sysd-versions-subdirs = $(subdirs) $(config-sysdirs)' ; \
@@ -466,8 +472,9 @@  $(common-objpfx)sysd-versions: $(common-objpfx)Versions.all \
 	  | LC_ALL=C $(AWK) -v buildroot=$(common-objpfx) -v defsfile=$< \
 			    -v move_if_change='$(move-if-change)' \
 			    -f $(word 3,$^); \
-	) > $@T
-	mv -f $@T $@
+	) > $(common-objpfx)sysd-versionsT
+	mv -f $(common-objpfx)sysd-versionsT $(common-objpfx)sysd-versions
+	touch $@
 endif # avoid-generated
 endif # $(build-shared) = yes
 endif # sysd-sorted-done
diff --git a/scripts/versions.awk b/scripts/versions.awk
index df33529..df08d06 100644
--- a/scripts/versions.awk
+++ b/scripts/versions.awk
@@ -101,6 +101,10 @@  END {
 
   oldlib = "";
   oldver = "";
+  real_first_ver_header = buildroot "first-versions.h"
+  first_ver_header = real_first_ver_header "T"
+  printf("#ifndef _FIRST_VERSIONS_H\n") > first_ver_header;
+  printf("#define _FIRST_VERSIONS_H\n") > first_ver_header;
   printf("version-maps =");
   while (getline < tmpfile) {
     if ($1 != oldlib) {
@@ -127,11 +131,24 @@  END {
     printf("   ") > outfile;
     for (n = 3; n <= NF; ++n) {
       printf(" %s", $n) > outfile;
+      sym = $n;
+      sub(";", "", sym);
+      first_ver_macro = "FIRST_VERSION_" oldlib "_" sym;
+      if (!(first_ver_macro in first_ver_seen) \
+	  && oldver ~ "^GLIBC_[0-9]" \
+	  && sym ~ "^[A-Za-z0-9_]*$") {
+	ver_val = oldver;
+	gsub("\\.", "_", ver_val);
+	printf("#define %s %s\n", first_ver_macro, ver_val) > first_ver_header;
+	first_ver_seen[first_ver_macro] = 1;
+      }
     }
     printf("\n") > outfile;
   }
   printf("\n");
+  printf("#endif /* first-versions.h */\n") > first_ver_header;
   closeversion(oldver, veryoldver);
   close_and_move(outfile, real_outfile);
+  close_and_move(first_ver_header, real_first_ver_header);
   #system("rm -f " tmpfile);
 }
diff --git a/sysdeps/ieee754/ldbl-opt/math-type-macros-double.h b/sysdeps/ieee754/ldbl-opt/math-type-macros-double.h
index a83c2b3..67b5268 100644
--- a/sysdeps/ieee754/ldbl-opt/math-type-macros-double.h
+++ b/sysdeps/ieee754/ldbl-opt/math-type-macros-double.h
@@ -19,48 +19,19 @@ 
 #ifndef _MATH_TYPE_MACROS_DOUBLE
 
 #include <math_ldbl_opt.h>
-
-#define LDOUBLE_cabsl_libm_version GLIBC_2_1
-#define LDOUBLE_cargl_libm_version GLIBC_2_1
-#define LDOUBLE_cimagl_libm_version GLIBC_2_1
-#define LDOUBLE_conjl_libm_version GLIBC_2_1
-#define LDOUBLE_creall_libm_version GLIBC_2_1
-#define LDOUBLE_cacosl_libm_version GLIBC_2_1
-#define LDOUBLE_cacoshl_libm_version GLIBC_2_1
-#define LDOUBLE_ccosl_libm_version GLIBC_2_1
-#define LDOUBLE_ccoshl_libm_version GLIBC_2_1
-#define LDOUBLE_casinl_libm_version GLIBC_2_1
-#define LDOUBLE_csinl_libm_version GLIBC_2_1
-#define LDOUBLE_casinhl_libm_version GLIBC_2_1
-#define LDOUBLE_csinhl_libm_version GLIBC_2_1
-#define LDOUBLE_catanl_libm_version GLIBC_2_1
-#define LDOUBLE_catanhl_libm_version GLIBC_2_1
-#define LDOUBLE_ctanl_libm_version GLIBC_2_1
-#define LDOUBLE_ctanhl_libm_version GLIBC_2_1
-#define LDOUBLE_cexpl_libm_version GLIBC_2_1
-#define LDOUBLE_clogl_libm_version GLIBC_2_1
-#define LDOUBLE_cprojl_libm_version GLIBC_2_1
-#define LDOUBLE_csqrtl_libm_version GLIBC_2_1
-#define LDOUBLE_cpowl_libm_version GLIBC_2_1
-#define LDOUBLE_clog10l_libm_version GLIBC_2_1
-#define LDOUBLE___clog10l_libm_version GLIBC_2_1
-#define LDOUBLE_fdiml_libm_version GLIBC_2_1
-#define LDOUBLE_fmaxl_libm_version GLIBC_2_1
-#define LDOUBLE_fminl_libm_version GLIBC_2_1
-#define LDOUBLE_ilogbl_libm_version GLIBC_2_0
-#define LDOUBLE_nanl_libm_version GLIBC_2_1
+#include <first-versions.h>
 
 /* Define compat symbols for long double on platforms
    where it was not always a distinct type.  */
 #if !defined M_LIBM_NEED_COMPAT
 # define M_LIBM_NEED_COMPAT(f) \
-  LONG_DOUBLE_COMPAT (libm, LDOUBLE_ ## f ## l_libm_version)
+  LONG_DOUBLE_COMPAT (libm, FIRST_VERSION_libm_ ## f ## l)
 #endif
 
 #if !defined declare_mgen_libm_compat
 # define declare_mgen_libm_compat(from, to)	      \
   compat_symbol (libm, from, to ## l,		      \
-		 LDOUBLE_ ## to ## l_libm_version);
+		 FIRST_VERSION_libm_ ## to ## l);
 #endif
 
 #include_next <math-type-macros-double.h>