(root)/
gcc-13.2.0/
libquadmath/
update-quadmath.py
       1  #!/usr/bin/python3
       2  # Update libquadmath code from glibc sources.
       3  # Copyright (C) 2018 Free Software Foundation, Inc.
       4  # This file is part of the libquadmath library.
       5  #
       6  # Libquadmath is free software; you can redistribute it and/or
       7  # modify it under the terms of the GNU Lesser General Public
       8  # License as published by the Free Software Foundation; either
       9  # version 2.1 of the License, or (at your option) any later version.
      10  #
      11  # Libquadmath is distributed in the hope that it will be useful,
      12  # but WITHOUT ANY WARRANTY; without even the implied warranty of
      13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14  # Lesser General Public License for more details.
      15  #
      16  # You should have received a copy of the GNU Lesser General Public
      17  # License along with libquadmath; if not, see
      18  # <https://www.gnu.org/licenses/>.
      19  
      20  # Usage: update-quadmath.py glibc_srcdir quadmath_srcdir
      21  
      22  import argparse
      23  from collections import defaultdict
      24  import os.path
      25  import re
      26  
      27  
      28  def replace_in_file(repl_map, extra_map, src, dest):
      29      """Apply the replacements in repl_map, then those in extra_map, to the
      30      file src, producing dest."""
      31      with open(src, 'r') as src_file:
      32          text = src_file.read()
      33      for re_src, re_repl in sorted(repl_map.items()):
      34          text = re.sub(re_src, re_repl, text)
      35      for re_src, re_repl in sorted(extra_map.items()):
      36          text = re.sub(re_src, re_repl, text)
      37      text = text.rstrip() + '\n'
      38      with open(dest, 'w') as dest_file:
      39          dest_file.write(text)
      40  
      41  
      42  def update_sources(glibc_srcdir, quadmath_srcdir):
      43      """Update libquadmath sources."""
      44      glibc_ldbl128 = os.path.join(glibc_srcdir, 'sysdeps/ieee754/ldbl-128')
      45      glibc_math = os.path.join(glibc_srcdir, 'math')
      46      quadmath_math = os.path.join(quadmath_srcdir, 'math')
      47      float128_h = os.path.join(glibc_srcdir,
      48                                'sysdeps/ieee754/float128/float128_private.h')
      49      repl_map = {}
      50      # Use float128_private.h to get an initial list of names to
      51      # replace for libquadmath.
      52      repl_names = {}
      53      with open(float128_h, 'r') as header:
      54          for line in header:
      55              line = line.strip()
      56              if not line.startswith('#define '):
      57                  continue
      58              match = re.fullmatch('^#define[ \t]+([a-zA-Z0-9_]+)'
      59                                   '[ \t]+([a-zA-Z0-9_]+)', line)
      60              if not match:
      61                  continue
      62              macro = match.group(1)
      63              result = match.group(2)
      64              result = result.replace('f128', 'q')
      65              result = result.replace('__ieee754_', '')
      66              if result not in ('__expq_table', '__sincosq_table',
      67                                '__builtin_signbit'):
      68                  result = result.replace('__', '')
      69              result = result.replace('_do_not_use', '')
      70              if result in ('rem_pio2q', 'kernel_sincosq', 'kernel_sinq',
      71                            'kernel_cosq', 'kernel_tanq', 'gammaq_r',
      72                            'gamma_productq', 'lgamma_negq', 'lgamma_productq',
      73                            'lgammaq_r', 'x2y2m1q'):
      74                  # Internal function names, for which the above removal
      75                  # of leading '__' was inappropriate and a leading
      76                  # '__quadmath_' needs adding instead.  In the
      77                  # libquadmath context, lgammaq_r is an internal name.
      78                  result = '__quadmath_' + result
      79              if result == 'ieee854_float128_shape_type':
      80                  result = 'ieee854_float128'
      81              if result == 'HUGE_VAL_F128':
      82                  result = 'HUGE_VALQ'
      83              repl_names[macro] = result
      84      # More such names that aren't simply defined as object-like macros
      85      # in float128_private.h.
      86      repl_names['_Float128'] = '__float128'
      87      repl_names['SET_RESTORE_ROUNDL'] = 'SET_RESTORE_ROUNDF128'
      88      repl_names['parts32'] = 'words32'
      89      for macro in ('GET_LDOUBLE_LSW64', 'GET_LDOUBLE_MSW64',
      90                    'GET_LDOUBLE_WORDS64', 'SET_LDOUBLE_LSW64',
      91                    'SET_LDOUBLE_MSW64', 'SET_LDOUBLE_WORDS64'):
      92          repl_names[macro] = macro.replace('LDOUBLE', 'FLT128')
      93      # The classication macros are replaced.
      94      for macro in ('FP_NAN', 'FP_INFINITE', 'FP_ZERO', 'FP_SUBNORMAL',
      95                    'FP_NORMAL'):
      96          repl_names[macro] = 'QUAD' + macro
      97      for macro in ('fpclassify', 'signbit', 'isnan', 'isinf', 'issignaling'):
      98          repl_names[macro] = macro + 'q'
      99      repl_names['isfinite'] = 'finiteq'
     100      # Map comparison macros to the __builtin forms.
     101      for macro in ('isgreater', 'isgreaterequal', 'isless', 'islessequal',
     102                    'islessgreater', 'isunordered'):
     103          repl_names[macro] = '__builtin_' + macro
     104      # Replace macros used in type-generic templates in glibc.
     105      repl_names['FLOAT'] = '__float128'
     106      repl_names['CFLOAT'] = '__complex128'
     107      repl_names['M_NAN'] = 'nanq ("")'
     108      repl_names['M_HUGE_VAL'] = 'HUGE_VALQ'
     109      repl_names['INFINITY'] = '__builtin_inf ()'
     110      for macro in ('MIN_EXP', 'MAX_EXP', 'MIN', 'MAX', 'MANT_DIG', 'EPSILON'):
     111          repl_names['M_%s' % macro] = 'FLT128_%s' % macro
     112      for macro in ('COPYSIGN', 'FABS', 'SINCOS', 'SCALBN', 'LOG1P', 'ATAN2',
     113                    'COSH', 'EXP', 'HYPOT', 'LOG', 'SINH', 'SQRT'):
     114          repl_names['M_%s' % macro] = macro.lower() + 'q'
     115      # Each such name is replaced when it appears as a whole word.
     116      for macro in repl_names:
     117          repl_map[r'\b%s\b' % macro] = repl_names[macro]
     118      # Also replace the L macro for constants; likewise M_LIT and M_MLIT.
     119      repl_map[r'\bL *\((.*?)\)'] = r'\1Q'
     120      repl_map[r'\bM_LIT *\((.*?)\)'] = r'\1Q'
     121      repl_map[r'\bM_MLIT *\((.*?)\)'] = r'\1q'
     122      # M_DECL_FUNC and M_SUF need similar replacements.
     123      repl_map[r'\bM_DECL_FUNC *\((?:__)?(?:ieee754_)?(.*?)\)'] = r'\1q'
     124      repl_map[r'\bM_SUF *\((?:__)?(?:ieee754_)?(.*?)\)'] = r'\1q'
     125      # Further adjustments are then needed for certain internal
     126      # functions called via M_SUF.
     127      repl_map[r'\bx2y2m1q\b'] = '__quadmath_x2y2m1q'
     128      repl_map[r'\bkernel_casinhq\b'] = '__quadmath_kernel_casinhq'
     129      # Replace calls to __set_errno.
     130      repl_map[r'\b__set_errno *\((.*?)\)'] = r'errno = \1'
     131      # Eliminate glibc diagnostic macros.
     132      repl_map[r' *\bDIAG_PUSH_NEEDS_COMMENT;'] = ''
     133      repl_map[r' *\bDIAG_IGNORE_NEEDS_COMMENT *\(.*?\);'] = ''
     134      repl_map[r' *\bDIAG_POP_NEEDS_COMMENT;'] = ''
     135      # Different names used in union.
     136      repl_map[r'\.d\b'] = '.value'
     137      repl_map[r'\bunion ieee854_float128\b'] = 'ieee854_float128'
     138      # Calls to alias and hidden_def macros are all eliminated.
     139      for macro in ('strong_alias', 'weak_alias', 'libm_alias_ldouble',
     140                    'declare_mgen_alias', 'declare_mgen_finite_alias',
     141                    'libm_hidden_def', 'mathx_hidden_def'):
     142          repl_map[r'\b%s *\(.*?\);?' % macro] = ''
     143      # Replace all #includes with a single include of quadmath-imp.h.
     144      repl_map['(\n+#include[^\n]*)+\n+'] = '\n\n#include "quadmath-imp.h"\n\n'
     145      # Omitted from this list because code comes from more than one
     146      # glibc source file: rem_pio2.
     147      ldbl_files = {
     148          'e_acoshl.c': 'acoshq.c', 'e_acosl.c': 'acosq.c',
     149          's_asinhl.c': 'asinhq.c', 'e_asinl.c': 'asinq.c',
     150          'e_atan2l.c': 'atan2q.c', 'e_atanhl.c': 'atanhq.c',
     151          's_atanl.c': 'atanq.c', 's_cbrtl.c': 'cbrtq.c', 's_ceill.c': 'ceilq.c',
     152          's_copysignl.c': 'copysignq.c', 'e_coshl.c': 'coshq.c',
     153          's_cosl.c': 'cosq.c', 'k_cosl.c': 'cosq_kernel.c',
     154          's_erfl.c': 'erfq.c', 's_expm1l.c': 'expm1q.c', 'e_expl.c': 'expq.c',
     155          't_expl.h': 'expq_table.h', 's_fabsl.c': 'fabsq.c',
     156          's_finitel.c': 'finiteq.c', 's_floorl.c': 'floorq.c',
     157          's_fmal.c': 'fmaq.c', 'e_fmodl.c': 'fmodq.c', 's_frexpl.c': 'frexpq.c',
     158          'e_lgammal_r.c': 'lgammaq.c', 'lgamma_negl.c': 'lgammaq_neg.c',
     159          'lgamma_productl.c': 'lgammaq_product.c', 'e_hypotl.c': 'hypotq.c',
     160          'e_ilogbl.c': 'ilogbq.c', 's_isinfl.c': 'isinfq.c',
     161          's_isnanl.c': 'isnanq.c', 's_issignalingl.c': 'issignalingq.c',
     162          'e_j0l.c': 'j0q.c', 'e_j1l.c': 'j1q.c', 'e_jnl.c': 'jnq.c',
     163          's_llrintl.c': 'llrintq.c', 's_llroundl.c': 'llroundq.c',
     164          'e_log10l.c': 'log10q.c', 's_log1pl.c': 'log1pq.c',
     165          'e_log2l.c': 'log2q.c', 's_logbl.c': 'logbq.c', 'e_logl.c': 'logq.c',
     166          's_lrintl.c': 'lrintq.c', 's_lroundl.c': 'lroundq.c',
     167          's_modfl.c': 'modfq.c', 's_nearbyintl.c': 'nearbyintq.c',
     168          's_nextafterl.c': 'nextafterq.c', 'e_powl.c': 'powq.c',
     169          'e_remainderl.c': 'remainderq.c', 's_remquol.c': 'remquoq.c',
     170          's_rintl.c': 'rintq.c', 's_roundl.c': 'roundq.c',
     171          's_scalblnl.c': 'scalblnq.c', 's_scalbnl.c': 'scalbnq.c',
     172          's_signbitl.c': 'signbitq.c', 't_sincosl.c': 'sincos_table.c',
     173          's_sincosl.c': 'sincosq.c', 'k_sincosl.c': 'sincosq_kernel.c',
     174          'e_sinhl.c': 'sinhq.c', 's_sinl.c': 'sinq.c',
     175          'k_sinl.c': 'sinq_kernel.c', 's_tanhl.c': 'tanhq.c',
     176          's_tanl.c': 'tanq.c', 'k_tanl.c': 'tanq_kernel.c',
     177          'e_gammal_r.c': 'tgammaq.c', 'gamma_productl.c': 'tgammaq_product.c',
     178          's_truncl.c': 'truncq.c', 'x2y2m1l.c': 'x2y2m1q.c'
     179          }
     180      template_files = {
     181          's_cacosh_template.c': 'cacoshq.c', 's_cacos_template.c': 'cacosq.c',
     182          's_casinh_template.c': 'casinhq.c',
     183          'k_casinh_template.c': 'casinhq_kernel.c',
     184          's_casin_template.c': 'casinq.c', 's_catanh_template.c': 'catanhq.c',
     185          's_catan_template.c': 'catanq.c', 's_ccosh_template.c': 'ccoshq.c',
     186          's_cexp_template.c': 'cexpq.c', 'cimag_template.c': 'cimagq.c',
     187          's_clog10_template.c': 'clog10q.c', 's_clog_template.c': 'clogq.c',
     188          'conj_template.c': 'conjq.c', 's_cproj_template.c': 'cprojq.c',
     189          'creal_template.c': 'crealq.c', 's_csinh_template.c': 'csinhq.c',
     190          's_csin_template.c': 'csinq.c', 's_csqrt_template.c': 'csqrtq.c',
     191          's_ctanh_template.c': 'ctanhq.c', 's_ctan_template.c': 'ctanq.c',
     192          'e_exp2_template.c': 'exp2q.c', 's_fdim_template.c': 'fdimq.c',
     193          's_fmax_template.c': 'fmaxq.c', 's_fmin_template.c': 'fminq.c',
     194          's_ldexp_template.c': 'ldexpq.c'
     195          }
     196      # Some files have extra substitutions to apply.
     197      extra_maps = defaultdict(dict)
     198      extra_maps['expq.c'] = {r'#include "quadmath-imp\.h"\n':
     199                              '#include "quadmath-imp.h"\n'
     200                              '#include "expq_table.h"\n'}
     201      extra_maps['ilogbq.c'] = {r'#include "quadmath-imp\.h"\n':
     202                                '#include <math.h>\n'
     203                                '#include "quadmath-imp.h"\n'
     204                                '#ifndef FP_ILOGB0\n'
     205                                '# define FP_ILOGB0 INT_MIN\n'
     206                                '#endif\n'
     207                                '#ifndef FP_ILOGBNAN\n'
     208                                '# define FP_ILOGBNAN INT_MAX\n'
     209                                '#endif\n',
     210                                r'return ([A-Z0-9_]+);':
     211                                r'{ errno = EDOM; feraiseexcept (FE_INVALID); '
     212                                r'return \1; }'}
     213      extra_maps['lgammaq.c'] = {r'#include "quadmath-imp\.h"\n':
     214                                 '#include "quadmath-imp.h"\n'
     215                                 '#ifdef HAVE_MATH_H_SIGNGAM\n'
     216                                 '# include <math.h>\n'
     217                                 '#endif\n'
     218                                 '__float128\n'
     219                                 'lgammaq (__float128 x)\n'
     220                                 '{\n'
     221                                 '#ifndef HAVE_MATH_H_SIGNGAM\n'
     222                                 '  int signgam;\n'
     223                                 '#endif\n'
     224                                 '  return __quadmath_lgammaq_r (x, &signgam);\n'
     225                                 '}\n'}
     226      extra_maps['tgammaq.c'] = {r'#include "quadmath-imp\.h"\n':
     227                                 '#include "quadmath-imp.h"\n'
     228                                 '__float128\n'
     229                                 'tgammaq (__float128 x)\n'
     230                                 '{\n'
     231                                 '  int sign;\n'
     232                                 '  __float128 ret;\n'
     233                                 '  ret = __quadmath_gammaq_r (x, &sign);\n'
     234                                 '  return sign < 0 ? -ret : ret;\n'
     235                                 '}\n'}
     236      for src, dest in ldbl_files.items():
     237          replace_in_file(repl_map, extra_maps[dest],
     238                          os.path.join(glibc_ldbl128, src),
     239                          os.path.join(quadmath_math, dest))
     240      for src, dest in template_files.items():
     241          replace_in_file(repl_map, extra_maps[dest],
     242                          os.path.join(glibc_math, src),
     243                          os.path.join(quadmath_math, dest))
     244  
     245  def main():
     246      parser = argparse.ArgumentParser(description='Update libquadmath code.')
     247      parser.add_argument('glibc_srcdir', help='glibc source directory')
     248      parser.add_argument('quadmath_srcdir', help='libquadmath source directory')
     249      args = parser.parse_args()
     250      update_sources(args.glibc_srcdir, args.quadmath_srcdir)
     251  
     252  
     253  if __name__ == '__main__':
     254      main()