1# Copyright (C) 2003-2021 Free Software Foundation, Inc. 2# Contributed by Kelley Cook, June 2004. 3# Original code from Neil Booth, May 2003. 4# 5# This program is free software; you can redistribute it and/or modify it 6# under the terms of the GNU General Public License as published by the 7# Free Software Foundation; either version 3, or (at your option) any 8# later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program; see the file COPYING3. If not see 17# <http://www.gnu.org/licenses/>. 18 19# This Awk script reads in the option records generated from 20# opt-gather.awk, combines the flags of duplicate options and generates a 21# C header file. 22# 23# This program uses functions from opt-functions.awk and code from 24# opt-read.awk. 25# Usage: awk -f opt-functions.awk -f opt-read.awk -f opth-gen.awk \ 26# < inputfile > options.h 27 28# Dump out an enumeration into a .h file. 29# Combine the flags of duplicate options. 30END { 31print "/* This file is auto-generated by opth-gen.awk. */" 32print "" 33print "#ifndef OPTIONS_H" 34print "#define OPTIONS_H" 35print "" 36print "#include \"flag-types.h\"" 37print "" 38 39if (n_extra_h_includes > 0) { 40 for (i = 0; i < n_extra_h_includes; i++) { 41 print "#include " quote extra_h_includes[i] quote 42 } 43 print "" 44} 45 46print "#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)" 47print "#ifndef GENERATOR_FILE" 48print "#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS)" 49print "struct GTY(()) gcc_options" 50print "#else" 51print "struct gcc_options" 52print "#endif" 53print "{" 54print "#endif" 55 56for (i = 0; i < n_extra_vars; i++) { 57 var = extra_vars[i] 58 sub(" *=.*", "", var) 59 orig_var = var 60 name = var 61 type = var 62 type_after = var 63 sub("^.*[ *]", "", name) 64 sub("\\[.*\\]$", "", name) 65 sub("\\[.*\\]$", "", type) 66 sub(" *" name "$", "", type) 67 sub("^.*" name, "", type_after) 68 var_seen[name] = 1 69 print "#ifdef GENERATOR_FILE" 70 print "extern " orig_var ";" 71 print "#else" 72 print " " type " x_" name type_after ";" 73 print "#define " name " global_options.x_" name 74 print "#endif" 75} 76 77for (i = 0; i < n_opts; i++) { 78 if (flag_set_p("Save", flags[i])) 79 have_save = 1; 80 81 name = var_name(flags[i]); 82 if (name == "") 83 continue; 84 85 if (name in var_seen) 86 continue; 87 88 var_seen[name] = 1; 89 print "#ifdef GENERATOR_FILE" 90 print "extern " var_type(flags[i]) name ";" 91 print "#else" 92 print " " var_type(flags[i]) "x_" name ";" 93 print "#define " name " global_options.x_" name 94 print "#endif" 95} 96for (i = 0; i < n_opts; i++) { 97 name = static_var(opts[i], flags[i]); 98 if (name != "") { 99 print "#ifndef GENERATOR_FILE" 100 print " " var_type(flags[i]) "x_" name ";" 101 print "#define x_" name " do_not_use" 102 print "#endif" 103 } 104} 105for (i = 0; i < n_opts; i++) { 106 if (flag_set_p("SetByCombined", flags[i])) { 107 print "#ifndef GENERATOR_FILE" 108 print " bool frontend_set_" var_name(flags[i]) ";" 109 print "#endif" 110 } 111} 112print "#ifndef GENERATOR_FILE" 113print "};" 114print "extern struct gcc_options global_options;" 115print "extern const struct gcc_options global_options_init;" 116print "extern struct gcc_options global_options_set;" 117print "#define target_flags_explicit global_options_set.x_target_flags" 118print "#endif" 119print "#endif" 120print "" 121 122# All of the optimization switches gathered together so they can be saved and restored. 123# This will allow attribute((cold)) to turn on space optimization. 124 125# Change the type of normal switches from int to unsigned char to save space. 126# Also, order the structure so that pointer fields occur first, then int 127# fields, and then char fields to provide the best packing. 128 129print "#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)" 130print "" 131print "/* Structure to save/restore optimization and target specific options. */"; 132print "struct GTY(()) cl_optimization"; 133print "{"; 134 135n_opt_char = 4; 136n_opt_short = 0; 137n_opt_int = 0; 138n_opt_enum = 0; 139n_opt_other = 0; 140n_opt_explicit = 4; 141var_opt_char[0] = "unsigned char x_optimize"; 142var_opt_char[1] = "unsigned char x_optimize_size"; 143var_opt_char[2] = "unsigned char x_optimize_debug"; 144var_opt_char[3] = "unsigned char x_optimize_fast"; 145 146for (i = 0; i < n_opts; i++) { 147 if (flag_set_p("(Optimization|PerFunction)", flags[i])) { 148 name = var_name(flags[i]) 149 if(name == "") 150 continue; 151 152 if(name in var_opt_seen) 153 continue; 154 155 var_opt_seen[name]++; 156 n_opt_explicit++; 157 otype = var_type_struct(flags[i]); 158 if (otype ~ "^((un)?signed +)?int *$") 159 var_opt_int[n_opt_int++] = otype "x_" name; 160 161 else if (otype ~ "^((un)?signed +)?short *$") 162 var_opt_short[n_opt_short++] = otype "x_" name; 163 164 else if (otype ~ "^((un)?signed +)?char *$") 165 var_opt_char[n_opt_char++] = otype "x_" name; 166 167 else if (otype ~ ("^enum +[_" alnum "]+ *$")) 168 var_opt_enum[n_opt_enum++] = otype "x_" name; 169 170 else 171 var_opt_other[n_opt_other++] = otype "x_" name; 172 } 173} 174 175for (i = 0; i < n_opt_other; i++) { 176 print " " var_opt_other[i] ";"; 177} 178 179for (i = 0; i < n_opt_int; i++) { 180 print " " var_opt_int[i] ";"; 181} 182 183for (i = 0; i < n_opt_enum; i++) { 184 print " " var_opt_enum[i] ";"; 185} 186 187for (i = 0; i < n_opt_short; i++) { 188 print " " var_opt_short[i] ";"; 189} 190 191for (i = 0; i < n_opt_char; i++) { 192 print " " var_opt_char[i] ";"; 193} 194 195print " /* " n_opt_explicit " members */"; 196print " unsigned HOST_WIDE_INT explicit_mask[" int ((n_opt_explicit + 63) / 64) "];"; 197 198print "};"; 199print ""; 200 201# Target and optimization save/restore/print functions. 202print "/* Structure to save/restore selected target specific options. */"; 203print "struct GTY(()) cl_target_option"; 204print "{"; 205 206n_target_char = 0; 207n_target_short = 0; 208n_target_int = 0; 209n_target_enum = 0; 210n_target_other = 0; 211n_target_explicit = n_extra_target_vars; 212n_target_explicit_mask = 0; 213 214for (i = 0; i < n_target_save; i++) { 215 if (target_save_decl[i] ~ "^((un)?signed +)?int +[_" alnum "]+$") 216 var_target_int[n_target_int++] = target_save_decl[i]; 217 218 else if (target_save_decl[i] ~ "^((un)?signed +)?short +[_" alnum "]+$") 219 var_target_short[n_target_short++] = target_save_decl[i]; 220 221 else if (target_save_decl[i] ~ "^((un)?signed +)?char +[_ " alnum "]+$") 222 var_target_char[n_target_char++] = target_save_decl[i]; 223 224 else if (target_save_decl[i] ~ ("^enum +[_" alnum "]+ +[_" alnum "]+$")) { 225 var_target_enum[n_target_enum++] = target_save_decl[i]; 226 } 227 else 228 var_target_other[n_target_other++] = target_save_decl[i]; 229} 230 231if (have_save) { 232 for (i = 0; i < n_opts; i++) { 233 if (flag_set_p("Save", flags[i])) { 234 name = var_name(flags[i]) 235 if(name == "") 236 name = "target_flags"; 237 238 if(name in var_save_seen) 239 continue; 240 241 var_save_seen[name]++; 242 n_target_explicit++; 243 otype = var_type_struct(flags[i]) 244 245 if (opt_args("Mask", flags[i]) != "" \ 246 || opt_args("InverseMask", flags[i])) 247 var_target_explicit_mask[n_target_explicit_mask++] \ 248 = otype "explicit_mask_" name; 249 250 if (otype ~ "^((un)?signed +)?int *$") 251 var_target_int[n_target_int++] = otype "x_" name; 252 253 else if (otype ~ "^((un)?signed +)?short *$") 254 var_target_short[n_target_short++] = otype "x_" name; 255 256 else if (otype ~ "^((un)?signed +)?char *$") 257 var_target_char[n_target_char++] = otype "x_" name; 258 259 else if (otype ~ ("^enum +[_" alnum "]+ +[_" alnum "]+")) 260 var_target_enum[n_target_enum++] = otype "x_" name; 261 262 else 263 var_target_other[n_target_other++] = otype "x_" name; 264 } 265 } 266} else { 267 var_target_int[n_target_int++] = "int x_target_flags"; 268 n_target_explicit++; 269 var_target_explicit_mask[n_target_explicit_mask++] \ 270 = "int explicit_mask_target_flags"; 271} 272 273for (i = 0; i < n_target_other; i++) { 274 print " " var_target_other[i] ";"; 275} 276 277for (i = 0; i < n_target_enum; i++) { 278 print " " var_target_enum[i] ";"; 279} 280 281for (i = 0; i < n_target_int; i++) { 282 print " " var_target_int[i] ";"; 283} 284 285for (i = 0; i < n_target_short; i++) { 286 print " " var_target_short[i] ";"; 287} 288 289for (i = 0; i < n_target_char; i++) { 290 print " " var_target_char[i] ";"; 291} 292 293print " /* " n_target_explicit - n_target_explicit_mask " members */"; 294if (n_target_explicit > n_target_explicit_mask) { 295 print " unsigned HOST_WIDE_INT explicit_mask[" \ 296 int ((n_target_explicit - n_target_explicit_mask + 63) / 64) "];"; 297} 298 299for (i = 0; i < n_target_explicit_mask; i++) { 300 print " " var_target_explicit_mask[i] ";"; 301} 302 303print "};"; 304print ""; 305print ""; 306print "/* Save optimization variables into a structure. */" 307print "extern void cl_optimization_save (struct cl_optimization *, struct gcc_options *, struct gcc_options *);"; 308print ""; 309print "/* Restore optimization variables from a structure. */"; 310print "extern void cl_optimization_restore (struct gcc_options *, struct gcc_options *, struct cl_optimization *);"; 311print ""; 312print "/* Print optimization variables from a structure. */"; 313print "extern void cl_optimization_print (FILE *, int, struct cl_optimization *);"; 314print ""; 315print "/* Print different optimization variables from structures provided as arguments. */"; 316print "extern void cl_optimization_print_diff (FILE *, int, cl_optimization *ptr1, cl_optimization *ptr2);"; 317print ""; 318print "/* Save selected option variables into a structure. */" 319print "extern void cl_target_option_save (struct cl_target_option *, struct gcc_options *, struct gcc_options *);"; 320print ""; 321print "/* Restore selected option variables from a structure. */" 322print "extern void cl_target_option_restore (struct gcc_options *, struct gcc_options *, struct cl_target_option *);"; 323print ""; 324print "/* Print target option variables from a structure. */"; 325print "extern void cl_target_option_print (FILE *, int, struct cl_target_option *);"; 326print ""; 327print "/* Print different target option variables from structures provided as arguments. */"; 328print "extern void cl_target_option_print_diff (FILE *, int, cl_target_option *ptr1, cl_target_option *ptr2);"; 329print ""; 330print "/* Compare two target option variables from a structure. */"; 331print "extern bool cl_target_option_eq (const struct cl_target_option *, const struct cl_target_option *);"; 332print ""; 333print "/* Free heap memory used by target option variables. */"; 334print "extern void cl_target_option_free (struct cl_target_option *);"; 335print ""; 336print "/* Hash option variables from a structure. */"; 337print "extern hashval_t cl_target_option_hash (const struct cl_target_option *);"; 338print ""; 339print "/* Hash optimization from a structure. */"; 340print "extern hashval_t cl_optimization_hash (const struct cl_optimization *);"; 341print ""; 342print "/* Compare two optimization options. */"; 343print "extern bool cl_optimization_option_eq (cl_optimization const *ptr1, cl_optimization const *ptr2);" 344print ""; 345print "/* Free heap memory used by optimization options. */"; 346print "extern void cl_optimization_option_free (cl_optimization *ptr1);" 347print ""; 348print "/* Compare and report difference for a part of cl_optimization options. */"; 349print "extern void cl_optimization_compare (gcc_options *ptr1, gcc_options *ptr2);"; 350print ""; 351print "/* Generator files may not have access to location_t, and don't need these. */" 352print "#if defined(UNKNOWN_LOCATION)" 353print "bool " 354print "common_handle_option_auto (struct gcc_options *opts, " 355print " struct gcc_options *opts_set, " 356print " const struct cl_decoded_option *decoded, " 357print " unsigned int lang_mask, int kind, " 358print " location_t loc, " 359print " const struct cl_option_handlers *handlers, " 360print " diagnostic_context *dc); " 361for (i = 0; i < n_langs; i++) { 362 lang_name = lang_sanitized_name(langs[i]); 363 print "bool" 364 print lang_name "_handle_option_auto (struct gcc_options *opts," 365 print " struct gcc_options *opts_set," 366 print " size_t scode, const char *arg," 367 print " HOST_WIDE_INT value," 368 print " unsigned int lang_mask, int kind," 369 print " location_t loc," 370 print " const struct cl_option_handlers *handlers," 371 print " diagnostic_context *dc);" 372} 373print "void cpp_handle_option_auto (const struct gcc_options * opts, size_t scode," 374print " struct cpp_options * cpp_opts);" 375print "void init_global_opts_from_cpp(struct gcc_options * opts, " 376print " const struct cpp_options * cpp_opts);" 377print "#endif"; 378print "#endif"; 379print ""; 380 381for (i = 0; i < n_opts; i++) { 382 name = opt_args("Mask", flags[i]) 383 if (name == "") { 384 opt = opt_args("InverseMask", flags[i]) 385 if (opt ~ ",") 386 name = nth_arg(0, opt) 387 else 388 name = opt 389 } 390 if (name != "" && mask_bits[name] == 0) { 391 mask_bits[name] = 1 392 vname = var_name(flags[i]) 393 mask = "MASK_" 394 mask_1 = "1U" 395 if (vname != "") { 396 mask = "OPTION_MASK_" 397 if (host_wide_int[vname] == "yes") 398 mask_1 = "HOST_WIDE_INT_1U" 399 } else 400 extra_mask_bits[name] = 1 401 print "#define " mask name " (" mask_1 " << " masknum[vname]++ ")" 402 } 403} 404for (i = 0; i < n_extra_masks; i++) { 405 if (extra_mask_bits[extra_masks[i]] == 0) 406 print "#define MASK_" extra_masks[i] " (1U << " masknum[""]++ ")" 407} 408 409for (var in masknum) { 410 if (var != "" && host_wide_int[var] == "yes") { 411 print "#if defined(HOST_BITS_PER_WIDE_INT) && " masknum[var] " > HOST_BITS_PER_WIDE_INT" 412 print "#error too many masks for " var 413 print "#endif" 414 } 415 else if (masknum[var] > 32) { 416 if (var == "") 417 print "#error too many target masks" 418 else 419 print "#error too many masks for " var 420 } 421} 422print "" 423 424for (i = 0; i < n_opts; i++) { 425 name = opt_args("Mask", flags[i]) 426 if (name == "") { 427 opt = opt_args("InverseMask", flags[i]) 428 if (opt ~ ",") 429 name = nth_arg(0, opt) 430 else 431 name = opt 432 } 433 if (name != "" && mask_macros[name] == 0) { 434 mask_macros[name] = 1 435 vname = var_name(flags[i]) 436 mask = "OPTION_MASK_" 437 if (vname == "") { 438 vname = "target_flags" 439 mask = "MASK_" 440 extra_mask_macros[name] = 1 441 } 442 print "#define TARGET_" name \ 443 " ((" vname " & " mask name ") != 0)" 444 print "#define TARGET_" name "_P(" vname ")" \ 445 " (((" vname ") & " mask name ") != 0)" 446 } 447} 448for (i = 0; i < n_extra_masks; i++) { 449 if (extra_mask_macros[extra_masks[i]] == 0) 450 print "#define TARGET_" extra_masks[i] \ 451 " ((target_flags & MASK_" extra_masks[i] ") != 0)" 452} 453print "" 454 455for (i = 0; i < n_opts; i++) { 456 opt = opt_args("InverseMask", flags[i]) 457 if (opt ~ ",") { 458 vname = var_name(flags[i]) 459 mask = "OPTION_MASK_" 460 if (vname == "") { 461 vname = "target_flags" 462 mask = "MASK_" 463 } 464 print "#define TARGET_" nth_arg(1, opt) \ 465 " ((" vname " & " mask nth_arg(0, opt) ") == 0)" 466 } 467} 468print "" 469 470for (i = 0; i < n_langs; i++) { 471 macros[i] = "CL_" lang_sanitized_name(langs[i]) 472 s = substr(" ", length (macros[i])) 473 print "#define " macros[i] s " (1U << " i ")" 474 } 475print "#define CL_LANG_ALL ((1U << " n_langs ") - 1)" 476 477print "" 478print "enum opt_code" 479print "{" 480 481for (i = 0; i < n_opts; i++) 482 back_chain[i] = "N_OPTS"; 483 484enum_value = 0 485for (i = 0; i < n_opts; i++) { 486 # Combine the flags of identical switches. Switches 487 # appear many times if they are handled by many front 488 # ends, for example. 489 while( i + 1 != n_opts && opts[i] == opts[i + 1] ) { 490 flags[i + 1] = flags[i] " " flags[i + 1]; 491 i++; 492 } 493 494 len = length (opts[i]); 495 enum = opt_enum(opts[i]) 496 enum_string = enum " = " enum_value "," 497 498 # Aliases do not get enumeration names. 499 if ((flag_set_p("Alias.*", flags[i]) \ 500 && !flag_set_p("SeparateAlias", flags[i])) \ 501 || flag_set_p("Ignore", flags[i])) { 502 enum_string = "/* " enum_string " */" 503 } 504 505 # If this switch takes joined arguments, back-chain all 506 # subsequent switches to it for which it is a prefix. If 507 # a later switch S is a longer prefix of a switch T, T 508 # will be back-chained to S in a later iteration of this 509 # for() loop, which is what we want. 510 if (flag_set_p("Joined.*", flags[i])) { 511 for (j = i + 1; j < n_opts; j++) { 512 if (substr (opts[j], 1, len) != opts[i]) 513 break; 514 back_chain[j] = enum; 515 } 516 } 517 518 s = substr(" ", 519 length (enum_string)) 520 521 if (help[i] == "") 522 hlp = "0" 523 else 524 hlp = "N_(\"" help[i] "\")"; 525 526 print " " enum_string s "/* -" opts[i] " */" 527 enum_value++ 528} 529 530print " N_OPTS," 531print " OPT_SPECIAL_unknown," 532print " OPT_SPECIAL_ignore," 533print " OPT_SPECIAL_warn_removed," 534print " OPT_SPECIAL_program_name," 535print " OPT_SPECIAL_input_file" 536print "};" 537print "" 538print "#ifdef GCC_C_COMMON_C" 539print "/* Mapping from cpp message reasons to the options that enable them. */" 540print "#include <cpplib.h>" 541print "struct cpp_reason_option_codes_t" 542print "{" 543print " /* cpplib message reason. */" 544print " const enum cpp_warning_reason reason;" 545print " /* gcc option that controls this message. */" 546print " const int option_code;" 547print "};" 548print "" 549print "static const struct cpp_reason_option_codes_t cpp_reason_option_codes[] = {" 550for (i = 0; i < n_opts; i++) { 551 # With identical flags, pick only the last one. The 552 # earlier loop ensured that it has all flags merged, 553 # and a nonempty help text if one of the texts was nonempty. 554 while( i + 1 != n_opts && opts[i] == opts[i + 1] ) { 555 i++; 556 } 557 cpp_reason = nth_arg(0, opt_args("CppReason", flags[i])); 558 if (cpp_reason != "") { 559 cpp_reason = cpp_reason ","; 560 printf(" {%-40s %s},\n", cpp_reason, opt_enum(opts[i])) 561 } 562} 563printf(" {%-40s 0},\n", "CPP_W_NONE,") 564print "};" 565print "#endif" 566print "" 567print "#endif /* OPTIONS_H */" 568} 569