Files
mercury/compiler/globals.m
Zoltan Somogyi d067ea1255 Reduce the number of modules that set the exit status ...
... by removing globals.m, handle_options.m recompilation.used_file.m
from that set.

compiler/globals.m:
compiler/recompilation.used_file.m:
    Replace bespoke error reporting code with invocations of standardized
    error reporting predicates.

compiler/handle_options.m:
    Generate error_specs instead of writing out warnings directly.
2026-04-03 01:26:37 +11:00

1413 lines
52 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 1994-2012 The University of Melbourne.
% Copyright (C) 2013-2026 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.
%---------------------------------------------------------------------------%
%
% File: globals.m.
% Main author: fjh.
%
% This module exports the `globals' type and associated access predicates.
% The globals type is used to collect together all the various data
% that would be global variables in an imperative language.
% This global data is stored in the io.state.
%
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- module libs.globals.
:- interface.
:- import_module libs.file_util.
:- import_module libs.op_mode.
:- import_module libs.optimization_options.
:- import_module libs.options.
:- import_module libs.trace_params.
:- import_module mdbcomp.
:- import_module mdbcomp.feedback.
:- import_module mdbcomp.feedback.feedback_info.
:- import_module mdbcomp.sym_name. % for module_name
:- import_module parse_tree.
:- import_module parse_tree.prog_data_pragma.
:- import_module bool.
:- import_module getopt.
:- import_module io.
:- import_module list.
:- import_module map.
:- import_module maybe.
:- import_module set.
%---------------------------------------------------------------------------%
% The main type this module defines. The following sections define
% the types of some of the components of this type.
%
:- type globals.
%---------------------%
:- type maybe_stdlib_grades
---> stdlib_grades_unknown
; stdlib_grades_known(set(string)).
%---------------------%
:- type backend
---> high_level_backend
; low_level_backend.
:- type compilation_target
---> target_c % Generate C code (including GNU C).
; target_csharp % Generate C#.
; target_java. % Generate Java.
:- type foreign_language
---> lang_c
; lang_csharp
; lang_java.
% A string representation of the compilation target suitable
% for use in human-readable error messages.
%
:- func compilation_target_string(compilation_target) = string.
% Return if the compilation target uses high-level data.
%
:- func compilation_target_high_level_data(compilation_target) = bool.
:- func target_lang_to_foreign_export_lang(compilation_target)
= foreign_language.
% A string representation of the foreign language suitable
% for use in human-readable error messages.
%
:- func foreign_language_string(foreign_language) = string.
% A string representation of the foreign language suitable
% for use in machine-readable name mangling.
%
:- func simple_foreign_language_string(foreign_language) = string.
:- pred simple_foreign_language_string(foreign_language, string).
:- mode simple_foreign_language_string(in, out) is det.
:- mode simple_foreign_language_string(out, in) is semidet.
:- func all_foreign_language_strings = list(string).
%---------------------%
% We support these two word sizes.
%
:- type word_size
---> word_size_32
; word_size_64.
%---------------------%
% The GC method specifies how we do garbage collection.
% The last five alternatives are for the C back-ends;
% the first alternative is for compiling to C# or Java
% where the target language implementation handles garbage collection
% automatically.
%
:- type gc_method
---> gc_automatic
% It is the responsibility of the target language that
% we are compiling to handle GC.
; gc_none
% No garbage collection. However, memory may be recovered on
% backtracking if the --reclaim-heap-on-*failure options are set.
; gc_boehm
% The Boehm et al conservative collector.
; gc_boehm_debug
% Boehm collector with debugging enabled.
; gc_hgc
% Ralph Becket's hgc conservative collector.
; gc_accurate.
% Our own Mercury-specific home-grown copying collector.
% See runtime/mercury_accurate_gc.c and compiler/ml_elim_nested.m.
% Returns yes if the GC method is conservative, i.e. if it is `boehm'.
% Conservative GC methods do not support heap reclamation on failure.
%
:- func gc_is_conservative(gc_method) = bool.
%---------------------%
:- type termination_norm
---> norm_simple
; norm_total
; norm_num_data_elems
; norm_size_data_elems.
%---------------------%
:- type may_be_thread_safe == bool.
% For the C backends, what type of C compiler are we using?
%
:- type c_compiler_type
---> cc_gcc(
gcc_major_ver :: maybe(int),
% The major version number, if known.
gcc_minor_ver :: maybe(int),
% The minor version number, if known.
gcc_patch_level :: maybe(int)
% The patch level, if known.
% This is only available since gcc 3.0.
)
; cc_clang(maybe(clang_version))
; cc_cl_x86(maybe(int)) % MSVC targeting x86.
; cc_cl_x64(maybe(int)) % MSVC targeting x86_64 (x64).
; cc_unknown.
:- type clang_version
---> clang_version(int, int, int).
% For the csharp backend, which csharp compiler are we using?
%
:- type csharp_compiler_type
---> csharp_microsoft
; csharp_mono
; csharp_unknown.
:- type static_or_shared
---> sos_static
; sos_shared.
%---------------------%
% Which subdirectories should we put new files in, and which subdirectories
% should we assume existing files are in?
%
:- type subdir_setting
---> use_cur_dir
% All files are always in the current directory.
; use_cur_ngs_subdir
% Files can be either in the current directory,
% or in a non-grade-specific subdirectory.
; use_cur_ngs_gs_subdir.
% Files can be in the current directory,
% in a non-grade-specific subdirectory, or
% in a grade-specific subdirectory.
%---------------------%
% The strategy for determining the reuse possibilities, i.e., either
% reuse is only allowed between terms that have exactly the same cons_id,
% or reuse is also allowed between terms that have different cons_id, yet
% where the difference in arity is not bigger than a given threshold.
%
:- type reuse_strategy
---> same_cons_id
; within_n_cells_difference(int).
%---------------------%
% The env_type specifies the environment in which a Mercury program
% is being run or is expected to be run. This is used both for the
% compiler itself, via the --host-env-type option, and for the program
% being compiled, via the --target-env-type option. Note that users
% need to be able to specify the former because one Mercury install
% (e.g., on Windows) can be called from different environments.
%
:- type env_type
---> env_type_posix
% A generic POSIX-like environment: this covers most Linux systems,
% Mac OS X, FreeBSD, Solaris etc.
; env_type_cygwin
% The Cygwin shell and utilities on Windows.
; env_type_msys
% MinGW with the MSYS environment on Windows.
; env_type_win_cmd
% The Windows command-line interpreter (cmd.exe).
; env_type_powershell.
% Windows PowerShell.
% (NOTE: COMSPEC must be pointing to powershell.exe not cmd.exe.)
%---------------------%
% The tracing levels to use for a module when doing the source to source
% debugging transformation.
:- type ssdb_trace_level
---> ssdb_none
% No tracing of this module.
; ssdb_shallow
% Shallow trace all procedures in this module.
; ssdb_deep.
% Deep trace all procedures in this module.
%---------------------%
% This type specifies how the compiler should install files and
% directories. Values of this type only affect how the compiler itself does
% file installation; they do not affect file installation done by mmake.
:- type install_method
---> install_method_external_cmd
% Files and directories should be installed by invoking a command
% (e.g. cp or cp -R) via the shell of the underlying operation
% system. (See the file_install_cmd/0 type below.)
; install_method_internal_code.
% Files and directories should be installed by invoking an OS or
% target language call, or by using predicates implemented using
% standard Mercury file operations.
%---------------------%
% This type specifies the external command the compiler uses to install
% files.
%
:- type file_install_cmd
---> install_cmd_user(
string % Cmd.
)
% Command specified by the user using --install-command.
; install_cmd_cp.
% POSIX conformant cp command.
%---------------------%
:- type line_number_range
---> line_number_range(
maybe(int), % The minimum line number, if there is one.
maybe(int) % The maximum line number, if there is one.
).
% Map file names to the line number ranges for which to report errors.
% If a file name has no entry in this map, all its errors should be
% reported.
%
% An entry with the empty string as the key applies to every file.
:- type limit_error_contexts_map == map(string, list(line_number_range)).
%---------------------%
% Map each extension in the interface_ext, intermod_ext, c_incl_ext and
% lib_ext types to the list of directories we should search.
:- type ext_dirs_maps
---> ext_dirs_maps(
edm_interface :: ext_interface_dirs_map,
edm_intermod :: ext_intermod_dirs_map,
edm_c_incl :: ext_c_incl_dirs_map,
edm_lib :: ext_lib_dirs_map,
edm_stdlib :: ext_stdlib_dirs_map
).
:- type ext_interface_dirs_map == map(interface_ext, list(dir_name)).
:- type ext_intermod_dirs_map == map(intermod_ext, list(dir_name)).
:- type ext_c_incl_dirs_map == map(c_incl_ext, list(dir_name)).
:- type ext_lib_dirs_map == map(lib_ext, list(dir_name)).
:- type ext_stdlib_dirs_map == map(stdlib_ext, list(dir_name)).
:- type interface_ext
---> ife_int0
; ife_int1
; ife_int2
; ife_int3
; ife_module_dep
; ife_src.
:- type intermod_ext
---> ime_opt_plain
; ime_opt_trans
; ime_an_analysis_date
; ime_an_analysis_status
; ime_an_analysis
; ime_an_imdg
; ime_an_request
; ime_src. % XXX This option should not exist.
:- type c_incl_ext
---> cie_mh
; cie_mih
; cie_h. % Not created from Mercury code.
:- type lib_ext
---> le_a.
:- type stdlib_ext
---> sle_init
; sle_jar
; sle_dll.
%---------------------%
:- pred convert_target(string::in, compilation_target::out) is semidet.
:- pred convert_foreign_language(string::in, foreign_language::out) is semidet.
:- pred convert_gc_method(string::in, gc_method::out) is semidet.
:- pred convert_termination_norm(string::in, termination_norm::out) is semidet.
:- pred convert_maybe_thread_safe(string::in, may_be_thread_safe::out)
is semidet.
:- pred convert_c_compiler_type(string::in, c_compiler_type::out)
is semidet.
:- pred convert_csharp_compiler_type(string::in, csharp_compiler_type::out)
is semidet.
:- pred convert_static_or_shared(string::in, static_or_shared::out)
is semidet.
:- pred convert_reuse_strategy(string::in, int::in, reuse_strategy::out)
is semidet.
:- pred convert_env_type(string::in, env_type::out) is semidet.
:- pred convert_ssdb_trace_level(string::in, bool::in, ssdb_trace_level::out)
is semidet.
:- pred convert_limit_error_contexts(list(string)::in, list(string)::out,
limit_error_contexts_map::out) is det.
%---------------------%
:- type linked_target_ext_info_map == map(string, linked_target_ext_info).
:- type linked_target_ext_info
---> linked_target_ext_info(
% The user-visible name of the option.
string,
% What kind of linked target does the option specify?
linked_target_kind
).
:- type linked_target_kind
---> ltk_object_file
; ltk_pic_object_file
; ltk_all_object_file
; ltk_all_pic_object_file
; ltk_executable
; ltk_static_library
; ltk_shared_library
; ltk_library_install
; ltk_library_install_gs_gas.
%---------------------------------------------------------------------------%
%
% Access predicates for the `globals' structure.
%
:- pred globals_init(option_table::in, option_table::in, opt_tuple::in,
op_mode::in, maybe(feedback_info)::in, file_install_cmd::in,
trace_suppress_items::in, reuse_strategy::in,
limit_error_contexts_map::in, linked_target_ext_info_map::in,
c_compiler_type::in, csharp_compiler_type::in,
static_or_shared::in, static_or_shared::in, set(static_or_shared)::in,
maybe_stdlib_grades::in, compilation_target::in, subdir_setting::in,
word_size::in, gc_method::in, termination_norm::in, termination_norm::in,
trace_level::in, ssdb_trace_level::in, may_be_thread_safe::in,
env_type::in, env_type::in, env_type::in, install_method::in,
globals::out) is det.
:- pred get_default_options(globals::in, option_table::out) is det.
:- pred get_options(globals::in, option_table::out) is det.
:- pred get_opt_tuple(globals::in, opt_tuple::out) is det.
:- pred get_op_mode(globals::in, op_mode::out) is det.
:- pred get_maybe_feedback_info(globals::in,
maybe(feedback_info)::out) is det.
:- pred get_file_install_cmd(globals::in, file_install_cmd::out) is det.
:- pred get_ext_dirs_maps(globals::in, ext_dirs_maps::out) is det.
:- pred get_maybe_stdlib_grades(globals::in, maybe_stdlib_grades::out) is det.
:- pred get_trace_suppress(globals::in, trace_suppress_items::out) is det.
:- pred get_reuse_strategy(globals::in, reuse_strategy::out) is det.
:- pred get_limit_error_contexts_map(globals::in,
limit_error_contexts_map::out) is det.
:- pred get_linked_target_ext_map(globals::in,
linked_target_ext_info_map::out) is det.
:- pred get_grade_dir(globals::in, string::out) is det.
:- pred get_c_compiler_type(globals::in, c_compiler_type::out) is det.
:- pred get_csharp_compiler_type(globals::in, csharp_compiler_type::out)
is det.
:- pred get_linkage(globals::in, static_or_shared::out) is det.
:- pred get_mercury_linkage(globals::in, static_or_shared::out) is det.
:- pred get_library_install_linkages(globals::in, set(static_or_shared)::out)
is det.
:- pred get_target(globals::in, compilation_target::out) is det.
:- pred get_subdir_setting(globals::in, subdir_setting::out) is det.
:- pred get_word_size(globals::in, word_size::out) is det.
:- pred get_gc_method(globals::in, gc_method::out) is det.
:- pred get_termination_norm(globals::in, termination_norm::out) is det.
:- pred get_termination2_norm(globals::in, termination_norm::out) is det.
:- pred get_trace_level(globals::in, trace_level::out) is det.
:- pred get_ssdb_trace_level(globals::in, ssdb_trace_level::out) is det.
:- pred get_maybe_thread_safe(globals::in, may_be_thread_safe::out) is det.
:- pred get_host_env_type(globals::in, env_type::out) is det.
:- pred get_system_env_type(globals::in, env_type::out) is det.
:- pred get_target_env_type(globals::in, env_type::out) is det.
:- pred get_install_method(globals::in, install_method::out) is det.
%---------------------%
:- pred set_options(option_table::in, globals::in, globals::out) is det.
:- pred set_opt_tuple(opt_tuple::in, globals::in, globals::out) is det.
:- pred set_op_mode(op_mode::in, globals::in, globals::out) is det.
:- pred set_maybe_feedback_info(maybe(feedback_info)::in,
globals::in, globals::out) is det.
:- pred set_file_install_cmd(file_install_cmd::in,
globals::in, globals::out) is det.
:- pred set_ext_dirs_maps(ext_dirs_maps::in,
globals::in, globals::out) is det.
:- pred set_maybe_stdlib_grades(maybe_stdlib_grades::in,
globals::in, globals::out) is det.
:- pred set_subdir_setting(subdir_setting::in,
globals::in, globals::out) is det.
:- pred set_word_size(word_size::in, globals::in, globals::out) is det.
:- pred set_gc_method(gc_method::in, globals::in, globals::out) is det.
:- pred set_trace_level(trace_level::in, globals::in, globals::out) is det.
:- pred set_trace_level_none(globals::in, globals::out) is det.
:- pred set_ssdb_trace_level(ssdb_trace_level::in,
globals::in, globals::out) is det.
%---------------------%
:- pred get_backend_foreign_languages(globals::in,
list(foreign_language)::out) is det.
:- pred set_option(option::in, option_data::in, globals::in, globals::out)
is det.
%---------------------%
:- pred lookup_option(globals::in, option::in, option_data::out) is det.
:- pred lookup_bool_option(globals, option, bool).
:- mode lookup_bool_option(in, in, out) is det.
:- mode lookup_bool_option(in, in, in) is semidet. % implied
:- pred lookup_int_option(globals::in, option::in, int::out) is det.
:- pred lookup_maybe_int_option(globals::in, option::in, maybe(int)::out)
is det.
:- pred lookup_string_option(globals::in, option::in, string::out) is det.
:- pred lookup_maybe_string_option(globals::in, option::in, maybe(string)::out)
is det.
:- pred lookup_accumulating_option(globals::in, option::in, list(string)::out)
is det.
%---------------------------------------------------------------------------%
%
% More complex options.
%
:- func lookup_current_backend(globals) = backend.
% Check if we should include variable information in the layout
% structures of call return sites.
%
:- pred want_return_var_layouts(globals::in, eff_trace_level::in, bool::out)
is det.
% Check that the current grade supports tabling of the specified kind.
%
:- pred current_grade_supports_tabling(globals::in, tabled_eval_method::in,
bool::out) is det.
% Check that code compiled in the current grade can execute
% conjunctions in parallel.
%
:- pred current_grade_supports_par_conj(globals::in, bool::out) is det.
% Check that code compiled in the current grade supports concurrent
% execution, i.e. that spawn/3 will create a new thread instead of
% aborting execution.
%
:- pred current_grade_supports_concurrency(globals::in, bool::out) is det.
:- pred get_any_intermod(globals::in, bool::out) is det.
% Check if we may store double-width floats on the det stack.
%
:- pred double_width_floats_on_det_stack(globals::in, bool::out) is det.
%---------------------------------------------------------------------------%
:- pred globals_init_mutables(globals::in, io::di, io::uo) is det.
% Return whether this compiler invocation allows a higher order inst
% to be used as a mode.
%
:- func get_allow_ho_insts_as_modes = bool.
:- type maybe_smart_recompilation
---> do_not_disable_smart_recompilation
; disable_smart_recompilation.
:- pred io_get_disable_smart_recompilation(maybe_smart_recompilation::out,
io::di, io::uo) is det.
:- pred io_set_disable_smart_recompilation(maybe_smart_recompilation::in,
io::di, io::uo) is det.
:- type maybe_item_version_numbers
---> do_not_disable_item_version_numbers
; disable_item_version_numbers.
:- pred io_get_disable_generate_item_version_numbers(
maybe_item_version_numbers::out, io::di, io::uo) is det.
:- pred io_set_disable_generate_item_version_numbers(
maybe_item_version_numbers::in, io::di, io::uo) is det.
%---------------------------------------------------------------------------%
:- pred get_error_output_stream(globals::in, module_name::in,
io.text_output_stream::out, io::di, io::uo) is det.
:- pred get_inference_output_stream(globals::in, module_name::in,
io.text_output_stream::out, io::di, io::uo) is det.
:- pred get_debug_output_stream(globals::in, module_name::in,
io.text_output_stream::out, io::di, io::uo) is det.
:- pred get_recompile_output_stream(globals::in, module_name::in,
io.text_output_stream::out, io::di, io::uo) is det.
:- pred close_any_specific_compiler_streams(io::di, io::uo) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module libs.compute_grade.
:- import_module char.
:- import_module int.
:- import_module require.
:- import_module string.
%---------------------------------------------------------------------------%
compilation_target_string(target_c) = "C".
compilation_target_string(target_csharp) = "C#".
compilation_target_string(target_java) = "Java".
compilation_target_high_level_data(target_c) = no.
compilation_target_high_level_data(target_csharp) = yes.
compilation_target_high_level_data(target_java) = yes.
target_lang_to_foreign_export_lang(target_c) = lang_c.
target_lang_to_foreign_export_lang(target_csharp) = lang_csharp.
target_lang_to_foreign_export_lang(target_java) = lang_java.
foreign_language_string(lang_c) = "C".
foreign_language_string(lang_csharp) = "C#".
foreign_language_string(lang_java) = "Java".
simple_foreign_language_string(Lang) = Str :-
simple_foreign_language_string(Lang, Str).
simple_foreign_language_string(lang_c, "c").
simple_foreign_language_string(lang_csharp, "csharp").
simple_foreign_language_string(lang_java, "java").
all_foreign_language_strings = ["c", "C", "csharp", "C#", "java", "Java"].
gc_is_conservative(gc_boehm) = yes.
gc_is_conservative(gc_boehm_debug) = yes.
gc_is_conservative(gc_hgc) = yes.
gc_is_conservative(gc_none) = no.
gc_is_conservative(gc_accurate) = no.
gc_is_conservative(gc_automatic) = no.
%---------------------------------------------------------------------------%
convert_target(String, Target) :-
convert_target_2(string.to_lower(String), Target).
:- pred convert_target_2(string::in, compilation_target::out) is semidet.
convert_target_2("csharp", target_csharp).
convert_target_2("java", target_java).
convert_target_2("c", target_c).
:- pred convert_foreign_language_det(string::in, foreign_language::out) is det.
convert_foreign_language_det(String, ForeignLang) :-
( if convert_foreign_language(String, ForeignLangPrime) then
ForeignLang = ForeignLangPrime
else
unexpected($pred, "invalid foreign_language string")
).
convert_foreign_language(String, ForeignLanguage) :-
% XXX What is the point of allowing JaVa or CshArP as language names?
convert_foreign_language_2(string.to_lower(String), ForeignLanguage).
:- pred convert_foreign_language_2(string::in, foreign_language::out)
is semidet.
convert_foreign_language_2("c", lang_c).
convert_foreign_language_2("c#", lang_csharp).
convert_foreign_language_2("csharp", lang_csharp).
% XXX What the hell is the space for?
convert_foreign_language_2("c sharp", lang_csharp).
convert_foreign_language_2("java", lang_java).
convert_gc_method("none", gc_none).
convert_gc_method("conservative", gc_boehm).
convert_gc_method("boehm", gc_boehm).
convert_gc_method("boehm_debug", gc_boehm_debug).
convert_gc_method("hgc", gc_hgc).
convert_gc_method("accurate", gc_accurate).
convert_gc_method("automatic", gc_automatic).
convert_termination_norm("simple", norm_simple).
convert_termination_norm("total", norm_total).
convert_termination_norm("num-data-elems", norm_num_data_elems).
convert_termination_norm("size-data-elems", norm_size_data_elems).
convert_maybe_thread_safe("yes", yes).
convert_maybe_thread_safe("no", no).
convert_c_compiler_type(CC_Str, C_CompilerType) :-
( if convert_c_compiler_type_simple(CC_Str, C_CompilerType0) then
C_CompilerType = C_CompilerType0
else
convert_c_compiler_type_with_version(CC_Str, C_CompilerType)
).
:- pred convert_c_compiler_type_simple(string::in, c_compiler_type::out)
is semidet.
convert_c_compiler_type_simple("gcc", cc_gcc(no, no, no)).
convert_c_compiler_type_simple("clang", cc_clang(no)).
% For backwards compatibility we currently recognise "msvc"
% as a synonym for "msvc_x86".
convert_c_compiler_type_simple("msvc", cc_cl_x86(no)).
convert_c_compiler_type_simple("msvc_x86", cc_cl_x86(no)).
convert_c_compiler_type_simple("msvc_x64", cc_cl_x64(no)).
convert_c_compiler_type_simple("unknown", cc_unknown).
:- pred convert_c_compiler_type_with_version(string::in, c_compiler_type::out)
is semidet.
convert_c_compiler_type_with_version(CC_Str, C_CompilerType) :-
Tokens = string.words_separator(unify('_'), CC_Str),
( if Tokens = ["gcc", Major, Minor, Patch] then
convert_gcc_version(Major, Minor, Patch, C_CompilerType)
else if Tokens = ["clang", Major, Minor, Patch] then
convert_clang_version(Major, Minor, Patch, C_CompilerType)
else if
( Tokens = ["msvc", Version]
; Tokens = ["msvc", "x86", Version]
)
then
convert_msvc_x86_version(Version, C_CompilerType)
else if Tokens = ["msvc", "x64", Version] then
convert_msvc_x64_version(Version, C_CompilerType)
else
false
).
% Create the value of C compiler type when we have (some) version
% information for gcc available.
% We only accept version information that has the following form:
%
% u_u_u
% <major>_u_u
% <major>_<minor>_<u>
% <major>_<minor>_<patch>
%
% This means that setting the minor version number will not be accepted
% when the major version number is unknown. (It wouldn't be useful
% in any case.)
%
% <major> must be >= 2. (Mercury won't work with anything older than that)
% and <minor> and <patch> must be non-negative.
%
:- pred convert_gcc_version(string::in, string::in, string::in,
c_compiler_type::out) is semidet.
convert_gcc_version(MajorStr, MinorStr, PatchStr, C_CompilerType) :-
( if
MajorStr = "u",
MinorStr = "u",
PatchStr = "u"
then
C_CompilerType = cc_gcc(no, no, no)
else if
string.to_int(MajorStr, Major),
Major >= 2
then
( if
MinorStr = "u"
then
C_CompilerType = cc_gcc(yes(Major), no, no)
else if
string.to_int(MinorStr, Minor),
Minor >= 0
then
( if
PatchStr = "u"
then
C_CompilerType = cc_gcc(yes(Major), yes(Minor), no)
else if
string.to_int(PatchStr, Patch),
Patch >= 0
then
C_CompilerType = cc_gcc(yes(Major), yes(Minor), yes(Patch))
else
false
)
else
false
)
else
false
).
% Create the value of C compiler type when we have (some) version
% information for clang available.
% We only accept version information that has the following form:
%
% <major>_<minor>_<patch>
%
:- pred convert_clang_version(string::in, string::in, string::in,
c_compiler_type::out) is semidet.
convert_clang_version(MajorStr, MinorStr, PatchStr, C_CompilerType) :-
string.to_int(MajorStr, Major),
string.to_int(MinorStr, Minor),
string.to_int(PatchStr, Patch),
Major >= 0, Minor >= 0, Patch >= 0,
ClangVersion = clang_version(Major, Minor, Patch),
C_CompilerType = cc_clang(yes(ClangVersion)).
% Create the value of C compiler type when we have version information
% for Visual C available.
% The version number is an integer literal (corresponding to the value
% of the builtin macro _MSC_VER).
%
:- pred convert_msvc_x86_version(string::in, c_compiler_type::out) is semidet.
convert_msvc_x86_version(VersionStr, C_CompilerType) :-
string.to_int(VersionStr, Version),
Version > 0,
C_CompilerType = cc_cl_x86(yes(Version)).
:- pred convert_msvc_x64_version(string::in, c_compiler_type::out) is semidet.
convert_msvc_x64_version(VersionStr, C_CompilerType) :-
string.to_int(VersionStr, Version),
Version > 0,
C_CompilerType = cc_cl_x64(yes(Version)).
convert_csharp_compiler_type("microsoft", csharp_microsoft).
convert_csharp_compiler_type("mono", csharp_mono).
convert_csharp_compiler_type("unknown", csharp_unknown).
convert_static_or_shared("static", sos_static).
convert_static_or_shared("shared", sos_shared).
convert_reuse_strategy("same_cons_id", _, same_cons_id).
convert_reuse_strategy("within_n_cells_difference", NCells,
within_n_cells_difference(NCells)).
convert_env_type("posix", env_type_posix).
convert_env_type("cygwin", env_type_cygwin).
convert_env_type("msys", env_type_msys).
convert_env_type("windows", env_type_win_cmd).
convert_env_type("powershell", env_type_powershell).
convert_ssdb_trace_level("default", yes, ssdb_deep).
convert_ssdb_trace_level("default", no, ssdb_none).
convert_ssdb_trace_level("none", _, ssdb_none).
convert_ssdb_trace_level("shallow", _, ssdb_shallow).
convert_ssdb_trace_level("deep", _, ssdb_deep).
convert_limit_error_contexts(Options, BadOptions, Map) :-
convert_limit_error_contexts_acc(Options, [], RevBadOptions,
map.init, Map),
list.reverse(RevBadOptions, BadOptions).
:- pred convert_limit_error_contexts_acc(list(string)::in,
list(string)::in, list(string)::out,
limit_error_contexts_map::in, limit_error_contexts_map::out) is det.
convert_limit_error_contexts_acc([], !RevBadOptions, !Map).
convert_limit_error_contexts_acc([Option | Options], !RevBadOptions, !Map) :-
string.to_char_list(Option, OptionChars),
% Break up the option at the last colon.
% If there is no colon, the filename will be empty, and the line number
% range will apply to all files.
% If there is more than one colon, all but the last are will be considered
% part of the filename, which can be useful e.g. for drive specifiers
% on Windows.
list.reverse(OptionChars, RevOptionChars),
find_file_name_and_line_range_chars(RevOptionChars, [], LineRangeChars,
RevFileNameChars),
FileName = string.from_rev_char_list(RevFileNameChars),
LineRangeStr = string.from_char_list(LineRangeChars),
( if
string.split_at_char(',', LineRangeStr) = LineRangeStrs,
list.map(convert_line_number_range, LineRangeStrs, LineNumberRanges)
then
map.set(FileName, LineNumberRanges, !Map)
else
!:RevBadOptions = [Option | !.RevBadOptions]
),
convert_limit_error_contexts_acc(Options, !RevBadOptions, !Map).
:- pred find_file_name_and_line_range_chars(list(char)::in,
list(char)::in, list(char)::out, list(char)::out) is det.
find_file_name_and_line_range_chars([], !LineRangeChars, []).
find_file_name_and_line_range_chars([RevChar | RevChars],
!LineRangeChars, RevFileNameChars) :-
( if RevChar = (':') then
RevFileNameChars = RevChars
else
% This un-reverses the line range characters.
!:LineRangeChars = [RevChar | !.LineRangeChars],
find_file_name_and_line_range_chars(RevChars,
!LineRangeChars, RevFileNameChars)
).
:- pred convert_line_number_range(string::in, line_number_range::out)
is semidet.
convert_line_number_range(RangeStr, line_number_range(MaybeMin, MaybeMax)) :-
string.split_at_char('-', RangeStr) = [MinStr, MaxStr],
( if MinStr = "" then
MaybeMin = no
else
string.to_int(MinStr, Min),
MaybeMin = yes(Min)
),
( if MaxStr = "" then
MaybeMax = no
else
string.to_int(MaxStr, Max),
MaybeMax = yes(Max)
).
%---------------------------------------------------------------------------%
:- type read_only_globals
---> read_only_globals(
rog_trace_suppress_items :: trace_suppress_items,
rog_reuse_strategy :: reuse_strategy,
rog_limit_error_contexts_map :: limit_error_contexts_map,
rog_linked_target_ext_map :: linked_target_ext_info_map,
rog_grade_dir :: string,
rog_c_compiler_type :: c_compiler_type
).
:- type globals
---> globals(
% The default option table, with all options having their
% default values.
g_default_options :: option_table,
% The actual option table, in which the options we have
% processed (from the command line, from Mercury.options files,
% etc) have overridden the affected options' default values.
g_options :: option_table,
% The writeable fields that each require a full word.
g_opt_tuple :: opt_tuple,
g_op_mode :: op_mode,
g_maybe_feedback :: maybe(feedback_info),
g_file_install_cmd :: file_install_cmd,
g_ext_dirs_maps :: ext_dirs_maps,
g_maybe_stdlib_grades :: maybe_stdlib_grades,
% The readonly fields that each require a full word.
g_read_only :: read_only_globals,
% The sub-word-sized arguments, clustered together
% to allow them to be packed together.
g_csharp_compiler_type :: csharp_compiler_type,
% g_linkage holds the value of the --linkage option, while
% g_mercury_linkage does the same for --mercury-linkage.
g_linkage :: static_or_shared,
g_mercury_linkage :: static_or_shared,
g_library_install_linkages :: set(static_or_shared),
g_target :: compilation_target,
g_subdir_setting :: subdir_setting,
g_word_size :: word_size,
g_gc_method :: gc_method,
g_termination_norm :: termination_norm,
g_termination2_norm :: termination_norm,
g_trace_level :: trace_level,
g_ssdb_trace_level :: ssdb_trace_level,
g_may_be_thread_safe :: bool,
g_host_env_type :: env_type,
g_system_env_type :: env_type,
g_target_env_type :: env_type,
g_install_method :: install_method
).
globals_init(DefaultOptions, Options, OptTuple, OpMode,
MaybeFeedback, FileInstallCmd, TraceSuppress, ReuseStrategy,
LimitErrorContextsMap, LinkedTargetExtInfoMap,
C_CompilerType, CSharp_CompilerType,
Linkage, MercuryLinkage, LibLinkages,
MaybeStdLibGradeSet, Target, SubdirSetting, WordSize, GC_Method,
TerminationNorm, Termination2Norm,
TraceLevel, SSTraceLevel, MaybeThreadSafe,
HostEnvType, SystemEnvType, TargetEnvType, InstallMethod, Globals) :-
ExtDirsMaps0 = ext_dirs_maps(map.init, map.init, map.init,
map.init, map.init),
ReadOnlyGlobals0 = read_only_globals(TraceSuppress, ReuseStrategy,
LimitErrorContextsMap, LinkedTargetExtInfoMap, "", C_CompilerType),
Globals0 = globals(DefaultOptions, Options, OptTuple, OpMode,
MaybeFeedback, FileInstallCmd, ExtDirsMaps0, MaybeStdLibGradeSet,
ReadOnlyGlobals0, CSharp_CompilerType,
Linkage, MercuryLinkage, LibLinkages,
Target, SubdirSetting, WordSize, GC_Method,
TerminationNorm, Termination2Norm,
TraceLevel, SSTraceLevel, MaybeThreadSafe,
HostEnvType, SystemEnvType, TargetEnvType, InstallMethod),
compute_grade(Globals0, GradeDir),
% We used to strip out any `.picreg' part from GradeDir,
% while we still had it.
Globals = Globals0 ^ g_read_only ^ rog_grade_dir := GradeDir.
%---------------------%
get_default_options(Globals, X) :-
X = Globals ^ g_default_options.
get_options(Globals, X) :-
X = Globals ^ g_options.
get_opt_tuple(Globals, X) :-
X = Globals ^ g_opt_tuple.
get_op_mode(Globals, X) :-
X = Globals ^ g_op_mode.
get_maybe_feedback_info(Globals, X) :-
X = Globals ^ g_maybe_feedback.
get_file_install_cmd(Globals, X) :-
X = Globals ^ g_file_install_cmd.
get_ext_dirs_maps(Globals, X) :-
X = Globals ^ g_ext_dirs_maps.
get_maybe_stdlib_grades(Globals, X) :-
X = Globals ^ g_maybe_stdlib_grades.
get_trace_suppress(Globals, X) :-
X = Globals ^ g_read_only ^ rog_trace_suppress_items.
get_reuse_strategy(Globals, X) :-
X = Globals ^ g_read_only ^ rog_reuse_strategy.
get_limit_error_contexts_map(Globals, X) :-
X = Globals ^ g_read_only ^ rog_limit_error_contexts_map.
get_linked_target_ext_map(Globals, X) :-
X = Globals ^ g_read_only ^ rog_linked_target_ext_map.
get_grade_dir(Globals, X) :-
X = Globals ^ g_read_only ^ rog_grade_dir.
get_c_compiler_type(Globals, X) :-
X = Globals ^ g_read_only ^ rog_c_compiler_type.
get_csharp_compiler_type(Globals, X) :-
X = Globals ^ g_csharp_compiler_type.
get_linkage(Globals, X) :-
X = Globals ^ g_linkage.
get_mercury_linkage(Globals, X) :-
X = Globals ^ g_mercury_linkage.
get_library_install_linkages(Globals, X) :-
X = Globals ^ g_library_install_linkages.
get_target(Globals, X) :-
X = Globals ^ g_target.
get_subdir_setting(Globals, X) :-
X = Globals ^ g_subdir_setting.
get_word_size(Globals, X) :-
X = Globals ^ g_word_size.
get_gc_method(Globals, X) :-
X = Globals ^ g_gc_method.
get_termination_norm(Globals, X) :-
X = Globals ^ g_termination_norm.
get_termination2_norm(Globals, X) :-
X = Globals ^ g_termination2_norm.
get_trace_level(Globals, X) :-
X = Globals ^ g_trace_level.
get_ssdb_trace_level(Globals, X) :-
X = Globals ^ g_ssdb_trace_level.
get_maybe_thread_safe(Globals, X) :-
X = Globals ^ g_may_be_thread_safe.
get_host_env_type(Globals, X) :-
X = Globals ^ g_host_env_type.
get_system_env_type(Globals, X) :-
X = Globals ^ g_system_env_type.
get_target_env_type(Globals, X) :-
X = Globals ^ g_target_env_type.
get_install_method(Globals, X) :-
X = Globals ^ g_install_method.
set_options(X, !Globals) :-
!Globals ^ g_options := X.
set_opt_tuple(X, !Globals) :-
!Globals ^ g_opt_tuple := X.
set_op_mode(X, !Globals) :-
!Globals ^ g_op_mode := X.
set_maybe_feedback_info(X, !Globals) :-
!Globals ^ g_maybe_feedback := X.
set_file_install_cmd(X, !Globals) :-
!Globals ^ g_file_install_cmd := X.
set_ext_dirs_maps(X, !Globals) :-
!Globals ^ g_ext_dirs_maps := X.
set_maybe_stdlib_grades(X, !Globals) :-
!Globals ^ g_maybe_stdlib_grades := X.
set_subdir_setting(X, !Globals) :-
!Globals ^ g_subdir_setting := X.
set_word_size(X, !Globals) :-
!Globals ^ g_word_size := X.
set_gc_method(X, !Globals) :-
!Globals ^ g_gc_method := X.
set_trace_level(X, !Globals) :-
!Globals ^ g_trace_level := X.
set_trace_level_none(!Globals) :-
!Globals ^ g_trace_level := trace_level_none.
set_ssdb_trace_level(X, !Globals) :-
!Globals ^ g_ssdb_trace_level := X.
%---------------------------------------------------------------------------%
get_backend_foreign_languages(Globals, ForeignLangs) :-
lookup_accumulating_option(Globals, backend_foreign_languages, LangStrs),
list.map(convert_foreign_language_det, LangStrs, ForeignLangs).
set_option(Option, OptionData, !Globals) :-
get_options(!.Globals, OptionTable0),
map.set(Option, OptionData, OptionTable0, OptionTable),
set_options(OptionTable, !Globals).
%---------------------------------------------------------------------------%
lookup_option(Globals, Option, OptionData) :-
get_options(Globals, OptionTable),
map.lookup(OptionTable, Option, OptionData).
lookup_bool_option(Globals, Option, Value) :-
lookup_option(Globals, Option, OptionData),
( if OptionData = bool(Bool) then
Value = Bool
else
unexpected($pred,
string.format("invalid bool option (%s is %s)",
[s(string(Option)), s(string(OptionData))]))
).
lookup_int_option(Globals, Option, Value) :-
lookup_option(Globals, Option, OptionData),
( if OptionData = int(Int) then
Value = Int
else
unexpected($pred,
string.format("invalid int option (%s is %s)",
[s(string(Option)), s(string(OptionData))]))
).
lookup_maybe_int_option(Globals, Option, Value) :-
lookup_option(Globals, Option, OptionData),
( if OptionData = maybe_int(MaybeInt) then
Value = MaybeInt
else
unexpected($pred,
string.format("invalid maybe_int option (%s is %s)",
[s(string(Option)), s(string(OptionData))]))
).
lookup_string_option(Globals, Option, Value) :-
lookup_option(Globals, Option, OptionData),
( if OptionData = string(String) then
Value = String
else
unexpected($pred,
string.format("invalid string option (%s is %s)",
[s(string(Option)), s(string(OptionData))]))
).
lookup_maybe_string_option(Globals, Option, Value) :-
lookup_option(Globals, Option, OptionData),
( if OptionData = maybe_string(MaybeString) then
Value = MaybeString
else
unexpected($pred,
string.format("invalid maybe_string option (%s is %s)",
[s(string(Option)), s(string(OptionData))]))
).
lookup_accumulating_option(Globals, Option, Value) :-
lookup_option(Globals, Option, OptionData),
( if OptionData = accumulating(Accumulating) then
Value = Accumulating
else
unexpected($pred,
string.format("invalid accumulating option (%s is %s)",
[s(string(Option)), s(string(OptionData))]))
).
%---------------------------------------------------------------------------%
lookup_current_backend(Globals) = CurrentBackend :-
globals.lookup_bool_option(Globals, highlevel_code, HighLevel),
(
HighLevel = yes,
CurrentBackend = high_level_backend
;
HighLevel= no,
CurrentBackend = low_level_backend
).
want_return_var_layouts(Globals, EffTraceLevel, WantReturnLayouts) :-
% We need to generate layout info for call return labels
% if we are using accurate gc or if the user wants uplevel printing.
( if
(
get_gc_method(Globals, GC_Method),
GC_Method = gc_accurate
;
get_trace_suppress(Globals, TraceSuppress),
eff_trace_needs_return_info(EffTraceLevel, TraceSuppress) = yes
)
then
WantReturnLayouts = yes
else
WantReturnLayouts = no
).
current_grade_supports_tabling(Globals, TabledMethod, TablingSupported) :-
% Please keep this code in sync with find_grade_problems_for_tabling
% in table_gen.m.
globals.get_target(Globals, Target),
globals.get_gc_method(Globals, GC_Method),
globals.lookup_bool_option(Globals, parallel, Parallel),
globals.lookup_bool_option(Globals, use_trail, UseTrail),
globals.lookup_bool_option(Globals, profile_calls, ProfileCalls),
globals.lookup_bool_option(Globals, profile_deep, ProfileDeep),
% There is no point in checking for threadscope profiling,
% since it cannot be enabled without Parallel=yes.
% There is no point in checking for term size profiling or RBMM,
% since neither is production-ready.
( if
Target = target_c,
GC_Method \= gc_accurate,
Parallel = no,
require_complete_switch [TabledMethod]
(
TabledMethod = tabled_minimal(_),
UseTrail = no,
ProfileCalls = no,
ProfileDeep = no
;
( TabledMethod = tabled_loop_check
; TabledMethod = tabled_memo(_)
; TabledMethod = tabled_io(_, _)
)
)
then
TablingSupported = yes
else
TablingSupported = no
).
current_grade_supports_par_conj(Globals, ParConjSupported) :-
% Parallel conjunctions only supported on lowlevel C parallel grades.
% They are not (currently) supported if trailing is enabled.
%
globals.get_target(Globals, Target),
globals.lookup_bool_option(Globals, highlevel_code, HighLevelCode),
globals.lookup_bool_option(Globals, parallel, Parallel),
globals.lookup_bool_option(Globals, use_trail, UseTrail),
( if
Target = target_c,
HighLevelCode = no,
Parallel = yes,
UseTrail = no
then
ParConjSupported = yes
else
ParConjSupported = no
).
current_grade_supports_concurrency(Globals, ThreadsSupported) :-
globals.get_target(Globals, Target),
(
Target = target_c,
globals.lookup_bool_option(Globals, parallel, Parallel),
ThreadsSupported = Parallel
;
( Target = target_java
; Target = target_csharp
),
ThreadsSupported = yes
).
get_any_intermod(Globals, AnyIntermod) :-
lookup_bool_option(Globals, intermodule_optimization, IntermodOpt),
lookup_bool_option(Globals, intermodule_analysis, IntermodAnalysis),
AnyIntermod = bool.or(IntermodOpt, IntermodAnalysis).
double_width_floats_on_det_stack(Globals, FloatDwords) :-
globals.lookup_int_option(Globals, bits_per_word, TargetWordBits),
globals.lookup_bool_option(Globals, single_prec_float, SinglePrecFloat),
( if TargetWordBits = 64 then
FloatDwords = no
else if TargetWordBits = 32 then
(
SinglePrecFloat = yes,
FloatDwords = no
;
SinglePrecFloat = no,
FloatDwords = yes
)
else
unexpected($pred, "bits_per_word not 32 or 64")
).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- mutable(allow_ho_insts_as_modes, bool, yes, ground,
[untrailed, attach_to_io_state]).
:- mutable(disable_smart_recompilation,
maybe_smart_recompilation, do_not_disable_smart_recompilation, ground,
[untrailed, attach_to_io_state]).
:- mutable(disable_generate_item_version_numbers,
maybe_item_version_numbers, do_not_disable_item_version_numbers, ground,
[untrailed, attach_to_io_state]).
%---------------------------------------------------------------------------%
globals_init_mutables(Globals, !IO) :-
globals.lookup_bool_option(Globals, allow_ho_insts_as_modes, Allow),
set_allow_ho_insts_as_modes(Allow, !IO).
get_allow_ho_insts_as_modes = Allow :-
promise_pure (
semipure get_allow_ho_insts_as_modes(Allow)
).
io_get_disable_smart_recompilation(DisableSmartRecomp, !IO) :-
get_disable_smart_recompilation(DisableSmartRecomp, !IO).
io_set_disable_smart_recompilation(DisableSmartRecomp, !IO) :-
set_disable_smart_recompilation(DisableSmartRecomp, !IO).
io_get_disable_generate_item_version_numbers(DisableItemVerions, !IO) :-
get_disable_generate_item_version_numbers(DisableItemVerions, !IO).
io_set_disable_generate_item_version_numbers(DisableItemVerions, !IO) :-
set_disable_generate_item_version_numbers(DisableItemVerions, !IO).
%---------------------------------------------------------------------------%
:- type compiler_output_stream
---> general_stream(io.text_output_stream)
% A stream such as stdout or stderr, that is open before
% the compiler begins running and does not have to be closed.
; specific_stream(io.text_output_stream)
% A stream opened for a specific purpose the first time there was
% a need for it. Must be closed before the compiler exits.
; no_stream.
% Either no stream has been set up for this purpose (yet),
% or it has already been closed.
:- mutable(output_stream_error, compiler_output_stream, no_stream, ground,
[untrailed, attach_to_io_state]).
:- mutable(output_stream_inference, compiler_output_stream, no_stream, ground,
[untrailed, attach_to_io_state]).
:- mutable(output_stream_debug, compiler_output_stream, no_stream, ground,
[untrailed, attach_to_io_state]).
:- mutable(output_stream_recompile, compiler_output_stream, no_stream, ground,
[untrailed, attach_to_io_state]).
get_error_output_stream(Globals, ModuleName, Stream, !IO) :-
get_output_stream(Globals, ModuleName, error_output_suffix,
get_output_stream_error, set_output_stream_error, Stream, !IO).
get_inference_output_stream(Globals, ModuleName, Stream, !IO) :-
get_output_stream(Globals, ModuleName, inference_output_suffix,
get_output_stream_inference, set_output_stream_inference, Stream, !IO).
get_debug_output_stream(Globals, ModuleName, Stream, !IO) :-
get_output_stream(Globals, ModuleName, debug_output_suffix,
get_output_stream_debug, set_output_stream_debug, Stream, !IO).
get_recompile_output_stream(Globals, ModuleName, Stream, !IO) :-
get_output_stream(Globals, ModuleName, recompile_output_suffix,
get_output_stream_recompile, set_output_stream_recompile, Stream, !IO).
:- pred get_output_stream(globals::in, module_name::in, option::in,
pred(compiler_output_stream, io, io)::in(pred(out, di, uo) is det),
pred(compiler_output_stream, io, io)::in(pred(in, di, uo) is det),
io.text_output_stream::out, io::di, io::uo) is det.
get_output_stream(Globals, ModuleName, Option, Get, Set, Stream, !IO) :-
Get(CompilerStream0, !IO),
(
CompilerStream0 = general_stream(Stream)
;
CompilerStream0 = specific_stream(Stream)
;
CompilerStream0 = no_stream,
globals.lookup_string_option(Globals, Option, Suffix),
( if Suffix = "" then
% The user does not want to redirect this kind output
% to a module-specific file.
io.stderr_stream(StdErr, !IO),
Stream = StdErr,
CompilerStream = general_stream(Stream)
else
FileName = sym_name_to_string(ModuleName) ++ "." ++ Suffix,
io.open_output(FileName, OpenResult, !IO),
(
OpenResult = ok(Stream),
% The user wants to redirect this kind output
% to a module-specific file, and we can and do.
CompilerStream = specific_stream(Stream)
;
OpenResult = error(IOError),
% The user wants to redirect this kind output
% to a module-specific file, but we can't open it.
% Besides reporting the problem, acting as if
% the request wasn't made is the best we can do.
io.stderr_stream(StdErr, !IO),
report_cannot_open_file_for_input(StdErr, Globals, FileName,
IOError, !IO),
Stream = StdErr,
CompilerStream = general_stream(Stream)
)
),
Set(CompilerStream, !IO)
).
%---------------------%
close_any_specific_compiler_streams(!IO) :-
close_compiler_output_stream(
get_output_stream_error, set_output_stream_error, !IO),
close_compiler_output_stream(
get_output_stream_inference, set_output_stream_inference, !IO),
close_compiler_output_stream(
get_output_stream_debug, set_output_stream_debug, !IO),
close_compiler_output_stream(
get_output_stream_recompile, set_output_stream_recompile, !IO).
:- pred close_compiler_output_stream(
pred(compiler_output_stream, io, io)::in(pred(out, di, uo) is det),
pred(compiler_output_stream, io, io)::in(pred(in, di, uo) is det),
io::di, io::uo) is det.
close_compiler_output_stream(Get, Set, !IO) :-
Get(CompilerStream0, !IO),
(
CompilerStream0 = general_stream(_Stream)
% This stream does not need to be closed.
;
CompilerStream0 = specific_stream(Stream),
io.close_output(Stream, !IO),
Set(no_stream, !IO)
;
CompilerStream0 = no_stream
% There is no stream to close.
).
%---------------------------------------------------------------------------%
:- end_module libs.globals.
%---------------------------------------------------------------------------%