Files
mercury/compiler/compute_grade.m
Zoltan Somogyi 32006a1c7c Rename and generalize .c_debug to .target_debug.
runtime/mercury_grade.h:
    Rename the grade modifier, and the C macro that represents it.

compiler/options.m:
    Rename the --c-debug-grade option to --target-debug-grade.

compiler/compute_grade.m:
    Rename the grade modifier, and the option that represents it.

    Restrict the .target_debut grade modifier to MLDS grades.

compiler/handle_options.m:
    Implement --target-debug-grade by having it imply --target-debug.

compiler/compile_target_code.m:
compiler/link_target_code.m:
    Pay attention to either --target-debug-grade (for purposes related
    to the grade itself) and to --target-debug (for all other purposes).

scripts/canonical_grade.in:
scripts/canonical_grade.sh-subr:
scripts/final_grade_options.sh-subr:
scripts/init_grade_options.sh-subr:
scripts/parse_grade_options.sh-subr:
    Parse target_debug grade modifiers and --target-debug-grade options
    instead of c_debug grade modifiers and --c-debug-grade options.

    Add (normally commented-out) infrastructure to make it easier
    to debug changes.

    Restrict the .target_debut grade modifier to MLDS grades.

scripts/mgnuc.in:
scripts/mgnuc_file_opts.sh-subr:
    Rename some variables to clarify the distinction between the
    --target-debug option (which, like -g, enabled debugging of only one file)
    and the --target-debug-grade option (which enables it for the whole
    program).

configure.ac:
    Make it easier to debug grade-related changes by recording
    both autoconfigured and user-supplied grades that the rejected by
    the canonical_grade script.

    Conform to the changes above.

README.sanitizers:
doc/user_guide.texi:
grade_lib/grade_spec.m:
grade_lib/grade_string.m:
scripts/ml.in:
tests/warnings/help_text.err_exp:
tools/lmc.in:
tools/test_mercury:
    Conform to the changes above.

scripts/Mmake.vars.in:
    Add some XXXs about style.
2025-08-09 21:48:23 +02:00

760 lines
30 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 1994-2012 The University of Melbourne.
% Copyright (C) 2014-2017, 2019-2022, 2024-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.
%---------------------------------------------------------------------------%
%
% This module computes the grade from the values of the options.
%
%---------------------------------------------------------------------------%
:- module libs.compute_grade.
:- interface.
:- import_module libs.globals.
:- import_module libs.options.
:- import_module parse_tree.
:- import_module parse_tree.error_spec.
:- import_module list.
%---------------------------------------------------------------------------%
% This predicate generates error messages for various combinations of
% grade components (or their equivalent command line options) that are
% incompatible with each other.
%
% NOTE this predicate does not check *all* combinations, some of the checks
% are carried out by the predicate convert_options_to_globals, while others
% are carried out by the code that decomposes the grade string.
%
% NOTE: since grade components may be specified by either a grade component
% or via a command line option, please try to ensure that the error
% messages generated by this predicate cover both situations.
%
% XXX we don't currently handle the .par, .threadscope or any undocumented
% grade components here.
%
:- pred check_grade_component_compatibility(globals::in,
compilation_target::in, gc_method::in,
list(error_spec)::in, list(error_spec)::out) is det.
% Apply some sanity checks to the library grade set and then apply any
% library grade filters to that set.
%
% XXX we could do better with the sanity checks, currently we only
% check that all the grade components are valid and that there are
% no duplicate grade components.
%
% XXX Actuall, I (zs) see no sanity checks here at all.
%
:- pred handle_libgrade_component_incl_excl(globals::in, globals::out,
list(error_spec)::in, list(error_spec)::out) is det.
% The inverse of compute_grade: given a grade, set the appropriate options.
%
:- pred convert_grade_option(string::in, option_table::in, option_table::out)
is semidet.
%---------------------------------------------------------------------------%
% Given the current set of options, figure out which grade to use.
%
:- pred compute_grade(globals::in, string::out) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module libs.compiler_util.
:- import_module assoc_list.
:- import_module bool.
:- import_module char.
:- import_module getopt.
:- import_module int.
:- import_module map.
:- import_module maybe.
:- import_module pair.
:- import_module set.
:- import_module solutions.
:- import_module string.
%---------------------------------------------------------------------------%
check_grade_component_compatibility(Globals, Target, GC_Method, !Specs) :-
TargetStr = compilation_target_string(Target),
% Check that the GC method is compatible with the target language.
%
(
Target = target_c
% XXX how are we supposed to handle gc_automatic for C?
;
( Target = target_csharp
; Target = target_java
),
(
% At this point, both of these values are acceptable for the
% non-C targets.
( GC_Method = gc_automatic
; GC_Method = gc_none
)
;
( GC_Method = gc_boehm
; GC_Method = gc_boehm_debug
),
BoehmSpec =
[words("Use of Boehm GC is incompatible with"),
words("target language"), words(TargetStr), suffix("."), nl],
add_error(phase_options, BoehmSpec, !Specs)
;
GC_Method = gc_hgc,
HGCSpec =
[words("Use of HGC is incompatible with"),
words("target language"), words(TargetStr), suffix("."), nl],
add_error(phase_options, HGCSpec, !Specs)
;
GC_Method = gc_accurate,
AGCSpec =
[words("Use of accurate GC is incompatible with"),
words("target language"), words(TargetStr), suffix("."), nl],
add_error(phase_options, AGCSpec, !Specs)
)
),
% Time profiling is only supported by the C back-ends.
%
globals.lookup_bool_option(Globals, profile_time, ProfileTime),
(
ProfileTime = yes,
(
( Target = target_java
; Target = target_csharp
),
TimeProfpec =
[words("Time profiling is incompatible with"),
words("target language"), words(TargetStr), suffix("."), nl],
add_error(phase_options, TimeProfpec, !Specs)
;
Target = target_c
)
;
ProfileTime = no
),
% Memory profiling is only supported by the C back-ends.
%
globals.lookup_bool_option(Globals, profile_memory, ProfileMemory),
(
ProfileMemory = yes,
(
( Target = target_java
; Target = target_csharp
),
MemProfpec =
[words("Memory profiling is incompatible with"),
words("target language"), words(TargetStr), suffix("."), nl],
add_error(phase_options, MemProfpec, !Specs)
;
Target = target_c
)
;
ProfileMemory = no
),
% Compatibility with profile_deep is checked by
% handle_profiling_options in handle_options.m.
% Compatibility with debugging is checked by
% handle_debugging_options in handle_options.m.
% Trailing is only supported by the C back-ends.
%
globals.lookup_bool_option(Globals, use_trail, UseTrail),
(
UseTrail = yes,
(
( Target = target_java
; Target = target_csharp
),
TrailSpec =
[words("Trailing is incompatible with"),
words("target language"), words(TargetStr), suffix("."), nl],
add_error(phase_options, TrailSpec, !Specs)
;
Target = target_c
)
;
UseTrail = no
),
% Stack segments are only supported by the low level C back-end.
%
globals.lookup_bool_option(Globals, stack_segments, StackSegments),
globals.lookup_bool_option(Globals, highlevel_code, HighLevelCode),
(
StackSegments = yes,
(
Target = target_c,
(
HighLevelCode = yes,
StackSegmentpec =
[words("Stack segments are incompatible with"),
words("the high-level C backend."), nl],
add_error(phase_options, StackSegmentpec, !Specs)
;
HighLevelCode = no
)
;
( Target = target_java
; Target = target_csharp
),
StackSegmentpec =
[words("Stack segments are incompatible with"),
words("target language"), words(TargetStr), suffix("."), nl],
add_error(phase_options, StackSegmentpec, !Specs)
)
;
StackSegments = no
),
% Single precision floats are only compatible with the C back-ends.
% (At least for Mercury, that's currently the case.)
globals.lookup_bool_option(Globals, single_prec_float, SinglePrecFloat),
(
SinglePrecFloat = yes,
(
( Target = target_java
; Target = target_csharp
),
SPFSpec =
[words("Single precision floats are incompatible with"),
words("target language"), words(TargetStr), suffix("."), nl],
add_error(phase_options, SPFSpec, !Specs)
;
Target = target_c
)
;
SinglePrecFloat = no
),
globals.lookup_bool_option(Globals, target_debug_grade, TargetDebugGrade),
(
TargetDebugGrade = yes,
(
HighLevelCode = no,
TDGSpec =
[words("The target_debug grade modifier is incompatible with"),
words("the low level C backend."), nl],
add_error(phase_options, TDGSpec, !Specs)
;
HighLevelCode = yes
)
;
TargetDebugGrade = no
).
%---------------------------------------------------------------------------%
handle_libgrade_component_incl_excl(!Globals, !Specs) :-
globals.lookup_accumulating_option(!.Globals,
library_install_grades_incl_components, IncludeComponentStrs),
globals.lookup_accumulating_option(!.Globals,
library_install_grades_excl_components, OmitComponentStrs),
list.foldl2(string_to_grade_component("included"),
IncludeComponentStrs, [], IncludeComponents, !Specs),
list.foldl2(string_to_grade_component("excluded"),
OmitComponentStrs, [], OmitComponents, !Specs),
some [!LibGrades] (
globals.lookup_accumulating_option(!.Globals, library_install_grades,
!:LibGrades),
% NOTE: the two calls to foldl2 here will preserve the original
% relative ordering of the library grades.
list.foldl2(filter_grade(must_contain, IncludeComponents),
!.LibGrades, [], !:LibGrades, !Specs),
list.foldl2(filter_grade(must_not_contain, OmitComponents),
!.LibGrades, [], !:LibGrades, !Specs),
globals.set_option(library_install_grades, accumulating(!.LibGrades),
!Globals)
).
% string_to_grade_component(OptionStr, Comp, !Comps, !Specs):
%
% If `Comp' is a string that represents a valid grade component
% then add it to !Comps. If it is not, then emit an error message.
% `OptionStr' should be the name of the command line option for
% which the error is to be reported.
%
:- pred string_to_grade_component(string::in, string::in,
list(string)::in, list(string)::out,
list(error_spec)::in, list(error_spec)::out) is det.
string_to_grade_component(FilterDesc, Comp, !Comps, !Specs) :-
% XXX Including FilterDesc in the error messages seems odd, because
% the resulting text can be read as implying that
%
% - a string is NOT a valid grade component for e.g. inclusion, but
% - the same string IS a valid grade component for e.g. exclusion,
%
% even though of course that implication is false.
( if grade_component_table(Comp, _, _, _, _) then
!:Comps = [Comp | !.Comps]
else
Pieces = [words("Unknown"), words(FilterDesc),
words("library grade component:"), quote(Comp), suffix("."), nl],
add_error(phase_options, Pieces, !Specs)
).
% filter_grade(FilterPred, Components, GradeString, !Grades, !Specs):
%
% Convert `GradeString' into a list of grade component strings, and
% then check whether the given grade should be filtered from the
% library grade set by applying the closure `FilterPred(Components)',
% to that list. The grade is removed from the library grade set if
% that application fails.
%
% Emits an error if `GradeString' cannot be converted into a list
% of grade component strings.
%
:- pred filter_grade(
pred(list(string), list(string))::in(pred(in, in) is semidet),
list(string)::in, string::in, list(string)::in, list(string)::out,
list(error_spec)::in, list(error_spec)::out) is det.
filter_grade(FilterPred, CondComponents, GradeString, !Grades, !Specs) :-
grade_string_to_comp_strings(GradeString, MaybeGrade, !Specs),
(
MaybeGrade = yes(GradeComponents),
( if FilterPred(CondComponents, GradeComponents) then
!:Grades = [GradeString | !.Grades]
else
true
)
;
MaybeGrade = no
).
:- pred must_contain(list(string)::in, list(string)::in) is semidet.
must_contain(IncludeComponents, GradeComponents) :-
all [Component] (
list.member(Component, IncludeComponents)
=>
list.member(Component, GradeComponents)
).
:- pred must_not_contain(list(string)::in, list(string)::in) is semidet.
must_not_contain(OmitComponents, GradeComponents) :-
all [Component] (
list.member(Component, OmitComponents)
=>
not list.member(Component, GradeComponents)
).
% Convert a grade string into a list of component strings.
% Emit an invalid grade error if the conversion fails.
%
:- pred grade_string_to_comp_strings(string::in, maybe(list(string))::out,
list(error_spec)::in, list(error_spec)::out) is det.
grade_string_to_comp_strings(GradeString, MaybeGrade, !Specs) :-
split_grade_string(GradeString, Components),
IsValidComponent =
( pred(Str::in) is semidet :-
grade_component_table(Str, _, _, _, _)
),
list.filter(IsValidComponent, Components,
ValidComponents0, InvalidComponents),
(
InvalidComponents = [],
list.sort_and_remove_dups(ValidComponents0, ValidComponents),
( if list.length(ValidComponents0) > list.length(ValidComponents) then
GradeSpec =
[words("Invalid library grade:"), quote(GradeString), nl],
add_error(phase_options, GradeSpec, !Specs),
MaybeGrade = no
else
MaybeGrade = yes(ValidComponents)
)
;
InvalidComponents = [_ | _],
GradeSpec =
[words("Invalid library grade:"), quote(GradeString), nl],
add_error(phase_options, GradeSpec, !Specs),
MaybeGrade = no
).
%---------------------------------------------------------------------------%
% IMPORTANT: any changes here may require similar changes to other files,
% see the list of files at the top of runtime/mercury_grade.h
%
% The grade_component type should have one constructor for each
% dimension of the grade. It is used when converting the components
% of the grade string to make sure the grade string doesn't contain
% more than one value for each dimension (eg *.gc.agc).
% Adding a value here will require adding clauses to the
% grade_component_table.
%
% A --grade option causes all the grade dependent options to be
% reset, and only those described by the grade string to be set.
% The value to which a grade option should be reset should be given
% in the grade_start_values table below.
%
% The ordering of the components here is the same as the order used in
% scripts/canonical_grand.sh-subr, and any change here will require a
% corresponding change there. The only place where the ordering actually
% matters is for constructing the pathname for the grade of the library,
% etc for linking (and installation).
%
:- type grade_component
---> comp_gcc_ext % gcc extensions etc. -- see
% grade_component_table
; comp_par % parallelism / multithreading
; comp_par_threadscope
% Whether to support theadscope profiling of
% parallel grades.
; comp_gc % the kind of GC to use
; comp_prof % what profiling options to use
; comp_term_size % whether or not to record term sizes
; comp_trail % whether or not to use trailing
; comp_minimal_model % whether we set up for minimal model tabling
; comp_pregen_spf % whether to assume settings for the
% pregenerated C source distribution;
% and whether or not to use single precision
% floating point values.
; comp_lowlevel % what to do to target code
; comp_trace % tracing/debugging options
; comp_stack_extend % automatic stack extension
; comp_regions. % Whether or not to use region-based memory
% management.
convert_grade_option(GradeString, Options0, Options) :-
reset_grade_options(Options0, Options1),
split_grade_string(GradeString, Components),
set.init(NoComps),
list.foldl2(
( pred(CompStr::in, Opts0::in, Opts::out,
CompSet0::in, CompSet::out) is semidet :-
grade_component_table(CompStr, Comp, CompOpts, MaybeTargets, _),
% Check that the component isn't mentioned more than once.
not set.member(Comp, CompSet0),
set.insert(Comp, CompSet0, CompSet),
add_option_list(CompOpts, Opts0, Opts1),
% XXX Here the behaviour matches what used to happen and that is
% to only set the target option iff there was only one possible
% target. Is this a bug?
( if MaybeTargets = yes([Target]) then
add_option_list([target - Target], Opts1, Opts)
else
Opts = Opts1
)
), Components, Options1, Options, NoComps, _FinalComps).
:- pred add_option_list(list(pair(option, option_data))::in, option_table::in,
option_table::out) is det.
add_option_list(CompOpts, Opts0, Opts) :-
list.foldl(
( pred(Opt::in, Opts1::in, Opts2::out) is det :-
Opt = Option - Data,
map.set(Option, Data, Opts1, Opts2)
), CompOpts, Opts0, Opts).
%---------------------------------------------------------------------------%
compute_grade(Globals, GradeStr) :-
globals.get_options(Globals, Options),
compute_grade_components(Options, Components),
(
Components = [],
GradeStr = "none"
;
Components = [_ | _],
ComponentNames = assoc_list.values(Components),
GradeStr = string.join_list(".", ComponentNames)
).
:- pred compute_grade_components(option_table::in,
list(pair(grade_component, string))::out) is det.
compute_grade_components(Options, GradeComponents) :-
solutions(
( pred(CompData::out) is nondet :-
grade_component_table(Name, Comp, CompOpts, MaybeTargets,
IncludeInGradeString),
% For a possible component of the grade string, include it in the
% actual grade string if all the option settings that it implies
% are true.
all [Opt, Value] (
list.member(Opt - Value, CompOpts)
=>
map.search(Options, Opt, Value)
),
% Don't include `.mm' or `.dmm' in grade strings because they are
% just synonyms for `.mmsc' and `.dmmsc' respectively.
IncludeInGradeString = yes,
% When checking gcc_ext there exist grades which can have
% more than one possible target, ensure that the target
% in the options table matches one of the possible targets.
(
MaybeTargets = yes(Targets),
list.member(Target, Targets),
map.search(Options, target, Target)
;
MaybeTargets = no
),
% NOTE We return Comp alongside name, even though our caller
% ignores it, because we want solutions to sort grade components
% on Comp, not on Name.
CompData = Comp - Name
), GradeComponents).
% grade_component_table(ComponetStr, Component, Options, MaybeTargets,
% IncludeGradeStr):
%
% `IncludeGradeStr' is `yes' if the component should be included
% in the grade string. It is `no' for those components that are
% just synonyms for other comments, as .mm is for .mmsc.
%
:- pred grade_component_table(string, grade_component,
list(pair(option, option_data)), maybe(list(option_data)), bool).
:- mode grade_component_table(in, out, out, out, out) is semidet.
:- mode grade_component_table(out, in, out, out, out) is multi.
:- mode grade_component_table(out, out, out, out, out) is multi.
% Base components.
% These specify the basic compilation model we use,
% including the choice of back-end and the use of gcc extensions.
grade_component_table("none", comp_gcc_ext, [
asm_labels - bool(no),
gcc_non_local_gotos - bool(no),
gcc_global_registers - bool(no),
highlevel_code - bool(no) ],
yes([string("c")]), yes).
grade_component_table("reg", comp_gcc_ext, [
asm_labels - bool(no),
gcc_non_local_gotos - bool(no),
gcc_global_registers - bool(yes),
highlevel_code - bool(no)],
yes([string("c")]), yes).
grade_component_table("jump", comp_gcc_ext, [
asm_labels - bool(no),
gcc_non_local_gotos - bool(yes),
gcc_global_registers - bool(no),
highlevel_code - bool(no)],
yes([string("c")]), yes).
grade_component_table("asm_jump", comp_gcc_ext, [
asm_labels - bool(yes),
gcc_non_local_gotos - bool(yes),
gcc_global_registers - bool(no),
highlevel_code - bool(no)],
yes([string("c")]), yes).
grade_component_table("fast", comp_gcc_ext, [
asm_labels - bool(no),
gcc_non_local_gotos - bool(yes),
gcc_global_registers - bool(yes),
highlevel_code - bool(no)],
yes([string("c")]), yes).
grade_component_table("asm_fast", comp_gcc_ext, [
asm_labels - bool(yes),
gcc_non_local_gotos - bool(yes),
gcc_global_registers - bool(yes),
highlevel_code - bool(no)],
yes([string("c")]), yes).
grade_component_table("hlc", comp_gcc_ext, [
asm_labels - bool(no),
gcc_non_local_gotos - bool(no),
gcc_global_registers - bool(no),
highlevel_code - bool(yes)],
yes([string("c")]), yes).
grade_component_table("java", comp_gcc_ext, [
asm_labels - bool(no),
gcc_non_local_gotos - bool(no),
gcc_global_registers - bool(no),
highlevel_code - bool(yes)],
yes([string("java")]), yes).
grade_component_table("csharp", comp_gcc_ext, [
asm_labels - bool(no),
gcc_non_local_gotos - bool(no),
gcc_global_registers - bool(no),
highlevel_code - bool(yes)],
yes([string("csharp")]), yes).
% Parallelism/multithreading components.
grade_component_table("par", comp_par, [parallel - bool(yes)], no, yes).
% Threadscope profiling in parallel grades.
grade_component_table("threadscope", comp_par_threadscope,
[threadscope - bool(yes)], no, yes).
% GC components.
grade_component_table("gc", comp_gc, [gc - string("boehm")], no, yes).
grade_component_table("gcd", comp_gc, [gc - string("boehm_debug")], no, yes).
grade_component_table("hgc", comp_gc, [gc - string("hgc")], no, yes).
grade_component_table("agc", comp_gc, [gc - string("accurate")], no, yes).
% Profiling components.
grade_component_table("prof", comp_prof,
[profile_time - bool(yes), profile_calls - bool(yes),
profile_memory - bool(no), profile_deep - bool(no)], no, yes).
grade_component_table("proftime", comp_prof,
[profile_time - bool(yes), profile_calls - bool(no),
profile_memory - bool(no), profile_deep - bool(no)], no, yes).
grade_component_table("profcalls", comp_prof,
[profile_time - bool(no), profile_calls - bool(yes),
profile_memory - bool(no), profile_deep - bool(no)], no, yes).
grade_component_table("memprof", comp_prof,
[profile_time - bool(no), profile_calls - bool(yes),
profile_memory - bool(yes), profile_deep - bool(no)], no, yes).
grade_component_table("profall", comp_prof,
[profile_time - bool(yes), profile_calls - bool(yes),
profile_memory - bool(yes), profile_deep - bool(no)], no, yes).
grade_component_table("profdeep", comp_prof,
[profile_time - bool(no), profile_calls - bool(no),
profile_memory - bool(no), profile_deep - bool(yes)], no, yes).
% Term size components.
grade_component_table("tsw", comp_term_size,
[record_term_sizes_as_words - bool(yes),
record_term_sizes_as_cells - bool(no)], no, yes).
grade_component_table("tsc", comp_term_size,
[record_term_sizes_as_words - bool(no),
record_term_sizes_as_cells - bool(yes)], no, yes).
% Trailing components.
grade_component_table("tr", comp_trail,
[use_trail - bool(yes)], no, yes).
% Minimal model tabling components.
% NOTE: we do not include `.mm' and `.dmm' in grade strings
% because they are just synonyms for `.mmsc' and `.dmmsc'.
grade_component_table("mm", comp_minimal_model,
[use_minimal_model_stack_copy - bool(yes),
use_minimal_model_own_stacks - bool(no),
minimal_model_debug - bool(no)], no, no).
grade_component_table("dmm", comp_minimal_model,
[use_minimal_model_stack_copy - bool(yes),
use_minimal_model_own_stacks - bool(no),
minimal_model_debug - bool(yes)], no, no).
grade_component_table("mmsc", comp_minimal_model,
[use_minimal_model_stack_copy - bool(yes),
use_minimal_model_own_stacks - bool(no),
minimal_model_debug - bool(no)], no, yes).
grade_component_table("dmmsc", comp_minimal_model,
[use_minimal_model_stack_copy - bool(yes),
use_minimal_model_own_stacks - bool(no),
minimal_model_debug - bool(yes)], no, yes).
grade_component_table("mmos", comp_minimal_model,
[use_minimal_model_stack_copy - bool(no),
use_minimal_model_own_stacks - bool(yes),
minimal_model_debug - bool(no)], no, yes).
grade_component_table("dmmos", comp_minimal_model,
[use_minimal_model_stack_copy - bool(no),
use_minimal_model_own_stacks - bool(yes),
minimal_model_debug - bool(yes)], no, yes).
% Settings for pre-generated source distribution
% or single-precision floats.
grade_component_table("pregen", comp_pregen_spf,
[pregenerated_dist - bool(yes)], no, yes).
grade_component_table("spf", comp_pregen_spf,
[single_prec_float - bool(yes),
unboxed_float - bool(yes)], no, yes).
% Debugging/Tracing components.
grade_component_table("decldebug", comp_trace,
[exec_trace - bool(yes), decl_debug - bool(yes)], no, yes).
grade_component_table("debug", comp_trace,
[exec_trace - bool(yes), decl_debug - bool(no)], no, yes).
grade_component_table("ssdebug", comp_trace,
[source_to_source_debug - bool(yes)], no, yes).
% Target level debugging components.
grade_component_table("target_debug", comp_lowlevel,
[target_debug_grade - bool(yes)], no, yes).
% Stack extension components.
grade_component_table("exts", comp_stack_extend,
[extend_stacks_when_needed - bool(yes), stack_segments - bool(no)],
no, yes).
grade_component_table("stseg", comp_stack_extend,
[extend_stacks_when_needed - bool(no), stack_segments - bool(yes)],
no, yes).
% Region-based memory managment components
grade_component_table("rbmm", comp_regions,
[use_regions - bool(yes),
use_regions_debug - bool(no), use_regions_profiling - bool(no)],
no, yes).
grade_component_table("rbmmd", comp_regions,
[use_regions - bool(yes),
use_regions_debug - bool(yes), use_regions_profiling - bool(no)],
no, yes).
grade_component_table("rbmmp", comp_regions,
[use_regions - bool(yes),
use_regions_debug - bool(no), use_regions_profiling - bool(yes)],
no, yes).
grade_component_table("rbmmdp", comp_regions,
[use_regions - bool(yes),
use_regions_debug - bool(yes), use_regions_profiling - bool(yes)],
no, yes).
:- pred reset_grade_options(option_table::in, option_table::out) is det.
reset_grade_options(Options0, Options) :-
solutions.aggregate(grade_start_values,
( pred(Pair::in, Opts0::in, Opts::out) is det :-
Pair = Option - Value,
map.set(Option, Value, Opts0, Opts)
), Options0, Options).
:- pred grade_start_values(pair(option, option_data)::out) is multi.
grade_start_values(asm_labels - bool(no)).
grade_start_values(gcc_non_local_gotos - bool(no)).
grade_start_values(gcc_global_registers - bool(no)).
grade_start_values(highlevel_code - bool(no)).
grade_start_values(parallel - bool(no)).
grade_start_values(threadscope - bool(no)).
grade_start_values(gc - string("none")).
grade_start_values(profile_deep - bool(no)).
grade_start_values(profile_time - bool(no)).
grade_start_values(profile_calls - bool(no)).
grade_start_values(profile_memory - bool(no)).
grade_start_values(use_trail - bool(no)).
grade_start_values(use_minimal_model_stack_copy - bool(no)).
grade_start_values(use_minimal_model_own_stacks - bool(no)).
grade_start_values(minimal_model_debug - bool(no)).
grade_start_values(pregenerated_dist - bool(no)).
grade_start_values(single_prec_float - bool(no)).
grade_start_values(exec_trace - bool(no)).
grade_start_values(decl_debug - bool(no)).
grade_start_values(source_to_source_debug - bool(no)).
grade_start_values(extend_stacks_when_needed - bool(no)).
grade_start_values(stack_segments - bool(no)).
grade_start_values(use_regions - bool(no)).
grade_start_values(use_regions_debug - bool(no)).
grade_start_values(use_regions_profiling - bool(no)).
grade_start_values(target_debug_grade - bool(no)).
:- pred split_grade_string(string::in, list(string)::out) is det.
split_grade_string(GradeStr, Components) :-
Components = string.split_at_char('.', GradeStr).
%---------------------------------------------------------------------------%
:- end_module libs.compute_grade.
%---------------------------------------------------------------------------%