[m-dev.] for review: trailing for the MLDS back-end
Fergus Henderson
fjh at cs.mu.OZ.AU
Tue Dec 12 02:37:26 AEDT 2000
Estimated hours taken: 8
Implement trailing for the MLDS back-end.
library/private_builtin.m:
Define impure Mercury procedures corresponding to the
trailing operations in runtime/mercury_trail.h.
compiler/add_trail_ops.m:
A new HLDS->HLDS pass.
This implements trailing by inserting calls to the
trailing primitives declared in library/private_builtin.m.
compiler/mercury_compile.m:
Change the code for mercury_compile__mlds_backend so that
if trailing is enabled, it invokes the new add_trail_ops pass.
Workspace: /home/pgrad/fjh/ws/hg3
Index: compiler/add_trail_ops.m
===================================================================
RCS file: add_trail_ops.m
diff -N add_trail_ops.m
--- /dev/null Thu Mar 30 14:06:13 2000
+++ add_trail_ops.m Tue Dec 12 02:27:05 2000
@@ -0,0 +1,485 @@
+%-----------------------------------------------------------------------------%
+% Copyright (C) 2000 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.
+%-----------------------------------------------------------------------------%
+%
+% Author: fjh.
+%
+% This module is an HLDS-to-HLDS transformation that inserts code to
+% handle trailing. The transformation involves adding calls to impure
+% predicates defined in library/private_builtin.m, which in turn call
+% macros defined in runtime/mercury_trail.h.
+%
+% This pass is currently only used for the MLDS back-end.
+% For some reason (perhaps efficiency?? or more likely just historical?),
+% the LLDS back-end inserts the trail operations as it is generating
+% LLDS code, rather than via an HLDS to HLDS transformation.
+%
+% See compiler/notes/trailing.html for more information about trailing
+% in the Mercury implementation.
+%
+%-----------------------------------------------------------------------------%
+
+%-----------------------------------------------------------------------------%
+
+:- module add_trail_ops.
+:- interface.
+:- import_module hlds_pred, hlds_module.
+
+:- pred add_trail_ops(proc_info::in, module_info::in, proc_info::out) is det.
+
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module prog_data, prog_util, (inst).
+:- import_module hlds_goal, hlds_data, quantification, modules, type_util.
+:- import_module code_model, instmap.
+
+:- import_module bool, string.
+:- import_module assoc_list, list, map, set, varset, std_util, require.
+
+
+%
+% As we traverse the goal, we add new variables
+% keep track of XXX
+% construct it.
+%
+:- type trail_ops_info --->
+ trail_ops_info(
+ varset :: prog_varset,
+ var_types :: vartypes,
+ module_info :: module_info
+ ).
+
+add_trail_ops(Proc0, ModuleInfo0, Proc) :-
+ % The ModuleInfo argument is there just for passes_aux
+ proc_info_goal(Proc0, Goal0),
+ proc_info_varset(Proc0, VarSet0),
+ proc_info_vartypes(Proc0, VarTypes0),
+ TrailOpsInfo0 = trail_ops_info(VarSet0, VarTypes0, ModuleInfo0),
+ goal_add_trail_ops(Goal0, Goal, TrailOpsInfo0, TrailOpsInfo),
+ TrailOpsInfo = trail_ops_info(VarSet, VarTypes, _),
+ proc_info_set_goal(Proc0, Goal, Proc1),
+ proc_info_set_varset(Proc1, VarSet, Proc2),
+ proc_info_set_vartypes(Proc2, VarTypes, Proc3),
+ % The code below does not maintain the non-local variables,
+ % so we need to requantify.
+ % XXX it would be more efficient to maintain them
+ % rather than recomputing them every time.
+ requantify_proc(Proc3, Proc).
+
+:- pred goal_add_trail_ops(hlds_goal::in, hlds_goal::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+
+goal_add_trail_ops(GoalExpr0 - GoalInfo, GoalExpr - GoalInfo) -->
+ goal_expr_add_trail_ops(GoalExpr0, GoalInfo, GoalExpr).
+
+:- pred goal_expr_add_trail_ops(hlds_goal_expr::in, hlds_goal_info::in,
+ hlds_goal_expr::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+
+goal_expr_add_trail_ops(conj(Goals0), _, conj(Goals)) -->
+ conj_add_trail_ops(Goals0, Goals).
+
+goal_expr_add_trail_ops(par_conj(Goals0, SM), _, par_conj(Goals, SM)) -->
+ conj_add_trail_ops(Goals0, Goals).
+
+goal_expr_add_trail_ops(disj([], B), _, disj([], B)) --> [].
+
+goal_expr_add_trail_ops(disj(Goals0, B), GoalInfo, Goal) -->
+ { Goals0 = [_|_] },
+
+ { goal_info_get_context(GoalInfo, Context) },
+ { goal_info_get_code_model(GoalInfo, CodeModel) },
+
+ %
+ % Allocate a new trail ticket so that we can
+ % restore things on back-tracking
+ %
+ new_ticket_var(TicketVar),
+ gen_store_ticket(TicketVar, Context, StoreTicketGoal),
+ disj_add_trail_ops(Goals0, yes, CodeModel, TicketVar, Goals),
+ { Goal = conj([StoreTicketGoal, disj(Goals, B) - GoalInfo]) }.
+
+goal_expr_add_trail_ops(switch(A, B, Cases0, D), _, switch(A, B, Cases, D)) -->
+ cases_add_trail_ops(Cases0, Cases).
+
+goal_expr_add_trail_ops(not(Goal0), GoalInfo, Goal) -->
+ %
+ % We handle negations by converting them into if-then-elses.
+ %
+ { goal_info_get_context(GoalInfo, Context) },
+ { true_goal(Context, True) },
+ { fail_goal(Context, Fail) },
+ { map__init(SM) },
+ { IfThenElse = if_then_else([], Goal0, Fail, True, SM) },
+ goal_expr_add_trail_ops(IfThenElse, GoalInfo, Goal).
+
+goal_expr_add_trail_ops(some(A, B, Goal0), OuterGoalInfo, Goal) -->
+ { Goal0 = _ - InnerGoalInfo },
+ { goal_info_get_code_model(InnerGoalInfo, InnerCodeModel) },
+ { goal_info_get_code_model(OuterGoalInfo, OuterCodeModel) },
+ (
+ { InnerCodeModel = model_non },
+ { OuterCodeModel \= model_non }
+ ->
+ % handle commits
+
+ %
+ % before executing the goal, we save the ticket counter,
+ % and allocate a new trail ticket
+ %
+ { goal_info_get_context(OuterGoalInfo, Context) },
+ new_ticket_counter_var(SavedTicketCounterVar),
+ new_ticket_var(TicketVar),
+ gen_mark_ticket_stack(SavedTicketCounterVar, Context,
+ MarkTicketStackGoal),
+ gen_store_ticket(TicketVar, Context, StoreTicketGoal),
+ %
+ % next we execute the goal that we're committing across
+ %
+ goal_add_trail_ops(Goal0, Goal1),
+ %
+ % if the goal succeeds, then we have committed to that
+ % goal, so we need to commit the trail entries
+ % and prune any trail tickets that have been allocated
+ % since we saved the ticket counter
+ %
+ gen_reset_ticket_commit(TicketVar, Context,
+ ResetTicketCommitGoal),
+ gen_prune_tickets_to(SavedTicketCounterVar, Context,
+ PruneTicketsToGoal),
+ %
+ % if the goal fails, then we should undo the trail
+ % entries and discard this trail ticket before
+ % backtracking over it
+ %
+ gen_reset_ticket_undo(TicketVar, Context,
+ ResetTicketUndoGoal),
+ gen_discard_ticket(Context, DiscardTicketGoal),
+ { fail_goal(Context, FailGoal) },
+
+ % put it all together
+ { Goal2 = some(A, B, Goal1) - OuterGoalInfo },
+ { SuccCode = conj([Goal2, ResetTicketCommitGoal,
+ PruneTicketsToGoal]) - OuterGoalInfo },
+ ( { OuterCodeModel = model_semi } ->
+ { FailGoal = _ - FailGoalInfo },
+ { FailCode = conj([ResetTicketUndoGoal,
+ DiscardTicketGoal, FailGoal]) - FailGoalInfo },
+ { map__init(SM) },
+ { Goal3 = disj([SuccCode, FailCode], SM) -
+ OuterGoalInfo }
+ ;
+ { Goal3 = SuccCode }
+ ),
+ { Goal = conj([MarkTicketStackGoal, StoreTicketGoal, Goal3]) }
+ ;
+ goal_add_trail_ops(Goal0, Goal1),
+ { Goal = some(A, B, Goal1) }
+ ).
+
+goal_expr_add_trail_ops(if_then_else(A, Cond0, Then0, Else0, E), GoalInfo,
+ Goal) -->
+ goal_add_trail_ops(Cond0, Cond),
+ goal_add_trail_ops(Then0, Then1),
+ goal_add_trail_ops(Else0, Else1),
+ %
+ % Allocate a new trail ticket so that we can
+ % restore things if the condition fails.
+ %
+ new_ticket_var(TicketVar),
+ { goal_info_get_context(GoalInfo, Context) },
+ gen_store_ticket(TicketVar, Context, StoreTicketGoal),
+
+ %
+ % Commit the trail ticket entries if the condition
+ % succeeds.
+ %
+ { Then1 = _ - Then1GoalInfo },
+ { Cond = _ - CondGoalInfo },
+ { goal_info_get_code_model(CondGoalInfo, CondCodeModel) },
+ ( { CondCodeModel = model_non } ->
+ gen_reset_ticket_solve(TicketVar, Context,
+ ResetTicketSolveGoal),
+ { Then = conj([ResetTicketSolveGoal, Then1]) - Then1GoalInfo }
+ ;
+ gen_reset_ticket_commit(TicketVar, Context,
+ ResetTicketCommitGoal),
+ gen_prune_ticket(Context, PruneTicketGoal),
+ { Then = conj([ResetTicketCommitGoal, PruneTicketGoal, Then1])
+ - Then1GoalInfo }
+ ),
+ gen_reset_ticket_undo(TicketVar, Context, ResetTicketUndoGoal),
+ gen_discard_ticket(Context, DiscardTicketGoal),
+ { Else1 = _ - Else1GoalInfo },
+ { Else = conj([ResetTicketUndoGoal, DiscardTicketGoal, Else1])
+ - Else1GoalInfo },
+ { IfThenElse = if_then_else(A, Cond, Then, Else, E) - GoalInfo },
+ { Goal = conj([StoreTicketGoal, IfThenElse]) }.
+
+
+goal_expr_add_trail_ops(call(A,B,C,D,E,F), _, call(A,B,C,D,E,F)) --> [].
+
+goal_expr_add_trail_ops(generic_call(A,B,C,D), _, generic_call(A,B,C,D)) --> [].
+
+goal_expr_add_trail_ops(unify(A,B,C,D,E), _, unify(A,B,C,D,E)) --> [].
+
+goal_expr_add_trail_ops(PragmaForeign0, _, PragmaForeign) -->
+ { PragmaForeign0 = pragma_foreign_code(_,_,_,_,_,_,Impl) },
+ { Impl = nondet(_,_,_,_,_,_,_,_,_) ->
+ error("sorry, not implemented: nondet pragma foreign_code with --use-trail --high-level-code")
+ ;
+ PragmaForeign = PragmaForeign0
+ }.
+
+goal_expr_add_trail_ops(bi_implication(_, _), _, _) -->
+ % these should have been expanded out by now
+ { error("goal_expr_add_trail_ops: unexpected bi_implication") }.
+
+:- pred conj_add_trail_ops(hlds_goals::in, hlds_goals::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+conj_add_trail_ops(Goals0, Goals) -->
+ list__map_foldl(goal_add_trail_ops, Goals0, Goals).
+
+:- pred disj_add_trail_ops(hlds_goals::in, bool::in, code_model::in,
+ prog_var::in, hlds_goals::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+
+disj_add_trail_ops([], _, _, _, []) --> [].
+disj_add_trail_ops([Goal0 | Goals0], IsFirstBranch, CodeModel, TicketVar,
+ [Goal | Goals]) -->
+ { Goal0 = _ - GoalInfo0 },
+ { goal_info_get_context(GoalInfo0, Context) },
+ %
+ % First undo the effects of any earlier branches
+ %
+ ( { IsFirstBranch = yes } ->
+ { UndoList = [] }
+ ;
+ gen_reset_ticket_undo(TicketVar, Context, ResetTicketUndoGoal),
+ ( { Goals0 = [] } ->
+ %
+ % Once we've reached the last disjunct,
+ % we can discard the trail ticket
+ %
+ gen_discard_ticket(Context, DiscardTicketGoal),
+ { UndoList = [ResetTicketUndoGoal, DiscardTicketGoal] }
+ ;
+ { UndoList = [ResetTicketUndoGoal] }
+ )
+ ),
+ %
+ % Then execute the disjunct goal
+ %
+ goal_add_trail_ops(Goal0, Goal1),
+ %
+ % For model_semi and model_det disjunctions,
+ % once we reach the end of the disjunct goal,
+ % we're committing to this disjunct, so we need
+ % to prune the trail ticket.
+ %
+ ( { CodeModel = model_non } ->
+ { PruneList = [] }
+ ;
+ gen_reset_ticket_commit(TicketVar, Context,
+ ResetTicketCommitGoal),
+ gen_prune_ticket(Context, PruneTicketGoal),
+ { PruneList = [ResetTicketCommitGoal, PruneTicketGoal] }
+ ),
+ %
+ % Package up the stuff we built earlier.
+ %
+ { Goal1 = _ - GoalInfo1 },
+ { conj_list_to_goal(UndoList ++ [Goal1] ++ PruneList, GoalInfo1,
+ Goal) },
+
+ % Recursively handle the remaining disjuncts
+ disj_add_trail_ops(Goals0, no, CodeModel, TicketVar, Goals).
+
+:- pred cases_add_trail_ops(list(case)::in, list(case)::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+cases_add_trail_ops([], []) --> [].
+cases_add_trail_ops([Case0 | Cases0], [Case | Cases]) -->
+ { Case0 = case(ConsId, Goal0) },
+ { Case = case(ConsId, Goal) },
+ goal_add_trail_ops(Goal0, Goal),
+ cases_add_trail_ops(Cases0, Cases).
+
+%-----------------------------------------------------------------------------%
+
+:- pred gen_store_ticket(prog_var::in, prog_context::in, hlds_goal::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+
+gen_store_ticket(TicketVar, Context, SaveTicketGoal) -->
+ ModuleInfo =^ module_info,
+ { generate_call("store_ticket", [TicketVar],
+ det, yes(impure),
+ [TicketVar - ground_inst],
+ ModuleInfo, Context, SaveTicketGoal) }.
+
+:- pred gen_reset_ticket_undo(prog_var::in, prog_context::in, hlds_goal::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+
+gen_reset_ticket_undo(TicketVar, Context, ResetTicketGoal) -->
+ ModuleInfo =^ module_info,
+ { generate_call("reset_ticket_undo", [TicketVar],
+ det, yes(impure), [],
+ ModuleInfo, Context, ResetTicketGoal) }.
+
+:- pred gen_reset_ticket_solve(prog_var::in, prog_context::in, hlds_goal::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+
+gen_reset_ticket_solve(TicketVar, Context, ResetTicketGoal) -->
+ ModuleInfo =^ module_info,
+ { generate_call("reset_ticket_solve", [TicketVar],
+ det, yes(impure), [],
+ ModuleInfo, Context, ResetTicketGoal) }.
+
+:- pred gen_reset_ticket_commit(prog_var::in, prog_context::in, hlds_goal::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+
+gen_reset_ticket_commit(TicketVar, Context, ResetTicketGoal) -->
+ ModuleInfo =^ module_info,
+ { generate_call("reset_ticket_commit", [TicketVar],
+ det, yes(impure), [],
+ ModuleInfo, Context, ResetTicketGoal) }.
+
+:- pred gen_prune_ticket(prog_context::in, hlds_goal::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+
+gen_prune_ticket(Context, PruneTicketGoal) -->
+ ModuleInfo =^ module_info,
+ { generate_call("prune_ticket", [], det, yes(impure), [],
+ ModuleInfo, Context, PruneTicketGoal) }.
+
+:- pred gen_discard_ticket(prog_context::in, hlds_goal::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+
+gen_discard_ticket(Context, DiscardTicketGoal) -->
+ ModuleInfo =^ module_info,
+ { generate_call("discard_ticket", [], det, yes(impure), [],
+ ModuleInfo, Context, DiscardTicketGoal) }.
+
+:- pred gen_mark_ticket_stack(prog_var::in, prog_context::in, hlds_goal::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+
+gen_mark_ticket_stack(SavedTicketCounterVar, Context, MarkTicketStackGoal) -->
+ ModuleInfo =^ module_info,
+ { generate_call("mark_ticket_stack", [SavedTicketCounterVar],
+ det, yes(impure), [],
+ ModuleInfo, Context, MarkTicketStackGoal) }.
+
+:- pred gen_prune_tickets_to(prog_var::in, prog_context::in, hlds_goal::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+
+gen_prune_tickets_to(SavedTicketCounterVar, Context, PruneTicketsToGoal) -->
+ ModuleInfo =^ module_info,
+ { generate_call("prune_tickets_to", [SavedTicketCounterVar],
+ det, yes(impure), [],
+ ModuleInfo, Context, PruneTicketsToGoal) }.
+
+:- func ground_inst = (inst).
+ground_inst = ground(unique, none).
+
+%-----------------------------------------------------------------------------%
+
+:- pred new_ticket_var(prog_var::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+
+new_ticket_var(Var) -->
+ new_var("TrailTicket", ticket_type, Var).
+
+:- pred new_ticket_counter_var(prog_var::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+
+new_ticket_counter_var(Var) -->
+ new_var("SavedTicketCounter", ticket_counter_type, Var).
+
+:- pred new_var(string::in, (type)::in, prog_var::out,
+ trail_ops_info::in, trail_ops_info::out) is det.
+
+new_var(Name, Type, Var, TOI0, TOI) :-
+ VarSet0 = TOI0 ^ varset,
+ VarTypes0 = TOI0 ^ var_types,
+ varset__new_named_var(VarSet0, Name, Var, VarSet),
+ map__det_insert(VarTypes0, Var, Type, VarTypes),
+ TOI = ((TOI0 ^ varset := VarSet)
+ ^ var_types := VarTypes).
+
+%-----------------------------------------------------------------------------%
+
+:- func ticket_type = (type).
+ticket_type = c_pointer_type.
+
+:- func ticket_counter_type = (type).
+ticket_counter_type = c_pointer_type.
+
+:- func c_pointer_type = (type).
+c_pointer_type = Type :-
+ mercury_public_builtin_module(BuiltinModule),
+ construct_type(qualified(BuiltinModule, "c_pointer") - 0, [], Type).
+
+%-----------------------------------------------------------------------------%
+
+% XXX copied from table_gen.m
+
+:- pred generate_call(string::in, list(prog_var)::in, determinism::in,
+ maybe(goal_feature)::in, assoc_list(prog_var, inst)::in,
+ module_info::in, term__context::in, hlds_goal::out) is det.
+
+generate_call(PredName, Args, Detism, MaybeFeature, InstMap, Module, Context,
+ CallGoal) :-
+ list__length(Args, Arity),
+ mercury_private_builtin_module(BuiltinModule),
+ module_info_get_predicate_table(Module, PredTable),
+ (
+ predicate_table_search_pred_m_n_a(PredTable,
+ BuiltinModule, PredName, Arity,
+ [PredId0])
+ ->
+ PredId = PredId0
+ ;
+ string__int_to_string(Arity, ArityS),
+ string__append_list(["can't locate ", PredName,
+ "/", ArityS], ErrorMessage),
+ error(ErrorMessage)
+ ),
+ module_info_pred_info(Module, PredId, PredInfo),
+ (
+ pred_info_procids(PredInfo, [ProcId0])
+ ->
+ ProcId = ProcId0
+ ;
+ string__int_to_string(Arity, ArityS),
+ string__append_list(["too many modes for pred ",
+ PredName, "/", ArityS], ErrorMessage),
+ error(ErrorMessage)
+
+ ),
+ Call = call(PredId, ProcId, Args, not_builtin, no,
+ qualified(BuiltinModule, PredName)),
+ set__init(NonLocals0),
+ set__insert_list(NonLocals0, Args, NonLocals),
+ determinism_components(Detism, _CanFail, NumSolns),
+ (
+ NumSolns = at_most_zero
+ ->
+ instmap_delta_init_unreachable(InstMapDelta)
+ ;
+ instmap_delta_from_assoc_list(InstMap, InstMapDelta)
+ ),
+ goal_info_init(NonLocals, InstMapDelta, Detism, CallGoalInfo0),
+ goal_info_set_context(CallGoalInfo0, Context, CallGoalInfo1),
+ (
+ MaybeFeature = yes(Feature),
+ goal_info_add_feature(CallGoalInfo1, Feature, CallGoalInfo)
+ ;
+ MaybeFeature = no,
+ CallGoalInfo = CallGoalInfo1
+ ),
+ CallGoal = Call - CallGoalInfo.
+
+%-----------------------------------------------------------------------------%
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.185
diff -u -d -r1.185 mercury_compile.m
--- compiler/mercury_compile.m 2000/11/19 02:23:22 1.185
+++ compiler/mercury_compile.m 2000/12/11 13:56:10
@@ -55,6 +55,7 @@
:- import_module bytecode_gen, bytecode.
% the MLDS back-end
+:- import_module add_trail_ops. % HLDS -> HLDS
:- import_module mark_static_terms. % HLDS -> HLDS
:- import_module mlds. % MLDS data structure
:- import_module ml_code_gen, rtti_to_mlds. % HLDS/RTTI -> MLDS
@@ -1648,6 +1649,27 @@
%-----------------------------------------------------------------------------%
+:- pred mercury_compile__maybe_add_trail_ops(module_info, bool, bool,
+ module_info, io__state, io__state).
+:- mode mercury_compile__maybe_add_trail_ops(in, in, in, out, di, uo)
+ is det.
+
+mercury_compile__maybe_add_trail_ops(HLDS0, Verbose, Stats, HLDS) -->
+ globals__io_lookup_bool_option(use_trail, UseTrail),
+ ( { UseTrail = yes } ->
+ maybe_write_string(Verbose,
+ "% Adding trailing operations...\n"),
+ maybe_flush_output(Verbose),
+ process_all_nonimported_procs(update_proc(add_trail_ops),
+ HLDS0, HLDS),
+ maybe_write_string(Verbose, "% done.\n"),
+ maybe_report_stats(Stats)
+ ;
+ { HLDS = HLDS0 }
+ ).
+
+%-----------------------------------------------------------------------------%
+
:- pred mercury_compile__maybe_write_dependency_graph(module_info, bool, bool,
module_info, io__state, io__state).
:- mode mercury_compile__maybe_write_dependency_graph(in, in, in, out, di, uo)
@@ -2438,7 +2460,11 @@
process_all_nonimported_nonaditi_procs, HLDS53),
mercury_compile__maybe_dump_hlds(HLDS53, "53", "simplify2"),
- mercury_compile__maybe_mark_static_terms(HLDS53, Verbose, Stats,
+ mercury_compile__maybe_add_trail_ops(HLDS53, Verbose, Stats,
+ HLDS55),
+ mercury_compile__maybe_dump_hlds(HLDS55, "55", "add_trail_ops"),
+
+ mercury_compile__maybe_mark_static_terms(HLDS55, Verbose, Stats,
HLDS60),
mercury_compile__maybe_dump_hlds(HLDS60, "60", "mark_static"),
Index: library/private_builtin.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/private_builtin.m,v
retrieving revision 1.58
diff -u -d -r1.58 private_builtin.m
--- library/private_builtin.m 2000/11/23 02:00:01 1.58
+++ library/private_builtin.m 2000/12/11 14:18:27
@@ -463,6 +463,103 @@
%-----------------------------------------------------------------------------%
+ % This section of the module contains predicates that are used
+ % by the MLDS back-end, to implement trailing.
+ % (The LLDS back-end does not use these; instead it inserts
+ % the corresponding LLDS instructions directly during code
+ % generation.)
+ % These predicates should not be used by user programs directly.
+
+:- interface.
+
+:- type ticket == c_pointer.
+:- type ticket_counter == c_pointer.
+
+ % For documentation, see the corresponding LLDS
+
+:- impure pred store_ticket(ticket::out) is det.
+:- impure pred reset_ticket_undo(ticket::in) is det.
+:- impure pred reset_ticket_commit(ticket::in) is det.
+:- impure pred reset_ticket_solve(ticket::in) is det.
+:- impure pred discard_ticket is det.
+:- impure pred prune_ticket is det.
+:- impure pred mark_ticket_stack(ticket_counter::out) is det.
+:- impure pred prune_tickets_to(ticket_counter::in) is det.
+
+ % N.B. interface continued below.
+
+:- implementation.
+
+:- pragma c_code(store_ticket(Ticket::out),
+ [will_not_call_mercury, thread_safe],
+"
+#ifdef MR_USE_TRAIL
+ MR_store_ticket(Ticket);
+#else
+ Ticket = 0;
+#endif
+").
+
+:- pragma c_code(reset_ticket_undo(Ticket::in),
+ [will_not_call_mercury, thread_safe],
+"
+#ifdef MR_USE_TRAIL
+ MR_reset_ticket(Ticket, MR_undo);
+#endif
+").
+
+:- pragma c_code(reset_ticket_commit(Ticket::in),
+ [will_not_call_mercury, thread_safe],
+"
+#ifdef MR_USE_TRAIL
+ MR_reset_ticket(Ticket, MR_commit);
+#endif
+").
+
+:- pragma c_code(reset_ticket_solve(Ticket::in),
+ [will_not_call_mercury, thread_safe],
+"
+#ifdef MR_USE_TRAIL
+ MR_reset_ticket(Ticket, MR_solve);
+#endif
+").
+
+:- pragma c_code(discard_ticket,
+ [will_not_call_mercury, thread_safe],
+"
+#ifdef MR_USE_TRAIL
+ MR_discard_ticket();
+#endif
+").
+
+:- pragma c_code(prune_ticket,
+ [will_not_call_mercury, thread_safe],
+"
+#ifdef MR_USE_TRAIL
+ MR_prune_ticket();
+#endif
+").
+
+:- pragma c_code(mark_ticket_stack(TicketCounter::out),
+ [will_not_call_mercury, thread_safe],
+"
+#ifdef MR_USE_TRAIL
+ MR_mark_ticket_stack(TicketCounter);
+#else
+ TicketCounter = 0;
+#endif
+").
+
+:- pragma c_code(prune_tickets_to(TicketCounter::in),
+ [will_not_call_mercury, thread_safe],
+"
+#ifdef MR_USE_TRAIL
+ MR_prune_tickets_to(TicketCounter);
+#endif
+").
+
+%-----------------------------------------------------------------------------%
+
:- interface.
% This section of the module is for miscellaneous predicates
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
| of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to: mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions: mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------
More information about the developers
mailing list