Files
mercury/compiler/globals.m
Fergus Henderson 89adfe0d7b Clean up the handling of the --java' and --gc' compilation options.
Estimated hours taken: 3
Branches: main

Clean up the handling of the `--java' and `--gc' compilation options.

README.Java:
	Document the `--java' and `--target java' options,
	and use `--java' rather than `--grade java' in the examples.

compiler/handle_options.m:
	Fix a bug where `mmc --java --output-grade-string'
	was printing "java.gc" instead of "java".  It was calling
	set_gc_method to set the gc_method field in the globals structure,
	but it was not setting the corresponding string option in the
	options table, and compute_grade was looking at the string option.
	The fix was to also set the string option.

scripts/parse_grade_options.sh-subr:
	Handle the `--java' and `--java-only' options.

scripts/final_grade_options.sh-subr:
	For the IL and Java back-ends, set the gc_method to automatic.
	For the Java back-end, set highlevel_data to true.

compiler/globals.m:
	Fix an XXX: add a new alternative to the gc_method type,
	"automatic", to distinguish lack of GC ("none") from the
	automatic GC done by Java or the .NET CLR.

compiler/options.m:
doc/user_guide.texi:
	Document the new `--gc automatic' alternative for the `--gc' option.
	Delete the documentation of the deprecated `--gc conservative'
	option (which has been replaced with `--gc boehm').

compiler/compile_target_code.m:
compiler/handle_options.m:
scripts/parse_grade_options.sh-subr:
scripts/final_grade_options.sh-subr:
	Handle the new `--gc automatic' option..
2004-02-10 12:43:33 +00:00

590 lines
20 KiB
Mathematica

%-----------------------------------------------------------------------------%
% Copyright (C) 1994-2004 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%
:- module libs__globals.
% 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.
%-----------------------------------------------------------------------------%
:- interface.
:- import_module libs__options.
:- import_module libs__trace_params.
:- import_module parse_tree.
:- import_module parse_tree__prog_data. % for module_name.
:- import_module bool, getopt, list, map, io, std_util.
:- type globals.
:- type compilation_target
---> c % Generate C code (including GNU C)
; il % Generate IL assembler code
% IL is the Microsoft .NET Intermediate Language
; java % Generate Java
% (Work in progress)
; asm. % Compile directly to assembler via the GCC back-end.
% Do not go via C, instead generate GCC's internal
% `tree' data structure.
% (Work in progress.)
:- type foreign_language
---> c
% ; cplusplus
; csharp
; managed_cplusplus
; java
; il
.
% The GC method specifies how we do garbage collection.
% The last four alternatives are for the C and asm back-ends;
% the first alternative is for compiling to IL or Java,
% where the target language implementation handles garbage
% collection automatically.
%
:- type gc_method
---> automatic % It is the responsibility of the target language
% that we are compiling to to handle GC.
; none % No garbage collection.
% But memory may be recovered on backtracking,
% if the --reclaim-heap-on-*failure options are set.
; boehm % The Boehm et al conservative collector.
; mps % A different conservative collector, based on
% Ravenbrook Limited's MPS (Memory Pool System) kit.
% Benchmarking indicated that this one performed worse
% than the Boehm collector, so we don't really
% support this option anymore.
; accurate
% Our own 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' or `mps'.
% Conservative GC methods don't support heap
% reclamation on failure.
:- func gc_is_conservative(gc_method) = bool.
:- type tags_method
---> none
; low
; high.
:- type termination_norm
---> simple
; total
; num_data_elems
; size_data_elems.
% Map from module name to file name.
:- type source_file_map == map(module_name, string).
:- 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_tags_method(string::in, tags_method::out) is semidet.
:- pred convert_termination_norm(string::in, termination_norm::out) is semidet.
%-----------------------------------------------------------------------------%
% Access predicates for the `globals' structure.
:- pred globals__init(option_table::di, compilation_target::di, gc_method::di,
tags_method::di, termination_norm::di,
trace_level::di, trace_suppress_items::di, globals::uo) is det.
:- pred globals__get_options(globals::in, option_table::out) is det.
:- pred globals__get_target(globals::in, compilation_target::out) is det.
:- pred globals__get_backend_foreign_languages(globals::in,
list(foreign_language)::out) is det.
:- pred globals__get_gc_method(globals::in, gc_method::out) is det.
:- pred globals__get_tags_method(globals::in, tags_method::out) is det.
:- pred globals__get_termination_norm(globals::in, termination_norm::out)
is det.
:- pred globals__get_trace_level(globals::in, trace_level::out) is det.
:- pred globals__get_trace_suppress(globals::in, trace_suppress_items::out)
is det.
:- pred globals__get_source_file_map(globals::in, maybe(source_file_map)::out)
is det.
:- pred globals__set_options(globals::in, option_table::in, globals::out)
is det.
:- pred globals__set_gc_method(globals::in, gc_method::in, globals::out)
is det.
:- pred globals__set_tags_method(globals::in, tags_method::in, globals::out)
is det.
:- pred globals__set_trace_level(globals::in, trace_level::in, globals::out)
is det.
:- pred globals__set_trace_level_none(globals::in, globals::out) is det.
:- pred globals__set_source_file_map(globals::in, maybe(source_file_map)::in,
globals::out) is det.
:- pred globals__lookup_option(globals::in, option::in, option_data::out)
is det.
:- pred globals__lookup_bool_option(globals, option, bool).
:- mode globals__lookup_bool_option(in, in, out) is det.
:- mode globals__lookup_bool_option(in, in, in) is semidet. % implied
:- pred globals__lookup_int_option(globals::in, option::in, int::out) is det.
:- pred globals__lookup_string_option(globals::in, option::in, string::out)
is det.
:- pred globals__lookup_maybe_string_option(globals::in, option::in,
maybe(string)::out) is det.
:- pred globals__lookup_accumulating_option(globals::in, option::in,
list(string)::out) is det.
%-----------------------------------------------------------------------------%
% More complex options
% Check if static code addresses are available in the
% current grade of compilation.
:- pred globals__have_static_code_addresses(globals::in, bool::out) is det.
% Check if we should include variable information in the layout
% structures of call return sites.
:- pred globals__want_return_var_layouts(globals::in, bool::out) is det.
% globals__imported_is_constant(NonLocalGotos, AsmLabels, IsConst)
% figures out whether an imported label address is a constant.
% This depends on how we treat labels.
:- pred globals__imported_is_constant(bool::in, bool::in, bool::out) is det.
%-----------------------------------------------------------------------------%
% Access predicates for storing a `globals' structure in the
% io__state using io__set_globals and io__get_globals.
:- pred globals__io_init(option_table::di, compilation_target::in,
gc_method::in, tags_method::in,
termination_norm::in, trace_level::in, trace_suppress_items::in,
io__state::di, io__state::uo) is det.
:- pred globals__io_get_target(compilation_target::out,
io__state::di, io__state::uo) is det.
:- pred globals__io_get_backend_foreign_languages(list(foreign_language)::out,
io__state::di, io__state::uo) is det.
:- pred globals__io_lookup_foreign_language_option(option::in,
foreign_language::out, io__state::di, io__state::uo) is det.
:- pred globals__io_get_gc_method(gc_method::out,
io__state::di, io__state::uo) is det.
:- pred globals__io_get_tags_method(tags_method::out,
io__state::di, io__state::uo) is det.
:- pred globals__io_get_termination_norm(termination_norm::out,
io__state::di, io__state::uo) is det.
:- pred globals__io_get_trace_level(trace_level::out,
io__state::di, io__state::uo) is det.
:- pred globals__io_get_trace_suppress(trace_suppress_items::out,
io__state::di, io__state::uo) is det.
:- pred globals__io_get_globals(globals::out, io__state::di, io__state::uo)
is det.
:- pred globals__io_set_globals(globals::di, io__state::di, io__state::uo)
is det.
:- pred globals__io_set_option(option::in, option_data::in,
io__state::di, io__state::uo) is det.
:- pred globals__io_set_gc_method(gc_method::in,
io__state::di, io__state::uo) is det.
:- pred globals__io_set_tags_method(tags_method::in,
io__state::di, io__state::uo) is det.
:- pred globals__io_set_trace_level(trace_level::in,
io__state::di, io__state::uo) is det.
:- pred globals__io_set_trace_level_none(io__state::di, io__state::uo) is det.
:- pred globals__io_lookup_option(option::in, option_data::out,
io__state::di, io__state::uo) is det.
:- pred globals__io_lookup_bool_option(option::in, bool::out,
io__state::di, io__state::uo) is det.
:- pred globals__io_lookup_int_option(option::in, int::out,
io__state::di, io__state::uo) is det.
:- pred globals__io_lookup_string_option(option::in, string::out,
io__state::di, io__state::uo) is det.
:- pred globals__io_lookup_maybe_string_option(option::in, maybe(string)::out,
io__state::di, io__state::uo) is det.
:- pred globals__io_lookup_accumulating_option(option::in, list(string)::out,
io__state::di, io__state::uo) is det.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module map, std_util, require, string.
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("java", java).
convert_target_2("asm", asm).
convert_target_2("il", il).
convert_target_2("c", c).
convert_foreign_language(String, ForeignLanguage) :-
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", c).
convert_foreign_language_2("mc++", managed_cplusplus).
convert_foreign_language_2("managedc++", managed_cplusplus).
convert_foreign_language_2("managed c++", managed_cplusplus).
convert_foreign_language_2("c#", csharp).
convert_foreign_language_2("csharp", csharp).
convert_foreign_language_2("c sharp", csharp).
convert_foreign_language_2("il", il).
convert_foreign_language_2("java", java).
convert_gc_method("none", none).
convert_gc_method("conservative", boehm).
convert_gc_method("boehm", boehm).
convert_gc_method("mps", mps).
convert_gc_method("accurate", accurate).
convert_gc_method("automatic", automatic).
convert_tags_method("none", none).
convert_tags_method("low", low).
convert_tags_method("high", high).
convert_termination_norm("simple", simple).
convert_termination_norm("total", total).
convert_termination_norm("num-data-elems", num_data_elems).
convert_termination_norm("size-data-elems", size_data_elems).
gc_is_conservative(boehm) = yes.
gc_is_conservative(mps) = yes.
gc_is_conservative(none) = no.
gc_is_conservative(accurate) = no.
gc_is_conservative(automatic) = no.
%-----------------------------------------------------------------------------%
:- type globals
---> globals(
options :: option_table,
target :: compilation_target,
gc_method :: gc_method,
tags_method :: tags_method,
termination_norm :: termination_norm,
trace_level :: trace_level,
trace_suppress_items :: trace_suppress_items,
source_file_map :: maybe(source_file_map)
).
globals__init(Options, Target, GC_Method, TagsMethod,
TerminationNorm, TraceLevel, TraceSuppress,
globals(Options, Target, GC_Method, TagsMethod,
TerminationNorm, TraceLevel, TraceSuppress, no)).
globals__get_options(Globals, Globals ^ options).
globals__get_target(Globals, Globals ^ target).
globals__get_gc_method(Globals, Globals ^ gc_method).
globals__get_tags_method(Globals, Globals ^ tags_method).
globals__get_termination_norm(Globals, Globals ^ termination_norm).
globals__get_trace_level(Globals, Globals ^ trace_level).
globals__get_trace_suppress(Globals, Globals ^ trace_suppress_items).
globals__get_source_file_map(Globals, Globals ^ source_file_map).
globals__get_backend_foreign_languages(Globals, ForeignLangs) :-
globals__lookup_accumulating_option(Globals, backend_foreign_languages,
LangStrs),
ForeignLangs = list__map(func(String) = ForeignLang :-
( convert_foreign_language(String, ForeignLang0) ->
ForeignLang = ForeignLang0
;
error("globals__io_get_backend_foreign_languages: " ++
"invalid foreign_language string")
), LangStrs).
globals__set_options(Globals, Options, Globals ^ options := Options).
globals__set_gc_method(Globals, GC_Method,
Globals ^ gc_method := GC_Method).
globals__set_tags_method(Globals, Tags_Method,
Globals ^ tags_method := Tags_Method).
globals__set_trace_level(Globals, TraceLevel,
Globals ^ trace_level := TraceLevel).
globals__set_trace_level_none(Globals,
Globals ^ trace_level := trace_level_none).
globals__set_source_file_map(Globals, SourceFileMap,
Globals ^ source_file_map := SourceFileMap).
globals__lookup_option(Globals, Option, OptionData) :-
globals__get_options(Globals, OptionTable),
map__lookup(OptionTable, Option, OptionData).
%-----------------------------------------------------------------------------%
globals__lookup_bool_option(Globals, Option, Value) :-
globals__lookup_option(Globals, Option, OptionData),
( OptionData = bool(Bool) ->
Value = Bool
;
error("globals__lookup_bool_option: invalid bool option")
).
globals__lookup_string_option(Globals, Option, Value) :-
globals__lookup_option(Globals, Option, OptionData),
( OptionData = string(String) ->
Value = String
;
error("globals__lookup_string_option: invalid string option")
).
globals__lookup_int_option(Globals, Option, Value) :-
globals__lookup_option(Globals, Option, OptionData),
( OptionData = int(Int) ->
Value = Int
;
error("globals__lookup_int_option: invalid int option")
).
globals__lookup_maybe_string_option(Globals, Option, Value) :-
globals__lookup_option(Globals, Option, OptionData),
( OptionData = maybe_string(MaybeString) ->
Value = MaybeString
;
error(
"globals__lookup_string_option: invalid maybe_string option")
).
globals__lookup_accumulating_option(Globals, Option, Value) :-
globals__lookup_option(Globals, Option, OptionData),
( OptionData = accumulating(Accumulating) ->
Value = Accumulating
;
error("globals__lookup_accumulating_option: invalid accumulating option")
).
%-----------------------------------------------------------------------------%
globals__have_static_code_addresses(Globals, IsConst) :-
globals__get_options(Globals, OptionTable),
globals__have_static_code_addresses_2(OptionTable, IsConst).
:- pred globals__have_static_code_addresses_2(option_table::in,
bool::out) is det.
globals__have_static_code_addresses_2(OptionTable, IsConst) :-
getopt__lookup_bool_option(OptionTable, gcc_non_local_gotos,
NonLocalGotos),
getopt__lookup_bool_option(OptionTable, asm_labels, AsmLabels),
globals__imported_is_constant(NonLocalGotos, AsmLabels, IsConst).
globals__want_return_var_layouts(Globals, WantReturnLayouts) :-
% We need to generate layout info for call return labels
% if we are using accurate gc or if the user wants uplevel printing.
(
(
globals__get_gc_method(Globals, GC_Method),
GC_Method = accurate
;
globals__get_trace_level(Globals, TraceLevel),
globals__get_trace_suppress(Globals, TraceSuppress),
trace_needs_return_info(TraceLevel, TraceSuppress)
= yes
)
->
WantReturnLayouts = yes
;
WantReturnLayouts = no
).
% The logic of this function and how it is used to select the default
% type_info method must agree with the code in runtime/typeinfo.h.
globals__imported_is_constant(NonLocalGotos, AsmLabels, IsConst) :-
(
NonLocalGotos = yes,
AsmLabels = no
->
%
% with non-local gotos but no asm labels, jumps to code
% addresses in different c_modules must be done via global
% variables; the value of these global variables is not
% constant (i.e. not computable at load time), since they
% can't be initialized until we call init_modules().
%
IsConst = no
;
IsConst = yes
).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
globals__io_init(Options, Target, GC_Method, TagsMethod,
TerminationNorm, TraceLevel, TraceSuppress) -->
{ copy(Target, Target1) },
{ copy(GC_Method, GC_Method1) },
{ copy(TagsMethod, TagsMethod1) },
{ copy(TerminationNorm, TerminationNorm1) },
{ copy(TraceLevel, TraceLevel1) },
{ copy(TraceSuppress, TraceSuppress1) },
{ globals__init(Options, Target1, GC_Method1, TagsMethod1,
TerminationNorm1, TraceLevel1, TraceSuppress1, Globals) },
globals__io_set_globals(Globals).
globals__io_get_target(Target) -->
globals__io_get_globals(Globals),
{ globals__get_target(Globals, Target) }.
globals__io_get_gc_method(GC_Method) -->
globals__io_get_globals(Globals),
{ globals__get_gc_method(Globals, GC_Method) }.
globals__io_get_tags_method(Tags_Method) -->
globals__io_get_globals(Globals),
{ globals__get_tags_method(Globals, Tags_Method) }.
globals__io_get_termination_norm(TerminationNorm) -->
globals__io_get_globals(Globals),
{ globals__get_termination_norm(Globals, TerminationNorm) }.
globals__io_get_trace_level(TraceLevel) -->
globals__io_get_globals(Globals),
{ globals__get_trace_level(Globals, TraceLevel) }.
globals__io_get_trace_suppress(TraceSuppress) -->
globals__io_get_globals(Globals),
{ globals__get_trace_suppress(Globals, TraceSuppress) }.
globals__io_get_globals(Globals) -->
io__get_globals(UnivGlobals),
{
univ_to_type(UnivGlobals, Globals0)
->
Globals = Globals0
;
error("globals__io_get_globals: univ_to_type failed")
}.
globals__io_set_globals(Globals) -->
{ type_to_univ(Globals, UnivGlobals) },
io__set_globals(UnivGlobals).
%-----------------------------------------------------------------------------%
globals__io_lookup_option(Option, OptionData) -->
globals__io_get_globals(Globals),
{ globals__get_options(Globals, OptionTable) },
{ map__lookup(OptionTable, Option, OptionData) }.
globals__io_set_option(Option, OptionData) -->
globals__io_get_globals(Globals0),
{ globals__get_options(Globals0, OptionTable0) },
{ map__set(OptionTable0, Option, OptionData, OptionTable) },
{ globals__set_options(Globals0, OptionTable, Globals1) },
% XXX there is a bit of a design flaw with regard to
% uniqueness and io__set_globals
{ unsafe_promise_unique(Globals1, Globals) },
globals__io_set_globals(Globals).
globals__io_set_gc_method(GC_Method) -->
globals__io_get_globals(Globals0),
{ globals__set_gc_method(Globals0, GC_Method, Globals1) },
{ unsafe_promise_unique(Globals1, Globals) },
% XXX there is a bit of a design flaw with regard to
% uniqueness and io__set_globals
globals__io_set_globals(Globals).
globals__io_set_tags_method(Tags_Method) -->
globals__io_get_globals(Globals0),
{ globals__set_tags_method(Globals0, Tags_Method, Globals1) },
{ unsafe_promise_unique(Globals1, Globals) },
% XXX there is a bit of a design flaw with regard to
% uniqueness and io__set_globals
globals__io_set_globals(Globals).
globals__io_set_trace_level(TraceLevel) -->
globals__io_get_globals(Globals0),
{ globals__set_trace_level(Globals0, TraceLevel, Globals1) },
{ unsafe_promise_unique(Globals1, Globals) },
% XXX there is a bit of a design flaw with regard to
% uniqueness and io__set_globals
globals__io_set_globals(Globals).
% This predicate is needed because mercury_compile.m doesn't know
% anything about type trace_level.
globals__io_set_trace_level_none -->
globals__io_set_trace_level(trace_level_none).
%-----------------------------------------------------------------------------%
globals__io_lookup_foreign_language_option(Option, ForeignLang) -->
globals__io_lookup_string_option(Option, String),
{ convert_foreign_language(String, ForeignLang0) ->
ForeignLang = ForeignLang0
;
error("globals__io_lookup_foreign_language_option: invalid foreign_language option")
}.
globals__io_get_backend_foreign_languages(ForeignLangs) -->
globals__io_get_globals(Globals),
{ globals__get_backend_foreign_languages(Globals, ForeignLangs) }.
globals__io_lookup_bool_option(Option, Value) -->
globals__io_get_globals(Globals),
{ globals__lookup_bool_option(Globals, Option, Value) }.
globals__io_lookup_int_option(Option, Value) -->
globals__io_get_globals(Globals),
{ globals__lookup_int_option(Globals, Option, Value) }.
globals__io_lookup_string_option(Option, Value) -->
globals__io_get_globals(Globals),
{ globals__lookup_string_option(Globals, Option, Value) }.
globals__io_lookup_maybe_string_option(Option, Value) -->
globals__io_get_globals(Globals),
{ globals__lookup_maybe_string_option(Globals, Option, Value) }.
globals__io_lookup_accumulating_option(Option, Value) -->
globals__io_get_globals(Globals),
{ globals__lookup_accumulating_option(Globals, Option, Value) }.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%