mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 09:23:44 +00:00
Estimated hours taken: 50 Branches: main This patch adds preliminary support for deterministic, dependent parallel conjunctions to the low-level backend. In other backends dependent parallel conjunctions are converted into plain conjunctions. For a parallel conjunction (A & B), if the goal B is dependent on a variable X which is bound by goal A, we transform the conjunction such that goal B must wait for the value to be produced by A before it begins executing. This transformation is not yet useful in practice (you might as well use a sequential conjunction). A later version of this transformation will move the synchronisation deeper into the goals so that B can execute as much as possible before it waits for the value from A. There is no coroutining support yet so if there are not enough threads available then dependent parallel conjunctions can cause the program to deadlock. configure.in: runtime/mercury_conf.h.in: Check for existence of semaphore.h and #define MR_HAVE_SEMAPHORE_H if it does. library/library.m: library/par_builtin.m: library/private_builtin.m: mdbcomp/prim_data.m: mdbcomp/program_representation.m: Add a new module `par_builtin' to hold synchronisation primitives. compiler/modules.m: Import `par_builtin' module in parallel grades. compiler/dep_par_conj.m: compiler/transform_hlds.m: compiler/mercury_compile.m: Add a transformation to detect dependent parallel conjunctions and insert the necessary synchronisation code. compiler/hlds_goal.m: Consider empty parallel conjunctions as atomic, the same as plain conjunctions. compiler/inlining.m: Flatten parallel conjunctions when inlining, as for plain conjunctions. compiler/live_vars.m: Fix build_live_sets_in_par_conj to handle dependent parallel conjunctions. compiler/liveness.m: Delay deaths in parallel conjunctions the same way as for plain conjunctions. Update detect_resume_points_in_par_conj for dependent parallel conjunctions. compiler/mode_util.m: Treat parallel and plain conjunctions equally when recomputing instmap deltas. compiler/modes.m: compiler/unique_modes.m: Treat parallel and plain conjunctions equally when checking modes and uniqueness. However, don't flatten parallel conjunctions into plain conjunctions and vice versa. compiler/simplify.m: Don't reset instmaps and seen calls after each conjunct of a parallel conjunction. compiler/store_alloc.m: Update allocation for dependent parallel conjunctions. compiler/switch_detection.m: Detect switches in parallel conjunctions the same as plain conjunctions. compiler/par_conj_gen.m: Add a todo comment. tests/Mmakefile: tests/par_conj/.cvsignore: tests/par_conj/Mmakefile: tests/par_conj/dep_par_1.m: tests/par_conj/dep_par_10.m: tests/par_conj/dep_par_11.m: tests/par_conj/dep_par_11b.m: tests/par_conj/dep_par_11c.m: tests/par_conj/dep_par_12.m: tests/par_conj/dep_par_13.m: tests/par_conj/dep_par_14.m: tests/par_conj/dep_par_14b.m: tests/par_conj/dep_par_14c.m: tests/par_conj/dep_par_14d.m: tests/par_conj/dep_par_16.m: tests/par_conj/dep_par_17.m: tests/par_conj/dep_par_18.m: tests/par_conj/dep_par_2.m: tests/par_conj/dep_par_20.m: tests/par_conj/dep_par_21.m: tests/par_conj/dep_par_22.m: tests/par_conj/dep_par_23.m: tests/par_conj/dep_par_3.m: tests/par_conj/dep_par_3b.m: tests/par_conj/dep_par_3c.m: tests/par_conj/dep_par_4.m: tests/par_conj/dep_par_5.m: tests/par_conj/dep_par_5b.m: tests/par_conj/dep_par_5c.m: tests/par_conj/dep_par_5d.m: tests/par_conj/dep_par_6.m: tests/par_conj/dep_par_7.m: tests/par_conj/dep_par_8.m: tests/par_conj/dep_par_9.m: tests/par_conj/indep_par_append.exp: tests/par_conj/indep_par_append.m: tests/par_conj/indep_par_nested.exp: tests/par_conj/indep_par_nested.m: Add some parallel conjunction test cases. The dependent parallel conjunction tests are not yet executed as they can deadlock if there are not enough threads available. browser/RESERVED_MACRO_NAMES: library/RESERVED_MACRO_NAMES: runtime/RESERVED_MACRO_NAMES: trace/RESERVED_MACRO_NAMES: Add LINUX_THREADS, _REENTRANT and _THREAD_SAFE.
328 lines
13 KiB
Mathematica
328 lines
13 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2005-2006 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.
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% File: prim_data.m.
|
|
% Main authors: fjh, zs.
|
|
%
|
|
% This module contains some types and predicates that are, or are planned to
|
|
% be, shared between the compiler and the debugger.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module mdbcomp.prim_data.
|
|
|
|
:- interface.
|
|
|
|
% This enumeration must be EXACTLY the same as the MR_PredFunc enum
|
|
% in runtime/mercury_stack_layout.h, and in the same order, since the
|
|
% code (in browser) assumes the representation is the same.
|
|
:- type pred_or_func
|
|
---> predicate
|
|
; function.
|
|
|
|
% The kinds of events with which MR_trace may be called, either
|
|
% by compiler-generated code, or by code in the standard library
|
|
% referring to compiler-generated data structures.
|
|
%
|
|
% This enumeration must be EXACTLY the same as the MR_trace_port enum
|
|
% in runtime/mercury_trace_base.h, and in the same order, since the
|
|
% code (in browser) assumes the representation is the same.
|
|
:- type trace_port
|
|
---> call
|
|
; exit
|
|
; redo
|
|
; fail
|
|
; exception
|
|
; ite_cond
|
|
; ite_then
|
|
; ite_else
|
|
; neg_enter
|
|
; neg_success
|
|
; neg_failure
|
|
; disj
|
|
; switch
|
|
; nondet_pragma_first
|
|
; nondet_pragma_later.
|
|
|
|
% was in compiler/prog_data.m
|
|
|
|
% The order that the sym_name function symbols appear in can be significant
|
|
% for module dependency ordering.
|
|
:- type sym_name
|
|
---> unqualified(string)
|
|
; qualified(sym_name, string).
|
|
|
|
:- type module_name == sym_name.
|
|
|
|
% was in compiler/proc_label.m
|
|
|
|
% A proc_label is a data structure a backend can use to as the basis
|
|
% of the label used as the entry point of a procedure.
|
|
%
|
|
% The defining module is the module that provides the code for the
|
|
% predicate, the declaring module contains the `:- pred' declaration.
|
|
% When these are different, as for specialised versions of predicates
|
|
% from `.opt' files, the defining module's name may need to be added
|
|
% as a qualifier to the label.
|
|
:- type proc_label
|
|
---> ordinary_proc_label(
|
|
ord_defining_module :: module_name,
|
|
ord_p_or_f :: pred_or_func,
|
|
ord_declaring_module :: module_name,
|
|
ord_pred_name :: string,
|
|
ord_arity :: int,
|
|
ord_mode_number :: int
|
|
)
|
|
; special_proc_label(
|
|
spec_defining_module :: module_name,
|
|
spec_spec_id :: special_pred_id,
|
|
% The special_pred_id indirectly
|
|
% defines the predicate name.
|
|
spec_type_module :: module_name,
|
|
spec_type_name :: string,
|
|
spec_type_arity :: int,
|
|
spec_mode_number :: int
|
|
).
|
|
|
|
:- type special_pred_id
|
|
---> spec_pred_unify
|
|
; spec_pred_index
|
|
; spec_pred_compare
|
|
; spec_pred_init.
|
|
|
|
% special_pred_name_arity(SpecialPredId, GenericPredName, TargetName,
|
|
% Arity):
|
|
%
|
|
% True iff there is a special predicate of category SpecialPredId,
|
|
% called builtin.GenericPredName/Arity, and for which the name of the
|
|
% predicate in the target language is TargetName.
|
|
%
|
|
:- pred special_pred_name_arity(special_pred_id, string, string, int).
|
|
:- mode special_pred_name_arity(in, out, out, out) is det.
|
|
:- mode special_pred_name_arity(out, in, out, out) is semidet.
|
|
:- mode special_pred_name_arity(out, out, in, out) is semidet.
|
|
|
|
% get_special_pred_id_generic_name(SpecialPredId) = GenericPredName:
|
|
%
|
|
% The name of the generic predicate for SpecialPredId is
|
|
% builtin.GenericPredName.
|
|
%
|
|
:- func get_special_pred_id_generic_name(special_pred_id) = string.
|
|
|
|
% get_special_pred_id_target_name(SpecialPredId) = TargetName:
|
|
%
|
|
% The name of the predicate in the target language for SpecialPredId is
|
|
% TargetName.
|
|
%
|
|
:- func get_special_pred_id_target_name(special_pred_id) = string.
|
|
|
|
% get_special_pred_id_name(SpecialPredId) = Arity:
|
|
%
|
|
% The arity of the SpecialPredId predicate is Arity.
|
|
%
|
|
:- func get_special_pred_id_arity(special_pred_id) = int.
|
|
|
|
% string_to_sym_name(String, Separator, SymName):
|
|
%
|
|
% Convert a string, possibly prefixed with module qualifiers (separated
|
|
% by Separator), into a symbol name.
|
|
%
|
|
:- pred string_to_sym_name(string::in, string::in, sym_name::out) is det.
|
|
|
|
% sym_name_to_string(SymName, Separator, String):
|
|
%
|
|
% Convert a symbol name to a string, with module qualifiers separated
|
|
% by Separator.
|
|
%
|
|
:- pred sym_name_to_string(sym_name::in, string::in, string::out) is det.
|
|
:- func sym_name_to_string(sym_name, string) = string.
|
|
|
|
% sym_name_to_string(SymName, String):
|
|
%
|
|
% Convert a symbol name to a string, with module qualifiers separated by
|
|
% the standard Mercury module qualifier operator.
|
|
%
|
|
:- pred sym_name_to_string(sym_name::in, string::out) is det.
|
|
:- func sym_name_to_string(sym_name) = string.
|
|
|
|
% is_submodule(SymName1, SymName2):
|
|
%
|
|
% True iff SymName1 is a submodule of SymName2.
|
|
% For example mod1.mod2.mod3 is a submodule of mod1.mod2.
|
|
%
|
|
:- pred is_submodule(module_name::in, module_name::in) is semidet.
|
|
|
|
% insert_module_qualifier(ModuleName, SymName0, SymName):
|
|
%
|
|
% Prepend the specified ModuleName onto the module qualifiers in SymName0,
|
|
% giving SymName.
|
|
%
|
|
:- pred insert_module_qualifier(string::in, sym_name::in, sym_name::out)
|
|
is det.
|
|
|
|
% Returns the name of the module containing public builtins;
|
|
% originally this was "mercury_builtin", but it later became
|
|
% just "builtin", and it may eventually be renamed "std.builtin".
|
|
% This module is automatically imported, as if via `import_module'.
|
|
%
|
|
:- pred mercury_public_builtin_module(sym_name::out) is det.
|
|
:- func mercury_public_builtin_module = sym_name.
|
|
|
|
% Returns the name of the module containing private builtins;
|
|
% traditionally this was "mercury_builtin", but it later became
|
|
% "private_builtin", and it may eventually be renamed
|
|
% "std.private_builtin". This module is automatically imported,
|
|
% as if via `use_module'.
|
|
%
|
|
:- pred mercury_private_builtin_module(sym_name::out) is det.
|
|
:- func mercury_private_builtin_module = sym_name.
|
|
|
|
% Returns the name of the module containing builtins for tabling;
|
|
% originally these were in "private_builtin", but were then moved into
|
|
% a separate module. This module is automatically imported iff any
|
|
% predicate is tabled.
|
|
%
|
|
:- pred mercury_table_builtin_module(sym_name::out) is det.
|
|
:- func mercury_table_builtin_module = sym_name.
|
|
|
|
% Returns the name of the module containing the builtins for deep
|
|
% profiling. This module is automatically imported iff deep profiling
|
|
% is enabled.
|
|
%
|
|
:- pred mercury_profiling_builtin_module(sym_name::out) is det.
|
|
:- func mercury_profiling_builtin_module = sym_name.
|
|
|
|
% Returns the name of the module containing the builtins for term size
|
|
% profiling. This module is automatically imported iff term size profiling
|
|
% is enabled.
|
|
%
|
|
:- pred mercury_term_size_prof_builtin_module(sym_name::out) is det.
|
|
:- func mercury_term_size_prof_builtin_module = sym_name.
|
|
|
|
% Returns the name of the module containing the builtins for parallelism.
|
|
% This module is automatically imported iff building in a .par grade.
|
|
%
|
|
:- pred mercury_par_builtin_module(sym_name::out) is det.
|
|
:- func mercury_par_builtin_module = sym_name.
|
|
|
|
% Returns the sym_name of the module with the given name in the
|
|
% Mercury standard library.
|
|
%
|
|
:- pred mercury_std_lib_module_name(string::in, sym_name::out) is det.
|
|
:- func mercury_std_lib_module_name(string) = sym_name.
|
|
|
|
% Succeeds iff the specified module is one of the builtin modules listed
|
|
% above which may be automatically imported.
|
|
%
|
|
:- pred any_mercury_builtin_module(sym_name::in) is semidet.
|
|
|
|
% Succeeds iff the specified module will never be traced.
|
|
%
|
|
:- pred non_traced_mercury_builtin_module(sym_name::in) is semidet.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module int.
|
|
:- import_module list.
|
|
:- import_module string.
|
|
|
|
string_to_sym_name(String, ModuleSeparator, Result) :-
|
|
% This would be simpler if we had a string.rev_sub_string_search/3 pred.
|
|
% With that, we could search for underscores right-to-left, and construct
|
|
% the resulting symbol directly. Instead, we search for them left-to-right,
|
|
% and then call insert_module_qualifier to fix things up.
|
|
(
|
|
string.sub_string_search(String, ModuleSeparator, LeftLength),
|
|
LeftLength > 0
|
|
->
|
|
string.left(String, LeftLength, ModuleName),
|
|
string.length(String, StringLength),
|
|
string.length(ModuleSeparator, SeparatorLength),
|
|
RightLength = StringLength - LeftLength - SeparatorLength,
|
|
string.right(String, RightLength, Name),
|
|
string_to_sym_name(Name, ModuleSeparator, NameSym),
|
|
insert_module_qualifier(ModuleName, NameSym, Result)
|
|
;
|
|
Result = unqualified(String)
|
|
).
|
|
|
|
insert_module_qualifier(ModuleName, unqualified(PlainName),
|
|
qualified(unqualified(ModuleName), PlainName)).
|
|
insert_module_qualifier(ModuleName, qualified(ModuleQual0, PlainName),
|
|
qualified(ModuleQual, PlainName)) :-
|
|
insert_module_qualifier(ModuleName, ModuleQual0, ModuleQual).
|
|
|
|
sym_name_to_string(SymName, String) :-
|
|
sym_name_to_string(SymName, ".", String).
|
|
|
|
sym_name_to_string(SymName) = String :-
|
|
sym_name_to_string(SymName, String).
|
|
|
|
sym_name_to_string(SymName, Separator) = String :-
|
|
sym_name_to_string(SymName, Separator, String).
|
|
|
|
sym_name_to_string(unqualified(Name), _Separator, Name).
|
|
sym_name_to_string(qualified(ModuleSym, Name), Separator, QualName) :-
|
|
sym_name_to_string(ModuleSym, Separator, ModuleName),
|
|
string.append_list([ModuleName, Separator, Name], QualName).
|
|
|
|
is_submodule(SymName, SymName).
|
|
is_submodule(qualified(SymNameA, _), SymNameB) :-
|
|
is_submodule(SymNameA, SymNameB).
|
|
|
|
special_pred_name_arity(spec_pred_unify, "unify", "__Unify__", 2).
|
|
special_pred_name_arity(spec_pred_index, "index", "__Index__", 2).
|
|
special_pred_name_arity(spec_pred_compare, "compare", "__Compare__", 3).
|
|
special_pred_name_arity(spec_pred_init, "initialise", "__Initialise__", 1).
|
|
|
|
get_special_pred_id_generic_name(Id) = Name :-
|
|
special_pred_name_arity(Id, Name, _, _).
|
|
|
|
get_special_pred_id_target_name(Id) = Name :-
|
|
special_pred_name_arity(Id, _, Name, _).
|
|
|
|
get_special_pred_id_arity(Id) = Arity :-
|
|
special_pred_name_arity(Id, _, _, Arity).
|
|
|
|
% We may eventually want to put the standard library into a package "std":
|
|
% mercury_public_builtin_module = qualified(unqualified("std"), "builtin").
|
|
% mercury_private_builtin_module(M) =
|
|
% qualified(unqualified("std"), "private_builtin"))).
|
|
mercury_public_builtin_module = unqualified("builtin").
|
|
mercury_public_builtin_module(mercury_public_builtin_module).
|
|
mercury_private_builtin_module = unqualified("private_builtin").
|
|
mercury_private_builtin_module(mercury_private_builtin_module).
|
|
mercury_table_builtin_module = unqualified("table_builtin").
|
|
mercury_table_builtin_module(mercury_table_builtin_module).
|
|
mercury_profiling_builtin_module = unqualified("profiling_builtin").
|
|
mercury_profiling_builtin_module(mercury_profiling_builtin_module).
|
|
mercury_term_size_prof_builtin_module = unqualified("term_size_prof_builtin").
|
|
mercury_term_size_prof_builtin_module(mercury_term_size_prof_builtin_module).
|
|
mercury_par_builtin_module = unqualified("par_builtin").
|
|
mercury_par_builtin_module(mercury_par_builtin_module).
|
|
mercury_std_lib_module_name(Name) = unqualified(Name).
|
|
mercury_std_lib_module_name(Name, unqualified(Name)).
|
|
|
|
any_mercury_builtin_module(Module) :-
|
|
( mercury_public_builtin_module(Module)
|
|
; mercury_private_builtin_module(Module)
|
|
; mercury_table_builtin_module(Module)
|
|
; mercury_profiling_builtin_module(Module)
|
|
; mercury_term_size_prof_builtin_module(Module)
|
|
; mercury_par_builtin_module(Module)
|
|
).
|
|
|
|
non_traced_mercury_builtin_module(Module) :-
|
|
( mercury_table_builtin_module(Module)
|
|
; mercury_profiling_builtin_module(Module)
|
|
; mercury_term_size_prof_builtin_module(Module)
|
|
; mercury_par_builtin_module(Module)
|
|
).
|