1 /* Generate macros based on the combined_fn enum. 2 Copyright (C) 2015-2017 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free 8 Software Foundation; either version 3, or (at your option) any later 9 version. 10 11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20 /* Automatically generate code fragments related to combined_fn. 21 22 The program looks for math built-in functions that have float, double 23 and long double variants, such as {sqrtf, sqrt, sqrtl}, and that may 24 or may not have an associated internal function as well. It also looks 25 for integer built-in functions that have int, long, long long and 26 intmax_t variants, such as {clz, clzl, clzll, clzimax}, and that 27 again may or may not have an associated internal function as well. 28 29 When run with -c, the generator prints a list of macros such as: 30 31 CASE_CFN_SQRT 32 33 for each group of functions described above, with 'case CFN_*' 34 statements for each built-in and internal function in the group. 35 For example, there are both built-in and internal implementations 36 of SQRT, so "CASE_CFN_SQRT:" is equivalent to: 37 38 case CFN_BUILT_IN_SQRTF: 39 case CFN_BUILT_IN_SQRT: 40 case CFN_BUILT_IN_SQRTL: 41 case CFN_SQRT: 42 43 The macros for groups with no internal function drop the last line. 44 45 When run with -o, the generator prints a similar list of 46 define_operator_list directives, for use by match.pd. Each operator 47 list starts with the built-in functions, in order of ascending type width. 48 This is followed by an entry for the internal function, or "null" if there 49 is no internal function for the group. For example: 50 51 (define_operator_list SQRT 52 BUILT_IN_SQRTF 53 BUILT_IN_SQRT 54 BUILT_IN_SQRTL 55 IFN_SQRT) 56 57 and: 58 59 (define_operator_list CABS 60 BUILT_IN_CABSF 61 BUILT_IN_CABS 62 BUILT_IN_CABSL 63 null) */ 64 65 #include "bconfig.h" 66 #include "system.h" 67 #include "coretypes.h" 68 #include "hash-table.h" 69 #include "hash-set.h" 70 #include "errors.h" 71 72 typedef hash_set <nofree_string_hash> string_set; 73 74 /* Add all names in null-terminated list NAMES to SET. */ 75 76 static void 77 add_to_set (string_set *set, const char *const *names) 78 { 79 for (unsigned int i = 0; names[i]; ++i) 80 set->add (names[i]); 81 } 82 83 /* Return true if *BUILTINS contains BUILT_IN_<NAME><SUFFIX> for all 84 suffixes in null-terminated list SUFFIXES. */ 85 86 static bool 87 is_group (string_set *builtins, const char *name, const char *const *suffixes) 88 { 89 for (unsigned int i = 0; suffixes[i]; ++i) 90 if (!builtins->contains (ACONCAT (("BUILT_IN_", name, suffixes[i], NULL)))) 91 return false; 92 return true; 93 } 94 95 /* Print a macro for all combined functions related to NAME, with the 96 null-terminated list of suffixes in SUFFIXES. INTERNAL_P says whether 97 CFN_<NAME> also exists. */ 98 99 static void 100 print_case_cfn (const char *name, bool internal_p, 101 const char *const *suffixes) 102 { 103 printf ("#define CASE_CFN_%s", name); 104 if (internal_p) 105 printf (" \\\n case CFN_%s", name); 106 for (unsigned int i = 0; suffixes[i]; ++i) 107 printf ("%s \\\n case CFN_BUILT_IN_%s%s", 108 internal_p || i > 0 ? ":" : "", name, suffixes[i]); 109 printf ("\n"); 110 } 111 112 /* Print an operator list for all combined functions related to NAME, 113 with the null-terminated list of suffixes in SUFFIXES. INTERNAL_P 114 says whether CFN_<NAME> also exists. */ 115 116 static void 117 print_define_operator_list (const char *name, bool internal_p, 118 const char *const *suffixes) 119 { 120 printf ("(define_operator_list %s\n", name); 121 for (unsigned int i = 0; suffixes[i]; ++i) 122 printf (" BUILT_IN_%s%s\n", name, suffixes[i]); 123 if (internal_p) 124 printf (" IFN_%s)\n", name); 125 else 126 printf (" null)\n"); 127 } 128 129 const char *const builtin_names[] = { 130 #define DEF_BUILTIN(ENUM, N, C, T, LT, B, F, NA, AT, IM, COND) \ 131 #ENUM, 132 #include "builtins.def" 133 NULL 134 }; 135 136 const char *const internal_fn_flt_names[] = { 137 #define DEF_INTERNAL_FLT_FN(NAME, FLAGS, OPTAB, TYPE) \ 138 #NAME, 139 #include "internal-fn.def" 140 NULL 141 }; 142 143 const char *const internal_fn_int_names[] = { 144 #define DEF_INTERNAL_INT_FN(NAME, FLAGS, OPTAB, TYPE) \ 145 #NAME, 146 #include "internal-fn.def" 147 NULL 148 }; 149 150 static const char *const flt_suffixes[] = { "F", "", "L", NULL }; 151 static const char *const int_suffixes[] = { "", "L", "LL", "IMAX", NULL }; 152 153 static const char *const *const suffix_lists[] = { 154 flt_suffixes, 155 int_suffixes, 156 NULL 157 }; 158 159 int 160 main (int argc, char **argv) 161 { 162 /* Check arguments. */ 163 progname = argv[0]; 164 if (argc != 2 165 || argv[1][0] != '-' 166 || !strchr ("co", argv[1][1]) 167 || argv[1][2]) 168 fatal ("usage: %s [-c|-o] > file", progname); 169 int type = argv[1][1]; 170 171 /* Collect the set of built-in and internal functions. */ 172 string_set builtins; 173 string_set internal_fns; 174 add_to_set (&builtins, builtin_names); 175 add_to_set (&internal_fns, internal_fn_flt_names); 176 add_to_set (&internal_fns, internal_fn_int_names); 177 178 /* Check the functions. */ 179 for (unsigned int i = 0; internal_fn_flt_names[i]; ++i) 180 { 181 const char *name = internal_fn_flt_names[i]; 182 if (!is_group (&builtins, name, flt_suffixes)) 183 error ("DEF_INTERNAL_FLT_FN (%s) has no associated built-in" 184 " functions", name); 185 } 186 for (unsigned int i = 0; internal_fn_int_names[i]; ++i) 187 { 188 const char *name = internal_fn_int_names[i]; 189 if (!is_group (&builtins, name, int_suffixes)) 190 error ("DEF_INTERNAL_INT_FN (%s) has no associated built-in" 191 " functions", name); 192 } 193 194 /* Go through the built-in functions in declaration order, outputting 195 definitions as appropriate. */ 196 for (unsigned int i = 0; builtin_names[i]; ++i) 197 { 198 const char *name = builtin_names[i]; 199 if (strncmp (name, "BUILT_IN_", 9) == 0) 200 { 201 const char *root = name + 9; 202 for (unsigned int j = 0; suffix_lists[j]; ++j) 203 if (is_group (&builtins, root, suffix_lists[j])) 204 { 205 bool internal_p = internal_fns.contains (root); 206 if (type == 'c') 207 print_case_cfn (root, internal_p, suffix_lists[j]); 208 else 209 print_define_operator_list (root, internal_p, 210 suffix_lists[j]); 211 } 212 } 213 } 214 215 if (fflush (stdout) || fclose (stdout) || have_error) 216 return FATAL_EXIT_CODE; 217 return SUCCESS_EXIT_CODE; 218 } 219