[m-rev.] for review: inline par_conj primitives

Zoltan Somogyi zs at csse.unimelb.edu.au
Wed Jun 10 16:48:36 AEST 2009


For review by Peter Wang or Paul Bone.

Zoltan.

A first step in allowing users to ask the compiler to implement the primitive
operations needed for dependent parallel conjunctions *either* as calls to
library/par_builtin (as at present), *or* as inline C code.

The second option should be faster, and should also solve the problem
of the compiler not optimizing away unnecessary calls to par_builtin.get.
The reason was that in the absence of access to the code of par_builtin.get,
simplify.m does not know whether that predicate can loop forever or throw
an exception. The corresponding foreign proc can be marked to show that
it can do neither.

At the moment, the second option doesn't work, but debugging the problem
should be simpler once this diff is installed. This is due to the change
in the names of the primitive operations to satisfy the readability demands
of the paper describing dependent AND-parallelism.

This diff passes bootcheck in asm_fast.gc.par with no new test case failures.

runtime/mercury_par_builtin.[ch]:
	New module that contains definitions of the types and operations
	that implement dependent parallel conjunctions.

	The content of this module is copied over from library/par_builtin.m,
	modified slightly for definition as macros.

runtime/mercury_types.h:
	Move the definition of MR_Future here, to define the type name even if
	the structure is not defined (since it is defined and referred to only
	in some grades).

runtime/mercury_imp.h:
	#include the new module.

runtime/Mmakefile:
	Add the new module.

library/par_builtin.m:
	Refer to the definitions in runtime/mercury_par_builtin.h.

	Rename the operations here to make their names meaningful *without*
	module qualification.

compiler/options.m:
	Add the option --no-inline-par-builtins.

	Put some help messages in an order consistent with the rest of the
	module.

compiler/prog_type.m:
	Move the definition of the future_type here from dep_par_conj.m,
	since the definitions of other similar types are here.

compiler/dep_par_conj.m:
	Use foreign_procs instead of calls for parallel builtins unless
	--no-inline-par-builtins is given.

compiler/goal_util.m:
	Fix some comments.

mdbcomp/program_representation.m:
	Conform to the changes in the names of predicates.

cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/libatomic_ops-1.2
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/doc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/gcc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/hpc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/ibmc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/icc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/sunc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/tests
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing boehm_gc/windows-untested
cvs diff: Diffing boehm_gc/windows-untested/vc60
cvs diff: Diffing boehm_gc/windows-untested/vc70
cvs diff: Diffing boehm_gc/windows-untested/vc71
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/add_pragma.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/add_pragma.m,v
retrieving revision 1.90
diff -u -r1.90 add_pragma.m
--- compiler/add_pragma.m	27 May 2009 05:48:36 -0000	1.90
+++ compiler/add_pragma.m	1 Jun 2009 02:48:28 -0000
@@ -3473,6 +3473,7 @@
     (
         ( Attr = max_stack_size(_)
         ; Attr = refers_to_llds_stack
+        ; Attr = needs_call_standard_output_registers
         ),
         Result = is_applicable_for_current_backend(CurrentBackend, Attrs)
     ;
Index: compiler/dep_par_conj.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/dep_par_conj.m,v
retrieving revision 1.34
diff -u -r1.34 dep_par_conj.m
--- compiler/dep_par_conj.m	19 Feb 2009 03:49:17 -0000	1.34
+++ compiler/dep_par_conj.m	20 Feb 2009 07:42:33 -0000
@@ -152,6 +152,7 @@
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.prim_data.
+:- import_module parse_tree.prog_mode.
 :- import_module parse_tree.prog_type.
 :- import_module parse_tree.prog_util.
 
@@ -776,7 +777,7 @@
 insert_wait_before_goal(ModuleInfo, FutureMap, ConsumedVar,
         Goal0, Goal, !VarSet, !VarTypes) :-
     map.lookup(FutureMap, ConsumedVar, FutureVar),
-    make_wait_goal(ModuleInfo, FutureVar, ConsumedVar, WaitGoal),
+    make_wait_goal(ModuleInfo, !.VarTypes, FutureVar, ConsumedVar, WaitGoal),
     conjoin_goals_update_goal_infos(Goal0 ^ hlds_goal_info, WaitGoal, Goal0,
         Goal).
 
@@ -787,7 +788,7 @@
 insert_wait_after_goal(ModuleInfo, FutureMap, ConsumedVar,
         Goal0, Goal, !VarSet, !VarTypes) :-
     map.lookup(FutureMap, ConsumedVar, FutureVar),
-    make_wait_goal(ModuleInfo, FutureVar, ConsumedVar, WaitGoal),
+    make_wait_goal(ModuleInfo, !.VarTypes, FutureVar, ConsumedVar, WaitGoal),
     conjoin_goals_update_goal_infos(Goal0 ^ hlds_goal_info, Goal0, WaitGoal,
         Goal).
 
@@ -1061,7 +1062,8 @@
 
 insert_signal_after_goal(ModuleInfo, FutureMap, ProducedVar,
         Goal0, Goal, !VarSet, !VarTypes) :-
-    make_signal_goal(ModuleInfo, FutureMap, ProducedVar, SignalGoal),
+    make_signal_goal(ModuleInfo, FutureMap, ProducedVar, !.VarTypes,
+        SignalGoal),
     conjoin_goals_update_goal_infos(Goal0 ^ hlds_goal_info, Goal0, SignalGoal,
         Goal).
 
@@ -1171,6 +1173,10 @@
                 % updated.
                 spec_initial_module         :: module_info,
 
+                % The variable types of the procedure we are scanning.
+                % This field is constant; it should never be updated.
+                spec_vartypes               :: vartypes,
+
                 % The current module. Updated when requesting a new
                 % specialization, since to get the pred_id for the specialized
                 % predicate we need to update the module_info.
@@ -1252,11 +1258,12 @@
     some [!PredInfo, !ProcInfo, !Goal, !SpecInfo] (
         module_info_pred_proc_info(!.ModuleInfo, PredId, ProcId,
             !:PredInfo, !:ProcInfo),
+        proc_info_get_vartypes(!.ProcInfo, VarTypes),
         proc_info_get_goal(!.ProcInfo, !:Goal),
-        !:SpecInfo = spec_info(DoneProcs, InitialModuleInfo,
+        !:SpecInfo = spec_info(DoneProcs, InitialModuleInfo, VarTypes,
             !.ModuleInfo, !.PendingParProcs, !.Pushability),
         specialize_sequences_in_goal(!Goal, !SpecInfo),
-        !.SpecInfo = spec_info(_, _,
+        !.SpecInfo = spec_info(_, _, _,
             !:ModuleInfo, !:PendingParProcs, !:Pushability),
         proc_info_set_goal(!.Goal, !ProcInfo),
         % Optimization opportunity: we should not fix up the same procedure
@@ -1369,7 +1376,8 @@
 map_arg_to_new_future(HeadVars, FutureArg, !FutureMap, !VarSet, !VarTypes) :-
     HeadVar = list.det_index1(HeadVars, FutureArg),
     map.lookup(!.VarTypes, HeadVar, VarType),
-    make_future_var(HeadVar, VarType, !VarSet, !VarTypes, FutureVar),
+    make_future_var(HeadVar, VarType, !VarSet, !VarTypes, FutureVar,
+        _FutureVarType),
     svmap.det_insert(HeadVar, FutureVar, !FutureMap).
 
 :- pred replace_head_vars(module_info::in, future_map::in,
@@ -1472,7 +1480,7 @@
         Goal = Goal0
     ;
         GoalExpr0 = shorthand(_),
-        unexpected(this_file, "shorthand")
+        unexpected(this_file, "specialize_sequences_in_goal: shorthand")
     ).
 
 :- pred specialize_sequences_in_conj(list(hlds_goal)::in, list(hlds_goal)::out,
@@ -1595,7 +1603,8 @@
             % XXX The simplify pass that comes later doesn't always remove
             % these calls, even if they're unnecessary.
 
-            list.map(make_get_goal(!.SpecInfo ^ spec_module_info),
+            VarTypes = !.SpecInfo ^ spec_vartypes,
+            list.map(make_get_goal(!.SpecInfo ^ spec_module_info, VarTypes),
                 PushedSignalPairs ++ PushedWaitPairs, GetGoals),
 
             RevGoals = GetGoals ++ [Goal] ++ UnPushedWaitGoals ++ RevGoals1,
@@ -1625,7 +1634,7 @@
     Goal = hlds_goal(GoalExpr, _),
     (
         GoalExpr = plain_call(_, _, WaitArgs, _, _, SymName),
-        SymName = qualified(mercury_par_builtin_module, "wait"),
+        SymName = qualified(mercury_par_builtin_module, wait_pred_name),
         WaitArgs = [FutureVar, ConsumedVar]
     ->
         % This is a wait goal.
@@ -1676,7 +1685,7 @@
     Goal = hlds_goal(GoalExpr, _),
     (
         GoalExpr = plain_call(_, _, SignalArgs, _, _, SymName),
-        SymName = qualified(mercury_par_builtin_module, "signal"),
+        SymName = qualified(mercury_par_builtin_module, signal_pred_name),
         SignalArgs = [FutureVar, ProducedVar]
     ->
         % This is a signal goal.
@@ -1882,16 +1891,16 @@
     list(mer_type)::out) is det.
 
 futurise_argtypes(_, [], ArgTypes, ArgTypes).
-futurise_argtypes(ArgNo, [FutureArg | FutureArgs], [ArgType0 | ArgTypes0],
-        [ArgType | ArgTypes]) :-
+futurise_argtypes(ArgNo, [FutureArg | FutureArgs], [ArgType | ArgTypes],
+        [FuturisedArgType | FuturisedArgTypes]) :-
     ( ArgNo = FutureArg ->
-        construct_future_type(ArgType0, ArgType),
-        futurise_argtypes(ArgNo+1, FutureArgs,
-            ArgTypes0, ArgTypes)
-    ;
-        ArgType = ArgType0,
-        futurise_argtypes(ArgNo+1, [FutureArg | FutureArgs],
-            ArgTypes0, ArgTypes)
+        FuturisedArgType = future_type(ArgType),
+        futurise_argtypes(ArgNo + 1, FutureArgs,
+            ArgTypes, FuturisedArgTypes)
+    ;
+        FuturisedArgType = ArgType,
+        futurise_argtypes(ArgNo + 1, [FutureArg | FutureArgs],
+            ArgTypes, FuturisedArgTypes)
     ).
 futurise_argtypes(_, [_ | _], [], _) :-
     unexpected(this_file,
@@ -2560,90 +2569,193 @@
 allocate_future(ModuleInfo, SharedVar, AllocGoal, !VarSet, !VarTypes,
         !FutureMap) :-
     map.lookup(!.VarTypes, SharedVar, SharedVarType),
-    make_future_var(SharedVar, SharedVarType, !VarSet, !VarTypes, FutureVar),
+    make_future_var(SharedVar, SharedVarType, !VarSet, !VarTypes,
+        FutureVar, FutureVarType),
     svmap.det_insert(SharedVar, FutureVar, !FutureMap),
 
     ModuleName = mercury_par_builtin_module,
-    PredName = "new_future",
-    Args = [FutureVar],
+    PredName = new_pred_name,
     Features = [],
     InstMapSrc = [FutureVar - ground(shared, none)],
     Context = term.context_init,
-    goal_util.generate_simple_call(ModuleName, PredName, pf_predicate,
-        only_mode, detism_det, purity_pure, Args, Features, InstMapSrc,
-        ModuleInfo, Context, AllocGoal).
+    ShouldInline = should_inline_par_builtin_calls(ModuleInfo),
+    (
+        ShouldInline = no,
+        ArgVars = [FutureVar],
+        generate_simple_call(ModuleName, PredName, pf_predicate,
+            only_mode, detism_det, purity_pure, ArgVars, Features, InstMapSrc,
+            ModuleInfo, Context, AllocGoal)
+    ;
+        ShouldInline = yes,
+        ForeignAttrs = par_builtin_foreign_proc_attributes(purity_pure, no),
+        Arg1 = foreign_arg(FutureVar, yes("Future" - out_mode),
+            FutureVarType, native_if_possible),
+        Args = [Arg1],
+        ExtraArgs = [],
+        Code = "MR_par_builtin_new_future(Future);",
+        generate_foreign_proc(ModuleName, PredName, pf_predicate,
+            only_mode, detism_det, purity_pure, ForeignAttrs, Args, ExtraArgs,
+            no, Code, Features, InstMapSrc, ModuleInfo, Context, AllocGoal)
+    ).
 
     % Given a variable SharedVar of type SharedVarType, add a new variable
     % FutureVar of type future(SharedVarType).
     %
 :- pred make_future_var(prog_var::in, mer_type::in,
     prog_varset::in, prog_varset::out, vartypes::in, vartypes::out,
-    prog_var::out) is det.
+    prog_var::out, mer_type::out) is det.
 
-make_future_var(SharedVar, SharedVarType, !VarSet, !VarTypes, FutureVar) :-
-    construct_future_type(SharedVarType, FutureType),
+make_future_var(SharedVar, SharedVarType, !VarSet, !VarTypes,
+        FutureVar, FutureVarType) :-
+    FutureVarType = future_type(SharedVarType),
     varset.lookup_name(!.VarSet, SharedVar, SharedVarName),
     svvarset.new_named_var("Future" ++ SharedVarName, FutureVar, !VarSet),
-    svmap.det_insert(FutureVar, FutureType, !VarTypes).
-
-    % Construct type future(T) given type T.
-    %
-:- pred construct_future_type(mer_type::in, mer_type::out) is det.
+    svmap.det_insert(FutureVar, FutureVarType, !VarTypes).
 
-construct_future_type(T, FutureT) :-
-    Future = qualified(mercury_par_builtin_module, "future"),
-    FutureCtor = type_ctor(Future, 1),
-    construct_type(FutureCtor, [T], FutureT).
+:- pred make_wait_goal(module_info::in, vartypes::in,
+    prog_var::in, prog_var::in, hlds_goal::out) is det.
 
-:- pred make_wait_goal(module_info::in, prog_var::in, prog_var::in,
-    hlds_goal::out) is det.
-
-make_wait_goal(ModuleInfo, FutureVar, WaitVar, WaitGoal) :-
-    make_wait_or_get(ModuleInfo, FutureVar, WaitVar, "wait", WaitGoal).
+make_wait_goal(ModuleInfo, VarTypes, FutureVar, WaitVar, WaitGoal) :-
+    make_wait_or_get(ModuleInfo, VarTypes, FutureVar, WaitVar, wait_pred,
+        WaitGoal).
 
-:- pred make_get_goal(module_info::in, future_var_pair::in,
+:- pred make_get_goal(module_info::in, vartypes::in, future_var_pair::in,
     hlds_goal::out) is det.
 
-make_get_goal(ModuleInfo, future_var_pair(FutureVar, WaitVar), WaitGoal) :-
-    make_wait_or_get(ModuleInfo, FutureVar, WaitVar, "get", WaitGoal).
+make_get_goal(ModuleInfo, VarTypes, future_var_pair(FutureVar, WaitVar),
+        WaitGoal) :-
+    make_wait_or_get(ModuleInfo, VarTypes, FutureVar, WaitVar, get_pred,
+        WaitGoal).
+
+:- type wait_or_get_pred
+    --->    wait_pred
+    ;       get_pred.
 
-:- pred make_wait_or_get(module_info::in, prog_var::in, prog_var::in,
-    string::in, hlds_goal::out) is det.
+:- pred make_wait_or_get(module_info::in, vartypes::in,
+    prog_var::in, prog_var::in, wait_or_get_pred::in, hlds_goal::out) is det.
 
-make_wait_or_get(ModuleInfo, FutureVar, WaitVar, PredName, WaitGoal) :-
+make_wait_or_get(ModuleInfo, VarTypes, FutureVar, ConsumedVar, WaitOrGetPred,
+        WaitGoal) :-
     ModuleName = mercury_par_builtin_module,
-    Args = [FutureVar, WaitVar],
+    (
+        WaitOrGetPred = wait_pred,
+        PredName = wait_pred_name,
+        Code = "MR_par_builtin_wait_future(Future, Value);"
+    ;
+        WaitOrGetPred = get_pred,
+        PredName = get_pred_name,
+        Code = "MR_par_builtin_get_future(Future, Value);"
+    ),
     Features = [],
-    InstMapSrc = [WaitVar - ground(shared, none)],
+    InstMapSrc = [ConsumedVar - ground(shared, none)],
     Context = term.context_init,
-    goal_util.generate_simple_call(ModuleName, PredName, pf_predicate,
-        only_mode, detism_det, purity_pure, Args, Features, InstMapSrc,
-        ModuleInfo, Context, WaitGoal).
+    ShouldInline = should_inline_par_builtin_calls(ModuleInfo),
+    (
+        ShouldInline = no,
+        ArgVars = [FutureVar, ConsumedVar],
+        generate_simple_call(ModuleName, PredName, pf_predicate,
+            only_mode, detism_det, purity_pure, ArgVars, Features, InstMapSrc,
+            ModuleInfo, Context, WaitGoal)
+    ;
+        ShouldInline = yes,
+        ForeignAttrs = par_builtin_foreign_proc_attributes(purity_pure, no),
+        Arg1 = foreign_arg(FutureVar, yes("Future" - in_mode),
+            map.lookup(VarTypes, FutureVar), native_if_possible),
+        Arg2 = foreign_arg(ConsumedVar, yes("Value" - out_mode),
+            map.lookup(VarTypes, ConsumedVar), native_if_possible),
+        Args = [Arg1, Arg2],
+        ExtraArgs = [],
+        generate_foreign_proc(ModuleName, PredName, pf_predicate,
+            only_mode, detism_det, purity_pure, ForeignAttrs, Args, ExtraArgs,
+            no, Code, Features, InstMapSrc, ModuleInfo, Context, WaitGoal)
+    ).
 
 :- pred make_signal_goal(module_info::in, future_map::in, prog_var::in,
-    hlds_goal::out) is det.
+    vartypes::in, hlds_goal::out) is det.
 
-make_signal_goal(ModuleInfo, FutureMap, ProducedVar, SignalGoal) :-
+make_signal_goal(ModuleInfo, FutureMap, ProducedVar, VarTypes, SignalGoal) :-
     FutureVar = map.lookup(FutureMap, ProducedVar),
     ModuleName = mercury_par_builtin_module,
-    PredName = "signal",
-    Args = [FutureVar, ProducedVar],
+    PredName = signal_pred_name,
     Features = [],
     InstMapSrc = [],
     Context = term.context_init,
-    goal_util.generate_simple_call(ModuleName, PredName, pf_predicate,
-        only_mode, detism_det, purity_impure, Args, Features, InstMapSrc,
-        ModuleInfo, Context, SignalGoal).
+    ShouldInline = should_inline_par_builtin_calls(ModuleInfo),
+    (
+        ShouldInline = no,
+        ArgVars = [FutureVar, ProducedVar],
+        generate_simple_call(ModuleName, PredName, pf_predicate,
+            only_mode, detism_det, purity_impure, ArgVars, Features,
+            InstMapSrc, ModuleInfo, Context, SignalGoal)
+    ;
+        ShouldInline = yes,
+        ForeignAttrs = par_builtin_foreign_proc_attributes(purity_impure,
+            yes(needs_call_standard_output_registers)),
+        Arg1 = foreign_arg(FutureVar, yes("Future" - in_mode),
+            map.lookup(VarTypes, FutureVar), native_if_possible),
+        Arg2 = foreign_arg(ProducedVar, yes("Value" - in_mode),
+            map.lookup(VarTypes, ProducedVar), native_if_possible),
+        Args = [Arg1, Arg2],
+        ExtraArgs = [],
+        Code = "MR_par_builtin_signal_future(Future, Value);",
+        generate_foreign_proc(ModuleName, PredName, pf_predicate,
+            only_mode, detism_det, purity_impure, ForeignAttrs,
+            Args, ExtraArgs, no, Code, Features, InstMapSrc, ModuleInfo,
+            Context, SignalGoal)
+    ).
 
 :- pred is_wait_goal(hlds_goal::in) is semidet.
 
 is_wait_goal(hlds_goal(plain_call(_, _, _, _, _, SymName), _GoalInfo)) :-
-    SymName = qualified(mercury_par_builtin_module, "wait").
+    SymName = qualified(mercury_par_builtin_module, wait_pred_name).
 
 :- pred is_signal_goal(hlds_goal::in) is semidet.
 
 is_signal_goal(hlds_goal(plain_call(_, _, _, _, _, SymName), _GoalInfo)) :-
-    SymName = qualified(mercury_par_builtin_module, "signal").
+    SymName = qualified(mercury_par_builtin_module, signal_pred_name).
+
+:- func new_pred_name = string.
+:- func wait_pred_name = string.
+:- func get_pred_name = string.
+:- func signal_pred_name = string.
+
+new_pred_name = "new_future".
+wait_pred_name = "wait_future".
+get_pred_name = "get_future".
+signal_pred_name = "signal_future".
+
+:- func should_inline_par_builtin_calls(module_info) = bool.
+
+should_inline_par_builtin_calls(ModuleInfo) = ShouldInline :-
+    module_info_get_globals(ModuleInfo, Globals),
+    globals.lookup_bool_option(Globals, inline_par_builtins, ShouldInline).
+
+:- func par_builtin_foreign_proc_attributes(purity,
+    maybe(pragma_foreign_proc_extra_attribute))
+    = pragma_foreign_proc_attributes.
+
+par_builtin_foreign_proc_attributes(Purity, MaybeExtraAttr) = Attrs :-
+    some [!Attrs] (
+        !:Attrs = default_attributes(lang_c),
+        set_may_call_mercury(proc_will_not_call_mercury, !Attrs),
+        % Even signal is thread safe, since it does its own locking.
+        set_thread_safe(proc_thread_safe, !Attrs),
+        set_purity(Purity, !Attrs),
+        set_terminates(proc_terminates, !Attrs),
+        set_may_throw_exception(proc_will_not_throw_exception, !Attrs),
+        set_may_modify_trail(proc_will_not_modify_trail, !Attrs),
+        set_affects_liveness(proc_does_not_affect_liveness, !Attrs),
+        set_allocates_memory(proc_allocates_bounded_memory, !Attrs),
+        set_registers_roots(proc_does_not_register_roots, !Attrs),
+        set_may_duplicate(yes(proc_may_duplicate), !Attrs),
+        (
+            MaybeExtraAttr = no
+        ;
+            MaybeExtraAttr = yes(ExtraAttr),
+            add_extra_attribute(ExtraAttr, !Attrs)
+        ),
+        Attrs = !.Attrs
+    ).
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/goal_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/goal_util.m,v
retrieving revision 1.167
diff -u -r1.167 goal_util.m
--- compiler/goal_util.m	10 Mar 2009 05:00:29 -0000	1.167
+++ compiler/goal_util.m	12 Mar 2009 01:20:13 -0000
@@ -333,7 +333,8 @@
     hlds_goal::in, bool::out, module_info::in, module_info::out) is det.
 
     % generate_simple_call(ModuleName, ProcName, PredOrFunc, ModeNo, Detism,
-    %   Purity, Args, Features, InstMapDelta, ModuleInfo, Context, CallGoal):
+    %   Purity, Args, Features, InstMapDeltaSrc, ModuleInfo, Context,
+    %   CallGoal):
     %
     % Generate a call to a builtin procedure (e.g. from the private_builtin
     % or table_builtin module). This is used by HLDS->HLDS transformation
@@ -352,14 +353,14 @@
 
     % generate_foreign_proc(ModuleName, ProcName, PredOrFunc, ModeNo, Detism,
     %   Purity, Attributes, Args, ExtraArgs, MaybeTraceRuntimeCond, Code,
-    %   Features, InstMapDelta, ModuleInfo, Context, CallGoal):
+    %   Features, InstMapDeltaSrc, ModuleInfo, Context, CallGoal):
     %
     % generate_foreign_proc is similar to generate_simple_call,
     % but also assumes that the called predicate is defined via a
     % foreign_proc, that the foreign_proc's arguments are as given in
     % Args, its attributes are Attributes, and its code is Code.
     % As well as returning a foreign_code instead of a call, effectively
-    % inlining the call, generate_foreign_proc also and passes ExtraArgs
+    % inlining the call, generate_foreign_proc also passes ExtraArgs
     % as well as Args.
     %
 :- pred generate_foreign_proc(module_name::in, string::in, pred_or_func::in,
Index: compiler/mercury_to_mercury.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mercury_to_mercury.m,v
retrieving revision 1.335
diff -u -r1.335 mercury_to_mercury.m
--- compiler/mercury_to_mercury.m	16 Apr 2009 02:09:08 -0000	1.335
+++ compiler/mercury_to_mercury.m	17 Apr 2009 07:12:12 -0000
@@ -4314,6 +4314,8 @@
 extra_attribute_to_string(backend(high_level_backend)) = "high_level_backend".
 extra_attribute_to_string(max_stack_size(Size)) =
     "max_stack_size(" ++ string.int_to_string(Size) ++ ")".
+extra_attribute_to_string(needs_call_standard_output_registers) =
+    "needs_call_standard_output_registers".
 
 %-----------------------------------------------------------------------------%
 
Index: compiler/ml_code_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/ml_code_gen.m,v
retrieving revision 1.214
diff -u -r1.214 ml_code_gen.m
--- compiler/ml_code_gen.m	16 Jan 2009 02:31:23 -0000	1.214
+++ compiler/ml_code_gen.m	16 Jan 2009 02:37:07 -0000
@@ -3103,16 +3103,28 @@
 :- func get_target_code_attributes(foreign_language,
     pragma_foreign_proc_extra_attributes) = target_code_attributes.
 
-get_target_code_attributes(_, []) = [].
-get_target_code_attributes(Lang, [refers_to_llds_stack | Attrs]) =
-        get_target_code_attributes(Lang, Attrs).
-get_target_code_attributes(Lang, [backend(_Backend) | Attrs]) =
-        get_target_code_attributes(Lang, Attrs).
-get_target_code_attributes(Lang, [max_stack_size(N) | Attrs]) =
-    ( Lang = lang_il ->
-        [max_stack_size(N) | get_target_code_attributes(Lang, Attrs)]
+get_target_code_attributes(_Lang, []) = [].
+get_target_code_attributes(Lang, [ProcAttr | ProcAttrs]) = TargetAttrs :-
+    TargetAttrs1 = get_target_code_attributes(Lang, ProcAttrs),
+    (
+        ProcAttr = max_stack_size(N),
+        (
+            Lang = lang_il,
+            TargetAttrs = [max_stack_size(N) | TargetAttrs1]
+        ;
+            ( Lang = lang_c
+            ; Lang = lang_csharp
+            ; Lang = lang_java
+            ; Lang = lang_erlang
+            ),
+            TargetAttrs = TargetAttrs1
+        )
     ;
-        []
+        ( ProcAttr = refers_to_llds_stack
+        ; ProcAttr = backend(_)
+        ; ProcAttr = needs_call_standard_output_registers
+        ),
+        TargetAttrs = TargetAttrs1
     ).
 
 %---------------------------------------------------------------------------%
Index: compiler/options.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.648
diff -u -r1.648 options.m
--- compiler/options.m	21 May 2009 04:42:15 -0000	1.648
+++ compiler/options.m	1 Jun 2009 02:48:29 -0000
@@ -645,6 +645,7 @@
     ;       tuple_trace_counts_file
     ;       tuple_costs_ratio
     ;       tuple_min_args
+    ;       inline_par_builtins
     ;       always_specialize_in_dep_par_conjs
     ;       allow_some_paths_only_waits
     ;       control_granularity
@@ -1497,6 +1498,7 @@
     tuple_trace_counts_file             -   string(""),
     tuple_costs_ratio                   -   int(100),
     tuple_min_args                      -   int(4),
+    inline_par_builtins                 -   bool(no),
     always_specialize_in_dep_par_conjs  -   bool(no),
     allow_some_paths_only_waits         -   bool(yes),
     control_granularity                 -   bool(no),
@@ -2363,6 +2365,7 @@
 long_option("tuple-trace-counts-file",  tuple_trace_counts_file).
 long_option("tuple-costs-ratio",    tuple_costs_ratio).
 long_option("tuple-min-args",       tuple_min_args).
+long_option("inline-par-builtins",  inline_par_builtins).
 long_option("always-specialize-in-dep-par-conjs",
                                     always_specialize_in_dep_par_conjs).
 long_option("allow-some-paths-only-waits",
@@ -4833,19 +4836,22 @@
         % "\ttransformation will consider passing together as a",
         % "\ttuple. This is mostly to speed up the compilation",
         % "\tprocess by not pursuing (presumably) unfruitful searches.",
+% This is for measurements by implementors only.
+%       "--no-inline-par-builtins",
+%       "\tGenerate calls to the predicates of par_builtin.m, instead of",
+%       "\tbodily including their definitions as C code.",
+%       Actually, this is the default for now.
+% This is for measurements by implementors only.
+%       "--always-specialize-in-dep-par-conjs",
+%       "\tWhen the transformation for handling dependent parallel conjunctions",
+%       "\tadds waits and/or signals around a call, create a specialized",
+%       "\tversion of the called procedure, even if this is not profitable.",
         "--control-granularity",
         "\tDon't try to generate more parallelism than the machine can",
         "\thandle, which is specified using --parallelism-target.",
         "--parallelism-target <n>",
         "\tSpecify the number of CPUs of the target machine, for use by",
         "\tthe --control-granularity option.",
-        "--always-specialize-in-dep-par-conjs",
-% This is for measurements by implementors only.
-%       "\tWhen the transformation for handling dependent parallel conjunctions",
-%       "\tadds waits and/or signals around a call, create a specialized",
-%       "\tversion of the called procedure, even if this is not profitable.",
-        "--control-granularity",
-        "\tEnable the granularity control transformation.",
         "--distance-granularity <distance>",
         "\tControl the granularity of parallel execution using the",
         "\tspecified distance value.", 
Index: compiler/prog_data.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_data.m,v
retrieving revision 1.216
diff -u -r1.216 prog_data.m
--- compiler/prog_data.m	19 Feb 2009 03:49:17 -0000	1.216
+++ compiler/prog_data.m	20 Feb 2009 07:42:34 -0000
@@ -787,71 +787,54 @@
 :- pred set_may_call_mercury(proc_may_call_mercury::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_thread_safe(proc_thread_safe::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_foreign_language(foreign_language::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_tabled_for_io(proc_tabled_for_io::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_purity(purity::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_terminates(proc_terminates::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_user_annotated_sharing(user_annotated_sharing::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_may_throw_exception(proc_may_throw_exception::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_legacy_purity_behaviour(bool::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_ordinary_despite_detism(bool::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_may_modify_trail(proc_may_modify_trail::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_may_call_mm_tabled(may_call_mm_tabled::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_box_policy(box_policy::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_affects_liveness(proc_affects_liveness::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_allocates_memory(proc_allocates_memory::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_registers_roots(proc_registers_roots::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred set_may_duplicate(maybe(proc_may_duplicate)::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
-
 :- pred add_extra_attribute(pragma_foreign_proc_extra_attribute::in,
     pragma_foreign_proc_attributes::in,
     pragma_foreign_proc_attributes::out) is det.
@@ -961,7 +944,16 @@
 :- type pragma_foreign_proc_extra_attribute
     --->    max_stack_size(int)
     ;       refers_to_llds_stack
-    ;       backend(backend).
+    ;       backend(backend)
+    ;       needs_call_standard_output_registers.
+            % On the LLDS backend, this foreign_proc needs to put its outputs
+            % into the same registers as if it were a call. This is useful
+            % if the code of the foreign procedure being invoked can suspend
+            % for a while, resume at a label in the runtime system, and then
+            % return from code at that label. The code that places the outputs
+            % must put them where calls expect them, but without this
+            % attribute, the LLDS code generator could try to put the output
+            % somewhere else.
 
 :- type pragma_foreign_proc_extra_attributes ==
     list(pragma_foreign_proc_extra_attribute).
Index: compiler/prog_type.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_type.m,v
retrieving revision 1.48
diff -u -r1.48 prog_type.m
--- compiler/prog_type.m	22 May 2009 02:51:21 -0000	1.48
+++ compiler/prog_type.m	1 Jun 2009 02:48:29 -0000
@@ -309,6 +309,7 @@
 :- func io_io_type = mer_type.
 :- func stm_atomic_type = mer_type.
 :- func region_type = mer_type.
+:- func future_type(mer_type) = mer_type.
 
     % Succeed iff the given variable is of region_type.
     %
@@ -924,6 +925,10 @@
     Module = mercury_region_builtin_module,
     Name = qualified(Module, "region").
 
+future_type(ValueType) = defined_type(Name, [ValueType], kind_star) :-
+    Module = mercury_par_builtin_module,
+    Name = qualified(Module, "future").
+
 is_region_var(VarTypes, Var)  :-
     map.lookup(VarTypes, Var, Type),
     Type = region_type.
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing debian/patches
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/base64
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/fixed
cvs diff: Diffing extras/gator
cvs diff: Diffing extras/gator/generations
cvs diff: Diffing extras/gator/generations/1
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_allegro
cvs diff: Diffing extras/graphics/mercury_allegro/examples
cvs diff: Diffing extras/graphics/mercury_allegro/samples
cvs diff: Diffing extras/graphics/mercury_allegro/samples/demo
cvs diff: Diffing extras/graphics/mercury_allegro/samples/mandel
cvs diff: Diffing extras/graphics/mercury_allegro/samples/pendulum2
cvs diff: Diffing extras/graphics/mercury_allegro/samples/speed
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/log4m
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/mopenssl
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/net
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/posix/samples
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/solver_types
cvs diff: Diffing extras/solver_types/library
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/windows_installer_generator
cvs diff: Diffing extras/windows_installer_generator/sample
cvs diff: Diffing extras/windows_installer_generator/sample/images
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
Index: library/par_builtin.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/par_builtin.m,v
retrieving revision 1.18
diff -u -r1.18 par_builtin.m
--- library/par_builtin.m	4 Jun 2009 08:07:06 -0000	1.18
+++ library/par_builtin.m	4 Jun 2009 08:12:05 -0000
@@ -5,11 +5,11 @@
 % This file may only be copied under the terms of the GNU Library General
 % Public License - see the file COPYING.LIB in the Mercury distribution.
 %---------------------------------------------------------------------------%
-% 
+%
 % File: par_builtin.m.
 % Main authors: wangp.
 % Stability: low.
-% 
+%
 % This file is automatically imported, as if via `use_module', into every
 % module in lowlevel parallel grades.  It is intended for the builtin procedures
 % that the compiler generates implicit calls to when implementing parallel
@@ -18,7 +18,7 @@
 % This module is a private part of the Mercury implementation; user modules
 % should never explicitly import this module. The interface for this module
 % does not get included in the Mercury library reference manual.
-% 
+%
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -29,31 +29,33 @@
 
 :- type future(T).
 
-    % Allocate a new future object.  A future acts as an intermediary for a
+    % Allocate a new future object. A future acts as an intermediary for a
     % shared variable between parallel conjuncts, when one conjunct produces
     % the value for other conjuncts.
     %
 :- pred new_future(future(T)::uo) is det.
 
-    % wait(Future, Value):
+    % wait_future(Future, Value):
     %
-    % Wait until Future is signalled, blocking if necessary.  Then the value
-    % bound to the variable associated with the future is bound to Value.
+    % Wait until Future is signalled, blocking if necessary. Then set Value
+    % to the value bound to the variable associated with the future.
     %
-:- pred wait(future(T)::in, T::out) is det.
+:- pred wait_future(future(T)::in, T::out) is det.
 
-    % get(Future, Value):
+    % get_future(Future, Value):
     %
-    % Like wait but assumes the future has been signalled already.
+    % Like wait_future but assumes the future has been signalled already.
     %
-:- pred get(future(T)::in, T::out) is det.
+:- pred get_future(future(T)::in, T::out) is det.
 
-    % Notify that the variable associated with the given future has been bound
-    % to a value.  Threads waiting on the future will be woken.  Future waits
-    % on the future will succeed immediately.  A future can only be signalled
-    % once.
+    % Notify any waiting threads that the variable associated with the given
+    % future has been bound to a value. Threads waiting on the future will be
+    % woken up, and future waits on the future will succeed immediately.
+    % A future can only be signalled once.
+    % XXX The implementation actually allows a future to be signalled
+    % more than once, provided the signals specify the same value.
     %
-:- impure pred signal(future(T)::in, T::in) is det.
+:- impure pred signal_future(future(T)::in, T::in) is det.
 
 % The following predicates are intended to be used as conditions to decide if
 % something should be done in parallel or sequence. Success should indicate
@@ -86,31 +88,6 @@
 
 :- implementation.
 
-:- pragma foreign_decl("C",
-"
-    #include ""mercury_context.h""
-    #include ""mercury_thread.h""
-
-    typedef struct MR_Future MR_Future;
-
-#ifdef MR_THREAD_SAFE
-    struct MR_Future {
-        /* lock preventing concurrent accesses */
-        MercuryLock     MR_fut_lock;
-        /* whether this future has been signalled yet */
-        int             MR_fut_signalled;
-
-        /* linked list of all the contexts blocked on this future */
-        MR_Context      *MR_fut_suspended;
-        MR_Word         MR_fut_value;
-    };
-#else /* !MR_THREAD_SAFE */
-    struct MR_Future {
-        char dummy; /* ANSI C doesn't allow empty structs */
-    };
-#endif /* !MR_THREAD_SAFE */
-").
-
 :- pragma foreign_type("C", future(T), "MR_Future *",
     [can_pass_as_mercury_type]).
 
@@ -119,123 +96,53 @@
 :- pragma foreign_type("Erlang", future(T), "").
 :- pragma foreign_type("Java", future(T), "java.lang.Object").
 
+%-----------------------------------------------------------------------------%
+
 :- pragma foreign_proc("C",
     new_future(Future::uo),
-    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        may_not_duplicate],
 "
-#if (!defined MR_HIGHLEVEL_CODE) && (defined MR_THREAD_SAFE)
-
-    MR_Word fut_addr;
-
-    MR_incr_hp(fut_addr, MR_round_up(sizeof(MR_Future), sizeof(MR_Word)));
-    Future = (MR_Future *) fut_addr;
-
-    pthread_mutex_init(&(Future->MR_fut_lock), MR_MUTEX_ATTR);
-
-    /*
-    ** The mutex needs to be destroyed when the future is garbage collected.
-    ** For efficiency we might want to ignore this altogether, e.g. on Linux
-    ** pthread_mutex_destroy() only checks that the mutex is unlocked.
-    **
-    ** We initialize the value field only to prevent its previous value,
-    ** which may point to an allocated block, keeping that block alive.
-    ** Semantically, the value field is undefined at this point in time.
-    */
-  #ifdef MR_CONSERVATIVE_GC
-    GC_REGISTER_FINALIZER(Future, MR_finalize_future, NULL, NULL, NULL);
-    Future->MR_fut_value = 0;
-  #endif
-
-    Future->MR_fut_signalled = MR_FALSE;
-    Future->MR_fut_suspended = NULL;
-
-#else
-
-    MR_fatal_error(""internal error: par_builtin should only be used by ""
-        ""lowlevel parallel grades"");
-
-#endif
+    MR_par_builtin_new_future(Future);
 ").
 
-:- pragma foreign_decl("C", "
-#ifdef MR_CONSERVATIVE_GC
-    void MR_finalize_future(void *obj, void *cd);
-#endif
+:- pragma foreign_proc("C",
+    wait_future(Future::in, Value::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        may_not_duplicate],
+"
+    MR_par_builtin_wait_future(Future, Value);
 ").
 
-:- pragma foreign_code("C", "
-#ifdef MR_CONSERVATIVE_GC
-    void
-    MR_finalize_future(void *obj, void *cd)
-    {
-        MR_Future *fut = (MR_Future *) obj;
-
-      #ifdef MR_THREAD_SAFE
-        pthread_mutex_destroy(&(fut->MR_fut_lock));
-      #endif
-    }
-#endif
+:- pragma foreign_proc("C",
+    get_future(Future::in, Value::out),
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
+        may_not_duplicate],
+"
+    MR_par_builtin_get_future(Future, Value);
 ").
 
 :- pragma foreign_proc("C",
-    wait(Future::in, Value::out),
-    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
+    signal_future(Future::in, Value::in),
+    [will_not_call_mercury, thread_safe, will_not_modify_trail,
+        may_not_duplicate],
 "
-#if (!defined MR_HIGHLEVEL_CODE) && (defined MR_THREAD_SAFE)
-
-    /*
-    ** It would be nice if we could rely on an invariant such as
-    ** `if MR_fut_signalled is true, then reading MR_fut_value is ok'
-    ** even *without* wrapping up those two field accesses in the mutex,
-    ** taking the mutex only when MR_fut_signalled is false. (We would
-    ** then have to repeat the test of MR_fut_signalled, of course.)
-    ** Unfortunately, memory systems today cannot be relied on to provide
-    ** the required level of consistency.
-    */
-
-    MR_LOCK(&(Future->MR_fut_lock), ""future.wait"");
-
-    if (Future->MR_fut_signalled) {
-        Value = Future->MR_fut_value;
-        MR_UNLOCK(&(Future->MR_fut_lock), ""future.wait"");
-    } else {
-        MR_Context *ctxt;
-
-        /*
-        ** Put the address of the future at a fixed place known to
-        ** mercury__par_builtin__wait_resume, to wit, the top of the stack.
-        */
-        MR_incr_sp(1);
-        MR_sv(1) = (MR_Word) Future;
-
-        /*
-        ** Save this context and put it on the list of suspended contexts for
-        ** this future.
-        */
-        ctxt = MR_ENGINE(MR_eng_this_context);
-        MR_save_context(ctxt);
-
-        ctxt->MR_ctxt_resume = MR_ENTRY(mercury__par_builtin__wait_resume);
-        ctxt->MR_ctxt_next = Future->MR_fut_suspended;
-        Future->MR_fut_suspended = ctxt;
-
-        MR_UNLOCK(&(Future->MR_fut_lock), ""future.wait"");
-
-        MR_ENGINE(MR_eng_this_context) = NULL;
-        MR_runnext();
-    }
-
-#else
-
-    MR_fatal_error(""internal error: par_builtin.wait"");
-    Value = -1;
+    MR_par_builtin_signal_future(Future, Value);
+").
 
-#endif
+:- pragma foreign_proc("C",
+    evaluate_parallelism_condition,
+    [will_not_call_mercury, thread_safe],
+"
+    /* All uses of this predicate should override the body. */
+    MR_fatal_error(""evaluate_parallelism_condition called"");
 ").
 
+%-----------------------------------------------------------------------------%
+
     % `wait_resume' is the piece of code we jump to when a thread suspended
     % on a future resumes after the future is signalled.
-    % 
+    %
 :- pragma foreign_decl("C",
 "
 /*
@@ -302,6 +209,8 @@
     #endif
 ").
 
+<<<<<<< par_builtin.m
+=======
 :- pragma foreign_proc("C",
     get(Future::in, Value::out),
     [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
@@ -398,5 +307,6 @@
     IO = IO0; 
 ").
 
+>>>>>>> 1.18
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
cvs diff: Diffing mdbcomp
Index: mdbcomp/program_representation.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/mdbcomp/program_representation.m,v
retrieving revision 1.47
diff -u -r1.47 program_representation.m
--- mdbcomp/program_representation.m	2 Apr 2009 09:49:27 -0000	1.47
+++ mdbcomp/program_representation.m	5 Apr 2009 23:44:00 -0000
@@ -1715,9 +1715,9 @@
 no_type_info_builtin_2(table_builtin, "table_lookup_insert_typeclassinfo", 3).
 no_type_info_builtin_2(term_size_prof_builtin, "increment_size", 2).
 no_type_info_builtin_2(par_builtin, "new_future", 1).
-no_type_info_builtin_2(par_builtin, "wait", 2).
-no_type_info_builtin_2(par_builtin, "get", 2).
-no_type_info_builtin_2(par_builtin, "signal", 2).
+no_type_info_builtin_2(par_builtin, "wait_future", 2).
+no_type_info_builtin_2(par_builtin, "get_future", 2).
+no_type_info_builtin_2(par_builtin, "signal_future", 2).
 
     % True iff the given predicate is defined with an :- external
     % declaration.  Note that the arity includes the hidden type info
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
Index: runtime/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/Mmakefile,v
retrieving revision 1.145
diff -u -r1.145 Mmakefile
--- runtime/Mmakefile	19 Mar 2008 05:30:00 -0000	1.145
+++ runtime/Mmakefile	4 Nov 2008 04:15:41 -0000
@@ -1,5 +1,5 @@
 #-----------------------------------------------------------------------------#
-# Copyright (C) 1998-2007 The University of Melbourne.
+# Copyright (C) 1998-2008 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.
 #-----------------------------------------------------------------------------#
@@ -70,6 +70,7 @@
 			mercury_misc.h		\
 			mercury_mm_own_stacks.h	\
 			mercury_overflow.h	\
+			mercury_par_builtin.h	\
 			mercury_proc_id.h	\
 			mercury_prof.h		\
 			mercury_prof_mem.h	\
@@ -180,6 +181,7 @@
 			mercury_minimal_model.c	\
 			mercury_misc.c		\
 			mercury_mm_own_stacks.c	\
+			mercury_par_builtin.c		\
 			mercury_prof.c		\
 			mercury_profiling_builtin.c	\
 			mercury_prof_mem.c	\
Index: runtime/mercury_imp.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_imp.h,v
retrieving revision 1.27
diff -u -r1.27 mercury_imp.h
--- runtime/mercury_imp.h	9 Oct 2007 07:59:54 -0000	1.27
+++ runtime/mercury_imp.h	4 Nov 2008 04:15:42 -0000
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1993-1998,2000,2003-2007 The University of Melbourne.
+** Copyright (C) 1993-1998,2000,2003-2008 The University of Melbourne.
 ** This file may only be copied under the terms of the GNU Library General
 ** Public License - see the file COPYING.LIB in the Mercury distribution.
 */
@@ -89,6 +89,7 @@
 #ifdef MR_USE_MINIMAL_MODEL_OWN_STACKS
 #include	"mercury_mm_own_stacks.h"
 #endif
+#include	"mercury_par_builtin.h"
 
 #include	"mercury_univ.h"
 #include	"mercury_complexity.h"
Index: runtime/mercury_par_builtin.c
===================================================================
RCS file: runtime/mercury_par_builtin.c
diff -N runtime/mercury_par_builtin.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ runtime/mercury_par_builtin.c	25 Oct 2008 06:24:40 -0000
@@ -0,0 +1,27 @@
+/*
+vim: ft=c ts=4 sw=4 et
+*/
+/*
+** Copyright (C) 2008 The University of Melbourne.
+** This file may only be copied under the terms of the GNU Library General
+** Public License - see the file COPYING.LIB in the Mercury distribution.
+*/
+
+#include "mercury_types.h"
+#include "mercury_par_builtin.h"
+
+#ifdef MR_CONSERVATIVE_GC
+
+void
+MR_finalize_future(void *obj, void *cd)
+{
+    MR_Future *future;
+    
+    future = (MR_Future *) obj;
+
+  #ifdef MR_THREAD_SAFE
+    pthread_mutex_destroy(&(future->MR_fut_lock));
+  #endif
+}
+
+#endif
Index: runtime/mercury_par_builtin.h
===================================================================
RCS file: runtime/mercury_par_builtin.h
diff -N runtime/mercury_par_builtin.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ runtime/mercury_par_builtin.h	3 Nov 2008 04:29:47 -0000
@@ -0,0 +1,208 @@
+/*
+vim: ft=c ts=4 sw=4 et
+*/
+/*
+** Copyright (C) 2008 The University of Melbourne.
+** This file may only be copied under the terms of the GNU Library General
+** Public License - see the file COPYING.LIB in the Mercury distribution.
+*/
+
+/*
+** This module contains the definitions of the primitive operations we use to
+** implement dependent AND-parallelism as C macros. The macros can be invoked
+** either from the predicates representing the operations in par_builtin.m
+** in the library directory, or from a foreign_proc version of those
+** predicates inserted directly into compiler-generated code.
+*/
+
+#ifndef MERCURY_PAR_BUILTIN_H
+#define MERCURY_PAR_BUILTIN_H
+
+#include "mercury_context.h"
+#include "mercury_thread.h"
+
+#ifdef MR_THREAD_SAFE
+
+    struct MR_Future_Struct {
+        /* lock preventing concurrent accesses */
+        MercuryLock     MR_fut_lock;
+
+        /* whether this future has been signalled yet */
+        int             MR_fut_signalled;
+
+        /* linked list of all the contexts blocked on this future */
+        MR_Context      *MR_fut_suspended;
+
+        MR_Word         MR_fut_value;
+    };
+
+#else /* !MR_THREAD_SAFE */
+
+    struct MR_Future_Struct {
+        char dummy; /* ANSI C doesn't allow empty structs */
+    };
+
+#endif /* !MR_THREAD_SAFE */
+
+
+/*
+** The mutex in the future needs to be destroyed when the future is garbage
+** collected. For efficiency we might want to ignore this altogether,
+** e.g. on Linux pthread_mutex_destroy() only checks that the mutex
+** is unlocked.
+**
+** We initialize the value field only to prevent its previous value,
+** which may point to an allocated block, keeping that block alive.
+** Semantically, the value field is undefined at this point in time.
+*/
+
+#ifdef MR_CONSERVATIVE_GC
+    extern  void    MR_finalize_future(void *obj, void *cd);
+
+    #define MR_register_future_finalizer(Future)                            \
+        do {                                                                \
+            GC_REGISTER_FINALIZER(Future, MR_finalize_future,               \
+                NULL, NULL, NULL);                                          \
+            Future->MR_fut_value = 0;                                       \
+        } while (0)
+#else
+    #define MR_register_future_finalizer(Future)                            \
+        ((void) 0)
+#endif
+
+#ifdef MR_LL_PARALLEL_CONJ
+
+    #define MR_par_builtin_new_future(Future)                               \
+        do {                                                                \
+            MR_Word fut_addr;                                               \
+                                                                            \
+            MR_incr_hp(fut_addr,                                            \
+                MR_round_up(sizeof(MR_Future), sizeof(MR_Word)));           \
+            Future = (MR_Future *) fut_addr;                                \
+                                                                            \
+            pthread_mutex_init(&(Future->MR_fut_lock), MR_MUTEX_ATTR);      \
+            MR_register_future_finalizer(Future);                           \
+                                                                            \
+            Future->MR_fut_signalled = MR_FALSE;                            \
+            Future->MR_fut_suspended = NULL;                                \
+        } while (0)
+
+    /*
+    ** It would be nice if we could rely on an invariant such as
+    ** `if MR_fut_signalled is true, then reading MR_fut_value is ok'
+    ** even *without* wrapping up those two field accesses in the mutex,
+    ** taking the mutex only when MR_fut_signalled is false. (We would
+    ** then have to repeat the test of MR_fut_signalled, of course.)
+    ** Unfortunately, memory systems today cannot be relied on to provide
+    ** the required level of consistency; some don't have any way to ask
+    ** for the necessary memory barrier.
+    */
+
+    MR_declare_entry(mercury__par_builtin__wait_resume);
+
+    #define MR_par_builtin_wait_future(Future, Value)                       \
+        do {                                                                \
+            MR_LOCK(&(Future->MR_fut_lock), "future.wait");                 \
+                                                                            \
+            if (Future->MR_fut_signalled) {                                 \
+                Value = Future->MR_fut_value;                               \
+                MR_UNLOCK(&(Future->MR_fut_lock), "future.wait");           \
+            } else {                                                        \
+                MR_Context *ctxt;                                           \
+                                                                            \
+                /*                                                          \
+                ** Put the address of the future at a fixed place known to  \
+                ** mercury__par_builtin__wait_resume, to wit, the top of    \
+                ** the stack.                                               \
+                */                                                          \
+                MR_incr_sp(1);                                              \
+                MR_sv(1) = (MR_Word) Future;                                \
+                                                                            \
+                /*                                                          \
+                ** Save this context and put it on the list of suspended    \
+                ** contexts for this future.                                \
+                */                                                          \
+                ctxt = MR_ENGINE(MR_eng_this_context);                      \
+                MR_save_context(ctxt);                                      \
+                                                                            \
+                ctxt->MR_ctxt_resume =                                      \
+                    MR_ENTRY(mercury__par_builtin__wait_resume);            \
+                ctxt->MR_ctxt_next = Future->MR_fut_suspended;              \
+                Future->MR_fut_suspended = ctxt;                            \
+                                                                            \
+                MR_UNLOCK(&(Future->MR_fut_lock), "future.wait");           \
+                                                                            \
+                MR_ENGINE(MR_eng_this_context) = NULL;                      \
+                MR_runnext();                                               \
+            }                                                               \
+        } while (0)
+
+    #define MR_par_builtin_get_future(Future, Value)                        \
+        do {                                                                \
+            assert(Future->MR_fut_signalled);                               \
+            Value = Future->MR_fut_value;                                   \
+        } while (0)
+
+    #define MR_par_builtin_signal_future(Future, Value)                     \
+        do {                                                                \
+            MR_Context *ctxt;                                               \
+            MR_Context *next;                                               \
+                                                                            \
+            MR_LOCK(&(Future->MR_fut_lock), "future.signal");               \
+                                                                            \
+            /*                                                              \
+            ** If the same future is passed twice to a procedure then it    \
+            ** could be signalled twice, but the value must be the same.    \
+            */                                                              \
+            if (Future->MR_fut_signalled) {                                 \
+                assert(Future->MR_fut_value == Value);                      \
+            } else {                                                        \
+                Future->MR_fut_signalled = MR_TRUE;                         \
+                Future->MR_fut_value = Value;                               \
+            }                                                               \
+                                                                            \
+            /* Schedule all the contexts blocked on this future. */         \
+            ctxt = Future->MR_fut_suspended;                                \
+            while (ctxt != NULL) {                                          \
+                next = ctxt->MR_ctxt_next;                                  \
+                MR_schedule_context(ctxt);  /* clobbers MR_ctxt_next */     \
+                ctxt = next;                                                \
+            }                                                               \
+            Future->MR_fut_suspended = NULL;                                \
+                                                                            \
+            MR_UNLOCK(&(Future->MR_fut_lock), "future.signal");             \
+        } while (0)
+
+#else
+
+    #define MR_par_builtin_new_future(Future)                               \
+        do {                                                                \
+            MR_fatal_error("internal error: "                               \
+                "new_future should only be used "                           \
+                "by lowlevel parallel grades");                             \
+        } while (0)
+
+    #define MR_par_builtin_wait_future(Future, Value)                       \
+        do {                                                                \
+            MR_fatal_error("internal error: "                               \
+                "wait_future should only be used "                          \
+                "by lowlevel parallel grades");                             \
+        } while (0)
+
+    #define MR_par_builtin_get_future(Future, Value)                        \
+        do {                                                                \
+            MR_fatal_error("internal error: "                               \
+                "get_future should only be used "                           \
+                "by lowlevel parallel grades");                             \
+        } while (0)
+
+    #define MR_par_builtin_signal_future(Future, Value)                     \
+        do {                                                                \
+            MR_fatal_error("internal error: "                               \
+                "signal_future should only be used "                        \
+                "by lowlevel parallel grades");                             \
+        } while (0)
+
+#endif
+
+#endif /* not MERCURY_PAR_BUILTIN_H */
Index: runtime/mercury_types.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_types.h,v
retrieving revision 1.56
diff -u -r1.56 mercury_types.h
--- runtime/mercury_types.h	23 Jan 2008 11:44:48 -0000	1.56
+++ runtime/mercury_types.h	4 Nov 2008 04:15:49 -0000
@@ -2,7 +2,7 @@
 ** vim: ts=4 sw=4 expandtab
 */
 /*
-** Copyright (C) 1995-2007 The University of Melbourne.
+** Copyright (C) 1995-2008 The University of Melbourne.
 ** This file may only be copied under the terms of the GNU Library General
 ** Public License - see the file COPYING.LIB in the Mercury distribution.
 */
@@ -26,7 +26,7 @@
 
 /*
 ** MR_VARIABLE_SIZED -- what to put between the []s when declaring
-**			a variable length array at the end of a struct.
+**          a variable length array at the end of a struct.
 **
 ** The preferred values, if the compiler understands them, convey to the
 ** implementation that the array has a variable length. The default value
@@ -39,15 +39,15 @@
 ** both MR_MAX_VIRTUAL_R_REG and MR_PSEUDOTYPEINFO_MAX_VAR.
 */
 
-#if __STDC_VERSION__ >= 199901	/* January 1999 */
+#if __STDC_VERSION__ >= 199901  /* January 1999 */
   /* Use C9X-style variable-length arrays. */
-  #define	MR_VARIABLE_SIZED	/* nothing */
+  #define   MR_VARIABLE_SIZED   /* nothing */
 #elif defined(__GNUC__)
   /* Use GNU-style variable-length arrays */
-  #define	MR_VARIABLE_SIZED	0
+  #define   MR_VARIABLE_SIZED   0
 #else
   /* Just fake it by pretending that the array has a fixed size */
-  #define	MR_VARIABLE_SIZED	1024
+  #define   MR_VARIABLE_SIZED   1024
 #endif
 
 /*
@@ -77,9 +77,9 @@
 typedef unsigned char                   MR_uint_least8_t;
 typedef signed char                     MR_int_least8_t;
 
-/* 
+/*
 ** This section defines the basic types that we use.
-** Note that we require 
+** Note that we require
 **      sizeof(MR_Word) == sizeof(MR_Integer) == sizeof(MR_CodePtr).
 */
 
@@ -140,20 +140,20 @@
 */
 
 typedef struct {
-	MR_Integer size;
-	MR_Word elements[MR_VARIABLE_SIZED];
+    MR_Integer size;
+    MR_Word elements[MR_VARIABLE_SIZED];
 } MR_ArrayType;
 
-typedef MR_ArrayType		*MR_ArrayPtr;
-typedef const MR_ArrayType	*MR_ConstArrayPtr;
+typedef MR_ArrayType        *MR_ArrayPtr;
+typedef const MR_ArrayType  *MR_ConstArrayPtr;
 
 typedef struct {
-	MR_Integer num_bits;
-	MR_uint_least8_t elements[MR_VARIABLE_SIZED];
+    MR_Integer num_bits;
+    MR_uint_least8_t elements[MR_VARIABLE_SIZED];
 } MR_BitmapType;
 
-typedef MR_BitmapType		*MR_BitmapPtr;
-typedef const MR_BitmapType	*MR_ConstBitmapPtr;
+typedef MR_BitmapType       *MR_BitmapPtr;
+typedef const MR_BitmapType *MR_ConstBitmapPtr;
 
 #ifndef MR_HIGHLEVEL_CODE
   /*
@@ -286,10 +286,10 @@
 typedef struct MR_ConsDebug_Struct              MR_ConsDebug;
 typedef struct MR_GenDebug_Struct               MR_GenDebug;
 
-typedef	MR_Word		                            *MR_AnswerBlock;
-typedef	MR_Subgoal	                            *MR_SubgoalPtr;
-typedef	MR_Consumer	                            *MR_ConsumerPtr;
-typedef	MR_Generator	                        *MR_GeneratorPtr;
+typedef MR_Word                                 *MR_AnswerBlock;
+typedef MR_Subgoal                              *MR_SubgoalPtr;
+typedef MR_Consumer                             *MR_ConsumerPtr;
+typedef MR_Generator                            *MR_GeneratorPtr;
 
 typedef struct MR_TableStepStats_Struct         MR_TableStepStats;
 typedef struct MR_TableStats_Struct             MR_TableStats;
@@ -308,4 +308,6 @@
 typedef struct MR_RegionCommitSave_Struct       MR_RegionCommitSave;
 typedef struct MR_RegionProfUnit_Struct         MR_RegionProfUnit;
 
+typedef struct MR_Future_Struct                 MR_Future;
+
 #endif /* not MERCURY_TYPES_H */
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/standalone_c
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/solver_types
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing slice
cvs diff: Diffing ssdb
cvs diff: Diffing tests
cvs diff: Diffing tests/analysis
cvs diff: Diffing tests/analysis/ctgc
cvs diff: Diffing tests/analysis/excp
cvs diff: Diffing tests/analysis/ext
cvs diff: Diffing tests/analysis/sharing
cvs diff: Diffing tests/analysis/table
cvs diff: Diffing tests/analysis/trail
cvs diff: Diffing tests/analysis/unused_args
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/par_conj
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/stm
cvs diff: Diffing tests/stm/orig
cvs diff: Diffing tests/stm/orig/stm-compiler
cvs diff: Diffing tests/stm/orig/stm-compiler/test1
cvs diff: Diffing tests/stm/orig/stm-compiler/test10
cvs diff: Diffing tests/stm/orig/stm-compiler/test2
cvs diff: Diffing tests/stm/orig/stm-compiler/test3
cvs diff: Diffing tests/stm/orig/stm-compiler/test4
cvs diff: Diffing tests/stm/orig/stm-compiler/test5
cvs diff: Diffing tests/stm/orig/stm-compiler/test6
cvs diff: Diffing tests/stm/orig/stm-compiler/test7
cvs diff: Diffing tests/stm/orig/stm-compiler/test8
cvs diff: Diffing tests/stm/orig/stm-compiler/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/bm2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/stmqueue
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test10
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test11
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par/test9
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test1
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test2
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test3
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test4
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test5
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test6
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test7
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test8
cvs diff: Diffing tests/stm/orig/stm-compiler-par-asm_fast/test9
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/trailing
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list