mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 09:23:44 +00:00
... to the user guide entries of the affected optimization options.
compiler/print_help.m:
Implement the above.
doc/user_guide.texi:
Expect the additions, both from this diff, and earlier ones.
tools/make_optimization_options_middle:
compiler/optimization_options.m:
To make the above slightly simpler to implement, add a subtype
of the option_data type, and change the type of the predicate
that returns the options enabled at each optimization level
to use this subtype.
configure.ac:
Require the installed compiler to support the fix without which
the subtype definition would make the automatically-generated
contents of libs.optimization_options.int2 invalid.
458 lines
19 KiB
Awk
Executable File
458 lines
19 KiB
Awk
Executable File
#!/usr/bin/awk -f
|
|
# vim: ts=4 sw=4 et ft=awk
|
|
#---------------------------------------------------------------------------#
|
|
# Copyright (C) 2020, 2025 The Mercury team.
|
|
# This file may only be copied under the terms of the GNU General
|
|
# Public License - see the file COPYING in the Mercury distribution.
|
|
#---------------------------------------------------------------------------#
|
|
#
|
|
# The input to this file, make_optimization_options_db, has one line
|
|
# for every optimization option. Each line must have either three
|
|
# or four fields.
|
|
#
|
|
# - The first field indicates what kind of option this is. It must be
|
|
# one of "bool", "int" and "string".
|
|
#
|
|
# - The second field gives the initial value of the option.
|
|
#
|
|
# - If the option is boolean, the initial value must be either "n" or "y".
|
|
#
|
|
# - If the option is an integer, the initial value must be an integer.
|
|
#
|
|
# - If the option is a string, the initial value will be set
|
|
# to the empty string regardless of the contents of the second field.
|
|
#
|
|
# - The third field is the name of the option in options.m.
|
|
#
|
|
# - The fourth field, if it exists, gives the name of the option
|
|
# in the file this script helps generate, optimization_options.m.
|
|
# If there is no fourth field, the name is taken to be the same
|
|
# as the name in the third field.
|
|
#
|
|
# For boolean options, the name in make_optimization_options_db should be
|
|
# a verb, because when we generate a bespoke type for it, its two function
|
|
# symbols will be named "verb" and "do_not_verb".
|
|
#
|
|
|
|
BEGIN {
|
|
next_bool_opt = 0;
|
|
next_int_opt = 0;
|
|
next_string_opt = 0;
|
|
|
|
next_bool_n_opt = 0;
|
|
next_bool_y_opt = 0;
|
|
}
|
|
{
|
|
if (NF == 3 || NF == 4) {
|
|
kind = $1;
|
|
initial_value = $2;
|
|
option_name = $3;
|
|
if (NF == 4) {
|
|
option_field_name = $4;
|
|
} else {
|
|
option_field_name = $3;
|
|
}
|
|
|
|
if (kind == "bool") {
|
|
bool_opts[next_bool_opt] = option_name;
|
|
bool_field_names[next_bool_opt] = option_field_name;
|
|
if (initial_value == "y") {
|
|
bool_defaults[next_bool_opt] = option_field_name;
|
|
|
|
bool_y_opts[next_bool_y_opt] = option_name;
|
|
next_bool_y_opt++;
|
|
} else if (initial_value == "n") {
|
|
bool_defaults[next_bool_opt] = "do_not_" option_field_name;
|
|
|
|
bool_n_opts[next_bool_n_opt] = option_name;
|
|
next_bool_n_opt++;
|
|
} else {
|
|
printf("ERROR: bad bool default <%s>\n", $0);
|
|
}
|
|
bool_initial_value[next_bool_opt] = initial_value;
|
|
next_bool_opt++;
|
|
} else if (kind == "int") {
|
|
int_opts[next_int_opt] = $3;
|
|
int_field_names[next_int_opt] = option_field_name;
|
|
int_defaults[next_int_opt] = initial_value + 0;
|
|
next_int_opt++;
|
|
} else if (kind == "string") {
|
|
string_opts[next_string_opt] = $3;
|
|
string_field_names[next_string_opt] = option_field_name;
|
|
# String options are always initialized to the empty string.
|
|
# To avoid this messing up awk's field counting, we require
|
|
# a dash to fill in the black.
|
|
if (initial_value == "-") {
|
|
string_defaults[next_int_opt] = "";
|
|
} else {
|
|
printf("ERROR: bad string default <%s>\n", $0);
|
|
}
|
|
next_string_opt++;
|
|
} else {
|
|
printf("ERROR: line with unknown type: <%s>\n", $0);
|
|
}
|
|
} else {
|
|
printf("ERROR: line with %d fields: <%s>\n", NF, $0);
|
|
}
|
|
}
|
|
END {
|
|
doc_switch_type_name = "documented_optimization_option";
|
|
doc_switch_type_functor_name = "doc_oo";
|
|
switch_type_name = "optimization_option";
|
|
doc_switch_var_name = "DocOptOption";
|
|
switch_var_name = "OptOption";
|
|
record_type_name = "opt_tuple";
|
|
record_var_name = "OptTuple";
|
|
|
|
for (i = 0; i < next_bool_opt; i++) {
|
|
printf(":- type maybe_%s\n", bool_field_names[i]);
|
|
printf(" ---> %s\n", bool_field_names[i]);
|
|
printf(" ; do_not_%s.\n", bool_field_names[i]);
|
|
}
|
|
|
|
printf("\n%%---------------------%%\n\n");
|
|
|
|
printf(":- type %s\n", switch_type_name);
|
|
for (i = 0; i < next_bool_opt; i++) {
|
|
prefix=";";
|
|
suffix="";
|
|
|
|
if (i == 0)
|
|
prefix = "--->";
|
|
|
|
printf("%-4s%-4s%-4soo_%s(bool)%s\n",
|
|
"", prefix, "", bool_field_names[i], suffix);
|
|
}
|
|
for (i = 0; i < next_int_opt; i++) {
|
|
prefix=";";
|
|
suffix="";
|
|
printf("%-4s%-4s%-4soo_%s(int)%s\n", "",
|
|
prefix, "", int_field_names[i], suffix);
|
|
}
|
|
for (i = 0; i < next_string_opt; i++) {
|
|
prefix=";";
|
|
suffix="";
|
|
|
|
printf("%-4s%-4s%-4soo_%s(string)%s\n",
|
|
"", prefix, "", string_field_names[i], suffix);
|
|
}
|
|
printf("%-4s%-4s%-4soo_opt_level(int)\n", "", prefix, "");
|
|
printf("%-4s%-4s%-4soo_opt_for_space.\n", "", prefix, "");
|
|
|
|
printf("\n%%---------------------%%\n\n");
|
|
|
|
printf(":- type %s\n", record_type_name);
|
|
printf("%-4s--->%-4s%s(\n", "", "", record_type_name);
|
|
for (i = 0; i < next_bool_opt; i++) {
|
|
suffix = ",";
|
|
printf("%-16sot_%-26s :: maybe_%s%s\n",
|
|
"", bool_field_names[i], bool_field_names[i], suffix);
|
|
}
|
|
for (i = 0; i < next_int_opt; i++) {
|
|
suffix = ",";
|
|
printf("%-16sot_%-26s :: int%s\n", "", int_field_names[i], suffix);
|
|
}
|
|
for (i = 0; i < next_string_opt; i++) {
|
|
suffix = ",";
|
|
if (i == next_string_opt-1)
|
|
suffix = "";
|
|
|
|
printf("%-16sot_%-26s :: string%s\n",
|
|
"", string_field_names[i], suffix);
|
|
}
|
|
printf("%-12s).\n", "");
|
|
|
|
# Put this predicate first, even though it is the least important
|
|
# exported predicate here and should therefore come last. The reason
|
|
# for that is that opts_enabled_at_level is not generated here.
|
|
# Instead, it is defined in make_optimization_options_db_end,
|
|
# which *guarantees* that it will come after any predicate defined
|
|
# by the output of this script. We put this predicate at the front
|
|
# to avoid putting it in the middle of a related-to-each-other
|
|
# predicates.
|
|
printf("\n");
|
|
printf(":- pred bool_option_initial_n_y(%s::out, %s::out) is det.\n",
|
|
"list(option)", "list(option)");
|
|
|
|
printf("\n");
|
|
printf(":- pred process_optimization_options(option_table::in,\n");
|
|
printf("%-4slist(%s)::in, %s::out) is det.\n",
|
|
"", switch_type_name, record_type_name);
|
|
printf("\n");
|
|
|
|
printf(":- type %s\n", doc_switch_type_name);
|
|
printf("%-4s--->%-4s%s(\n", "", "", doc_switch_type_functor_name);
|
|
printf("%-16s%s,\n", "", switch_type_name);
|
|
printf("%-16soption,\n", "");
|
|
printf("%-16soption_data_bool_int\n", "");
|
|
printf("%-12s).\n", "");
|
|
printf("\n");
|
|
|
|
printf(":- type option_data_bool_int =< option_data\n");
|
|
printf("%-4s--->%-4s%s\n", "", "", "bool(bool)");
|
|
printf("%-4s;%-7s%s\n", "", "", "int(int).");
|
|
printf("\n");
|
|
|
|
printf(":- pred opts_enabled_at_level(int::in, list(string)::out,\n");
|
|
printf("%-4slist(%s)::out) is semidet.\n", "", doc_switch_type_name);
|
|
|
|
printf("\n");
|
|
printf("%%---------------------------------------------------------------------------%%\n");
|
|
printf("\n");
|
|
|
|
printf(":- implementation.\n");
|
|
|
|
printf("\n");
|
|
printf(":- import_module int.\n");
|
|
printf(":- import_module map.\n");
|
|
printf(":- import_module string.\n");
|
|
|
|
printf("\n%%---------------------%%\n");
|
|
|
|
printf("\n");
|
|
printf("bool_option_initial_n_y(No, Yes) :-\n");
|
|
printf("%-4sNo = [\n", "");
|
|
for (i = 0; i < next_bool_n_opt; i++) {
|
|
suffix = ",";
|
|
if (i == next_bool_n_opt-1) {
|
|
suffix = "";
|
|
}
|
|
printf("%-8soptopt_%s%s\n", "", bool_n_opts[i], suffix);
|
|
}
|
|
printf("%-4s],\n", "");
|
|
printf("%-4sYes = [\n", "");
|
|
for (i = 0; i < next_bool_y_opt; i++) {
|
|
suffix = ",";
|
|
if (i == next_bool_y_opt-1) {
|
|
suffix = "";
|
|
}
|
|
printf("%-8soptopt_%s%s\n", "", bool_y_opts[i], suffix);
|
|
}
|
|
printf("%-4s].\n", "");
|
|
|
|
printf("\n%%---------------------%%\n\n");
|
|
|
|
printf("process_optimization_options(OptionTable, OptOptions, !:OptTuple) :-\n");
|
|
printf("%-4s!:OptTuple = init_opt_tuple,\n", "");
|
|
printf("%-4slist.foldl2(\n", "");
|
|
printf("%-8supdate_opt_tuple(not_from_opt_level, OptionTable),\n", "");
|
|
printf("%-8sOptOptions, !OptTuple, not_seen_opt_level, MaybeSeenOptLevel),\n", "");
|
|
printf("%-4s(\n", "");
|
|
printf("%-8sMaybeSeenOptLevel = not_seen_opt_level,\n", "");
|
|
printf("%-8sget_default_opt_level(OptionTable, DefaultOptLevel),\n", "");
|
|
printf("%-8sset_opts_upto_level(OptionTable, 0, DefaultOptLevel,\n",
|
|
"");
|
|
printf("%-12s!OptTuple, MaybeSeenOptLevel, _)\n", "");
|
|
printf("%-4s;\n", "");
|
|
printf("%-8sMaybeSeenOptLevel = seen_opt_level\n", "");
|
|
printf("%-4s).\n", "");
|
|
|
|
printf("\n%%---------------------%%\n");
|
|
|
|
printf("\n");
|
|
printf(":- func init_opt_tuple = %s.\n\n", record_type_name);
|
|
|
|
printf("init_opt_tuple =\n");
|
|
printf("%-4s%s(\n", "", record_type_name);
|
|
for (i = 0; i < next_bool_opt; i++) {
|
|
printf("%-8s%s,\n", "", bool_defaults[i]);
|
|
}
|
|
for (i = 0; i < next_int_opt; i++) {
|
|
printf("%-8s%s,\n", "", int_defaults[i]);
|
|
}
|
|
for (i = 0; i < next_string_opt; i++) {
|
|
suffix = ",";
|
|
if (i == next_string_opt-1) {
|
|
suffix = "";
|
|
}
|
|
printf("%-8s%s%s\n", "", "\"\"", suffix);
|
|
}
|
|
printf("%-4s).\n", "");
|
|
|
|
printf("\n%%---------------------%%\n");
|
|
|
|
printf("\n");
|
|
printf(":- type maybe_seen_opt_level\n");
|
|
printf("%-4s%-8snot_seen_opt_level\n", "", "--->");
|
|
printf("%-4s%-8sseen_opt_level.\n", "", ";");
|
|
|
|
printf("\n");
|
|
printf(":- type maybe_from_opt_level\n");
|
|
printf("%-4s%-8snot_from_opt_level\n", "", "--->");
|
|
printf("%-4s%-8sfrom_opt_level.\n", "", ";");
|
|
|
|
printf("\n");
|
|
printf(":- pred update_opt_tuple(maybe_from_opt_level::in, ");
|
|
printf("option_table::in,\n");
|
|
printf("%-4s%s::in, %s::in, %s::out,\n",
|
|
"", switch_type_name, record_type_name, record_type_name);
|
|
printf("%-4smaybe_seen_opt_level::in, maybe_seen_opt_level::out) is det.\n", "");
|
|
printf("\n");
|
|
|
|
# Each arm of the switch that handles an ordinary bool or int option
|
|
# forwards its work to a separate tiny predicate. We used to generate
|
|
# inline code for them, but this led to the Java bytecode generated
|
|
# for update_opt_tuple to exceed the 64k limit on the size of a single
|
|
# method. This was Mantis bug #522.
|
|
|
|
printf("update_opt_tuple(FromOptLevel, OptionTable, %s, !%s,\n",
|
|
switch_var_name, record_var_name);
|
|
printf("%-8s!MaybeSeenOptLevel) :-\n",
|
|
"", switch_var_name, record_var_name);
|
|
printf("%-4srequire_complete_switch [%s]\n", "", switch_var_name);
|
|
lparen_or_semi = "(";
|
|
for (i = 0; i < next_bool_opt; i++) {
|
|
printf("%-4s%s\n", "", lparen_or_semi);
|
|
lparen_or_semi = ";";
|
|
printf("%-8s%s = oo_%s(Bool),\n", "",
|
|
switch_var_name, bool_field_names[i]);
|
|
if (bool_field_names[i] == "opt_delay_slot") {
|
|
printf("%-8supdate_opt_tuple_bool_%s(OptionTable, Bool, !%s)\n",
|
|
"", bool_field_names[i], record_var_name);
|
|
} else {
|
|
printf("%-8supdate_opt_tuple_bool_%s(Bool, !%s)\n",
|
|
"", bool_field_names[i], record_var_name);
|
|
}
|
|
}
|
|
for (i = 0; i < next_int_opt; i++) {
|
|
printf("%-4s%s\n", "", lparen_or_semi);
|
|
lparen_or_semi = ";";
|
|
printf("%-8s%s = oo_%s(N),\n",
|
|
"", switch_var_name, int_field_names[i]);
|
|
printf("%-8supdate_opt_tuple_int_%s(FromOptLevel, N, !%s)\n",
|
|
"", int_field_names[i], record_var_name);
|
|
}
|
|
for (i = 0; i < next_string_opt; i++) {
|
|
printf("%-4s%s\n", "", lparen_or_semi);
|
|
lparen_or_semi = ";";
|
|
printf("%-8s%s = oo_%s(Str),\n",
|
|
"", switch_var_name, string_field_names[i]);
|
|
printf("%-8s!%s ^ ot_%s := Str\n",
|
|
"", record_var_name, string_field_names[i]);
|
|
}
|
|
printf("%-4s%s\n", "", lparen_or_semi);
|
|
lparen_or_semi = ";";
|
|
printf("%-8s%s = oo_opt_level(OptLevel),\n", "", switch_var_name);
|
|
printf("%-8sset_opts_upto_level(OptionTable, 0, OptLevel, !%s, !.MaybeSeenOptLevel, _),\n",
|
|
"", record_var_name);
|
|
printf("%-8s!:MaybeSeenOptLevel = seen_opt_level\n", "");
|
|
|
|
printf("%-4s%s\n", "", lparen_or_semi);
|
|
printf("%-8s%s = oo_opt_for_space,\n", "", switch_var_name);
|
|
printf("%-8sset_opts_for_space(!%s)\n", "", record_var_name);
|
|
printf("%-4s).\n\n", "");
|
|
|
|
for (i = 0; i < next_bool_opt; i++) {
|
|
if (bool_field_names[i] == "opt_delay_slot") {
|
|
printf(":- pred update_opt_tuple_bool_%s(",
|
|
bool_field_names[i]);
|
|
printf("option_table::in, bool::in,\n");
|
|
printf("%-4s%s::in, %s::out) is det.\n\n",
|
|
"", record_type_name, record_type_name);
|
|
printf("update_opt_tuple_bool_%s(OptionTable, Bool, !%s) :-\n",
|
|
bool_field_names[i], record_var_name);
|
|
} else {
|
|
printf(":- pred update_opt_tuple_bool_%s(",
|
|
bool_field_names[i]);
|
|
printf("bool::in,\n");
|
|
printf("%-4s%s::in, %s::out) is det.\n\n",
|
|
"", record_type_name, record_type_name);
|
|
printf("update_opt_tuple_bool_%s(Bool, !%s) :-\n",
|
|
bool_field_names[i], record_var_name);
|
|
}
|
|
|
|
printf("%-4sOldValue = !.%s ^ ot_%s,\n",
|
|
"", record_var_name, bool_field_names[i]);
|
|
printf("%-4s( if\n", "");
|
|
if (bool_field_names[i] == "opt_delay_slot") {
|
|
printf("%-8sgetopt.lookup_bool_option(OptionTable, have_delay_slot, yes),\n",
|
|
"");
|
|
}
|
|
printf("%-8sBool = yes\n", "");
|
|
printf("%-4sthen\n", "");
|
|
printf("%-8s(\n", "");
|
|
printf("%-12sOldValue = do_not_%s,\n", "", bool_field_names[i]);
|
|
printf("%-12s!%s ^ ot_%s := %s\n",
|
|
"", record_var_name, bool_field_names[i], bool_field_names[i]);
|
|
printf("%-8s;\n", "");
|
|
printf("%-12sOldValue = %s\n", "", bool_field_names[i]);
|
|
printf("%-8s)\n", "");
|
|
printf("%-4selse\n", "");
|
|
printf("%-8s(\n", "");
|
|
printf("%-12sOldValue = do_not_%s\n", "", bool_field_names[i]);
|
|
printf("%-8s;\n", "");
|
|
printf("%-12sOldValue = %s,\n", "", bool_field_names[i]);
|
|
printf("%-12s!%s ^ ot_%s := do_not_%s\n",
|
|
"", record_var_name, bool_field_names[i], bool_field_names[i]);
|
|
printf("%-8s)\n", "");
|
|
printf("%-4s).\n\n", "");
|
|
}
|
|
|
|
for (i = 0; i < next_int_opt; i++) {
|
|
printf(":- pred update_opt_tuple_int_%s(\n",
|
|
int_field_names[i]);
|
|
printf("%-4smaybe_from_opt_level::in, int::in,\n", "");
|
|
printf("%-4s%s::in, %s::out) is det.\n\n",
|
|
"", record_type_name, record_type_name);
|
|
printf("update_opt_tuple_int_%s(FromOptLevel, N, !%s) :-\n",
|
|
int_field_names[i], record_var_name);
|
|
|
|
printf("%-4s(\n", "");
|
|
printf("%-8sFromOptLevel = not_from_opt_level,\n", "");
|
|
printf("%-8s!%s ^ ot_%s := N\n",
|
|
"", record_var_name, int_field_names[i]);
|
|
printf("%-4s;\n", "");
|
|
printf("%-8sFromOptLevel = from_opt_level,\n", "");
|
|
printf("%-8sOldN = !.%s ^ ot_%s,\n",
|
|
"", record_var_name, int_field_names[i]);
|
|
printf("%-8s!%s ^ ot_%s := int.max(OldN, N)\n",
|
|
"", record_var_name, int_field_names[i]);
|
|
printf("%-4s).\n\n", "");
|
|
}
|
|
|
|
###################################################################
|
|
|
|
# The code from here to the end of the script generates code that
|
|
# should be included in the special_handler predicate in options.m.
|
|
|
|
handler_file = "handler_file";
|
|
arm_start = "(";
|
|
for (i = 0; i < next_bool_opt; i++) {
|
|
printf("%-8s%s\n", "", arm_start) > handler_file;
|
|
arm_start = ";";
|
|
printf("%-12sOption = optopt_%s,\n",
|
|
"", bool_opts[i]) > handler_file;
|
|
printf("%-12sSpecialData = bool(Bool),\n", "") > handler_file;
|
|
printf("%-12sOptOption = oo_%s(Bool)\n",
|
|
"", bool_field_names[i]) > handler_file;
|
|
}
|
|
for (i = 0; i < next_int_opt; i++) {
|
|
printf("%-8s;\n", "") > handler_file;
|
|
printf("%-12sOption = optopt_%s,\n",
|
|
"", int_opts[i]) > handler_file;
|
|
printf("%-12sSpecialData = int(N),\n", "") > handler_file;
|
|
printf("%-12sOptOption = oo_%s(N)\n",
|
|
"", int_field_names[i]) > handler_file;
|
|
}
|
|
for (i = 0; i < next_string_opt; i++) {
|
|
printf("%-8s;\n", "") > handler_file;
|
|
printf("%-12sOption = optopt_%s,\n",
|
|
"", string_opts[i]) > handler_file;
|
|
printf("%-12sSpecialData = string(Str),\n", "") > handler_file;
|
|
printf("%-12sOptOption = oo_%s(Str)\n",
|
|
"", string_field_names[i]) > handler_file;
|
|
}
|
|
|
|
printf("%-8s;\n", "") > handler_file;
|
|
printf("%-12sOption = opt_level,\n", "") > handler_file;
|
|
printf("%-12sSpecialData = int(N),\n", "") > handler_file;
|
|
printf("%-12sOptOption = oo_opt_level(N)\n", "") > handler_file;
|
|
|
|
printf("%-8s;\n", "") > handler_file;
|
|
printf("%-12sOption = opt_space,\n", "") > handler_file;
|
|
printf("%-12sSpecialData = none,\n", "") > handler_file;
|
|
printf("%-12sOptOption = oo_opt_for_space\n", "") > handler_file;
|
|
|
|
printf("%-8s),\n", "") > handler_file;
|
|
}
|