1#!/usr/bin/python3 2# Produce headers of assembly constants from C expressions. 3# Copyright (C) 2018-2022 Free Software Foundation, Inc. 4# This file is part of the GNU C Library. 5# 6# The GNU C Library 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# The GNU C Library 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 the GNU C Library; if not, see 18# <https://www.gnu.org/licenses/>. 19 20# The input to this script looks like: 21# #cpp-directive ... 22# NAME1 23# NAME2 expression ... 24# A line giving just a name implies an expression consisting of just that name. 25 26import argparse 27 28import glibcextract 29 30 31def gen_test(sym_data): 32 """Generate a test for the values of some C constants. 33 34 The first argument is as for glibcextract.compute_c_consts. 35 36 """ 37 out_lines = [] 38 for arg in sym_data: 39 if isinstance(arg, str): 40 if arg == 'START': 41 out_lines.append('#include <stdint.h>\n' 42 '#include <stdio.h>\n' 43 '#include <bits/wordsize.h>\n' 44 '#if __WORDSIZE == 64\n' 45 'typedef uint64_t c_t;\n' 46 '# define U(n) UINT64_C (n)\n' 47 '#else\n' 48 'typedef uint32_t c_t;\n' 49 '# define U(n) UINT32_C (n)\n' 50 '#endif\n' 51 'static int\n' 52 'do_test (void)\n' 53 '{\n' 54 # Compilation test only, using static 55 # assertions. 56 ' return 0;\n' 57 '}\n' 58 '#include <support/test-driver.c>') 59 else: 60 out_lines.append(arg) 61 continue 62 name = arg[0] 63 value = arg[1] 64 out_lines.append('_Static_assert (U (asconst_%s) == (c_t) (%s), ' 65 '"value of %s");' 66 % (name, value, name)) 67 return '\n'.join(out_lines) 68 69 70def main(): 71 """The main entry point.""" 72 parser = argparse.ArgumentParser( 73 description='Produce headers of assembly constants.') 74 parser.add_argument('--cc', metavar='CC', 75 help='C compiler (including options) to use') 76 parser.add_argument('--test', action='store_true', 77 help='Generate test case instead of header') 78 parser.add_argument('--python', action='store_true', 79 help='Generate Python file instead of header') 80 parser.add_argument('sym_file', 81 help='.sym file to process') 82 args = parser.parse_args() 83 sym_data = [] 84 with open(args.sym_file, 'r') as sym_file: 85 started = False 86 for line in sym_file: 87 line = line.strip() 88 if line == '': 89 continue 90 # Pass preprocessor directives through. 91 if line.startswith('#'): 92 sym_data.append(line) 93 continue 94 words = line.split(maxsplit=1) 95 if not started: 96 sym_data.append('START') 97 started = True 98 # Separator. 99 if words[0] == '--': 100 continue 101 name = words[0] 102 value = words[1] if len(words) > 1 else words[0] 103 sym_data.append((name, value)) 104 if not started: 105 sym_data.append('START') 106 if args.test: 107 print(gen_test(sym_data)) 108 elif args.python: 109 consts = glibcextract.compute_c_consts(sym_data, args.cc) 110 print('# GENERATED FILE\n' 111 '\n' 112 '# Constant definitions.\n' 113 '# See gen-as-const.py for details.\n') 114 print(''.join('%s = %s\n' % c for c in sorted(consts.items())), end='') 115 else: 116 consts = glibcextract.compute_c_consts(sym_data, args.cc) 117 print(''.join('#define %s %s\n' % c for c in sorted(consts.items())), end='') 118 119if __name__ == '__main__': 120 main() 121