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