]>
Commit | Line | Data |
---|---|---|
4239f144 JM |
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 | |
667b3ec1 | 146 | # glibc source file: rem_pio2. |
4239f144 JM |
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', | |
667b3ec1 | 157 | 's_fmal.c': 'fmaq.c', 'e_fmodl.c': 'fmodq.c', 's_frexpl.c': 'frexpq.c', |
4239f144 JM |
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() |