1 /* Generate macros based on the combined_fn enum. 2 Copyright (C) 2015-2018 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. FLOATN_P is a suffix to the operator name, blank 98 for normal operators, "_FN" for _Float<N>/_Float<N>X operators only, and 99 "_ALL" for both the traditional operators and the _Float<N>/_Float<N>X 100 operators. */ 101 102 static void 103 print_case_cfn (const char *name, bool internal_p, 104 const char *const *suffixes, const char *floatn) 105 { 106 printf ("#define CASE_CFN_%s%s", name, floatn); 107 if (internal_p) 108 printf (" \\\n case CFN_%s%s", name, floatn); 109 for (unsigned int i = 0; suffixes[i]; ++i) 110 printf ("%s \\\n case CFN_BUILT_IN_%s%s", 111 internal_p || i > 0 ? ":" : "", name, suffixes[i]); 112 printf ("\n"); 113 } 114 115 /* Print an operator list for all combined functions related to NAME, with the 116 null-terminated list of suffixes in SUFFIXES. INTERNAL_P says whether 117 CFN_<NAME> also exists. FLOATN_P is a suffix to the operator name, blank 118 for normal operators, "_FN" for _Float<N>/_Float<N>X operators only, and 119 "_ALL" for both the traditional operators and the _Float<N>/_Float<N>X 120 operators. */ 121 122 static void 123 print_define_operator_list (const char *name, bool internal_p, 124 const char *const *suffixes, 125 const char *floatn) 126 { 127 printf ("(define_operator_list %s%s\n", name, floatn); 128 for (unsigned int i = 0; suffixes[i]; ++i) 129 printf (" BUILT_IN_%s%s\n", name, suffixes[i]); 130 if (internal_p) 131 printf (" IFN_%s)\n", name); 132 else 133 printf (" null)\n"); 134 } 135 136 const char *const builtin_names[] = { 137 #define DEF_BUILTIN(ENUM, N, C, T, LT, B, F, NA, AT, IM, COND) \ 138 #ENUM, 139 #include "builtins.def" 140 NULL 141 }; 142 143 const char *const internal_fn_flt_names[] = { 144 #define DEF_INTERNAL_FLT_FN(NAME, FLAGS, OPTAB, TYPE) \ 145 #NAME, 146 #include "internal-fn.def" 147 NULL 148 }; 149 150 const char *const internal_fn_int_names[] = { 151 #define DEF_INTERNAL_INT_FN(NAME, FLAGS, OPTAB, TYPE) \ 152 #NAME, 153 #include "internal-fn.def" 154 NULL 155 }; 156 157 static const char *const flt_suffixes[] = { "F", "", "L", NULL }; 158 static const char *const fltfn_suffixes[] = { "F16", "F32", "F64", "F128", 159 "F32X", "F64X", "F128X", NULL }; 160 static const char *const fltall_suffixes[] = { "F", "", "L", "F16", "F32", 161 "F64", "F128", "F32X", "F64X", 162 "F128X", NULL }; 163 static const char *const int_suffixes[] = { "", "L", "LL", "IMAX", NULL }; 164 165 static const char *const *const suffix_lists[] = { 166 flt_suffixes, 167 int_suffixes, 168 NULL 169 }; 170 171 int 172 main (int argc, char **argv) 173 { 174 /* Check arguments. */ 175 progname = argv[0]; 176 if (argc != 2 177 || argv[1][0] != '-' 178 || !strchr ("co", argv[1][1]) 179 || argv[1][2]) 180 fatal ("usage: %s [-c|-o] > file", progname); 181 int type = argv[1][1]; 182 183 /* Collect the set of built-in and internal functions. */ 184 string_set builtins; 185 string_set internal_fns; 186 add_to_set (&builtins, builtin_names); 187 add_to_set (&internal_fns, internal_fn_flt_names); 188 add_to_set (&internal_fns, internal_fn_int_names); 189 190 /* Check the functions. */ 191 for (unsigned int i = 0; internal_fn_flt_names[i]; ++i) 192 { 193 const char *name = internal_fn_flt_names[i]; 194 if (!is_group (&builtins, name, flt_suffixes)) 195 error ("DEF_INTERNAL_FLT_FN (%s) has no associated built-in" 196 " functions", name); 197 } 198 for (unsigned int i = 0; internal_fn_int_names[i]; ++i) 199 { 200 const char *name = internal_fn_int_names[i]; 201 if (!is_group (&builtins, name, int_suffixes)) 202 error ("DEF_INTERNAL_INT_FN (%s) has no associated built-in" 203 " functions", name); 204 } 205 206 /* Go through the built-in functions in declaration order, outputting 207 definitions as appropriate. */ 208 for (unsigned int i = 0; builtin_names[i]; ++i) 209 { 210 const char *name = builtin_names[i]; 211 if (strncmp (name, "BUILT_IN_", 9) == 0) 212 { 213 const char *root = name + 9; 214 for (unsigned int j = 0; suffix_lists[j]; ++j) 215 { 216 const char *const *const suffix = suffix_lists[j]; 217 218 if (is_group (&builtins, root, suffix)) 219 { 220 bool internal_p = internal_fns.contains (root); 221 222 if (type == 'c') 223 print_case_cfn (root, internal_p, suffix, ""); 224 else 225 print_define_operator_list (root, internal_p, suffix, ""); 226 227 /* Support the _Float<N> and _Float<N>X math functions if 228 they exist. We put these out as a separate CFN or 229 operator macro, so code can add support or not as 230 needed. We also put out a combined CFN or operator 231 macro that includes both the traditional names and the 232 _Float<N> and _Float<N>X versions. */ 233 if (suffix == flt_suffixes 234 && is_group (&builtins, root, fltfn_suffixes)) 235 { 236 if (type == 'c') 237 { 238 print_case_cfn (root, false, fltfn_suffixes, "_FN"); 239 print_case_cfn (root, false, fltall_suffixes, "_ALL"); 240 } 241 else 242 { 243 print_define_operator_list (root, false, 244 fltfn_suffixes, "_FN"); 245 print_define_operator_list (root, internal_p, 246 fltall_suffixes, "_ALL"); 247 } 248 } 249 } 250 } 251 } 252 } 253 254 if (fflush (stdout) || fclose (stdout) || have_error) 255 return FATAL_EXIT_CODE; 256 return SUCCESS_EXIT_CODE; 257 } 258